2018-11-21 05:47:46 +00:00
|
|
|
package executor
|
|
|
|
|
|
|
|
import (
|
2019-12-01 05:22:47 +00:00
|
|
|
"fmt"
|
2021-07-01 14:49:29 +00:00
|
|
|
"net"
|
2019-12-01 05:22:47 +00:00
|
|
|
"os"
|
2021-07-01 14:49:29 +00:00
|
|
|
"runtime"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2020-06-18 10:11:02 +00:00
|
|
|
"sync"
|
2019-12-01 05:22:47 +00:00
|
|
|
|
2021-06-10 06:05:56 +00:00
|
|
|
"github.com/Dreamacro/clash/adapter"
|
|
|
|
"github.com/Dreamacro/clash/adapter/outboundgroup"
|
2019-06-27 09:04:25 +00:00
|
|
|
"github.com/Dreamacro/clash/component/auth"
|
2020-02-15 13:42:46 +00:00
|
|
|
"github.com/Dreamacro/clash/component/dialer"
|
2021-09-06 15:07:34 +00:00
|
|
|
"github.com/Dreamacro/clash/component/iface"
|
2021-02-18 15:41:50 +00:00
|
|
|
"github.com/Dreamacro/clash/component/profile"
|
|
|
|
"github.com/Dreamacro/clash/component/profile/cachefile"
|
2020-02-15 13:42:46 +00:00
|
|
|
"github.com/Dreamacro/clash/component/resolver"
|
2020-05-28 04:13:05 +00:00
|
|
|
"github.com/Dreamacro/clash/component/trie"
|
2018-11-21 05:47:46 +00:00
|
|
|
"github.com/Dreamacro/clash/config"
|
|
|
|
C "github.com/Dreamacro/clash/constant"
|
2021-07-04 12:32:59 +00:00
|
|
|
"github.com/Dreamacro/clash/constant/provider"
|
2018-12-05 13:13:29 +00:00
|
|
|
"github.com/Dreamacro/clash/dns"
|
2021-06-13 09:23:10 +00:00
|
|
|
P "github.com/Dreamacro/clash/listener"
|
|
|
|
authStore "github.com/Dreamacro/clash/listener/auth"
|
2021-07-01 14:49:29 +00:00
|
|
|
"github.com/Dreamacro/clash/listener/tproxy"
|
|
|
|
"github.com/Dreamacro/clash/listener/tun/dev"
|
2018-11-21 05:47:46 +00:00
|
|
|
"github.com/Dreamacro/clash/log"
|
2020-02-15 13:42:46 +00:00
|
|
|
"github.com/Dreamacro/clash/tunnel"
|
2018-11-21 05:47:46 +00:00
|
|
|
)
|
|
|
|
|
2021-10-10 15:44:09 +00:00
|
|
|
var mux sync.Mutex
|
2020-06-18 10:11:02 +00:00
|
|
|
|
2019-12-01 05:22:47 +00:00
|
|
|
func readConfig(path string) ([]byte, error) {
|
|
|
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-10-09 12:35:06 +00:00
|
|
|
data, err := os.ReadFile(path)
|
2019-12-01 05:22:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(data) == 0 {
|
2020-08-25 14:19:59 +00:00
|
|
|
return nil, fmt.Errorf("configuration file %s is empty", path)
|
2019-12-01 05:22:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return data, err
|
|
|
|
}
|
|
|
|
|
2018-11-21 05:47:46 +00: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) {
|
2019-12-01 05:22:47 +00:00
|
|
|
buf, err := readConfig(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-12-25 07:12:11 +00:00
|
|
|
return ParseWithBytes(buf)
|
2019-12-01 05:22:47 +00:00
|
|
|
}
|
|
|
|
|
2019-12-25 07:12:11 +00:00
|
|
|
// ParseWithBytes config with buffer
|
2019-12-01 05:22:47 +00:00
|
|
|
func ParseWithBytes(buf []byte) (*config.Config, error) {
|
2019-12-25 07:12:11 +00:00
|
|
|
return config.Parse(buf)
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ApplyConfig dispatch configure to all parts
|
2018-11-30 09:42:40 +00:00
|
|
|
func ApplyConfig(cfg *config.Config, force bool) {
|
2020-06-18 10:11:02 +00:00
|
|
|
mux.Lock()
|
|
|
|
defer mux.Unlock()
|
|
|
|
|
2019-06-27 09:04:25 +00:00
|
|
|
updateUsers(cfg.Users)
|
2019-12-08 04:17:24 +00:00
|
|
|
updateProxies(cfg.Proxies, cfg.Providers)
|
2018-11-21 05:47:46 +00:00
|
|
|
updateRules(cfg.Rules)
|
2019-09-11 09:00:55 +00:00
|
|
|
updateHosts(cfg.Hosts)
|
2021-02-18 15:41:50 +00:00
|
|
|
updateProfile(cfg)
|
2021-07-01 14:49:29 +00:00
|
|
|
updateIPTables(cfg.DNS, cfg.General)
|
2021-07-28 14:13:21 +00:00
|
|
|
updateDNS(cfg.DNS, cfg.General)
|
2021-07-10 09:01:40 +00:00
|
|
|
updateGeneral(cfg.General, force)
|
|
|
|
updateExperimental(cfg)
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func GetGeneral() *config.General {
|
|
|
|
ports := P.GetPorts()
|
2019-06-27 12:45:12 +00:00
|
|
|
authenticator := []string{}
|
|
|
|
if auth := authStore.Authenticator(); auth != nil {
|
|
|
|
authenticator = auth.Users()
|
|
|
|
}
|
|
|
|
|
|
|
|
general := &config.General{
|
2020-06-18 10:11:02 +00:00
|
|
|
Inbound: config.Inbound{
|
|
|
|
Port: ports.Port,
|
|
|
|
SocksPort: ports.SocksPort,
|
|
|
|
RedirPort: ports.RedirPort,
|
2020-11-09 02:46:10 +00:00
|
|
|
TProxyPort: ports.TProxyPort,
|
2020-06-18 10:11:02 +00:00
|
|
|
MixedPort: ports.MixedPort,
|
2021-07-01 14:49:29 +00:00
|
|
|
Tun: P.Tun(),
|
2020-06-18 10:11:02 +00:00
|
|
|
Authentication: authenticator,
|
|
|
|
AllowLan: P.AllowLan(),
|
|
|
|
BindAddress: P.BindAddress(),
|
|
|
|
},
|
|
|
|
Mode: tunnel.Mode(),
|
|
|
|
LogLevel: log.Level(),
|
2021-01-07 05:59:39 +00:00
|
|
|
IPv6: !resolver.DisableIPv6,
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
2019-06-27 12:45:12 +00:00
|
|
|
|
|
|
|
return general
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
|
|
|
|
2020-06-27 06:19:31 +00:00
|
|
|
func updateExperimental(c *config.Config) {}
|
2019-04-24 04:02:52 +00:00
|
|
|
|
2021-07-01 14:49:29 +00:00
|
|
|
func updateDNS(c *config.DNS, general *config.General) {
|
2020-08-25 14:19:59 +00:00
|
|
|
if !c.Enable {
|
2020-02-15 13:42:46 +00:00
|
|
|
resolver.DefaultResolver = nil
|
2022-02-22 18:38:50 +00:00
|
|
|
resolver.MainResolver = nil
|
2020-09-17 02:48:42 +00:00
|
|
|
resolver.DefaultHostMapper = nil
|
|
|
|
dns.ReCreateServer("", nil, nil)
|
2018-12-05 13:13:29 +00:00
|
|
|
return
|
|
|
|
}
|
2020-09-17 02:48:42 +00:00
|
|
|
|
|
|
|
cfg := dns.Config{
|
2018-12-05 13:13:29 +00:00
|
|
|
Main: c.NameServer,
|
|
|
|
Fallback: c.Fallback,
|
|
|
|
IPv6: c.IPv6,
|
|
|
|
EnhancedMode: c.EnhancedMode,
|
2019-05-02 16:05:14 +00:00
|
|
|
Pool: c.FakeIPRange,
|
2020-08-11 02:28:17 +00:00
|
|
|
Hosts: c.Hosts,
|
2019-09-15 05:36:45 +00:00
|
|
|
FallbackFilter: dns.FallbackFilter{
|
2021-08-25 07:15:13 +00:00
|
|
|
GeoIP: c.FallbackFilter.GeoIP,
|
|
|
|
GeoIPCode: c.FallbackFilter.GeoIPCode,
|
|
|
|
IPCIDR: c.FallbackFilter.IPCIDR,
|
|
|
|
Domain: c.FallbackFilter.Domain,
|
2022-02-22 18:38:50 +00:00
|
|
|
GeoSite: c.FallbackFilter.GeoSite,
|
2019-09-15 05:36:45 +00:00
|
|
|
},
|
2020-02-15 13:42:46 +00:00
|
|
|
Default: c.DefaultNameserver,
|
2021-05-19 03:17:35 +00:00
|
|
|
Policy: c.NameServerPolicy,
|
2020-09-17 02:48:42 +00:00
|
|
|
}
|
2020-08-30 16:32:18 +00:00
|
|
|
|
2020-09-17 02:48:42 +00:00
|
|
|
r := dns.NewResolver(cfg)
|
2022-02-22 18:38:50 +00:00
|
|
|
mr := dns.NewMainResolver(r)
|
2020-09-17 02:48:42 +00:00
|
|
|
m := dns.NewEnhancer(cfg)
|
|
|
|
|
|
|
|
// reuse cache of old host mapper
|
|
|
|
if old := resolver.DefaultHostMapper; old != nil {
|
|
|
|
m.PatchFrom(old.(*dns.ResolverEnhancer))
|
2020-08-30 16:32:18 +00:00
|
|
|
}
|
|
|
|
|
2020-02-15 13:42:46 +00:00
|
|
|
resolver.DefaultResolver = r
|
2022-02-22 18:38:50 +00:00
|
|
|
resolver.MainResolver = mr
|
2020-09-17 02:48:42 +00:00
|
|
|
resolver.DefaultHostMapper = m
|
2021-07-01 14:49:29 +00:00
|
|
|
if general.Tun.Enable && strings.EqualFold(general.Tun.Stack, "system") {
|
|
|
|
resolver.DefaultLocalServer = dns.NewLocalServer(r, m)
|
|
|
|
}
|
2020-09-17 02:48:42 +00:00
|
|
|
|
2021-12-26 14:08:53 +00:00
|
|
|
dns.ReCreateServer(c.Listen, r, m)
|
2018-12-05 13:13:29 +00:00
|
|
|
}
|
|
|
|
|
2020-05-28 04:13:05 +00:00
|
|
|
func updateHosts(tree *trie.DomainTrie) {
|
2020-02-15 13:42:46 +00:00
|
|
|
resolver.DefaultHosts = tree
|
2019-09-11 09:00:55 +00:00
|
|
|
}
|
|
|
|
|
2019-12-08 04:17:24 +00:00
|
|
|
func updateProxies(proxies map[string]C.Proxy, providers map[string]provider.ProxyProvider) {
|
|
|
|
tunnel.UpdateProxies(proxies, providers)
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func updateRules(rules []C.Rule) {
|
2020-02-15 13:42:46 +00:00
|
|
|
tunnel.UpdateRules(rules)
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
|
|
|
|
2020-06-18 10:11:02 +00:00
|
|
|
func updateGeneral(general *config.General, force bool) {
|
2022-02-22 17:00:27 +00:00
|
|
|
log.SetLevel(log.DEBUG)
|
2020-02-15 13:42:46 +00:00
|
|
|
tunnel.SetMode(general.Mode)
|
2020-06-18 10:11:02 +00:00
|
|
|
resolver.DisableIPv6 = !general.IPv6
|
|
|
|
|
2021-07-01 14:49:29 +00: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 {
|
2021-11-03 07:02:40 +00:00
|
|
|
log.Debugln("Auto detect interface name is empty.")
|
2021-07-01 14:49:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.Debugln("Can not find auto detect interface. %s", err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-22 17:00:27 +00:00
|
|
|
log.Infoln("Use interface name: %s", general.Interface)
|
|
|
|
|
2021-11-07 08:48:51 +00:00
|
|
|
dialer.DefaultInterface.Store(general.Interface)
|
2022-03-02 21:02:17 +00:00
|
|
|
|
|
|
|
if general.RoutingMark > 0 {
|
|
|
|
dialer.DefaultRoutingMark.Store(int32(general.RoutingMark))
|
|
|
|
}
|
2020-06-27 06:19:31 +00:00
|
|
|
|
2021-09-06 15:07:34 +00:00
|
|
|
iface.FlushCache()
|
|
|
|
|
2020-06-18 10:11:02 +00:00
|
|
|
if !force {
|
2021-07-01 14:49:29 +00:00
|
|
|
log.SetLevel(general.LogLevel)
|
2020-06-18 10:11:02 +00:00
|
|
|
return
|
|
|
|
}
|
2018-12-03 15:41:40 +00:00
|
|
|
|
2018-11-21 05:47:46 +00:00
|
|
|
allowLan := general.AllowLan
|
|
|
|
P.SetAllowLan(allowLan)
|
2019-06-27 09:04:25 +00:00
|
|
|
|
2019-08-08 05:45:07 +00:00
|
|
|
bindAddress := general.BindAddress
|
|
|
|
P.SetBindAddress(bindAddress)
|
|
|
|
|
2021-06-13 09:23:10 +00:00
|
|
|
tcpIn := tunnel.TCPIn()
|
|
|
|
udpIn := tunnel.UDPIn()
|
|
|
|
|
2021-12-26 14:08:53 +00:00
|
|
|
P.ReCreateHTTP(general.Port, tcpIn)
|
|
|
|
P.ReCreateSocks(general.SocksPort, tcpIn, udpIn)
|
|
|
|
P.ReCreateRedir(general.RedirPort, tcpIn, udpIn)
|
|
|
|
P.ReCreateTProxy(general.TProxyPort, tcpIn, udpIn)
|
|
|
|
P.ReCreateMixed(general.MixedPort, tcpIn, udpIn)
|
2022-02-22 17:00:27 +00:00
|
|
|
P.ReCreateTun(general.Tun, tcpIn, udpIn)
|
2021-07-01 14:49:29 +00:00
|
|
|
|
|
|
|
log.SetLevel(general.LogLevel)
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
2019-06-27 09:04:25 +00:00
|
|
|
|
|
|
|
func updateUsers(users []auth.AuthUser) {
|
|
|
|
authenticator := auth.NewAuthenticator(users)
|
|
|
|
authStore.SetAuthenticator(authenticator)
|
|
|
|
if authenticator != nil {
|
|
|
|
log.Infoln("Authentication of local server updated")
|
|
|
|
}
|
|
|
|
}
|
2021-02-18 15:41:50 +00:00
|
|
|
|
|
|
|
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 06:05:56 +00:00
|
|
|
outbound, ok := proxy.(*adapter.Proxy)
|
2021-02-18 15:41:50 +00:00
|
|
|
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 14:49:29 +00: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-08 18:19:43 +00:00
|
|
|
tproxy.CleanUpTProxyLinuxIPTables()
|
|
|
|
|
2022-03-02 21:02:17 +00:00
|
|
|
dialer.DefaultRoutingMark.Store(2158)
|
2021-07-01 14:49:29 +00: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()
|
|
|
|
}
|
|
|
|
}
|