🦄 Sync 2026-10-14 11:17:33

This commit is contained in:
github-actions[bot] committed 2026-10-14 11:17:33 +08:00
1 parent ef45574e85
commit 8a95857cad
5 files changed
+150 -32

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=26.10.4
PKG_RELEASE:=332
PKG_RELEASE:=333
PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \
@@ -488,7 +488,16 @@ o:value("remote", translate("Remote DNS"))
o:value("direct", translate("Direct DNS"))
o.description = desc .. "</ul>"
o:depends({dns_shunt = "dnsmasq", tcp_proxy_mode = "proxy", chn_list = "direct"})
if has_smartdns then
o = s:taboption("DNS", ListValue, "smartdns_default_dns", translate("Default DNS"))
o.default = "direct"
o:value("remote", translate("Remote DNS"))
o:value("direct", translate("Direct DNS"))
o:value("auto", translate("Auto"))
o.description = desc
.. "<li>" .. translate("Auto: Prefer mainland China IPs returned by direct DNS and fall back to remote DNS when no usable result is available.") .. "</li>"
.. "</ul>"
o:depends({dns_shunt = "smartdns", tcp_proxy_mode = "proxy", chn_list = "direct"})
end
+3 -3
View File
@@ -226,9 +226,6 @@ msgstr "用于 DNS 查询时通知 DNS 服务器,客户端所在的地理位
msgid "This feature requires the DNS server to support the Edns Client Subnet (RFC7871)."
msgstr "此功能需要 DNS 服务器支持 EDNS Client Subnet(RFC7871)。"
msgid "The effect is better, recommend."
msgstr "效果更好,推荐使用。"
msgid "ChinaDNS-NG (recommended)"
msgstr "ChinaDNS-NG (推荐)"
@@ -253,6 +250,9 @@ msgstr "智能,接受直连 DNS 空响应"
msgid "Smart: Forward to both direct and remote DNS, if the direct DNS resolution result is a mainland China IP, then use the direct result, otherwise use the remote result."
msgstr "智能:同时转发给直连和远程 DNS,如果直连 DNS 解析结果是大陆 IP,则使用直连结果,否则使用远程结果。"
msgid "Auto: Prefer mainland China IPs returned by direct DNS and fall back to remote DNS when no usable result is available."
msgstr "自动:优先使用直连 DNS 返回的大陆 IP,无可用结果时回退到远程 DNS。"
msgid "In smart mode, no-ip reply from Direct DNS:"
msgstr "使用智能模式,直连 DNS 返回空响应时:"
@@ -1283,6 +1283,7 @@ start_dns() {
else
smartdns_remote_dns="tcp://1.1.1.1"
fi
local smartdns_default_dns=$(config_n_get @global[0] smartdns_default_dns direct)
echolog " - 域名解析:使用SmartDNS,请确保配置正常。"
china_ng_listen="127.0.0.1#${SMARTDNS_LISTEN_PORT}"
@@ -1296,7 +1297,7 @@ start_dns() {
local subnet_ip=$(config_n_get @global[0] remote_dns_client_ip)
lua $APP_PATH/helper_smartdns_add.lua -FLAG "default" -SMARTDNS_CONF "/tmp/etc/smartdns/$CONFIG.conf" \
-LISTEN_PORT ${SMARTDNS_LISTEN_PORT} -LOCAL_PORT ${SMARTDNS_LOCAL_PORT} -DNS_REDIRECT ${DNS_REDIRECT} \
-LOCAL_GROUP ${group_domestic:-null} -REMOTE_GROUP "passwall_proxy" -REMOTE_PROXY_SERVER ${GLOBAL_SOCKS_server} -USE_DEFAULT_DNS "${USE_DEFAULT_DNS:-direct}" \
-LOCAL_GROUP ${group_domestic:-null} -REMOTE_GROUP "passwall_proxy" -REMOTE_PROXY_SERVER ${GLOBAL_SOCKS_server} -USE_DEFAULT_DNS "${smartdns_default_dns}" \
-REMOTE_DNS ${smartdns_remote_dns} -DNS_MODE ${DNS_MODE:-socks} -TUN_DNS ${TUN_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}" \
-NODE ${NODE} -DEFAULT_PROXY_MODE "${TCP_PROXY_MODE}" -NO_PROXY_IPV6 ${FILTER_PROXY_IPV6:-0} -NFTFLAG ${nftflag:-0} \
@@ -60,6 +60,11 @@ local function is_file_nonzero(path)
return nil
end
local function get_new_port(start_port, protocol)
local cmd_format = ". /usr/share/passwall/utils.sh ; echo -n $(get_new_port %s %s)"
return tonumber(sys.exec(string.format(cmd_format, api.util.shellquote(tostring(start_port or "auto")), api.util.shellquote(protocol or "tcp,udp"))))
end
local function insert_unique(dest_table, value, lookup_table)
if not lookup_table[value] then
table.insert(dest_table, value)
@@ -113,10 +118,24 @@ sys.call("mkdir -p %s" % FLAG_PATH)
sys.call("mkdir -p %s" % CACHE_RULES_PATH)
local LOCAL_EXTEND_ARG = ""
if LOCAL_GROUP == "null" or LOCAL_GROUP == "" then
local LOCAL_SERVERS = {}
local SERVER_TYPES = {
udp = "server", tcp = "server-tcp", tls = "server-tls",
https = "server-https", quic = "server-quic", h3 = "server-h3"
}
if not LOCAL_GROUP or LOCAL_GROUP == "null" or LOCAL_GROUP == "" then
log(" * 注意:SmartDNS 国内分组名未设置,DNS 将无法正常工作!!!")
os.exit(1)
else
api.uci:foreach("smartdns", "server", function(s)
if s.enabled ~= "0" and s.server_group == LOCAL_GROUP and s.ip and s.ip ~= "" and SERVER_TYPES[s.type or "udp"] then
table.insert(LOCAL_SERVERS, s)
end
end)
if #LOCAL_SERVERS == 0 then
log(" * 注意:SmartDNS 国内分组 " .. LOCAL_GROUP .. " 没有可用的 DNS 服务器,DNS 将无法正常工作!!!")
os.exit(1)
end
--从smartdns配置中读取参数
local custom_conf_path = "/etc/smartdns/custom.conf"
local options = {
@@ -163,15 +182,14 @@ else
val = custom_config[opt.config_key] or api.uci_get("smartdns", "@smartdns[0]", opt.key) or opt.default
end
if val == "yes" then val = "1" elseif val == "no" then val = "0" end
local arg
if opt.yes_no then
local arg = (val == "1" and opt.arg_yes or opt.arg_no)
if arg and arg ~= "" then
LOCAL_EXTEND_ARG = LOCAL_EXTEND_ARG .. (LOCAL_EXTEND_ARG ~= "" and " " or "") .. arg
end
else
if val and (not opt.value or (opt.invert and val ~= opt.value) or (not opt.invert and val == opt.value)) then
LOCAL_EXTEND_ARG = LOCAL_EXTEND_ARG .. (LOCAL_EXTEND_ARG ~= "" and " " or "") .. (opt.prefix or "") .. (opt.arg or val)
end
arg = (val == "1" and opt.arg_yes or opt.arg_no)
elseif val and (not opt.value or (opt.invert and val ~= opt.value) or (not opt.invert and val == opt.value)) then
arg = (opt.prefix or "") .. (opt.arg or val)
end
if arg and arg ~= "" then
LOCAL_EXTEND_ARG = LOCAL_EXTEND_ARG .. (LOCAL_EXTEND_ARG ~= "" and " " or "") .. arg
end
end
end
@@ -182,10 +200,29 @@ end
if REMOTE_DNS then
REMOTE_DNS = REMOTE_DNS:gsub("#", ":")
end
sys.call('sed -i "/passwall/d" /etc/smartdns/custom.conf >/dev/null 2>&1')
local SANDBOX_GROUP = "passwall_" .. FLAG
local AUTO_GROUP = "passwall_auto"
local AUTO_ENTRY_GROUP = AUTO_GROUP .. "_entry"
local auto_config_lines = {}
--设置默认 DNS 分组(兜底组),全局代理模式仍使用远程组。
local DEFAULT_DNS_GROUP = (USE_DEFAULT_DNS == "direct" and LOCAL_GROUP) or
(USE_DEFAULT_DNS == "remote" and REMOTE_GROUP) or
(USE_DEFAULT_DNS == "auto" and AUTO_GROUP)
local only_global = (DEFAULT_PROXY_MODE == "proxy" and CHN_LIST == "0" and USE_GFW_LIST == "0") and 1
if only_global == 1 then
DEFAULT_DNS_GROUP = REMOTE_GROUP
end
local AUTO_PORT
if DEFAULT_DNS_GROUP == AUTO_GROUP then
AUTO_PORT = get_new_port(15453, "udp")
if not AUTO_PORT then
log(" * 注意:SmartDNS 自动模式无法获取可用的 UDP 回环端口!")
os.exit(1)
end
end
sys.call('sed -i "/passwall/d" /etc/smartdns/custom.conf >/dev/null 2>&1')
local force_https_soa = api.uci_get_c("@global[0]", "force_https_soa") or 0
local force_qtype_soa = tonumber(force_https_soa) == 1 and "force-qtype-SOA 65" or "force-qtype-SOA -,65"
local proxy_server_name = "psw-proxy-server"
local listen_address = "[::]:" .. LISTEN_PORT .. (DNS_REDIRECT and "" or "@lo")
local local_domain = DNS_REDIRECT and api.uci_get("dhcp", "@dnsmasq[0]", "domain")
@@ -194,7 +231,6 @@ config_lines = {
tonumber(LISTEN_PORT) ~= 0 and ("bind-tcp " .. listen_address .. " -group " .. SANDBOX_GROUP) or "",
(tonumber(LOCAL_PORT) ~= 0 and LOCAL_GROUP) and "bind [::]:" .. LOCAL_PORT .. "@lo -group " .. LOCAL_GROUP or "",
(tonumber(LOCAL_PORT) ~= 0 and LOCAL_GROUP) and "bind-tcp [::]:" .. LOCAL_PORT .. "@lo -group " .. LOCAL_GROUP or "",
tonumber(force_https_soa) == 1 and "force-qtype-SOA 65" or "force-qtype-SOA -,65",
"server 223.5.5.5 -bootstrap-dns",
-- Set the suffix before loading hosts/leases so initial records are expanded too.
(local_domain and local_domain ~= "") and "local-domain " .. local_domain or "",
@@ -224,6 +260,53 @@ if DNS_REDIRECT then
table.insert(config_lines, string.format("odhcpd-lease-file %q", odhcpd_lease))
end
end
if DEFAULT_DNS_GROUP == AUTO_GROUP then
-- 复制国内组中启用的 UCI DNS 服务器,原组不添加白名单过滤。
for _, s in ipairs(LOCAL_SERVERS) do
local server_type = SERVER_TYPES[s.type or "udp"]
local address = s.ip
if not address:find("://", 1, true) then
if address:find(":", 1, true) and not address:find("[", 1, true) then
address = "[" .. address .. "]"
end
if s.port and s.port ~= "" then address = address .. ":" .. s.port end
end
local args = {server_type, address}
for _, key in ipairs({"tls_host_verify", "host_name", "http_host", "spki_pin", "set_mark"}) do
if s[key] and s[key] ~= "" then
table.insert(args, "-" .. key:gsub("_", "-"))
table.insert(args, s[key])
end
end
for _, key in ipairs({"no_check_certificate", "blacklist_ip", "check_edns"}) do
if s[key] == "1" and not (key == "blacklist_ip" and NO_PROXY_IPV6 == "1") then
table.insert(args, "-" .. key:gsub("_", "-"))
end
end
if s.use_proxy == "1" then table.insert(args, "-proxy default-proxy") end
-- 国内副本作为主用服务器,不继承后备标记。
local addition_arg = api.trim((" " .. (s.addition_arg or "")):gsub("(%s)%-%-?fallback%f[%s%z]", "%1"))
if NO_PROXY_IPV6 == "1" then
-- 国内副本只使用白名单,避免远程 IPv6 黑名单同时过滤国内结果。
addition_arg = api.trim((" " .. addition_arg):gsub("(%s)%-%-?blacklist%-ip%f[%s%z]", "%1"))
end
if addition_arg ~= "" then table.insert(args, addition_arg) end
table.insert(args, "-exclude-default-group -whitelist-ip")
table.insert(auto_config_lines, table.concat(args, " "))
end
end
-- 由下方 DNS_MODE 分支调用,服务器参数来自 PassWall 的 REMOTE_DNS 或 TUN_DNS。
local function add_remote_server(server_param)
table.insert(config_lines, server_param .. " -group " .. REMOTE_GROUP .. " -exclude-default-group")
if DEFAULT_DNS_GROUP == AUTO_GROUP then
-- 远程副本作为自动组的后备服务器,保留代理、ECS 和传输协议参数。
local auto_param = server_param .. " -exclude-default-group -fallback"
if NO_PROXY_IPV6 == "1" then auto_param = auto_param .. " -blacklist-ip" end
table.insert(auto_config_lines, auto_param)
end
end
if DNS_MODE == "socks" then
for w in string.gmatch(REMOTE_DNS, '[^|]+') do
local server_dns = api.trim(w)
@@ -274,35 +357,60 @@ if DNS_MODE == "socks" then
server_param = server_param .. " -proxy " .. proxy_server_name
end
server_param = server_param .. " -group " .. REMOTE_GROUP .. " -exclude-default-group"
if SUBNET and SUBNET ~= "" and SUBNET ~= "0" then
server_param = server_param .. " -subnet " .. SUBNET
end
table.insert(config_lines, server_param)
add_remote_server(server_param)
end
else
local server_param = string.format("server %s -group %s -exclude-default-group", TUN_DNS:gsub("#", ":"), REMOTE_GROUP)
table.insert(config_lines, server_param)
add_remote_server("server " .. TUN_DNS:gsub("#", ":"))
log(" - " .. DNS_MODE:gsub("^%l",string.upper) .. " " .. TUN_DNS .. " -> " .. REMOTE_GROUP)
end
-- Isolate PassWall domain rules within dedicated group to avoid polluting SmartDNS default group
table.insert(config_lines, "group-begin " .. SANDBOX_GROUP)
--设置默认 DNS 分组(托底组)
local DEFAULT_DNS_GROUP = (USE_DEFAULT_DNS == "direct" and LOCAL_GROUP) or
(USE_DEFAULT_DNS == "remote" and REMOTE_GROUP)
local only_global = (DEFAULT_PROXY_MODE == "proxy" and CHN_LIST == "0" and USE_GFW_LIST == "0") and 1 --没有启用中国列表和GFW列表时(全局)
if only_global == 1 then
DEFAULT_DNS_GROUP = REMOTE_GROUP
if DEFAULT_DNS_GROUP == AUTO_GROUP then
-- IP 集合和过滤规则集中在自动规则组内。
if NO_PROXY_IPV6 == "1" then
table.insert(auto_config_lines, "ip-rules ::/0 -blacklist-ip")
end
for _, name in ipairs({"chnroute", "chnroute6"}) do
local path = RULES_PATH .. "/" .. name
if is_file_nonzero(path) then
local set_name = AUTO_GROUP .. "-" .. name
table.insert(auto_config_lines, string.format("ip-set -name %s -file %s", set_name, path))
local ip_rules = "ip-rules ip-set:" .. set_name .. " -whitelist-ip"
if name == "chnroute6" and NO_PROXY_IPV6 == "1" then
-- 最长前缀匹配时,大陆 IPv6 网段也需要黑名单标记才能过滤远程结果。
ip_rules = ip_rules .. " -blacklist-ip"
end
table.insert(auto_config_lines, ip_rules)
else
log(" * 注意:SmartDNS 智能模式大陆 IP 列表不存在或为空:" .. path)
end
end
-- 兜底通过 UDP 回环入口进入自动规则组,避免 IP 过滤影响其他查询。
table.insert(config_lines, "bind [::]:" .. AUTO_PORT .. "@lo -group " .. AUTO_GROUP)
table.insert(config_lines, "server [::1]:" .. AUTO_PORT .. " -group " .. AUTO_ENTRY_GROUP .. " -exclude-default-group")
table.insert(config_lines, "group-begin " .. AUTO_GROUP .. " -inherit none")
table.insert(config_lines, force_qtype_soa)
merge_array(config_lines, auto_config_lines)
table.insert(config_lines, "domain-rules /./ -nameserver " .. AUTO_GROUP .. (LOCAL_EXTEND_ARG ~= "" and " " .. LOCAL_EXTEND_ARG or ""))
table.insert(config_lines, "group-end")
end
-- PassWall 规则组不继承外部规则。
table.insert(config_lines, "group-begin " .. SANDBOX_GROUP .. " -inherit none")
table.insert(config_lines, force_qtype_soa)
if DEFAULT_DNS_GROUP then
local domain_rules_str = "domain-rules /./ -nameserver " .. DEFAULT_DNS_GROUP
local domain_rules_str = "domain-rules /./ -nameserver " .. (DEFAULT_DNS_GROUP == AUTO_GROUP and AUTO_ENTRY_GROUP or DEFAULT_DNS_GROUP)
if DEFAULT_DNS_GROUP == REMOTE_GROUP then
domain_rules_str = domain_rules_str .. " -speed-check-mode none -d no -no-serve-expired"
domain_rules_str = domain_rules_str .. " -address " .. ((only_global and IS_SHUNT_NODE) and "-6" or (NO_PROXY_IPV6 == "1" and "#6" or "-6"))
elseif DEFAULT_DNS_GROUP == LOCAL_GROUP then
domain_rules_str = domain_rules_str .. (LOCAL_EXTEND_ARG ~= "" and " " .. LOCAL_EXTEND_ARG or "")
elseif DEFAULT_DNS_GROUP == AUTO_GROUP then
-- 转接层只转发请求,测速、双栈优选及缓存交给自动规则组处理。
domain_rules_str = domain_rules_str .. " -speed-check-mode none -d no -no-cache"
end
table.insert(config_lines, domain_rules_str)
end
@@ -803,7 +911,7 @@ if #config_lines > 0 then
end
if DEFAULT_DNS_GROUP then
log(string.format(" - 默认 DNS 分组:%s", DEFAULT_DNS_GROUP))
log(string.format(" - 默认 DNS 分组:%s", DEFAULT_DNS_GROUP == AUTO_GROUP and "自动" or DEFAULT_DNS_GROUP))
end
fs.symlink(TMP_CONF_FILE, SMARTDNS_CONF)