From 1e13f516e816e27a4213654b3d3590e530063abb Mon Sep 17 00:00:00 2001 From: xiaorouji <60100640+xiaorouji@users.noreply.github.com> Date: Sat, 18 Feb 2023 23:30:48 +0800 Subject: [PATCH] luci: add smartdns logic --- .../luasrc/controller/passwall.lua | 7 +- .../model/cbi/passwall/client/global.lua | 58 +++ luci-app-passwall/po/zh-cn/passwall.po | 15 + .../root/usr/share/passwall/0_default_config | 1 + .../root/usr/share/passwall/app.sh | 23 + .../usr/share/passwall/helper_smartdns.sh | 30 ++ .../share/passwall/helper_smartdns_add.lua | 427 ++++++++++++++++++ .../root/usr/share/passwall/iptables.sh | 1 + .../root/usr/share/passwall/nftables.sh | 1 + 9 files changed, 562 insertions(+), 1 deletion(-) create mode 100755 luci-app-passwall/root/usr/share/passwall/helper_smartdns.sh create mode 100644 luci-app-passwall/root/usr/share/passwall/helper_smartdns_add.lua diff --git a/luci-app-passwall/luasrc/controller/passwall.lua b/luci-app-passwall/luasrc/controller/passwall.lua index e52338ca55..395a9632b6 100644 --- a/luci-app-passwall/luasrc/controller/passwall.lua +++ b/luci-app-passwall/luasrc/controller/passwall.lua @@ -211,7 +211,12 @@ end function index_status() local e = {} - e.dns_mode_status = luci.sys.call("netstat -apn | grep ':15353 ' >/dev/null") == 0 + local dns_shunt = uci:get(appname, "@global[0]", "dns_shunt") or "dnsmasq" + if dns_shunt == "smartdns" then + e.dns_mode_status = luci.sys.call("pidof smartdns >/dev/null") == 0 + else + e.dns_mode_status = luci.sys.call("netstat -apn | grep ':15353 ' >/dev/null") == 0 + end e.haproxy_status = luci.sys.call(string.format("/bin/busybox top -bn1 | grep -v grep | grep '%s/bin/' | grep haproxy >/dev/null", appname)) == 0 e["tcp_node_status"] = luci.sys.call("/bin/busybox top -bn1 | grep -v 'grep' | grep '/tmp/etc/passwall/bin/' | grep 'default' | grep 'TCP' >/dev/null") == 0 diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua index 89378eec45..a911dc68a5 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -265,10 +265,65 @@ s:tab("DNS", translate("DNS")) dns_shunt = s:taboption("DNS", ListValue, "dns_shunt", "DNS " .. translate("Shunt")) dns_shunt:value("dnsmasq", "Dnsmasq") dns_shunt:value("chinadns-ng", "Dnsmasq + ChinaDNS-NG") +if api.is_finded("smartdns") then + dns_shunt:value("smartdns", "SmartDNS") + group_domestic = s:taboption("DNS", Value, "group_domestic", translate("Domestic group name")) + group_domestic.placeholder = "local" + group_domestic:depends("dns_shunt", "smartdns") + group_domestic.description = translate("You only need to configure domestic DNS packets in SmartDNS and set it redirect or as Dnsmasq upstream, and fill in the domestic DNS group name here.") +end o = s:taboption("DNS", Flag, "filter_proxy_ipv6", translate("Filter Proxy Host IPv6"), translate("Experimental feature.")) o.default = "0" +if api.is_finded("smartdns") then + o = s:taboption("DNS", DynamicList, "smartdns_remote_dns", translate("Remote DNS")) + o:value("tcp://1.1.1.1") + o:value("tcp://8.8.4.4") + o:value("tcp://8.8.8.8") + o:value("tcp://9.9.9.9") + o:value("tcp://208.67.222.222") + o:value("tls://1.1.1.1") + o:value("tls://8.8.4.4") + o:value("tls://8.8.8.8") + o:value("tls://9.9.9.9") + o:value("tls://208.67.222.222") + o:value("https://1.1.1.1/dns-query") + o:value("https://8.8.4.4/dns-query") + o:value("https://8.8.8.8/dns-query") + o:value("https://9.9.9.9/dns-query") + o:value("https://208.67.222.222/dns-query") + o:value("https://dns.adguard.com/dns-query,176.103.130.130") + o:value("https://doh.libredns.gr/dns-query,116.202.176.26") + o:value("https://doh.libredns.gr/ads,116.202.176.26") + o:depends("dns_shunt", "smartdns") + o.cfgvalue = function(self, section) + return m:get(section, self.option) or {"tcp://1.1.1.1"} + end + function o.write(self, section, value) + local t = {} + local t2 = {} + if type(value) == "table" then + local x + for _, x in ipairs(value) do + if x and #x > 0 then + if not t2[x] then + t2[x] = x + t[#t+1] = x + end + end + end + else + t = { value } + end + return DynamicList.write(self, section, t) + end + + o = s:taboption("DNS", Flag, "smartdns_exclude_default_group", translate("Exclude Default Group"), translate("Exclude DNS Server from default group.")) + o.default = "0" + o:depends("dns_shunt", "smartdns") +end + ---- DNS Forward Mode dns_mode = s:taboption("DNS", ListValue, "dns_mode", translate("Filter Mode")) dns_mode:value("udp", translatef("Requery DNS By %s", "UDP")) @@ -282,6 +337,9 @@ end if has_xray then dns_mode:value("xray", "Xray") end +if api.is_finded("smartdns") then + dns_mode:depends({ dns_shunt = "smartdns", ['!reverse'] = true }) +end o = s:taboption("DNS", ListValue, "xray_dns_mode", translate("Request protocol")) o:value("tcp", "TCP") diff --git a/luci-app-passwall/po/zh-cn/passwall.po b/luci-app-passwall/po/zh-cn/passwall.po index 4cd5cdfe5b..936c815802 100644 --- a/luci-app-passwall/po/zh-cn/passwall.po +++ b/luci-app-passwall/po/zh-cn/passwall.po @@ -112,6 +112,21 @@ msgstr "与TCP节点相同" msgid "Current node: %s" msgstr "当前节点:%s" +msgid "DNS Shunt" +msgstr "DNS分流" + +msgid "Domestic group name" +msgstr "国内分组名" + +msgid "You only need to configure domestic DNS packets in SmartDNS and set it redirect or as Dnsmasq upstream, and fill in the domestic DNS group name here." +msgstr "您只需要在SmartDNS配置好国内DNS分组,并设置重定向或作为Dnsmasq上游,此处填入国内DNS分组名。" + +msgid "Exclude Default Group" +msgstr "从默认服务器组排除" + +msgid "Exclude DNS Server from default group." +msgstr "从default默认服务器组中排除" + msgid "Filter Mode" msgstr "过滤模式" diff --git a/luci-app-passwall/root/usr/share/passwall/0_default_config b/luci-app-passwall/root/usr/share/passwall/0_default_config index 3ac47fb0c1..3e3544897f 100644 --- a/luci-app-passwall/root/usr/share/passwall/0_default_config +++ b/luci-app-passwall/root/usr/share/passwall/0_default_config @@ -9,6 +9,7 @@ config global option dns_shunt 'chinadns-ng' option dns_mode 'tcp' option remote_dns '1.1.1.1' + list smartdns_remote_dns 'https://1.1.1.1/dns-query' option use_default_dns 'direct' option chinadns_ng_default_tag 'none' option use_direct_list '1' diff --git a/luci-app-passwall/root/usr/share/passwall/app.sh b/luci-app-passwall/root/usr/share/passwall/app.sh index 9b6319de54..1864a90178 100755 --- a/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/luci-app-passwall/root/usr/share/passwall/app.sh @@ -1259,6 +1259,28 @@ start_dns() { TUN_DNS="127.0.0.1#${dns_listen_port}" + [ "${DNS_SHUNT}" = "smartdns" ] && { + rm -rf $TMP_PATH2/dnsmasq_default* + local group_domestic=$(config_t_get global group_domestic) + local smartdns_remote_dns=$(config_t_get global smartdns_remote_dns) + if [ -n "${smartdns_remote_dns}" -a "${smartdns_remote_dns}" != "nil" ]; then + smartdns_remote_dns=$(echo ${smartdns_remote_dns} | tr -s ' ' '|') + else + smartdns_remote_dns="tcp://1.1.1.1" + fi + local smartdns_exclude_default_group=$(config_t_get global smartdns_exclude_default_group 0) + lua $APP_PATH/helper_smartdns_add.lua -FLAG "default" -SMARTDNS_CONF "/tmp/etc/smartdns/$CONFIG.conf" \ + -LOCAL_GROUP ${group_domestic:-nil} -REMOTE_GROUP "passwall_proxy" -REMOTE_PROXY_SERVER ${TCP_SOCKS_server} -REMOTE_EXCLUDE "${smartdns_exclude_default_group}" \ + -TUN_DNS ${smartdns_remote_dns} \ + -USE_DIRECT_LIST "${USE_DIRECT_LIST}" -USE_PROXY_LIST "${USE_PROXY_LIST}" -USE_BLOCK_LIST "${USE_BLOCK_LIST}" -USE_GFW_LIST "${USE_GFW_LIST}" -CHN_LIST "${CHN_LIST}" \ + -TCP_NODE ${TCP_NODE} -DEFAULT_PROXY_MODE "${TCP_PROXY_MODE}" -NO_PROXY_IPV6 ${FILTER_PROXY_IPV6:-0} -NFTFLAG ${nftflag:-0} \ + -NO_LOGIC_LOG ${NO_LOGIC_LOG:-0} + source $APP_PATH/helper_smartdns.sh restart + echolog " - 域名解析:使用SmartDNS,请确保配置正常。" + return + } + + rm -rf $TMP_PATH2/smartdns_default* case "$DNS_MODE" in dns2socks) local dns2socks_socks_server=$(echo $(config_t_get global socks_server 127.0.0.1:1080) | sed "s/#/:/g") @@ -1749,6 +1771,7 @@ stop() { unset V2RAY_LOCATION_ASSET unset XRAY_LOCATION_ASSET stop_crontab + source $APP_PATH/helper_smartdns.sh del source $APP_PATH/helper_dnsmasq.sh del source $APP_PATH/helper_dnsmasq.sh restart no_log=1 [ -s "$TMP_PATH/bridge_nf_ipt" ] && sysctl -w net.bridge.bridge-nf-call-iptables=$(cat $TMP_PATH/bridge_nf_ipt) >/dev/null 2>&1 diff --git a/luci-app-passwall/root/usr/share/passwall/helper_smartdns.sh b/luci-app-passwall/root/usr/share/passwall/helper_smartdns.sh new file mode 100755 index 0000000000..14254f141f --- /dev/null +++ b/luci-app-passwall/root/usr/share/passwall/helper_smartdns.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +restart() { + local no_log + eval_set_val $@ + _LOG_FILE=$LOG_FILE + [ -n "$no_log" ] && LOG_FILE="/dev/null" + rm -rf /tmp/smartdns.cache + /etc/init.d/smartdns reload >/dev/null 2>&1 + LOG_FILE=${_LOG_FILE} +} + +del() { + rm -rf /tmp/etc/smartdns/passwall.conf + sed -i "/passwall/d" /etc/smartdns/custom.conf >/dev/null 2>&1 + rm -rf /tmp/smartdns.cache + /etc/init.d/smartdns reload >/dev/null 2>&1 +} + +arg1=$1 +shift +case $arg1 in +del) + del $@ + ;; +restart) + restart $@ + ;; +*) ;; +esac diff --git a/luci-app-passwall/root/usr/share/passwall/helper_smartdns_add.lua b/luci-app-passwall/root/usr/share/passwall/helper_smartdns_add.lua new file mode 100644 index 0000000000..e74f38e95c --- /dev/null +++ b/luci-app-passwall/root/usr/share/passwall/helper_smartdns_add.lua @@ -0,0 +1,427 @@ +require "luci.sys" +local api = require "luci.passwall.api" +local appname = "passwall" + +local var = api.get_args(arg) +local FLAG = var["-FLAG"] +local SMARTDNS_CONF = var["-SMARTDNS_CONF"] +local LOCAL_GROUP = var["-LOCAL_GROUP"] +local REMOTE_GROUP = var["-REMOTE_GROUP"] +local REMOTE_PROXY_SERVER = var["-REMOTE_PROXY_SERVER"] +local REMOTE_EXCLUDE = var["-REMOTE_EXCLUDE"] +local TUN_DNS = var["-TUN_DNS"] +local TCP_NODE = var["-TCP_NODE"] +local USE_DIRECT_LIST = var["-USE_DIRECT_LIST"] +local USE_PROXY_LIST = var["-USE_PROXY_LIST"] +local USE_BLOCK_LIST = var["-USE_BLOCK_LIST"] +local USE_GFW_LIST = var["-USE_GFW_LIST"] +local CHN_LIST = var["-CHN_LIST"] +local DEFAULT_PROXY_MODE = var["-DEFAULT_PROXY_MODE"] +local NO_PROXY_IPV6 = var["-NO_PROXY_IPV6"] +local NO_LOGIC_LOG = var["-NO_LOGIC_LOG"] +local NFTFLAG = var["-NFTFLAG"] +local CACHE_PATH = api.CACHE_PATH +local CACHE_FLAG = "smartdns_" .. FLAG +local CACHE_DNS_PATH = CACHE_PATH .. "/" .. CACHE_FLAG +local CACHE_DNS_FILE = CACHE_DNS_PATH .. ".conf" +local CACHE_TEXT_FILE = CACHE_DNS_PATH .. ".txt" + +local uci = api.uci +local sys = api.sys +local fs = api.fs +local datatypes = api.datatypes + +local list1 = {} +local excluded_domain = {} +local excluded_domain_str = "!" + +local function log(...) + if NO_LOGIC_LOG == "1" then + return + end + api.log(...) +end + +local function check_ipset(domain, ipset) + if domain == "" or domain:find("#") then + return false + end + if not ipset then + return + end + for k,v in ipairs(list1[domain].ipsets) do + if ipset == v then + return true + end + end + return false +end + +local function set_domain_extra_param(domain, param) + if domain == "" or domain:find("#") then + return + end + if not list1[domain] then + list1[domain] = { + params = {} + } + end + if not list1[domain].params then + list1[domain].params = {} + end + if not list1[domain].params[param] then + list1[domain].params[param] = param + end +end + +local function set_domain_address(domain, address) + if domain == "" or domain:find("#") then + return + end + if not list1[domain] then + list1[domain] = {} + end + if not list1[domain].address then + list1[domain].address = address + end +end + +local function set_domain_group(domain, group) + if domain == "" or domain:find("#") then + return + end + if not group then + return + end + if not list1[domain] then + list1[domain] = {} + end + if not list1[domain].group then + list1[domain].group = group + if group == REMOTE_GROUP then + list1[domain].speed_check_mode = "none" + end + end +end + +local function set_domain_ipset(domain, ipset) + if domain == "" or domain:find("#") then + return + end + if not ipset then + return + end + if not list1[domain] then + list1[domain] = {} + end + if not list1[domain].ipsets then + list1[domain].ipsets = {} + end + for line in string.gmatch(ipset, '[^' .. "," .. ']+') do + if not check_ipset(domain, line) then + table.insert(list1[domain].ipsets, line) + end + end +end + +local function add_excluded_domain(domain) + if domain == "" or domain:find("#") then + return + end + table.insert(excluded_domain, domain) + excluded_domain_str = excluded_domain_str .. "|" .. domain +end + +local function check_excluded_domain(domain) + if domain == "" or domain:find("#") then + return false + end + for k,v in ipairs(excluded_domain) do + if domain:find(v) then + return true + end + end + return false +end + +local cache_text = "" +local nodes_address_md5 = luci.sys.exec("echo -n $(uci show passwall | grep '\\.address') | md5sum") +local new_rules = luci.sys.exec("echo -n $(find /usr/share/passwall/rules -type f | xargs md5sum)") +local new_text = SMARTDNS_CONF .. LOCAL_GROUP .. REMOTE_GROUP .. REMOTE_PROXY_SERVER .. REMOTE_EXCLUDE .. TUN_DNS .. USE_DIRECT_LIST .. USE_PROXY_LIST .. USE_BLOCK_LIST .. USE_GFW_LIST .. CHN_LIST .. DEFAULT_PROXY_MODE .. NO_PROXY_IPV6 .. nodes_address_md5 .. new_rules +if fs.access(CACHE_TEXT_FILE) then + for line in io.lines(CACHE_TEXT_FILE) do + cache_text = line + end +end + +if cache_text ~= new_text then + api.remove(CACHE_DNS_PATH .. "*") +end + +if LOCAL_GROUP == "nil" then + LOCAL_GROUP = nil +end + +if not REMOTE_GROUP or REMOTE_GROUP == "nil" then + REMOTE_GROUP = "passwall_proxy" + if TUN_DNS then + TUN_DNS = TUN_DNS:gsub("#", ":") + end + sys.call('sed -i "/passwall/d" /etc/smartdns/custom.conf >/dev/null 2>&1') +end + +if not fs.access(CACHE_DNS_FILE) then + local proxy_server_name = "passwall-proxy-server" + sys.call(string.format('echo "proxy-server socks5://%s -name %s" >> %s', REMOTE_PROXY_SERVER, proxy_server_name, CACHE_DNS_FILE)) + if true then + string.gsub(TUN_DNS, '[^' .. "|" .. ']+', function(w) + local server_dns = w + local server_param = string.format("server %s -group %s -proxy %s", "%s", REMOTE_GROUP, proxy_server_name) + + if REMOTE_EXCLUDE == "1" then + server_param = server_param .. " -exclude-default-group" + end + + local isHTTPS = w:find("https://") + if isHTTPS and isHTTPS == 1 then + local http_host = nil + local url = w + local port = 443 + local s = api.split(w, ",") + if s and #s > 1 then + url = s[1] + local dns_ip = s[2] + local host_port = api.get_domain_from_url(s[1]) + if host_port and #host_port > 0 then + http_host = host_port + local s2 = api.split(host_port, ":") + if s2 and #s2 > 1 then + http_host = s2[1] + port = s2[2] + end + url = url:gsub(http_host, dns_ip) + end + end + server_dns = url + if http_host then + server_dns = server_dns .. " -http-host " .. http_host + end + end + server_param = string.format(server_param, server_dns) + sys.exec(string.format('echo "%s" >> %s', server_param, CACHE_DNS_FILE)) + end) + end + + local setflag= (NFTFLAG == "1") and "inet#fw4#" or "" + local set_type= (NFTFLAG == "1") and "-nftset" or "-ipset" + + --始终用国内DNS解析节点域名 + uci:foreach(appname, "nodes", function(t) + local address = t.address + if address == "engage.cloudflareclient.com" then return end + if datatypes.hostname(address) then + set_domain_group(address, LOCAL_GROUP) + set_domain_ipset(address, "#4:" .. setflag .. "passwall_vpslist,#6:" .. setflag .. "passwall_vpslist6") + end + end) + log(string.format(" - 节点列表中的域名(vpslist)使用分组:%s", LOCAL_GROUP or "默认")) + + --屏蔽列表 + if USE_BLOCK_LIST == "1" then + if fs.access("/usr/share/passwall/rules/block_host") then + for line in io.lines("/usr/share/passwall/rules/block_host") do + if line ~= "" and not line:find("#") then + set_domain_address(line, "-") + end + end + end + end + + --直连(白名单)列表 + if USE_DIRECT_LIST == "1" then + if fs.access("/usr/share/passwall/rules/direct_host") then + for line in io.lines("/usr/share/passwall/rules/direct_host") do + if line ~= "" and not line:find("#") then + add_excluded_domain(line) + set_domain_group(line, LOCAL_GROUP) + set_domain_ipset(line, "#4:" .. setflag .. "passwall_whitelist,#6:" .. setflag .. "passwall_whitelist6") + end + end + log(string.format(" - 域名白名单(whitelist)使用分组:%s", LOCAL_GROUP or "默认")) + end + end + + --代理(黑名单)列表 + if USE_PROXY_LIST == "1" then + if fs.access("/usr/share/passwall/rules/proxy_host") then + for line in io.lines("/usr/share/passwall/rules/proxy_host") do + if line ~= "" and not line:find("#") then + add_excluded_domain(line) + local ipset_flag = "#4:" .. setflag .. "passwall_blacklist,#6:" .. setflag .. "passwall_blacklist6" + if NO_PROXY_IPV6 == "1" then + set_domain_address(line, "#6") + ipset_flag = "#4:" .. setflag .. "passwall_blacklist" + end + set_domain_group(line, REMOTE_GROUP) + set_domain_ipset(line, ipset_flag) + set_domain_extra_param(line, "-no-serve-expired") + end + end + log(string.format(" - 代理域名表(blacklist)使用分组:%s", REMOTE_GROUP or "默认")) + end + end + + --GFW列表 + if USE_GFW_LIST == "1" then + if fs.access("/usr/share/passwall/rules/gfwlist") then + local domain_set_name = "passwall-gfwlist" + local domain_file = CACHE_DNS_PATH .. "_gfwlist.list" + sys.exec('cat /usr/share/passwall/rules/gfwlist | grep -v -E "^#" | grep -v -E "' .. excluded_domain_str .. '" > ' .. domain_file) + sys.exec(string.format('echo "domain-set -name %s -file %s" >> %s', domain_set_name, domain_file, CACHE_DNS_FILE)) + local domain_rules_str = string.format('domain-rules /domain-set:%s/ -nameserver %s', domain_set_name, REMOTE_GROUP) + domain_rules_str = domain_rules_str .. " -speed-check-mode none" + domain_rules_str = domain_rules_str .. " -no-serve-expired" + if NO_PROXY_IPV6 == "1" then + domain_rules_str = domain_rules_str .. " -address #6" + domain_rules_str = domain_rules_str .. " " .. set_type .. " #4:" .. setflag .. "passwall_gfwlist" + else + domain_rules_str = domain_rules_str .. " " .. set_type .. " #4:" .. setflag .. "passwall_gfwlist" .. ",#6:" .. setflag .. "passwall_gfwlist6" + end + sys.exec(string.format('echo "%s" >> %s', domain_rules_str, CACHE_DNS_FILE)) + log(string.format(" - 防火墙域名表(gfwlist)使用分组:%s", REMOTE_GROUP or "默认")) + end + end + + --中国列表 + if CHN_LIST ~= "0" then + if fs.access("/usr/share/passwall/rules/chnlist") then + local domain_set_name = "passwall-chnlist" + local domain_file = CACHE_DNS_PATH .. "_chnlist.list" + sys.exec('cat /usr/share/passwall/rules/chnlist | grep -v -E "^#" | grep -v -E "' .. excluded_domain_str .. '" > ' .. domain_file) + sys.exec(string.format('echo "domain-set -name %s -file %s" >> %s', domain_set_name, domain_file, CACHE_DNS_FILE)) + + if CHN_LIST == "direct" then + local domain_rules_str = string.format('domain-rules /domain-set:%s/ %s', domain_set_name, LOCAL_GROUP and "-nameserver " .. LOCAL_GROUP or "") + domain_rules_str = domain_rules_str .. " " .. set_type .. " #4:" .. setflag .. "passwall_chnroute,#6:" .. setflag .. "passwall_chnroute6" + sys.exec(string.format('echo "%s" >> %s', domain_rules_str, CACHE_DNS_FILE)) + log(string.format(" - 中国域名表(chnroute)使用分组:%s", LOCAL_GROUP or "默认")) + end + if CHN_LIST == "proxy" then + local domain_rules_str = string.format('domain-rules /domain-set:%s/ -nameserver %s', domain_set_name, REMOTE_GROUP) + domain_rules_str = domain_rules_str .. " -speed-check-mode none" + domain_rules_str = domain_rules_str .. " -no-serve-expired" + if NO_PROXY_IPV6 == "1" then + domain_rules_str = domain_rules_str .. " -address #6" + domain_rules_str = domain_rules_str .. " " .. set_type .. " #4:" .. setflag .. "passwall_chnroute" + else + domain_rules_str = domain_rules_str .. " " .. set_type .. " #4:" .. setflag .. "passwall_chnroute" .. ",#6:" .. setflag .. "passwall_chnroute6" + end + sys.exec(string.format('echo "%s" >> %s', domain_rules_str, CACHE_DNS_FILE)) + log(string.format(" - 中国域名表(chnroute)使用分组:%s", REMOTE_GROUP or "默认")) + end + end + end + + --分流规则 + if uci:get(appname, TCP_NODE, "protocol") == "_shunt" then + local t = uci:get_all(appname, TCP_NODE) + local default_node_id = t["default_node"] or "_direct" + uci:foreach(appname, "shunt_rules", function(s) + local _node_id = t[s[".name"]] or "nil" + if _node_id ~= "nil" and _node_id ~= "_blackhole" then + if _node_id == "_default" then + _node_id = default_node_id + end + + local fwd_group = nil + local ipset_flag = nil + local no_ipv6 = nil + + if _node_id == "_direct" then + fwd_group = LOCAL_GROUP + ipset_flag = "#4:" .. setflag .. "passwall_whitelist,#6:" .. setflag .. "passwall_whitelist6" + else + fwd_group = REMOTE_GROUP + ipset_flag = "#4:" .. setflag .. "passwall_shuntlist,#6:" .. setflag .. "passwall_shuntlist6" + if NO_PROXY_IPV6 == "1" then + ipset_flag = "#4:" .. setflag .. "passwall_shuntlist" + no_ipv6 = true + end + end + + local domain_list = s.domain_list or "" + for line in string.gmatch(domain_list, "[^\r\n]+") do + if line ~= "" and not line:find("#") and not line:find("regexp:") and not line:find("geosite:") and not line:find("ext:") then + if line:find("domain:") or line:find("full:") then + line = string.match(line, ":([^:]+)$") + end + add_excluded_domain(line) + + if no_ipv6 then + set_domain_address(line, "#6") + end + set_domain_group(line, fwd_group) + set_domain_ipset(line, ipset_flag) + if fwd_group == REMOTE_GROUP then + set_domain_extra_param(line, "-no-serve-expired") + end + end + end + if _node_id ~= "_direct" then + log(string.format(" - V2ray/Xray分流规则(%s)使用分组:%s", s.remarks, fwd_group or "默认")) + end + end + end) + end + + local f_out = io.open(CACHE_DNS_FILE, "a") + for key, value in pairs(list1) do + local group_str = "" + local ipset_str = "" + local speed_check_mode_str = "" + local address_str = "" + local extra_param_str = "" + if value.group and #value.group > 0 then + group_str = group_str .. value.group + end + if group_str ~= "" then + group_str = " -n " .. group_str + end + if value.ipsets and #value.ipsets > 0 then + for i, ipset in ipairs(value.ipsets) do + ipset_str = ipset_str .. ipset .. "," + end + ipset_str = ipset_str:sub(1, #ipset_str - 1) + end + if ipset_str ~= "" then + ipset_str = " " .. set_type .. " " .. ipset_str + end + if value.address and #value.address > 0 then + address_str = address_str .. value.address + end + if address_str ~= "" then + address_str = " -a " .. address_str + end + if value.speed_check_mode and #value.speed_check_mode > 0 then + speed_check_mode_str = value.speed_check_mode + end + if speed_check_mode_str ~= "" then + speed_check_mode_str = " -c " .. speed_check_mode_str + end + if value.params then + for k2, v2 in pairs(value.params) do + extra_param_str = extra_param_str .. " " .. v2 + end + end + local str = string.format("domain-rules /%s/ %s%s%s%s%s\n", key, group_str, ipset_str, address_str, speed_check_mode_str, extra_param_str) + f_out:write(str) + end + f_out:close() + + f_out = io.open(CACHE_TEXT_FILE, "a") + f_out:write(new_text) + f_out:close() +end +fs.symlink(CACHE_DNS_FILE, SMARTDNS_CONF) +sys.call(string.format('echo "conf-file %s" >> /etc/smartdns/custom.conf', SMARTDNS_CONF)) +log(" - 请让SmartDNS作为Dnsmasq的上游或重定向!") diff --git a/luci-app-passwall/root/usr/share/passwall/iptables.sh b/luci-app-passwall/root/usr/share/passwall/iptables.sh index 2a7e94d890..5dfb52c123 100755 --- a/luci-app-passwall/root/usr/share/passwall/iptables.sh +++ b/luci-app-passwall/root/usr/share/passwall/iptables.sh @@ -1186,6 +1186,7 @@ flush_ipset_reload() { del_firewall_rule flush_ipset rm -rf /tmp/singbox_passwall* + rm -rf /tmp/etc/passwall_tmp/smartdns* rm -rf /tmp/etc/passwall_tmp/dnsmasq* /etc/init.d/passwall reload } diff --git a/luci-app-passwall/root/usr/share/passwall/nftables.sh b/luci-app-passwall/root/usr/share/passwall/nftables.sh index 0bff3d45f5..3c03748cc8 100755 --- a/luci-app-passwall/root/usr/share/passwall/nftables.sh +++ b/luci-app-passwall/root/usr/share/passwall/nftables.sh @@ -1225,6 +1225,7 @@ flush_nftset_reload() { del_firewall_rule flush_nftset rm -rf /tmp/singbox_passwall* + rm -rf /tmp/etc/passwall_tmp/smartdns* rm -rf /tmp/etc/passwall_tmp/dnsmasq* /etc/init.d/passwall reload }