Clash.Meta/hub/executor/executor.go

574 lines
15 KiB
Go
Raw Normal View History

2018-11-21 13:47:46 +08:00
package executor
import (
"fmt"
2023-09-01 03:11:35 +08:00
"net"
2022-04-12 20:20:04 +08:00
"net/netip"
"os"
2021-12-04 17:41:13 +08:00
"runtime"
2023-09-01 03:11:35 +08:00
"strconv"
2020-06-18 18:11:02 +08:00
"sync"
2023-09-01 03:11:35 +08:00
"time"
_ "unsafe"
2023-11-03 21:01:45 +08:00
"github.com/metacubex/mihomo/adapter"
"github.com/metacubex/mihomo/adapter/inbound"
"github.com/metacubex/mihomo/adapter/outboundgroup"
"github.com/metacubex/mihomo/component/auth"
"github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/geodata"
2024-09-09 16:08:48 +08:00
mihomoHttp "github.com/metacubex/mihomo/component/http"
2023-11-03 21:01:45 +08:00
"github.com/metacubex/mihomo/component/iface"
"github.com/metacubex/mihomo/component/keepalive"
2023-11-03 21:01:45 +08:00
"github.com/metacubex/mihomo/component/profile"
"github.com/metacubex/mihomo/component/profile/cachefile"
"github.com/metacubex/mihomo/component/resolver"
"github.com/metacubex/mihomo/component/resource"
"github.com/metacubex/mihomo/component/sniffer"
tlsC "github.com/metacubex/mihomo/component/tls"
2023-11-03 21:01:45 +08:00
"github.com/metacubex/mihomo/component/trie"
"github.com/metacubex/mihomo/component/updater"
2023-11-03 21:01:45 +08:00
"github.com/metacubex/mihomo/config"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/constant/provider"
"github.com/metacubex/mihomo/dns"
"github.com/metacubex/mihomo/listener"
authStore "github.com/metacubex/mihomo/listener/auth"
LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/inner"
"github.com/metacubex/mihomo/listener/tproxy"
"github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/ntp"
2023-11-03 21:01:45 +08:00
"github.com/metacubex/mihomo/tunnel"
2018-11-21 13:47:46 +08:00
)
2021-10-10 23:44:09 +08:00
var mux sync.Mutex
2020-06-18 18:11:02 +08:00
func readConfig(path string) ([]byte, error) {
if _, err := os.Stat(path); os.IsNotExist(err) {
return nil, err
}
2021-10-09 20:35:06 +08:00
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
if len(data) == 0 {
2020-08-25 22:19:59 +08:00
return nil, fmt.Errorf("configuration file %s is empty", path)
}
return data, err
}
2018-11-21 13:47:46 +08:00
// Parse config with default config path
func Parse() (*config.Config, error) {
return ParseWithPath(C.Path.Config())
}
// ParseWithPath parse config with custom config path
func ParseWithPath(path string) (*config.Config, error) {
buf, err := readConfig(path)
if err != nil {
return nil, err
}
return ParseWithBytes(buf)
}
// ParseWithBytes config with buffer
func ParseWithBytes(buf []byte) (*config.Config, error) {
return config.Parse(buf)
2018-11-21 13:47:46 +08:00
}
// ApplyConfig dispatch configure to all parts without ExternalController
2018-11-30 17:42:40 +08:00
func ApplyConfig(cfg *config.Config, force bool) {
2020-06-18 18:11:02 +08:00
mux.Lock()
defer mux.Unlock()
2024-09-09 16:08:48 +08:00
log.SetLevel(cfg.General.LogLevel)
tunnel.OnSuspend()
2023-09-22 14:45:34 +08:00
ca.ResetCertificate()
for _, c := range cfg.TLS.CustomTrustCert {
2023-09-22 14:45:34 +08:00
if err := ca.AddCertificate(c); err != nil {
log.Warnln("%s\nadd error: %s", c, err.Error())
}
}
updateExperimental(cfg.Experimental)
updateUsers(cfg.Users)
updateProxies(cfg.Proxies, cfg.Providers)
2022-12-04 13:37:14 +08:00
updateRules(cfg.Rules, cfg.SubRules, cfg.RuleProviders)
2022-04-16 08:29:38 +08:00
updateSniffer(cfg.Sniffer)
updateHosts(cfg.Hosts)
updateGeneral(cfg.General, true)
2023-09-01 03:11:35 +08:00
updateNTP(cfg.NTP)
updateDNS(cfg.DNS, cfg.General.IPv6)
updateListeners(cfg.General, cfg.Listeners, force)
updateTun(cfg.General) // tun should not care "force"
updateIPTables(cfg)
2022-11-18 22:57:33 +08:00
updateTunnels(cfg.Tunnels)
2022-01-21 22:38:02 +08:00
tunnel.OnInnerLoading()
initInnerTcp()
loadProxyProvider(cfg.Providers)
updateProfile(cfg)
loadRuleProvider(cfg.RuleProviders)
runtime.GC()
tunnel.OnRunning()
hcCompatibleProvider(cfg.Providers)
updateUpdater(cfg)
resolver.ResetConnection()
2018-11-21 13:47:46 +08:00
}
func initInnerTcp() {
inner.New(tunnel.Tunnel)
2022-05-08 00:04:16 +08:00
}
2018-11-21 13:47:46 +08:00
func GetGeneral() *config.General {
2022-11-18 22:57:33 +08:00
ports := listener.GetPorts()
2022-03-20 02:39:48 +08:00
var authenticator []string
if auth := authStore.Default.Authenticator(); auth != nil {
2019-06-27 20:45:12 +08:00
authenticator = auth.Users()
}
general := &config.General{
2020-06-18 18:11:02 +08:00
Inbound: config.Inbound{
Port: ports.Port,
SocksPort: ports.SocksPort,
RedirPort: ports.RedirPort,
TProxyPort: ports.TProxyPort,
MixedPort: ports.MixedPort,
Tun: listener.GetTunConf(),
2022-12-06 10:13:05 +08:00
TuicServer: listener.GetTuicConf(),
ShadowSocksConfig: ports.ShadowSocksConfig,
VmessConfig: ports.VmessConfig,
Authentication: authenticator,
2023-10-10 19:43:26 +08:00
SkipAuthPrefixes: inbound.SkipAuthPrefixes(),
LanAllowedIPs: inbound.AllowedIPs(),
LanDisAllowedIPs: inbound.DisAllowedIPs(),
AllowLan: listener.AllowLan(),
BindAddress: listener.BindAddress(),
InboundTfo: inbound.Tfo(),
InboundMPTCP: inbound.MPTCP(),
2020-06-18 18:11:02 +08:00
},
Mode: tunnel.Mode(),
UnifiedDelay: adapter.UnifiedDelay.Load(),
LogLevel: log.Level(),
IPv6: !resolver.DisableIPv6,
Interface: dialer.DefaultInterface.Load(),
RoutingMark: int(dialer.DefaultRoutingMark.Load()),
GeoXUrl: config.GeoXUrl{
GeoIp: geodata.GeoIpUrl(),
Mmdb: geodata.MmdbUrl(),
ASN: geodata.ASNUrl(),
GeoSite: geodata.GeoSiteUrl(),
},
2024-09-09 16:08:48 +08:00
GeoAutoUpdate: updater.GeoAutoUpdate(),
GeoUpdateInterval: updater.GeoUpdateInterval(),
GeodataMode: geodata.GeodataMode(),
GeodataLoader: geodata.LoaderName(),
GeositeMatcher: geodata.SiteMatcherName(),
TCPConcurrent: dialer.GetTcpConcurrent(),
FindProcessMode: tunnel.FindProcessMode(),
Sniffing: tunnel.IsSniffing(),
GlobalClientFingerprint: tlsC.GetGlobalFingerprint(),
2024-09-09 16:08:48 +08:00
GlobalUA: mihomoHttp.UA(),
ETagSupport: resource.ETag(),
KeepAliveInterval: int(keepalive.KeepAliveInterval() / time.Second),
KeepAliveIdle: int(keepalive.KeepAliveIdle() / time.Second),
DisableKeepAlive: keepalive.DisableKeepAlive(),
2018-11-21 13:47:46 +08:00
}
2019-06-27 20:45:12 +08:00
return general
2018-11-21 13:47:46 +08:00
}
func updateListeners(general *config.General, listeners map[string]C.InboundListener, force bool) {
listener.PatchInboundListeners(listeners, tunnel.Tunnel, true)
if !force {
return
}
allowLan := general.AllowLan
listener.SetAllowLan(allowLan)
2023-10-10 19:43:26 +08:00
inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes)
inbound.SetAllowedIPs(general.LanAllowedIPs)
inbound.SetDisAllowedIPs(general.LanDisAllowedIPs)
bindAddress := general.BindAddress
listener.SetBindAddress(bindAddress)
listener.ReCreateHTTP(general.Port, tunnel.Tunnel)
listener.ReCreateSocks(general.SocksPort, tunnel.Tunnel)
listener.ReCreateRedir(general.RedirPort, tunnel.Tunnel)
listener.ReCreateTProxy(general.TProxyPort, tunnel.Tunnel)
listener.ReCreateMixed(general.MixedPort, tunnel.Tunnel)
listener.ReCreateShadowSocks(general.ShadowSocksConfig, tunnel.Tunnel)
listener.ReCreateVmess(general.VmessConfig, tunnel.Tunnel)
listener.ReCreateTuic(general.TuicServer, tunnel.Tunnel)
}
func updateTun(general *config.General) {
2024-08-24 13:25:23 +08:00
listener.ReCreateTun(general.Tun, tunnel.Tunnel)
2022-12-04 13:37:14 +08:00
}
func updateExperimental(c *config.Experimental) {
if c.QUICGoDisableGSO {
_ = os.Setenv("QUIC_GO_DISABLE_GSO", strconv.FormatBool(true))
}
if c.QUICGoDisableECN {
_ = os.Setenv("QUIC_GO_DISABLE_ECN", strconv.FormatBool(true))
}
dialer.GetIP4PEnable(c.IP4PEnable)
}
2023-09-01 03:11:35 +08:00
func updateNTP(c *config.NTP) {
if c.Enable {
ntp.ReCreateNTPService(
net.JoinHostPort(c.Server, strconv.Itoa(c.Port)),
time.Duration(c.Interval),
c.DialerProxy,
c.WriteToSystem,
)
2023-09-01 03:11:35 +08:00
}
}
func updateDNS(c *config.DNS, generalIPv6 bool) {
if !c.Enable {
resolver.DefaultResolver = nil
resolver.DefaultHostMapper = nil
2022-05-02 14:21:37 +08:00
resolver.DefaultLocalServer = nil
resolver.ProxyServerHostResolver = nil
resolver.DirectHostResolver = nil
dns.ReCreateServer("", nil, nil)
return
}
cfg := dns.Config{
2024-08-15 20:04:24 +08:00
Main: c.NameServer,
Fallback: c.Fallback,
IPv6: c.IPv6 && generalIPv6,
IPv6Timeout: c.IPv6Timeout,
EnhancedMode: c.EnhancedMode,
Pool: c.FakeIPRange,
Hosts: c.Hosts,
FallbackIPFilter: c.FallbackIPFilter,
FallbackDomainFilter: c.FallbackDomainFilter,
Default: c.DefaultNameserver,
Policy: c.NameServerPolicy,
ProxyServer: c.ProxyServerNameserver,
DirectServer: c.DirectNameServer,
DirectFollowPolicy: c.DirectFollowPolicy,
2024-08-15 20:04:24 +08:00
CacheAlgorithm: c.CacheAlgorithm,
}
r := dns.NewResolver(cfg)
m := dns.NewEnhancer(cfg)
// reuse cache of old host mapper
if old := resolver.DefaultHostMapper; old != nil {
m.PatchFrom(old.(*dns.ResolverEnhancer))
}
resolver.DefaultResolver = r
resolver.DefaultHostMapper = m
resolver.DefaultLocalServer = dns.NewLocalServer(r.Resolver, m)
2024-05-06 14:03:29 +08:00
resolver.UseSystemHosts = c.UseSystemHosts
if r.ProxyResolver.Invalid() {
resolver.ProxyServerHostResolver = r.ProxyResolver
} else {
resolver.ProxyServerHostResolver = r.Resolver
}
if r.DirectResolver.Invalid() {
resolver.DirectHostResolver = r.DirectResolver
} else {
resolver.DirectHostResolver = r.Resolver
2022-03-28 00:44:13 +08:00
}
dns.ReCreateServer(c.Listen, r.Resolver, m)
2018-12-05 21:13:29 +08:00
}
func updateHosts(tree *trie.DomainTrie[resolver.HostValue]) {
resolver.DefaultHosts = resolver.NewHosts(tree)
2019-09-11 17:00:55 +08:00
}
2019-12-08 12:17:24 +08:00
func updateProxies(proxies map[string]C.Proxy, providers map[string]provider.ProxyProvider) {
tunnel.UpdateProxies(proxies, providers)
2018-11-21 13:47:46 +08:00
}
2022-12-04 13:37:14 +08:00
func updateRules(rules []C.Rule, subRules map[string][]C.Rule, ruleProviders map[string]provider.RuleProvider) {
tunnel.UpdateRules(rules, subRules, ruleProviders)
2018-11-21 13:47:46 +08:00
}
func loadProvider(pv provider.Provider) {
if pv.VehicleType() == provider.Compatible {
return
} else {
log.Infoln("Start initial provider %s", (pv).Name())
}
2022-05-08 00:04:16 +08:00
if err := pv.Initial(); err != nil {
switch pv.Type() {
case provider.Proxy:
{
2023-01-23 11:14:45 +08:00
log.Errorln("initial proxy provider %s error: %v", (pv).Name(), err)
}
case provider.Rule:
{
2023-01-23 11:14:45 +08:00
log.Errorln("initial rule provider %s error: %v", (pv).Name(), err)
}
}
}
}
func loadRuleProvider(ruleProviders map[string]provider.RuleProvider) {
2022-05-02 16:47:48 +08:00
wg := sync.WaitGroup{}
ch := make(chan struct{}, concurrentCount)
for _, ruleProvider := range ruleProviders {
2022-05-02 16:47:48 +08:00
ruleProvider := ruleProvider
wg.Add(1)
ch <- struct{}{}
2022-05-02 16:47:48 +08:00
go func() {
defer func() { <-ch; wg.Done() }()
2022-05-02 16:47:48 +08:00
loadProvider(ruleProvider)
2022-05-02 16:47:48 +08:00
}()
}
2022-05-02 16:47:48 +08:00
wg.Wait()
}
2022-05-02 16:47:48 +08:00
func loadProxyProvider(proxyProviders map[string]provider.ProxyProvider) {
// limit concurrent size
2022-05-02 16:47:48 +08:00
wg := sync.WaitGroup{}
ch := make(chan struct{}, concurrentCount)
2022-05-02 16:47:48 +08:00
for _, proxyProvider := range proxyProviders {
proxyProvider := proxyProvider
wg.Add(1)
ch <- struct{}{}
2022-05-02 16:47:48 +08:00
go func() {
defer func() { <-ch; wg.Done() }()
2022-05-02 16:47:48 +08:00
loadProvider(proxyProvider)
}()
}
2022-05-02 16:47:48 +08:00
wg.Wait()
}
func hcCompatibleProvider(proxyProviders map[string]provider.ProxyProvider) {
// limit concurrent size
wg := sync.WaitGroup{}
ch := make(chan struct{}, concurrentCount)
for _, proxyProvider := range proxyProviders {
proxyProvider := proxyProvider
if proxyProvider.VehicleType() == provider.Compatible {
log.Infoln("Start initial Compatible provider %s", proxyProvider.Name())
wg.Add(1)
ch <- struct{}{}
go func() {
defer func() { <-ch; wg.Done() }()
if err := proxyProvider.Initial(); err != nil {
log.Errorln("initial Compatible provider %s error: %v", proxyProvider.Name(), err)
}
}()
}
}
}
2022-03-09 05:08:35 +08:00
func updateSniffer(snifferConfig *sniffer.Config) {
dispatcher, err := sniffer.NewDispatcher(snifferConfig)
if err != nil {
log.Warnln("initial sniffer failed, err:%v", err)
}
tunnel.UpdateSniffer(dispatcher)
if snifferConfig.Enable {
2022-04-12 20:20:04 +08:00
log.Infoln("Sniffer is loaded and working")
} else {
log.Infoln("Sniffer is closed")
2022-04-12 20:20:04 +08:00
}
}
2022-12-06 10:13:05 +08:00
func updateTunnels(tunnels []LC.Tunnel) {
listener.PatchTunnel(tunnels, tunnel.Tunnel)
2022-11-18 22:57:33 +08:00
}
func updateUpdater(cfg *config.Config) {
general := cfg.General
updater.SetGeoAutoUpdate(general.GeoAutoUpdate)
updater.SetGeoUpdateInterval(general.GeoUpdateInterval)
controller := cfg.Controller
2024-10-05 13:40:00 +08:00
updater.DefaultUiUpdater = updater.NewUiUpdater(controller.ExternalUI, controller.ExternalUIURL, controller.ExternalUIName)
updater.DefaultUiUpdater.AutoDownloadUI()
}
//go:linkname temporaryUpdateGeneral github.com/metacubex/mihomo/config.temporaryUpdateGeneral
func temporaryUpdateGeneral(general *config.General) func() {
oldGeneral := GetGeneral()
updateGeneral(general, false)
return func() {
updateGeneral(oldGeneral, false)
}
}
func updateGeneral(general *config.General, logging bool) {
tunnel.SetMode(general.Mode)
tunnel.SetFindProcessMode(general.FindProcessMode)
2023-03-06 23:23:05 +08:00
resolver.DisableIPv6 = !general.IPv6
2022-03-20 02:39:48 +08:00
dialer.SetTcpConcurrent(general.TCPConcurrent)
if logging && general.TCPConcurrent {
log.Infoln("Use tcp concurrent")
}
2023-02-24 14:19:50 +08:00
inbound.SetTfo(general.InboundTfo)
inbound.SetMPTCP(general.InboundMPTCP)
2023-02-24 14:19:50 +08:00
keepalive.SetKeepAliveIdle(time.Duration(general.KeepAliveIdle) * time.Second)
keepalive.SetKeepAliveInterval(time.Duration(general.KeepAliveInterval) * time.Second)
keepalive.SetDisableKeepAlive(general.DisableKeepAlive)
adapter.UnifiedDelay.Store(general.UnifiedDelay)
dialer.DefaultInterface.Store(general.Interface)
2022-03-20 02:39:48 +08:00
dialer.DefaultRoutingMark.Store(int32(general.RoutingMark))
if logging && general.RoutingMark > 0 {
2022-03-20 02:39:48 +08:00
log.Infoln("Use routing mark: %#x", general.RoutingMark)
2022-03-03 05:02:17 +08:00
}
2021-11-17 16:03:47 +08:00
iface.FlushCache()
geodata.SetGeodataMode(general.GeodataMode)
geodata.SetLoader(general.GeodataLoader)
geodata.SetSiteMatcher(general.GeositeMatcher)
geodata.SetGeoIpUrl(general.GeoXUrl.GeoIp)
geodata.SetGeoSiteUrl(general.GeoXUrl.GeoSite)
geodata.SetMmdbUrl(general.GeoXUrl.Mmdb)
geodata.SetASNUrl(general.GeoXUrl.ASN)
mihomoHttp.SetUA(general.GlobalUA)
resource.SetETag(general.ETagSupport)
tlsC.SetGlobalUtlsClient(general.GlobalClientFingerprint)
2018-11-21 13:47:46 +08:00
}
func updateUsers(users []auth.AuthUser) {
authenticator := auth.NewAuthenticator(users)
authStore.Default.SetAuthenticator(authenticator)
if authenticator != nil {
log.Infoln("Authentication of local server updated")
}
}
func updateProfile(cfg *config.Config) {
profileCfg := cfg.Profile
profile.StoreSelected.Store(profileCfg.StoreSelected)
if profileCfg.StoreSelected {
patchSelectGroup(cfg.Proxies)
}
}
func patchSelectGroup(proxies map[string]C.Proxy) {
mapping := cachefile.Cache().SelectedMap()
if mapping == nil {
return
}
for name, proxy := range proxies {
2024-09-27 21:33:37 +08:00
outbound, ok := proxy.(C.Proxy)
if !ok {
continue
}
2024-09-27 21:33:37 +08:00
selector, ok := outbound.Adapter().(outboundgroup.SelectAble)
if !ok {
continue
}
selected, exist := mapping[name]
if !exist {
continue
}
selector.ForceSet(selected)
}
}
2021-11-17 16:03:47 +08:00
func updateIPTables(cfg *config.Config) {
tproxy.CleanupTProxyIPTables()
2022-03-09 05:08:35 +08:00
iptables := cfg.IPTables
if runtime.GOOS != "linux" || !iptables.Enable {
2022-03-09 05:08:35 +08:00
return
}
var err error
defer func() {
if err != nil {
log.Errorln("[IPTABLES] setting iptables failed: %s", err.Error())
2022-03-09 05:08:35 +08:00
os.Exit(2)
}
}()
if cfg.General.Tun.Enable {
err = fmt.Errorf("when tun is enabled, iptables cannot be set automatically")
return
}
var (
inboundInterface = "lo"
2022-03-23 11:04:43 +08:00
bypass = iptables.Bypass
tProxyPort = cfg.General.TProxyPort
dnsCfg = cfg.DNS
DnsRedirect = iptables.DnsRedirect
dnsPort netip.AddrPort
)
if tProxyPort == 0 {
err = fmt.Errorf("tproxy-port must be greater than zero")
2022-03-09 05:08:35 +08:00
return
}
if DnsRedirect {
if !dnsCfg.Enable {
err = fmt.Errorf("DNS server must be enable")
return
}
2021-12-04 17:41:13 +08:00
dnsPort, err = netip.ParseAddrPort(dnsCfg.Listen)
if err != nil {
err = fmt.Errorf("DNS server must be correct")
return
}
2021-07-01 22:49:29 +08:00
}
if iptables.InboundInterface != "" {
inboundInterface = iptables.InboundInterface
2021-12-04 17:41:13 +08:00
}
dialer.DefaultRoutingMark.CompareAndSwap(0, 2158)
2022-03-05 18:04:04 +08:00
err = tproxy.SetTProxyIPTables(inboundInterface, bypass, uint16(tProxyPort), DnsRedirect, dnsPort.Port())
if err != nil {
return
}
log.Infoln("[IPTABLES] Setting iptables completed")
2021-12-04 17:41:13 +08:00
}
2021-11-17 16:03:47 +08:00
2022-03-28 03:25:55 +08:00
func Shutdown() {
2023-09-02 14:10:26 +08:00
listener.Cleanup()
tproxy.CleanupTProxyIPTables()
2022-04-13 16:47:47 +08:00
resolver.StoreFakePoolState()
2022-03-28 03:25:55 +08:00
2023-11-03 21:01:45 +08:00
log.Warnln("Mihomo shutting down")
2021-11-17 16:03:47 +08:00
}