mihomo/hub/executor/executor.go

332 lines
7.9 KiB
Go
Raw Normal View History

2018-11-21 13:47:46 +08:00
package executor
import (
"fmt"
2021-07-01 22:49:29 +08:00
"net"
"os"
2021-07-01 22:49:29 +08:00
"runtime"
"strconv"
"strings"
2020-06-18 18:11:02 +08:00
"sync"
2021-06-10 14:05:56 +08:00
"github.com/Dreamacro/clash/adapter"
"github.com/Dreamacro/clash/adapter/outboundgroup"
"github.com/Dreamacro/clash/component/auth"
"github.com/Dreamacro/clash/component/dialer"
"github.com/Dreamacro/clash/component/iface"
"github.com/Dreamacro/clash/component/profile"
"github.com/Dreamacro/clash/component/profile/cachefile"
"github.com/Dreamacro/clash/component/resolver"
2021-10-15 14:11:14 +08:00
S "github.com/Dreamacro/clash/component/script"
"github.com/Dreamacro/clash/component/trie"
2018-11-21 13:47:46 +08:00
"github.com/Dreamacro/clash/config"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/constant/provider"
2018-12-05 21:13:29 +08:00
"github.com/Dreamacro/clash/dns"
2021-06-13 17:23:10 +08:00
P "github.com/Dreamacro/clash/listener"
authStore "github.com/Dreamacro/clash/listener/auth"
2021-07-01 22:49:29 +08:00
"github.com/Dreamacro/clash/listener/tproxy"
"github.com/Dreamacro/clash/listener/tun/dev"
2018-11-21 13:47:46 +08:00
"github.com/Dreamacro/clash/log"
"github.com/Dreamacro/clash/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
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()
updateUsers(cfg.Users)
2019-12-08 12:17:24 +08:00
updateProxies(cfg.Proxies, cfg.Providers)
2018-11-21 13:47:46 +08:00
updateRules(cfg.Rules)
2021-10-15 14:11:14 +08:00
updateRuleProviders(cfg.RuleProviders)
2019-09-11 17:00:55 +08:00
updateHosts(cfg.Hosts)
updateProfile(cfg)
2021-07-01 22:49:29 +08:00
updateIPTables(cfg.DNS, cfg.General)
2021-07-28 22:13:21 +08:00
updateDNS(cfg.DNS, cfg.General)
updateGeneral(cfg.General, force)
updateExperimental(cfg)
2018-11-21 13:47:46 +08:00
}
func GetGeneral() *config.General {
ports := P.GetPorts()
2019-06-27 20:45:12 +08:00
authenticator := []string{}
if auth := authStore.Authenticator(); auth != nil {
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,
2020-06-18 18:11:02 +08:00
MixedPort: ports.MixedPort,
2021-07-01 22:49:29 +08:00
Tun: P.Tun(),
2020-06-18 18:11:02 +08:00
Authentication: authenticator,
AllowLan: P.AllowLan(),
BindAddress: P.BindAddress(),
},
Mode: tunnel.Mode(),
LogLevel: log.Level(),
IPv6: !resolver.DisableIPv6,
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 updateExperimental(c *config.Config) {}
2021-07-01 22:49:29 +08:00
func updateDNS(c *config.DNS, general *config.General) {
2020-08-25 22:19:59 +08:00
if !c.Enable {
resolver.DefaultResolver = nil
2021-11-09 19:44:16 +08:00
resolver.MainResolver = nil
resolver.DefaultHostMapper = nil
dns.ReCreateServer("", nil, nil)
2018-12-05 21:13:29 +08:00
return
}
cfg := dns.Config{
2018-12-05 21:13:29 +08:00
Main: c.NameServer,
Fallback: c.Fallback,
IPv6: c.IPv6,
EnhancedMode: c.EnhancedMode,
2019-05-03 00:05:14 +08:00
Pool: c.FakeIPRange,
Hosts: c.Hosts,
2019-09-15 13:36:45 +08:00
FallbackFilter: dns.FallbackFilter{
2021-08-25 15:15:13 +08:00
GeoIP: c.FallbackFilter.GeoIP,
GeoIPCode: c.FallbackFilter.GeoIPCode,
IPCIDR: c.FallbackFilter.IPCIDR,
Domain: c.FallbackFilter.Domain,
2021-11-09 19:44:16 +08:00
GeoSite: c.FallbackFilter.GeoSite,
2019-09-15 13:36:45 +08:00
},
Default: c.DefaultNameserver,
Policy: c.NameServerPolicy,
}
r := dns.NewResolver(cfg)
2021-11-09 19:44:16 +08:00
mr := dns.NewMainResolver(r)
m := dns.NewEnhancer(cfg)
// reuse cache of old host mapper
if old := resolver.DefaultHostMapper; old != nil {
m.PatchFrom(old.(*dns.ResolverEnhancer))
}
resolver.DefaultResolver = r
2021-11-09 19:44:16 +08:00
resolver.MainResolver = mr
resolver.DefaultHostMapper = m
if general.Tun.Enable && !strings.EqualFold(general.Tun.Stack, "gvisor") {
2021-07-01 22:49:29 +08:00
resolver.DefaultLocalServer = dns.NewLocalServer(r, m)
} else {
resolver.DefaultLocalServer = nil
2021-07-01 22:49:29 +08:00
}
if err := dns.ReCreateServer(c.Listen, r, m); err != nil {
log.Errorln("Start DNS server error: %s", err.Error())
return
}
if c.Listen != "" {
log.Infoln("DNS server listening at: %s", c.Listen)
}
2018-12-05 21:13:29 +08:00
}
func updateHosts(tree *trie.DomainTrie) {
resolver.DefaultHosts = 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
}
func updateRules(rules []C.Rule) {
tunnel.UpdateRules(rules)
2018-11-21 13:47:46 +08:00
}
2021-10-15 14:11:14 +08:00
func updateRuleProviders(providers map[string]C.Rule) {
S.UpdateRuleProviders(providers)
}
2020-06-18 18:11:02 +08:00
func updateGeneral(general *config.General, force bool) {
tunnel.SetMode(general.Mode)
2020-06-18 18:11:02 +08:00
resolver.DisableIPv6 = !general.IPv6
2021-07-01 22:49:29 +08:00
if (general.Tun.Enable || general.TProxyPort != 0) && general.Interface == "" {
autoDetectInterfaceName, err := dev.GetAutoDetectInterface()
if err == nil {
if autoDetectInterfaceName != "" && autoDetectInterfaceName != "<nil>" {
general.Interface = autoDetectInterfaceName
} else {
log.Debugln("Auto detect interface name is empty.")
2021-07-01 22:49:29 +08:00
}
} else {
log.Debugln("Can not find auto detect interface. %s", err.Error())
}
}
dialer.DefaultInterface.Store(general.Interface)
2021-11-09 19:44:16 +08:00
log.Infoln("Use interface name: %s", general.Interface)
iface.FlushCache()
2020-06-18 18:11:02 +08:00
if !force {
2021-07-01 22:49:29 +08:00
log.SetLevel(general.LogLevel)
2020-06-18 18:11:02 +08:00
return
}
2018-12-03 23:41:40 +08:00
2018-11-21 13:47:46 +08:00
allowLan := general.AllowLan
P.SetAllowLan(allowLan)
bindAddress := general.BindAddress
P.SetBindAddress(bindAddress)
2021-06-13 17:23:10 +08:00
tcpIn := tunnel.TCPIn()
udpIn := tunnel.UDPIn()
if err := P.ReCreateHTTP(general.Port, tcpIn); err != nil {
2018-11-21 13:47:46 +08:00
log.Errorln("Start HTTP server error: %s", err.Error())
}
2021-06-13 17:23:10 +08:00
if err := P.ReCreateSocks(general.SocksPort, tcpIn, udpIn); err != nil {
log.Errorln("Start SOCKS server error: %s", err.Error())
2018-11-21 13:47:46 +08:00
}
2021-06-13 17:23:10 +08:00
if err := P.ReCreateRedir(general.RedirPort, tcpIn, udpIn); err != nil {
2018-11-21 13:47:46 +08:00
log.Errorln("Start Redir server error: %s", err.Error())
}
2021-06-13 17:23:10 +08:00
if err := P.ReCreateTProxy(general.TProxyPort, tcpIn, udpIn); err != nil {
log.Errorln("Start TProxy server error: %s", err.Error())
}
2021-06-13 17:23:10 +08:00
if err := P.ReCreateMixed(general.MixedPort, tcpIn, udpIn); err != nil {
log.Errorln("Start Mixed(http and socks) server error: %s", err.Error())
}
2021-07-01 22:49:29 +08:00
if err := P.ReCreateTun(general.Tun, tcpIn, udpIn); err != nil {
log.Errorln("Start Tun interface error: %s", err.Error())
S.Py_Finalize()
2021-07-01 22:49:29 +08:00
os.Exit(2)
}
log.SetLevel(general.LogLevel)
2018-11-21 13:47:46 +08:00
}
func updateUsers(users []auth.AuthUser) {
authenticator := auth.NewAuthenticator(users)
authStore.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 {
2021-06-10 14:05:56 +08:00
outbound, ok := proxy.(*adapter.Proxy)
if !ok {
continue
}
selector, ok := outbound.ProxyAdapter.(*outboundgroup.Selector)
if !ok {
continue
}
selected, exist := mapping[name]
if !exist {
continue
}
selector.Set(selected)
}
}
2021-07-01 22:49:29 +08:00
func updateIPTables(dns *config.DNS, general *config.General) {
if runtime.GOOS != "linux" || dns.Listen == "" || general.TProxyPort == 0 || general.Tun.Enable {
return
}
_, dnsPortStr, err := net.SplitHostPort(dns.Listen)
if dnsPortStr == "0" || dnsPortStr == "" || err != nil {
return
}
dnsPort, err := strconv.Atoi(dnsPortStr)
if err != nil {
return
}
2021-07-09 02:19:43 +08:00
tproxy.CleanUpTProxyLinuxIPTables()
2021-07-01 22:49:29 +08:00
err = tproxy.SetTProxyLinuxIPTables(general.Interface, general.TProxyPort, dnsPort)
if err != nil {
log.Errorln("Can not setting iptables for TProxy on linux, %s", err.Error())
os.Exit(2)
}
}
func CleanUp() {
P.CleanUp()
if runtime.GOOS == "linux" {
tproxy.CleanUpTProxyLinuxIPTables()
}
2021-10-15 14:11:14 +08:00
S.Py_Finalize()
2021-07-01 22:49:29 +08:00
}