From c219993925f5328e0fa38367f30868c60fcc3c0b Mon Sep 17 00:00:00 2001 From: Whale Choi Date: Mon, 17 Jun 2024 01:01:47 +0800 Subject: [PATCH] add adguardhome support --- README.md | 3 ++ README_zh_CN.md | 15 ++++-- config.yml | 23 ++++++++-- go.mod | 2 +- go.sum | 5 +- main/builds/config.go | 17 +++++-- main/commands/service.go | 84 +++++++++++++++++++++++++++++++--- main/commands/update.go | 82 +++++++++++++++++++++++++++------ main/proxies/tproxy/tproxy.go | 9 ++++ main/proxies/tun/tun.go | 9 ++++ main/serial/orderedmap.go | 20 ++++++++ main/serial/orderedmap_test.go | 10 ++++ main/switches/ray/rayswitch.go | 11 +++-- 13 files changed, 246 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 768ddad..f79b176 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ XrayHelper use yml format configuration file, default is `/data/adb/xray/xrayhel ## Update Components - update core `xrayhelper update core`, should configure **xrayHelper.coreType** first +- update adghome + `xrayhelper update adghome`, update adghome from [AdguardTeam/AdGuardHome](https://github.com/AdguardTeam/AdGuardHome) - update tun2socks `xrayhelper update tun2socks`, update tun2socks from [heiher/hev-socks5-tunnel](https://github.com/heiher/hev-socks5-tunnel) - update geodata @@ -52,6 +54,7 @@ XrayHelper use yml format configuration file, default is `/data/adb/xray/xrayhel ## Credits - [@Loyalsoldier/v2ray-rules-dat](https://github.com/Loyalsoldier/v2ray-rules-dat) - [@2dust/v2rayNG](https://github.com/2dust/v2rayNG) +- [@AdguardTeam/AdGuardHome](https://github.com/AdguardTeam/AdGuardHome) - [@heiher/hev-socks5-tunnel](https://github.com/heiher/hev-socks5-tunnel) - ~~[@haishanh/yacd](https://github.com/haishanh/yacd)~~ - [@MetaCubeX/Yacd-meta](https://github.com/MetaCubeX/Yacd-meta) diff --git a/README_zh_CN.md b/README_zh_CN.md index 7a125d9..34f2bb6 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -15,6 +15,14 @@ XrayHelper 使用 yml 格式的配置文件,默认使用`/data/adb/xray/xrayhe - `proxyTag`默认值`proxy`,使用 XrayHelper 进行节点切换时,将进行替换的出站代理 Tag - `subList`可选,数组,节点订阅链接(SIP002/v2rayNg/Hysteria/Hysteria2),也支持 clash 订阅链接(需要在订阅链接前添加`clash+`前缀) - `userAgent`可选,自定义 XrayHelper http 请求的 User-Agent +- clash + - `dnsPort`使用`mihomo`时必填,默认值`65533`,mihomo 监听的 dns 端口, XrayHelper 会将本机 DNS 请求劫持到该端口 + - `template`可选,mihomo 配置模板,指定配置模板后,该模板会**覆盖(或注入)** mihomo 配置文件对应内容 +- adgHome + - `enable`默认值`false`,是否随核心服务一同启动 AdGuardHome ,需要提前下载 adgHome 二进制文件(可使用命令`xrayhelper update adghome`),由于`mihomo`、`hysteria2`的 DNS 模块并不完善,仅建议与他们配合使用,其他核心直接使用核心 DNS 即可,使用不当可能导致 DNS 泄露 + - `address`启用时必填,默认值`127.0.0.1:65530`,AdGuardHome WebUI 监听地址 + - `workDir`启用时必填,AdGuardHome 的工作目录(该目录需包含配置文件`config.yaml`) + - `dnsPort`启用时必填,AdGuardHome 监听的 DNS 端口;需要注意,由于`hysteria2`没有 DNS 模块,使用该核心时 XrayHelper 会将本机 DNS 请求劫持到该端口 - proxy - `method`默认值`tproxy`,代理模式,可选`tproxy`、`tun`、`tun2socks`,使用 tun 模式时,请确保你的核心支持 tun 并正确配置它;使用 tun2socks 模式时,需要提前下载 tun2socks 二进制文件(可使用命令`xrayhelper update tun2socks`) - `tproxyPort`默认值`65535`,透明代理端口,该值需要与核心的 tproxy 入站代理端口相对应,`tproxy`模式需要 @@ -27,9 +35,6 @@ XrayHelper 使用 yml 格式的配置文件,默认使用`/data/adb/xray/xrayhe - `apList`,可选,数组,需代理的 ap 接口名,例如`wlan+`可代理 wlan 热点,`rndis+`可代理 usb 网络共享 - `ignoreList`,可选,数组,需要忽略的接口名,例如`wlan+`可以实现连上 wifi 不走代理 - `intraList`,可选,数组,CIDR,默认情况下,内网地址不会被标记,若需要将部分内网地址标记,可配置此项 -- clash - - `dnsPort`默认值`65533`,mihomo 监听的 dns 端口 - - `template`可选,mihomo 配置模板,指定配置模板后,该模板会**覆盖(或注入)** mihomo 配置文件对应内容 ## 命令 - service @@ -43,9 +48,10 @@ XrayHelper 使用 yml 格式的配置文件,默认使用`/data/adb/xray/xrayhe - `refresh`刷新系统代理规则 - update - `core`更新核心,需要指定 **xrayHelper.coreType** + - `adghome`从 [AdguardTeam/AdGuardHome](https://github.com/AdguardTeam/AdGuardHome) 更新 adghome + - `tun2socks`从 [hev-socks5-tunnel](https://github.com/heiher/hev-socks5-tunnel) 更新 tun2socks - `geodata`从 [Loyalsoldier/v2ray-rules-dat](https://github.com/Loyalsoldier/v2ray-rules-dat) 更新 GEO 数据文件 - `subscribe`更新订阅节点(或 clash 订阅)到`${xrayHelper.dataDir}/sub.txt`(或`${xrayHelper.dataDir}/clashSub#{index}.yaml`),需要指定 **xrayHelper.subList** - - `tun2socks`从 [hev-socks5-tunnel](https://github.com/heiher/hev-socks5-tunnel) 更新 tun2socks - `yacd-meta`更新 [Yacd-meta](https://github.com/MetaCubeX/Yacd-meta) 到`${xrayHelper.dataDir}/Yacd-meta-gh-pages` ### xray、sing-box、hysteria2 - switch @@ -64,6 +70,7 @@ XrayHelper 使用 yml 格式的配置文件,默认使用`/data/adb/xray/xrayhe ## 鸣谢 - [@Loyalsoldier/v2ray-rules-dat](https://github.com/Loyalsoldier/v2ray-rules-dat) - [@2dust/v2rayNG](https://github.com/2dust/v2rayNG) +- [@AdguardTeam/AdGuardHome](https://github.com/AdguardTeam/AdGuardHome) - [@heiher/hev-socks5-tunnel](https://github.com/heiher/hev-socks5-tunnel) - ~~[@haishanh/yacd](https://github.com/haishanh/yacd)~~ - [@MetaCubeX/Yacd-meta](https://github.com/MetaCubeX/Yacd-meta) diff --git a/config.yml b/config.yml index 554054b..163e0cc 100644 --- a/config.yml +++ b/config.yml @@ -20,6 +20,24 @@ xrayHelper: - clash+https://testclashsuburl.com # Optional, custom User-Agent for http requests send by xrayhelper userAgent: 'ClashMeta' +clash: + # Required for mihomo, Default value: 65533, all dns request will be redirected to the port which listen by mihomo + dnsPort: 65533 + # Optional, if not empty, the template config will replace (or inject to) the actual mihomo config + template: /data/adb/xray/mihomoconfs/template.yaml +adgHome: + # Default value: false, start AdGuardHome with core service or not + # please run command "xrayhelper update adghome" to install it first + # recommended for use with mihomo and hysteria2 only, because their DNS module is incomprehension + # improper usage will lead to dns leak + enable: false + # Required for adgHome, Default value: 127.0.0.1:65530, AdGuardHome's webui + address: 127.0.0.1:65530 + # Required for adgHome, AdGuardHome's workDir(need include config with ${workDir}/config.yaml) + workDir: /data/adb/xray/adghomeconfs/ + # Required for adgHome, Default value: 65531, AdGuardHome's DNS port + # Special, when your core is hysteria2, all dns request will be redirected to this port, because hysteria2 don't have DNS module + dnsPort: 65531 proxy: # Required, Default value: tproxy, proxy method you want to use, support tproxy, tun, tun2socks # If you use tun mode, please make sure your core support tun, and configure it correctly @@ -56,8 +74,3 @@ proxy: intraList: - 192.168.123.0/24 - fd12:3456:789a:bcde::/64 -clash: - # Required for mihomo, Default value: 65533, all dns request will be redirected to the port which listen by mihomo - dnsPort: 65533 - # Optional, if not empty, the template config will replace (or inject to) the actual mihomo config - template: /data/adb/xray/mihomoconfs/template.yaml diff --git a/go.mod b/go.mod index 5487af6..7b875cc 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/creasty/defaults v1.7.0 github.com/fatih/color v1.17.0 - github.com/jessevdk/go-flags v1.5.0 + github.com/jessevdk/go-flags v1.6.1 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 977a23e..c8e5d39 100644 --- a/go.sum +++ b/go.sum @@ -4,14 +4,13 @@ github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdB github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= -github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= +github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= diff --git a/main/builds/config.go b/main/builds/config.go index d35e313..b51ed40 100644 --- a/main/builds/config.go +++ b/main/builds/config.go @@ -30,6 +30,16 @@ var Config struct { SubList []string `yaml:"subList"` UserAgent string `yaml:"userAgent"` } `yaml:"xrayHelper"` + Clash struct { + DNSPort string `default:"65533" yaml:"dnsPort"` + Template string `yaml:"template"` + } `yaml:"clash"` + AdgHome struct { + Enable bool `default:"false" yaml:"enable"` + Address string `default:"127.0.0.1:65530" yaml:"address"` + WorkDir string `yaml:"workDir"` + DNSPort string `default:"65531" yaml:"dnsPort"` + } `yaml:"adgHome"` Proxy struct { Method string `default:"tproxy" yaml:"method"` TproxyPort string `default:"65535" yaml:"tproxyPort"` @@ -43,10 +53,6 @@ var Config struct { IgnoreList []string `yaml:"ignoreList"` IntraList []string `yaml:"intraList"` } `yaml:"proxy"` - Clash struct { - DNSPort string `default:"65533" yaml:"dnsPort"` - Template string `yaml:"template"` - } `yaml:"clash"` } // LoadConfig load program configuration file, should be called before any command Execute @@ -62,8 +68,9 @@ func LoadConfig() error { return e.New("unmarshal config failed, ", err).WithPrefix(tagConfig) } log.HandleDebug(Config.XrayHelper) - log.HandleDebug(Config.Proxy) log.HandleDebug(Config.Clash) + log.HandleDebug(Config.AdgHome) + log.HandleDebug(Config.Proxy) return nil } diff --git a/main/commands/service.go b/main/commands/service.go index 63fbc67..22feb6b 100644 --- a/main/commands/service.go +++ b/main/commands/service.go @@ -131,10 +131,19 @@ OUT: if listenFlag { if err := os.WriteFile(path.Join(builds.Config.XrayHelper.RunDir, "core.pid"), []byte(strconv.Itoa(service.Pid())), 0644); err != nil { _ = service.Kill() + stopService() return e.New("write core pid failed, ", err).WithPrefix(tagService) } + if builds.Config.AdgHome.Enable { + if err := startAdgHome(); err != nil { + _ = service.Kill() + stopService() + return err + } + } } else { _ = service.Kill() + stopService() return e.New("core service not listen, please check error.log").WithPrefix(tagService) } return nil @@ -214,6 +223,7 @@ func stopService() { } else { log.HandleDebug(err) } + stopAdgHome() } // getServicePid get core pid from pid file @@ -310,8 +320,6 @@ func replaceRayDNSStrategy(conf []byte, ipv6 bool) (replacedConf []byte, err err default: return nil, e.New("unsupported core type " + builds.Config.XrayHelper.CoreType).WithPrefix(tagService) } - // replace - jsonMap.Set("dns", dnsMap) // marshal marshal, err := json.MarshalIndent(jsonMap, "", " ") if err != nil { @@ -363,14 +371,11 @@ func overrideClashConfig(template string, target string) error { } // if enable AutoDNSStrategy if builds.Config.Proxy.AutoDNSStrategy { templateYamlMap.Set("ipv6", builds.Config.Proxy.EnableIPv6) - dns, ok := templateYamlMap.Get("dns") - if ok { + if dns, ok := templateYamlMap.Get("dns"); ok { // assert dns - dnsMap, ok := dns.Value.(serial.OrderedMap) - if ok { + if dnsMap, ok := dns.Value.(serial.OrderedMap); ok { dnsMap.Set("listen", "127.0.0.1:"+builds.Config.Clash.DNSPort) } - templateYamlMap.Set("dns", dnsMap) } } // save template @@ -397,3 +402,68 @@ func overrideClashConfig(template string, target string) error { } return nil } + +func startAdgHome() error { + adgHomePath := path.Join(path.Dir(builds.Config.XrayHelper.CorePath), "adguardhome") + adgHomeConfigPath := path.Join(builds.Config.AdgHome.WorkDir, "config.yaml") + adgHomeConfigFile, err := os.ReadFile(adgHomeConfigPath) + if err != nil { + return e.New("load adgHome config failed, ", err).WithPrefix(tagService) + } + var adgHomeConfig serial.OrderedMap + if err := yaml.Unmarshal(adgHomeConfigFile, &adgHomeConfig); err != nil { + return e.New("unmarshal adgHome config failed, ", err).WithPrefix(tagService) + } + if http, ok := adgHomeConfig.Get("http"); ok { + httpMap := http.Value.(serial.OrderedMap) + // set address + httpMap.Set("address", builds.Config.AdgHome.Address) + } + if dns, ok := adgHomeConfig.Get("dns"); ok { + dnsMap := dns.Value.(serial.OrderedMap) + // set dnsPort + dnsMap.Set("port", builds.Config.AdgHome.DNSPort) + // set dnsStrategy + if builds.Config.Proxy.AutoDNSStrategy { + dnsMap.Set("aaaa_disabled", !builds.Config.Proxy.EnableIPv6) + } + } + // save config + marshal, err := yaml.Marshal(adgHomeConfig) + if err != nil { + return e.New("marshal adgHome config failed, ", err).WithPrefix(tagService) + } + // write new config + if err := os.WriteFile(adgHomeConfigPath, marshal, 0644); err != nil { + return e.New("write adgHome config failed, ", err).WithPrefix(tagService) + } + // create adghome service + service := common.NewExternal(0, nil, nil, adgHomePath, + "--no-check-update", + "-w", builds.Config.AdgHome.WorkDir, + "-c", adgHomeConfigPath, + "--pidfile", path.Join(builds.Config.XrayHelper.RunDir, "adghome.pid"), + "-l", path.Join(builds.Config.XrayHelper.RunDir, "adghome.log")) + service.AppendEnv("SSL_CERT_DIR=/system/etc/security/cacerts/") + service.SetUidGid("0", common.CoreGid) + service.Start() + return nil +} + +func stopAdgHome() { + if _, err := os.Stat(path.Join(builds.Config.XrayHelper.RunDir, "adghome.pid")); err == nil { + pidFile, err := os.ReadFile(path.Join(builds.Config.XrayHelper.RunDir, "adghome.pid")) + if err != nil { + log.HandleDebug(err) + } + pid, _ := strconv.Atoi(string(pidFile)) + if serviceProcess, err := os.FindProcess(pid); err == nil { + _ = serviceProcess.Kill() + _ = os.Remove(path.Join(builds.Config.XrayHelper.RunDir, "adghome.pid")) + } else { + log.HandleDebug(err) + } + } else { + log.HandleDebug(err) + } +} diff --git a/main/commands/update.go b/main/commands/update.go index bdf05b5..4bce46f 100644 --- a/main/commands/update.go +++ b/main/commands/update.go @@ -5,7 +5,6 @@ import ( "XrayHelper/main/common" e "XrayHelper/main/errors" "XrayHelper/main/log" - "XrayHelper/main/proxies" "XrayHelper/main/serial" "archive/tar" "archive/zip" @@ -33,6 +32,7 @@ const ( geoipDownloadUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat" geositeDownloadUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat" tun2socksDownloadUrl = "https://github.com/heiher/hev-socks5-tunnel/releases/latest/download/hev-socks5-tunnel-linux-arm64" + adgHomeDownloadUrl = "https://github.com/AdguardTeam/AdGuardHome/releases/latest/download/AdGuardHome_linux_arm64.tar.gz" ) type UpdateCommand struct{} @@ -42,7 +42,7 @@ func (this *UpdateCommand) Execute(args []string) error { return err } if len(args) == 0 { - return e.New("not specify operation, available operation [core|tun2socks|geodata|subscribe|yacd-meta]").WithPrefix(tagUpdate).WithPathObj(*this) + return e.New("not specify operation, available operation [core|adghome|tun2socks|geodata|subscribe|yacd-meta]").WithPrefix(tagUpdate).WithPathObj(*this) } if len(args) > 1 { return e.New("too many arguments").WithPrefix(tagUpdate).WithPathObj(*this) @@ -69,6 +69,12 @@ func (this *UpdateCommand) Execute(args []string) error { return err } log.HandleInfo("update: update success") + case "adghome": + log.HandleInfo("update: updating adghome") + if err := updateAdgHome(); err != nil { + return err + } + log.HandleInfo("update: update success") case "tun2socks": log.HandleInfo("update: updating tun2socks") if err := updateTun2socks(); err != nil { @@ -94,7 +100,7 @@ func (this *UpdateCommand) Execute(args []string) error { } log.HandleInfo("update: update success") default: - return e.New("unknown operation " + args[0] + ", available operation [core|tun2socks|geodata|subscribe|yacd-meta]").WithPrefix(tagUpdate).WithPathObj(*this) + return e.New("unknown operation " + args[0] + ", available operation [core|adghome|tun2socks|geodata|subscribe|yacd-meta]").WithPrefix(tagUpdate).WithPathObj(*this) } return nil } @@ -139,17 +145,6 @@ func updateCore() error { if serviceRunFlag { log.HandleInfo("update: starting core with new version") _ = startService() - if err := builds.LoadPackage(); err != nil { - log.HandleError("update: load package failed, " + err.Error()) - } else { - proxy, err := proxies.NewProxy(builds.Config.Proxy.Method) - if err != nil { - log.HandleError("update: get proxy failed, " + err.Error()) - } else { - proxy.Disable() - _ = proxy.Enable() - } - } } return nil } @@ -382,6 +377,65 @@ func updateMihomo() (bool, error) { return serviceRunFlag, nil } +// updateAdgHome update AdgHome +func updateAdgHome() error { + serviceRunFlag := false + adgHomePath := path.Join(path.Dir(builds.Config.XrayHelper.CorePath), "adguardhome") + adgHomeGzipPath := path.Join(builds.Config.XrayHelper.DataDir, "adghome.tar.gz") + if err := common.DownloadFile(adgHomeGzipPath, adgHomeDownloadUrl); err != nil { + return err + } + // update core need stop core service first + if len(getServicePid()) > 0 { + log.HandleInfo("update: detect core is running, stop it") + stopService() + serviceRunFlag = true + _ = os.Remove(adgHomePath) + } + adgHomeGzip, err := os.Open(adgHomeGzipPath) + if err != nil { + return e.New("open gzip file failed, ", err).WithPrefix(tagUpdate) + } + defer func(adgHomeGzip *os.File) { + _ = adgHomeGzip.Close() + _ = os.Remove(adgHomeGzipPath) + }(adgHomeGzip) + gzipReader, err := gzip.NewReader(adgHomeGzip) + if err != nil { + return e.New("open gzip file failed, ", err).WithPrefix(tagUpdate) + } + defer func(gzipReader *gzip.Reader) { + _ = gzipReader.Close() + }(gzipReader) + tarReader := tar.NewReader(gzipReader) + for { + fileHeader, err := tarReader.Next() + if err != nil { + if err == io.EOF { + return e.New("cannot find adghome binary").WithPrefix(tagUpdate) + } + continue + } + if filepath.Base(fileHeader.Name) == "AdGuardHome" && fileHeader.Typeflag != tar.TypeDir { + saveFile, err := os.OpenFile(adgHomePath, os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0755) + if err != nil { + return e.New("cannot open file "+adgHomePath+", ", err).WithPrefix(tagUpdate) + } + _, err = io.Copy(saveFile, tarReader) + if err != nil { + return e.New("save file "+adgHomePath+" failed, ", err).WithPrefix(tagUpdate) + } + _ = saveFile.Close() + break + } + } + if serviceRunFlag { + log.HandleInfo("update: starting core") + _ = startService() + } + return nil +} + // updateTun2socks update tun2socks func updateTun2socks() error { if runtime.GOARCH != "arm64" { diff --git a/main/proxies/tproxy/tproxy.go b/main/proxies/tproxy/tproxy.go index f927d3e..c5d7902 100644 --- a/main/proxies/tproxy/tproxy.go +++ b/main/proxies/tproxy/tproxy.go @@ -57,6 +57,14 @@ func (this *Tproxy) Enable() error { this.Disable() return err } + case "hysteria2": + // hysteria2 don't have dns module, if enable AdgHome, as upstream dns resolver + if builds.Config.AdgHome.Enable { + if err := tools.RedirectDNS(builds.Config.AdgHome.DNSPort); err != nil { + this.Disable() + return err + } + } default: if !builds.Config.Proxy.EnableIPv6 { if err := tools.DisableIPV6DNS(); err != nil { @@ -76,6 +84,7 @@ func (this *Tproxy) Disable() { //always clean dns rules tools.EnableIPV6DNS() tools.CleanRedirectDNS(builds.Config.Clash.DNSPort) + tools.CleanRedirectDNS(builds.Config.AdgHome.DNSPort) } // addRoute Add ip route to proxy diff --git a/main/proxies/tun/tun.go b/main/proxies/tun/tun.go index 17f57b8..d97580b 100644 --- a/main/proxies/tun/tun.go +++ b/main/proxies/tun/tun.go @@ -57,6 +57,14 @@ func (this *Tun) Enable() error { this.Disable() return err } + case "hysteria2": + // hysteria2 don't have dns module, if enable AdgHome, as upstream dns resolver + if builds.Config.AdgHome.Enable { + if err := tools.RedirectDNS(builds.Config.AdgHome.DNSPort); err != nil { + this.Disable() + return err + } + } default: if !builds.Config.Proxy.EnableIPv6 { if err := tools.DisableIPV6DNS(); err != nil { @@ -84,6 +92,7 @@ func (this *Tun) Disable() { //always clean dns rules tools.EnableIPV6DNS() tools.CleanRedirectDNS(builds.Config.Clash.DNSPort) + tools.CleanRedirectDNS(builds.Config.AdgHome.DNSPort) } } diff --git a/main/serial/orderedmap.go b/main/serial/orderedmap.go index d13c246..aaaea4c 100644 --- a/main/serial/orderedmap.go +++ b/main/serial/orderedmap.go @@ -87,6 +87,17 @@ func (om *OrderedMap) Set(key string, value interface{}) { om.Values = append(om.Values, OrderedValue{key, value}) } +// SetValue change or add an OrderedValue to OrderedMap. +func (om *OrderedMap) SetValue(v *OrderedValue) { + for i := range om.Values { + if om.Values[i].Key == v.Key { + om.Values[i] = *v + return + } + } + om.Values = append(om.Values, *v) +} + // Delete remove an Object from OrderedMap. func (om *OrderedMap) Delete(key string) { for i, val := range om.Values { @@ -96,6 +107,15 @@ func (om *OrderedMap) Delete(key string) { } } +// DeleteValue remove an OrderedValue from OrderedMap. +func (om *OrderedMap) DeleteValue(v *OrderedValue) { + for i, val := range om.Values { + if val.Key == v.Key { + om.Values = append(om.Values[:i], om.Values[i+1:]...) + } + } +} + // MarshalJSON implements the json.Marshaler interface. func (arr OrderedArray) MarshalJSON() ([]byte, error) { var b []byte diff --git a/main/serial/orderedmap_test.go b/main/serial/orderedmap_test.go index a14c34a..0f25d96 100644 --- a/main/serial/orderedmap_test.go +++ b/main/serial/orderedmap_test.go @@ -43,6 +43,16 @@ clash: fmt.Print(err.Error()) return } + // change + if proxy, ok := yamlMap.Get("proxy"); ok { + proxyMap := proxy.Value.(OrderedMap) + if apList, ok := proxyMap.Get("apList"); ok { + proxyMap.Set("apList", append(apList.Value.(OrderedArray), "test+")) + } + if _, ok := proxyMap.Get("method"); ok { + proxyMap.Set("method", "test") + } + } marshal, _ := yaml.Marshal(yamlMap) fmt.Print(string(marshal)) } diff --git a/main/switches/ray/rayswitch.go b/main/switches/ray/rayswitch.go index c120d5d..87a13d4 100644 --- a/main/switches/ray/rayswitch.go +++ b/main/switches/ray/rayswitch.go @@ -181,11 +181,12 @@ func replaceProxyNode(conf []byte, index int) (replacedConf []byte, err error) { } if tag.Value == builds.Config.XrayHelper.ProxyTag { // replace - outbound, err = shareUrls[index].ToOutboundWithTag(builds.Config.XrayHelper.CoreType, builds.Config.XrayHelper.ProxyTag) + outbound, err := shareUrls[index].ToOutboundWithTag(builds.Config.XrayHelper.CoreType, builds.Config.XrayHelper.ProxyTag) if err != nil { return nil, err } outboundArray[i] = outbound + // array is a slice, need reset jsonMap.Set("outbounds", outboundArray) // marshal marshal, err := json.MarshalIndent(jsonMap, "", " ") @@ -210,16 +211,16 @@ func replaceProxyNode(conf []byte, index int) (replacedConf []byte, err error) { } // replace if server, ok := clientObject.Get("server"); ok { - yamlMap.Set("server", server.Value) + yamlMap.SetValue(server) } if auth, ok := clientObject.Get("auth"); ok { - yamlMap.Set("auth", auth.Value) + yamlMap.SetValue(auth) } if obfs, ok := clientObject.Get("obfs"); ok { - yamlMap.Set("obfs", obfs.Value) + yamlMap.SetValue(obfs) } if tls, ok := clientObject.Get("tls"); ok { - yamlMap.Set("tls", tls.Value) + yamlMap.SetValue(tls) } // marshal marshal, err := yaml.Marshal(yamlMap)