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  }