github.com/yaling888/clash@v1.53.0/hub/executor/executor.go (about)

     1  package executor
     2  
     3  import (
     4  	"fmt"
     5  	"net/netip"
     6  	"os"
     7  	"strings"
     8  	"sync"
     9  
    10  	"github.com/phuslu/log"
    11  	"github.com/samber/lo"
    12  
    13  	"github.com/yaling888/clash/adapter"
    14  	"github.com/yaling888/clash/adapter/outboundgroup"
    15  	"github.com/yaling888/clash/component/auth"
    16  	"github.com/yaling888/clash/component/dialer"
    17  	"github.com/yaling888/clash/component/iface"
    18  	"github.com/yaling888/clash/component/profile"
    19  	"github.com/yaling888/clash/component/profile/cachefile"
    20  	"github.com/yaling888/clash/component/resolver"
    21  	"github.com/yaling888/clash/component/trie"
    22  	"github.com/yaling888/clash/config"
    23  	C "github.com/yaling888/clash/constant"
    24  	"github.com/yaling888/clash/constant/provider"
    25  	"github.com/yaling888/clash/dns"
    26  	"github.com/yaling888/clash/listener"
    27  	authStore "github.com/yaling888/clash/listener/auth"
    28  	L "github.com/yaling888/clash/log"
    29  	"github.com/yaling888/clash/tunnel"
    30  )
    31  
    32  var mux sync.Mutex
    33  
    34  func readConfig(path string) ([]byte, error) {
    35  	if _, err := os.Stat(path); os.IsNotExist(err) {
    36  		return nil, err
    37  	}
    38  	data, err := os.ReadFile(path)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	if len(data) == 0 {
    44  		return nil, fmt.Errorf("configuration file %s is empty", path)
    45  	}
    46  
    47  	return data, err
    48  }
    49  
    50  // Parse config with default config path
    51  func Parse() (*config.Config, error) {
    52  	return ParseWithPath(C.Path.Config())
    53  }
    54  
    55  // ParseWithPath parse config with custom config path
    56  func ParseWithPath(path string) (*config.Config, error) {
    57  	buf, err := readConfig(path)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	return ParseWithBytes(buf)
    63  }
    64  
    65  // ParseWithBytes config with buffer
    66  func ParseWithBytes(buf []byte) (*config.Config, error) {
    67  	return config.Parse(buf)
    68  }
    69  
    70  // ApplyConfig dispatch configure to all parts
    71  func ApplyConfig(cfg *config.Config, force bool) {
    72  	mux.Lock()
    73  	defer mux.Unlock()
    74  
    75  	updateUsers(cfg.Users)
    76  	updateProxies(cfg.Proxies, cfg.Providers)
    77  	updateRules(cfg.Rules)
    78  	updateScript(cfg.RuleProviders, cfg.MainMatcher)
    79  	updateHosts(cfg.Hosts)
    80  	updateMitm(cfg.Mitm)
    81  	updateProfile(cfg)
    82  	updateDNS(cfg.DNS, &cfg.General.Tun)
    83  	updateGeneral(cfg.General, force)
    84  	updateInbounds(cfg.Inbounds, force)
    85  	updateExperimental(cfg)
    86  	updateTunnels(cfg.Tunnels)
    87  
    88  	L.SetLevel(cfg.General.LogLevel)
    89  }
    90  
    91  func GetGeneral() *config.General {
    92  	ports := listener.GetPorts()
    93  	auths := make([]string, 0)
    94  	if authM := authStore.Authenticator(); authM != nil {
    95  		auths = lo.Map(authM.Users(), func(s string, _ int) string {
    96  			l := len(s)
    97  			if l == 0 {
    98  				return ""
    99  			}
   100  			return fmt.Sprintf("%s****%s", s[0:1], s[l-1:l])
   101  		})
   102  	}
   103  
   104  	general := &config.General{
   105  		LegacyInbound: config.LegacyInbound{
   106  			Port:        ports.Port,
   107  			SocksPort:   ports.SocksPort,
   108  			RedirPort:   ports.RedirPort,
   109  			TProxyPort:  ports.TProxyPort,
   110  			MixedPort:   ports.MixedPort,
   111  			MitmPort:    ports.MitmPort,
   112  			AllowLan:    listener.AllowLan(),
   113  			BindAddress: listener.BindAddress(),
   114  		},
   115  		Authentication: auths,
   116  		Mode:           tunnel.Mode(),
   117  		LogLevel:       L.Level(),
   118  		IPv6:           !resolver.DisableIPv6,
   119  		Sniffing:       tunnel.Sniffing(),
   120  		Tun:            C.GetTunConf(),
   121  	}
   122  
   123  	return general
   124  }
   125  
   126  func updateExperimental(c *config.Config) {
   127  	tunnel.UDPFallbackMatch.Store(c.Experimental.UDPFallbackMatch)
   128  
   129  	udpPolicy := c.Experimental.UDPFallbackPolicy
   130  	if strings.EqualFold(udpPolicy, "direct") || strings.EqualFold(udpPolicy, "reject") {
   131  		udpPolicy = strings.ToUpper(udpPolicy)
   132  	}
   133  	tunnel.UDPFallbackPolicy.Store(udpPolicy)
   134  }
   135  
   136  func updateDNS(c *config.DNS, t *C.Tun) {
   137  	cfg := dns.Config{
   138  		Main:         c.NameServer,
   139  		Fallback:     c.Fallback,
   140  		IPv6:         c.IPv6,
   141  		EnhancedMode: c.EnhancedMode,
   142  		Pool:         c.FakeIPRange,
   143  		Hosts:        c.Hosts,
   144  		FallbackFilter: dns.FallbackFilter{
   145  			GeoIP:     c.FallbackFilter.GeoIP,
   146  			GeoIPCode: c.FallbackFilter.GeoIPCode,
   147  			IPCIDR:    c.FallbackFilter.IPCIDR,
   148  			Domain:    c.FallbackFilter.Domain,
   149  			GeoSite:   c.FallbackFilter.GeoSite,
   150  		},
   151  		Default:       c.DefaultNameserver,
   152  		Policy:        c.NameServerPolicy,
   153  		ProxyServer:   c.ProxyServerNameserver,
   154  		Remote:        c.RemoteNameserver,
   155  		SearchDomains: c.SearchDomains,
   156  	}
   157  
   158  	r := dns.NewResolver(cfg)
   159  	m := dns.NewEnhancer(cfg)
   160  
   161  	// reuse cache of old host mapper
   162  	if old := resolver.DefaultHostMapper; old != nil {
   163  		m.PatchFrom(old.(*dns.ResolverEnhancer))
   164  	}
   165  
   166  	resolver.DefaultResolver = r
   167  	resolver.DefaultHostMapper = m
   168  	resolver.DefaultLocalServer = dns.NewLocalServer(r, m)
   169  
   170  	resolver.RemoteDnsResolve = c.RemoteDnsResolve
   171  
   172  	if c.Enable {
   173  		dns.ReCreateServer(c.Listen, r, m)
   174  	} else {
   175  		if !t.Enable {
   176  			resolver.DefaultResolver = nil
   177  			resolver.DefaultHostMapper = nil
   178  			resolver.DefaultLocalServer = nil
   179  		}
   180  		dns.ReCreateServer("", nil, nil)
   181  	}
   182  
   183  	if cfg.Pool != nil {
   184  		t.TunAddressPrefix = cfg.Pool.IPNet()
   185  	}
   186  }
   187  
   188  func updateHosts(tree *trie.DomainTrie[netip.Addr]) {
   189  	resolver.DefaultHosts = tree
   190  }
   191  
   192  func updateProxies(proxies map[string]C.Proxy, providers map[string]provider.ProxyProvider) {
   193  	tunnel.UpdateProxies(proxies, providers)
   194  }
   195  
   196  func updateRules(rules []C.Rule) {
   197  	tunnel.UpdateRules(rules)
   198  }
   199  
   200  func updateScript(providers map[string]C.Rule, matcher C.Matcher) {
   201  	tunnel.UpdateScript(providers, matcher)
   202  }
   203  
   204  func updateMitm(mitm *config.Mitm) {
   205  	tunnel.UpdateRewrites(mitm.Hosts, mitm.Rules)
   206  }
   207  
   208  func updateTunnels(tunnels []config.Tunnel) {
   209  	listener.PatchTunnel(tunnels, tunnel.TCPIn(), tunnel.UDPIn())
   210  }
   211  
   212  func updateInbounds(inbounds []C.Inbound, force bool) {
   213  	if !force {
   214  		return
   215  	}
   216  	tcpIn := tunnel.TCPIn()
   217  	udpIn := tunnel.UDPIn()
   218  
   219  	listener.ReCreateListeners(inbounds, tcpIn, udpIn)
   220  }
   221  
   222  func updateGeneral(general *config.General, force bool) {
   223  	tunnel.SetMode(general.Mode)
   224  	resolver.SetDisableIPv6(!general.IPv6)
   225  
   226  	defaultInterface := general.Interface
   227  	if defaultInterface != "" || (defaultInterface == "" && !general.Tun.Enable) {
   228  		dialer.DefaultInterface.Store(defaultInterface)
   229  		if defaultInterface != "" {
   230  			log.Info().Str("name", defaultInterface).Msg("[Config] default interface")
   231  		}
   232  	}
   233  
   234  	if general.RoutingMark > 0 || (general.RoutingMark == 0 && general.TProxyPort == 0) {
   235  		dialer.DefaultRoutingMark.Store(int32(general.RoutingMark))
   236  		if general.RoutingMark > 0 {
   237  			log.Info().Int("mark", general.RoutingMark).Msg("[Config] routing")
   238  		}
   239  	}
   240  
   241  	iface.FlushCache()
   242  
   243  	if !force {
   244  		return
   245  	}
   246  
   247  	allowLan := general.AllowLan
   248  	listener.SetAllowLan(allowLan)
   249  
   250  	bindAddress := general.BindAddress
   251  	listener.SetBindAddress(bindAddress)
   252  
   253  	sniffing := general.Sniffing
   254  	tunnel.SetSniffing(sniffing)
   255  
   256  	log.Info().Bool("sniffing", sniffing).Msg("[Config] tls")
   257  
   258  	general.Tun.StopRouteListener = true
   259  
   260  	tcpIn := tunnel.TCPIn()
   261  	udpIn := tunnel.UDPIn()
   262  	ports := listener.Ports{
   263  		Port:       general.Port,
   264  		SocksPort:  general.SocksPort,
   265  		RedirPort:  general.RedirPort,
   266  		TProxyPort: general.TProxyPort,
   267  		MixedPort:  general.MixedPort,
   268  		MitmPort:   general.MitmPort,
   269  	}
   270  
   271  	listener.ReCreatePortsListeners(ports, tcpIn, udpIn)
   272  	listener.ReCreateAutoRedir(general.EBpf.AutoRedir, defaultInterface, tcpIn, udpIn)
   273  	listener.ReCreateTun(&general.Tun, tcpIn, udpIn)
   274  	listener.ReCreateRedirToTun(general.EBpf.RedirectToTun)
   275  }
   276  
   277  func updateUsers(users []auth.AuthUser) {
   278  	authenticator := auth.NewAuthenticator(users)
   279  	authStore.SetAuthenticator(authenticator)
   280  	if authenticator != nil {
   281  		log.Info().Msg("[Inbound] authentication of local server updated")
   282  	}
   283  }
   284  
   285  func updateProfile(cfg *config.Config) {
   286  	profileCfg := cfg.Profile
   287  
   288  	profile.StoreSelected.Store(profileCfg.StoreSelected)
   289  	if profileCfg.StoreSelected {
   290  		patchSelectGroup(cfg.Proxies)
   291  	}
   292  
   293  	L.SetTracing(profileCfg.Tracing)
   294  }
   295  
   296  func patchSelectGroup(proxies map[string]C.Proxy) {
   297  	mapping := cachefile.Cache().SelectedMap()
   298  	if mapping == nil {
   299  		return
   300  	}
   301  
   302  	for name, proxy := range proxies {
   303  		outbound, ok := proxy.(*adapter.Proxy)
   304  		if !ok {
   305  			continue
   306  		}
   307  
   308  		selector, ok := outbound.ProxyAdapter.(*outboundgroup.Selector)
   309  		if !ok {
   310  			continue
   311  		}
   312  
   313  		selected, exist := mapping[name]
   314  		if !exist {
   315  			continue
   316  		}
   317  
   318  		_ = selector.Set(selected)
   319  	}
   320  }
   321  
   322  func Shutdown() {
   323  	listener.Cleanup()
   324  	resolver.StoreFakePoolState()
   325  
   326  	L.SetLevel(L.INFO)
   327  	log.Info().Msg("[Main] Clash shutting down")
   328  }