github.com/metacubex/mihomo@v1.18.5/hub/executor/executor.go (about) 1 package executor 2 3 import ( 4 "fmt" 5 "net" 6 "net/netip" 7 "os" 8 "runtime" 9 "strconv" 10 "sync" 11 "time" 12 13 "github.com/metacubex/mihomo/adapter" 14 "github.com/metacubex/mihomo/adapter/inbound" 15 "github.com/metacubex/mihomo/adapter/outboundgroup" 16 "github.com/metacubex/mihomo/component/auth" 17 "github.com/metacubex/mihomo/component/ca" 18 "github.com/metacubex/mihomo/component/dialer" 19 G "github.com/metacubex/mihomo/component/geodata" 20 "github.com/metacubex/mihomo/component/iface" 21 "github.com/metacubex/mihomo/component/profile" 22 "github.com/metacubex/mihomo/component/profile/cachefile" 23 "github.com/metacubex/mihomo/component/resolver" 24 SNI "github.com/metacubex/mihomo/component/sniffer" 25 "github.com/metacubex/mihomo/component/trie" 26 "github.com/metacubex/mihomo/config" 27 C "github.com/metacubex/mihomo/constant" 28 "github.com/metacubex/mihomo/constant/features" 29 "github.com/metacubex/mihomo/constant/provider" 30 "github.com/metacubex/mihomo/dns" 31 "github.com/metacubex/mihomo/listener" 32 authStore "github.com/metacubex/mihomo/listener/auth" 33 LC "github.com/metacubex/mihomo/listener/config" 34 "github.com/metacubex/mihomo/listener/inner" 35 "github.com/metacubex/mihomo/listener/tproxy" 36 "github.com/metacubex/mihomo/log" 37 "github.com/metacubex/mihomo/ntp" 38 "github.com/metacubex/mihomo/tunnel" 39 ) 40 41 var mux sync.Mutex 42 43 func readConfig(path string) ([]byte, error) { 44 if _, err := os.Stat(path); os.IsNotExist(err) { 45 return nil, err 46 } 47 data, err := os.ReadFile(path) 48 if err != nil { 49 return nil, err 50 } 51 52 if len(data) == 0 { 53 return nil, fmt.Errorf("configuration file %s is empty", path) 54 } 55 56 return data, err 57 } 58 59 // Parse config with default config path 60 func Parse() (*config.Config, error) { 61 return ParseWithPath(C.Path.Config()) 62 } 63 64 // ParseWithPath parse config with custom config path 65 func ParseWithPath(path string) (*config.Config, error) { 66 buf, err := readConfig(path) 67 if err != nil { 68 return nil, err 69 } 70 71 return ParseWithBytes(buf) 72 } 73 74 // ParseWithBytes config with buffer 75 func ParseWithBytes(buf []byte) (*config.Config, error) { 76 return config.Parse(buf) 77 } 78 79 // ApplyConfig dispatch configure to all parts 80 func ApplyConfig(cfg *config.Config, force bool) { 81 mux.Lock() 82 defer mux.Unlock() 83 84 tunnel.OnSuspend() 85 86 ca.ResetCertificate() 87 for _, c := range cfg.TLS.CustomTrustCert { 88 if err := ca.AddCertificate(c); err != nil { 89 log.Warnln("%s\nadd error: %s", c, err.Error()) 90 } 91 } 92 93 updateUsers(cfg.Users) 94 updateProxies(cfg.Proxies, cfg.Providers) 95 updateRules(cfg.Rules, cfg.SubRules, cfg.RuleProviders) 96 updateSniffer(cfg.Sniffer) 97 updateHosts(cfg.Hosts) 98 updateGeneral(cfg.General) 99 updateNTP(cfg.NTP) 100 updateDNS(cfg.DNS, cfg.RuleProviders, cfg.General.IPv6) 101 updateListeners(cfg.General, cfg.Listeners, force) 102 updateIPTables(cfg) 103 updateTun(cfg.General) 104 updateExperimental(cfg) 105 updateTunnels(cfg.Tunnels) 106 107 tunnel.OnInnerLoading() 108 109 initInnerTcp() 110 loadProxyProvider(cfg.Providers) 111 updateProfile(cfg) 112 loadRuleProvider(cfg.RuleProviders) 113 runtime.GC() 114 tunnel.OnRunning() 115 hcCompatibleProvider(cfg.Providers) 116 117 log.SetLevel(cfg.General.LogLevel) 118 } 119 120 func initInnerTcp() { 121 inner.New(tunnel.Tunnel) 122 } 123 124 func GetGeneral() *config.General { 125 ports := listener.GetPorts() 126 var authenticator []string 127 if auth := authStore.Authenticator(); auth != nil { 128 authenticator = auth.Users() 129 } 130 131 general := &config.General{ 132 Inbound: config.Inbound{ 133 Port: ports.Port, 134 SocksPort: ports.SocksPort, 135 RedirPort: ports.RedirPort, 136 TProxyPort: ports.TProxyPort, 137 MixedPort: ports.MixedPort, 138 Tun: listener.GetTunConf(), 139 TuicServer: listener.GetTuicConf(), 140 ShadowSocksConfig: ports.ShadowSocksConfig, 141 VmessConfig: ports.VmessConfig, 142 Authentication: authenticator, 143 SkipAuthPrefixes: inbound.SkipAuthPrefixes(), 144 LanAllowedIPs: inbound.AllowedIPs(), 145 LanDisAllowedIPs: inbound.DisAllowedIPs(), 146 AllowLan: listener.AllowLan(), 147 BindAddress: listener.BindAddress(), 148 }, 149 Controller: config.Controller{}, 150 Mode: tunnel.Mode(), 151 LogLevel: log.Level(), 152 IPv6: !resolver.DisableIPv6, 153 GeodataMode: G.GeodataMode(), 154 GeoAutoUpdate: G.GeoAutoUpdate(), 155 GeoUpdateInterval: G.GeoUpdateInterval(), 156 GeodataLoader: G.LoaderName(), 157 GeositeMatcher: G.SiteMatcherName(), 158 Interface: dialer.DefaultInterface.Load(), 159 Sniffing: tunnel.IsSniffing(), 160 TCPConcurrent: dialer.GetTcpConcurrent(), 161 } 162 163 return general 164 } 165 166 func updateListeners(general *config.General, listeners map[string]C.InboundListener, force bool) { 167 listener.PatchInboundListeners(listeners, tunnel.Tunnel, true) 168 if !force { 169 return 170 } 171 172 allowLan := general.AllowLan 173 listener.SetAllowLan(allowLan) 174 inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes) 175 inbound.SetAllowedIPs(general.LanAllowedIPs) 176 inbound.SetDisAllowedIPs(general.LanDisAllowedIPs) 177 178 bindAddress := general.BindAddress 179 listener.SetBindAddress(bindAddress) 180 listener.ReCreateHTTP(general.Port, tunnel.Tunnel) 181 listener.ReCreateSocks(general.SocksPort, tunnel.Tunnel) 182 listener.ReCreateRedir(general.RedirPort, tunnel.Tunnel) 183 if !features.CMFA { 184 listener.ReCreateAutoRedir(general.EBpf.AutoRedir, tunnel.Tunnel) 185 } 186 listener.ReCreateTProxy(general.TProxyPort, tunnel.Tunnel) 187 listener.ReCreateMixed(general.MixedPort, tunnel.Tunnel) 188 listener.ReCreateShadowSocks(general.ShadowSocksConfig, tunnel.Tunnel) 189 listener.ReCreateVmess(general.VmessConfig, tunnel.Tunnel) 190 listener.ReCreateTuic(general.TuicServer, tunnel.Tunnel) 191 } 192 193 func updateExperimental(c *config.Config) { 194 if c.Experimental.QUICGoDisableGSO { 195 _ = os.Setenv("QUIC_GO_DISABLE_GSO", strconv.FormatBool(true)) 196 } 197 if c.Experimental.QUICGoDisableECN { 198 _ = os.Setenv("QUIC_GO_DISABLE_ECN", strconv.FormatBool(true)) 199 } 200 dialer.GetIP4PEnable(c.Experimental.IP4PEnable) 201 } 202 203 func updateNTP(c *config.NTP) { 204 if c.Enable { 205 ntp.ReCreateNTPService( 206 net.JoinHostPort(c.Server, strconv.Itoa(c.Port)), 207 time.Duration(c.Interval), 208 c.DialerProxy, 209 c.WriteToSystem, 210 ) 211 } 212 } 213 214 func updateDNS(c *config.DNS, ruleProvider map[string]provider.RuleProvider, generalIPv6 bool) { 215 if !c.Enable { 216 resolver.DefaultResolver = nil 217 resolver.DefaultHostMapper = nil 218 resolver.DefaultLocalServer = nil 219 dns.ReCreateServer("", nil, nil) 220 return 221 } 222 cfg := dns.Config{ 223 Main: c.NameServer, 224 Fallback: c.Fallback, 225 IPv6: c.IPv6 && generalIPv6, 226 IPv6Timeout: c.IPv6Timeout, 227 EnhancedMode: c.EnhancedMode, 228 Pool: c.FakeIPRange, 229 Hosts: c.Hosts, 230 FallbackFilter: dns.FallbackFilter{ 231 GeoIP: c.FallbackFilter.GeoIP, 232 GeoIPCode: c.FallbackFilter.GeoIPCode, 233 IPCIDR: c.FallbackFilter.IPCIDR, 234 Domain: c.FallbackFilter.Domain, 235 GeoSite: c.FallbackFilter.GeoSite, 236 }, 237 Default: c.DefaultNameserver, 238 Policy: c.NameServerPolicy, 239 ProxyServer: c.ProxyServerNameserver, 240 RuleProviders: ruleProvider, 241 CacheAlgorithm: c.CacheAlgorithm, 242 } 243 244 r := dns.NewResolver(cfg) 245 pr := dns.NewProxyServerHostResolver(r) 246 m := dns.NewEnhancer(cfg) 247 248 // reuse cache of old host mapper 249 if old := resolver.DefaultHostMapper; old != nil { 250 m.PatchFrom(old.(*dns.ResolverEnhancer)) 251 } 252 253 resolver.DefaultResolver = r 254 resolver.DefaultHostMapper = m 255 resolver.DefaultLocalServer = dns.NewLocalServer(r, m) 256 resolver.UseSystemHosts = c.UseSystemHosts 257 258 if pr.Invalid() { 259 resolver.ProxyServerHostResolver = pr 260 } 261 262 dns.ReCreateServer(c.Listen, r, m) 263 } 264 265 func updateHosts(tree *trie.DomainTrie[resolver.HostValue]) { 266 resolver.DefaultHosts = resolver.NewHosts(tree) 267 } 268 269 func updateProxies(proxies map[string]C.Proxy, providers map[string]provider.ProxyProvider) { 270 tunnel.UpdateProxies(proxies, providers) 271 } 272 273 func updateRules(rules []C.Rule, subRules map[string][]C.Rule, ruleProviders map[string]provider.RuleProvider) { 274 tunnel.UpdateRules(rules, subRules, ruleProviders) 275 } 276 277 func loadProvider(pv provider.Provider) { 278 if pv.VehicleType() == provider.Compatible { 279 return 280 } else { 281 log.Infoln("Start initial provider %s", (pv).Name()) 282 } 283 284 if err := pv.Initial(); err != nil { 285 switch pv.Type() { 286 case provider.Proxy: 287 { 288 log.Errorln("initial proxy provider %s error: %v", (pv).Name(), err) 289 } 290 case provider.Rule: 291 { 292 log.Errorln("initial rule provider %s error: %v", (pv).Name(), err) 293 } 294 295 } 296 } 297 } 298 299 func loadRuleProvider(ruleProviders map[string]provider.RuleProvider) { 300 wg := sync.WaitGroup{} 301 ch := make(chan struct{}, concurrentCount) 302 for _, ruleProvider := range ruleProviders { 303 ruleProvider := ruleProvider 304 wg.Add(1) 305 ch <- struct{}{} 306 go func() { 307 defer func() { <-ch; wg.Done() }() 308 loadProvider(ruleProvider) 309 310 }() 311 } 312 313 wg.Wait() 314 } 315 316 func loadProxyProvider(proxyProviders map[string]provider.ProxyProvider) { 317 // limit concurrent size 318 wg := sync.WaitGroup{} 319 ch := make(chan struct{}, concurrentCount) 320 for _, proxyProvider := range proxyProviders { 321 proxyProvider := proxyProvider 322 wg.Add(1) 323 ch <- struct{}{} 324 go func() { 325 defer func() { <-ch; wg.Done() }() 326 loadProvider(proxyProvider) 327 }() 328 } 329 330 wg.Wait() 331 } 332 func hcCompatibleProvider(proxyProviders map[string]provider.ProxyProvider) { 333 // limit concurrent size 334 wg := sync.WaitGroup{} 335 ch := make(chan struct{}, concurrentCount) 336 for _, proxyProvider := range proxyProviders { 337 proxyProvider := proxyProvider 338 if proxyProvider.VehicleType() == provider.Compatible { 339 log.Infoln("Start initial Compatible provider %s", proxyProvider.Name()) 340 wg.Add(1) 341 ch <- struct{}{} 342 go func() { 343 defer func() { <-ch; wg.Done() }() 344 if err := proxyProvider.Initial(); err != nil { 345 log.Errorln("initial Compatible provider %s error: %v", proxyProvider.Name(), err) 346 } 347 }() 348 } 349 350 } 351 352 } 353 func updateTun(general *config.General) { 354 if general == nil { 355 return 356 } 357 listener.ReCreateTun(general.Tun, tunnel.Tunnel) 358 listener.ReCreateRedirToTun(general.Tun.RedirectToTun) 359 } 360 361 func updateSniffer(sniffer *config.Sniffer) { 362 if sniffer.Enable { 363 dispatcher, err := SNI.NewSnifferDispatcher( 364 sniffer.Sniffers, sniffer.ForceDomain, sniffer.SkipDomain, 365 sniffer.ForceDnsMapping, sniffer.ParsePureIp, 366 ) 367 if err != nil { 368 log.Warnln("initial sniffer failed, err:%v", err) 369 } 370 371 tunnel.UpdateSniffer(dispatcher) 372 log.Infoln("Sniffer is loaded and working") 373 } else { 374 dispatcher, err := SNI.NewCloseSnifferDispatcher() 375 if err != nil { 376 log.Warnln("initial sniffer failed, err:%v", err) 377 } 378 379 tunnel.UpdateSniffer(dispatcher) 380 log.Infoln("Sniffer is closed") 381 } 382 } 383 384 func updateTunnels(tunnels []LC.Tunnel) { 385 listener.PatchTunnel(tunnels, tunnel.Tunnel) 386 } 387 388 func updateGeneral(general *config.General) { 389 tunnel.SetMode(general.Mode) 390 tunnel.SetFindProcessMode(general.FindProcessMode) 391 resolver.DisableIPv6 = !general.IPv6 392 393 if general.TCPConcurrent { 394 dialer.SetTcpConcurrent(general.TCPConcurrent) 395 log.Infoln("Use tcp concurrent") 396 } 397 398 inbound.SetTfo(general.InboundTfo) 399 inbound.SetMPTCP(general.InboundMPTCP) 400 401 adapter.UnifiedDelay.Store(general.UnifiedDelay) 402 403 dialer.DefaultInterface.Store(general.Interface) 404 dialer.DefaultRoutingMark.Store(int32(general.RoutingMark)) 405 if general.RoutingMark > 0 { 406 log.Infoln("Use routing mark: %#x", general.RoutingMark) 407 } 408 409 iface.FlushCache() 410 G.SetLoader(general.GeodataLoader) 411 G.SetSiteMatcher(general.GeositeMatcher) 412 } 413 414 func updateUsers(users []auth.AuthUser) { 415 authenticator := auth.NewAuthenticator(users) 416 authStore.SetAuthenticator(authenticator) 417 if authenticator != nil { 418 log.Infoln("Authentication of local server updated") 419 } 420 } 421 422 func updateProfile(cfg *config.Config) { 423 profileCfg := cfg.Profile 424 425 profile.StoreSelected.Store(profileCfg.StoreSelected) 426 if profileCfg.StoreSelected { 427 patchSelectGroup(cfg.Proxies) 428 } 429 } 430 431 func patchSelectGroup(proxies map[string]C.Proxy) { 432 mapping := cachefile.Cache().SelectedMap() 433 if mapping == nil { 434 return 435 } 436 437 for name, proxy := range proxies { 438 outbound, ok := proxy.(*adapter.Proxy) 439 if !ok { 440 continue 441 } 442 443 selector, ok := outbound.ProxyAdapter.(outboundgroup.SelectAble) 444 if !ok { 445 continue 446 } 447 448 selected, exist := mapping[name] 449 if !exist { 450 continue 451 } 452 453 selector.ForceSet(selected) 454 } 455 } 456 457 func updateIPTables(cfg *config.Config) { 458 tproxy.CleanupTProxyIPTables() 459 460 iptables := cfg.IPTables 461 if runtime.GOOS != "linux" || !iptables.Enable { 462 return 463 } 464 465 var err error 466 defer func() { 467 if err != nil { 468 log.Errorln("[IPTABLES] setting iptables failed: %s", err.Error()) 469 os.Exit(2) 470 } 471 }() 472 473 if cfg.General.Tun.Enable { 474 err = fmt.Errorf("when tun is enabled, iptables cannot be set automatically") 475 return 476 } 477 478 var ( 479 inboundInterface = "lo" 480 bypass = iptables.Bypass 481 tProxyPort = cfg.General.TProxyPort 482 dnsCfg = cfg.DNS 483 DnsRedirect = iptables.DnsRedirect 484 485 dnsPort netip.AddrPort 486 ) 487 488 if tProxyPort == 0 { 489 err = fmt.Errorf("tproxy-port must be greater than zero") 490 return 491 } 492 493 if DnsRedirect { 494 if !dnsCfg.Enable { 495 err = fmt.Errorf("DNS server must be enable") 496 return 497 } 498 499 dnsPort, err = netip.ParseAddrPort(dnsCfg.Listen) 500 if err != nil { 501 err = fmt.Errorf("DNS server must be correct") 502 return 503 } 504 } 505 506 if iptables.InboundInterface != "" { 507 inboundInterface = iptables.InboundInterface 508 } 509 510 if dialer.DefaultRoutingMark.Load() == 0 { 511 dialer.DefaultRoutingMark.Store(2158) 512 } 513 514 err = tproxy.SetTProxyIPTables(inboundInterface, bypass, uint16(tProxyPort), DnsRedirect, dnsPort.Port()) 515 if err != nil { 516 return 517 } 518 519 log.Infoln("[IPTABLES] Setting iptables completed") 520 } 521 522 func Shutdown() { 523 listener.Cleanup() 524 tproxy.CleanupTProxyIPTables() 525 resolver.StoreFakePoolState() 526 527 log.Warnln("Mihomo shutting down") 528 }