🎄 Sync 2026-08-10 20:58:00

This commit is contained in:
github-actions[bot] committed 2026-08-10 20:58:00 +08:00
1 parent f93918f4ae
commit e68eb29c6f
37 files changed
+318 -551

No files matched your search

+1 -1
View File
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2
PKG_VERSION:=26.8.7
PKG_RELEASE:=75
PKG_RELEASE:=76
PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \
@@ -171,19 +171,6 @@ node_socks_bind_local:depends({ node = "", ["!reverse"] = true })
s:tab("DNS", translate("DNS"))
o = s:taboption("DNS", TextValue, "direct_dns_shunt", translate("Direct domain DNS routing"))
o.description = "<br /><ul>"
.. "<li>" .. translate("Subdomain (recommended): Begining with 'domain:' and the rest is a domain. When the targeting domain is exactly the value, or is a subdomain of the value, this rule takes effect. Example: rule 'domain:v2ray.com' matches 'www.v2ray.com', 'v2ray.com', but not 'xv2ray.com'.") .. "</li>"
.. "<li>" .. translate("Full domain: Begining with 'full:' and the rest is a domain. When the targeting domain is exactly the value, the rule takes effect. Example: rule 'domain:v2ray.com' matches 'v2ray.com', but not 'www.v2ray.com'.") .. "</li>"
.. "<li>" .. translate("Such as:") .. "</li>"
.. "<li>" .. "domain:my-nodes.com tcp://223.5.5.5" .. "</li>"
.. "<li>" .. "domain:vpn.com udp://119.29.29.29:53" .. "</li>"
.. "<li>" .. "full:www.dnspod.com https://120.53.53.53/dns-query" .. "</li>"
.. "<li>" .. '<a style="color:red">' .. translate("Please note that the program will not start if the format is incorrect!") .. '</a>' .. "</li>"
.. "</ul>"
o.rows = 3
o.wrap = "off"
o = s:taboption("DNS", ListValue, "direct_dns_query_strategy", translate("Direct Query Strategy"))
o.default = "UseIP"
o:value("UseIP")
+3 -2
View File
@@ -5,7 +5,6 @@ nixio = require "nixio"
fs = require "nixio.fs"
sys = require "luci.sys"
uci = require"luci.model.uci".cursor()
cbi = require "luci.cbi"
util = require "luci.util"
datatypes = require "luci.cbi.datatypes"
jsonc = require "luci.jsonc"
@@ -1014,7 +1013,6 @@ local default_file_tree = {
}
function get_api_json(url)
local jsonc = require "luci.jsonc"
local return_code, content = curl_logic(url, nil, curl_args)
if return_code ~= 0 or content == "" then return {} end
return jsonc.parse(content) or {}
@@ -1387,6 +1385,7 @@ function set_apply_on_parse(map)
end
function set_default_cbi()
local cbi = require "luci.cbi"
if true then
--TextValue
local TextValue = cbi.TextValue
@@ -1418,6 +1417,7 @@ function set_default_cbi()
end
function return_map(map)
local cbi = require "luci.cbi"
local api = require "luci.passwall2.api"
if true then
-- header
@@ -1438,6 +1438,7 @@ function return_map(map)
end
function luci_types(id, m, s, type_name, option_prefix)
local cbi = require "luci.cbi"
local fv_type
local field_type = s.fields["type"]
if field_type then
@@ -111,34 +111,6 @@ for i, v in ipairs(cipherSuites) do
end
]]--
function parseDNS(str)
local result_dns_server
-- [proto]://[ip]
-- [proto]://[ip]:[port]
-- https://[ip]/[path]
-- https://[ip]:[port]/[path]
local _a = api.parseURL(str)
if _a then
if _a.protocol == "tcp" or _a.protocol == "udp" or _a.protocol == "https" then
result_dns_server = {
type = _a.protocol,
server = _a.hostname
}
if _a.port then
result_dns_server.server_port = _a.port
else
if _a.protocol == "https" then
result_dns_server.server_port = 443
else
result_dns_server.server_port = 53
end
end
result_dns_server.path = _a.pathname
end
end
return result_dns_server
end
function gen_outbound(flag, node, tag, proxy_table)
local result = nil
if node then
@@ -2023,6 +1995,7 @@ function gen_config(var)
else default_dns_flag = "direct"
end
dns.final = default_dns_flag
dns.strategy = default_dns_flag == "remote" and remote_strategy or direct_strategy
-- DNS in order of shunt
if dns_domain_rules and #dns_domain_rules > 0 then
@@ -2046,12 +2019,43 @@ function gen_config(var)
dns_rule.server = nil
end
if value.outboundTag == "direct" then
dns_rule.strategy = direct_strategy
local block_rule
if direct_strategy == "ipv4_only" then
block_rule = api.clone(dns_rule)
block_rule.query_type = { "AAAA" }
elseif direct_strategy == "ipv6_only" then
block_rule = api.clone(dns_rule)
block_rule.query_type = { "A" }
end
if block_rule then
block_rule.action = "predefined"
block_rule.rcode = "NOERROR"
block_rule.disable_cache = nil
block_rule.server = nil
table.insert(dns.rules, block_rule)
end
end
if value.outboundTag ~= "block" and value.outboundTag ~= "direct" then
dns_rule.server = "remote"
dns_rule.rewrite_ttl = 30
dns_rule.strategy = remote_strategy
if true then
local block_rule
if remote_strategy == "ipv4_only" then
block_rule = api.clone(dns_rule)
block_rule.query_type = { "AAAA" }
elseif remote_strategy == "ipv6_only" then
block_rule = api.clone(dns_rule)
block_rule.query_type = { "A" }
end
if block_rule then
block_rule.action = "predefined"
block_rule.rcode = "NOERROR"
block_rule.disable_cache = nil
block_rule.server = nil
block_rule.rewrite_ttl = nil
table.insert(dns.rules, block_rule)
end
end
dns_rule.client_subnet = remote_dns_client_ip
if value.outboundTag ~= COMMON.default_outbound_tag and remote_server.server and remote_dns_detour ~= "direct" then
local remote_dns_server = api.clone(remote_server)
@@ -2062,9 +2066,13 @@ function gen_config(var)
end
if value.fakedns then
local fakedns_dns_rule = api.clone(dns_rule)
fakedns_dns_rule.query_type = {
"A", "AAAA"
}
if remote_strategy == "ipv4_only" then
fakedns_dns_rule.query_type = { "A" }
elseif remote_strategy == "ipv6_only" then
fakedns_dns_rule.query_type = { "AAAA" }
else
fakedns_dns_rule.query_type = { "A", "AAAA" }
end
fakedns_dns_rule.server = fakedns_tag
fakedns_dns_rule.disable_cache = true
fakedns_dns_rule.client_subnet = nil
@@ -2076,23 +2084,26 @@ function gen_config(var)
end
end
if default_dns_flag == "remote" then
local dns_rule_query_type = { "A", "AAAA" }
if remote_strategy == "ipv4_only" then
dns_rule_query_type = { "A" }
elseif remote_strategy == "ipv6_only" then
dns_rule_query_type = { "AAAA" }
end
if remote_dns_fake then
-- When default is not direct and enable fakedns, default DNS use FakeDNS.
local fakedns_dns_rule = {
query_type = {
"A", "AAAA"
},
query_type = dns_rule_query_type,
server = fakedns_tag,
disable_cache = true,
rewrite_ttl = 30,
strategy = remote_strategy,
rewrite_ttl = 30
}
table.insert(dns.rules, fakedns_dns_rule)
else
local remote_dns_rule = {
query_type = dns_rule_query_type,
server = "remote",
disable_cache = true,
strategy = remote_strategy,
}
table.insert(dns.rules, remote_dns_rule)
end
@@ -2328,156 +2339,7 @@ function gen_proto_config(var)
return jsonc.stringify(config, 1)
end
function gen_front_dns_config(var)
local dns_listen_port = var["dns_listen_port"]
local direct_dns_udp_server = var["direct_dns_udp_server"]
local direct_dns_udp_port = var["direct_dns_udp_port"]
local direct_dns_query_strategy = var["direct_dns_query_strategy"]
local default_dns_udp_server = var["default_dns_udp_server"]
local default_dns_udp_port = var["default_dns_udp_port"]
local dns = {
servers = {},
rules = {}
}
local inbounds = {}
local outbounds = {}
local route = {}
local direct_strategy = "prefer_ipv6"
if direct_dns_query_strategy == "UseIPv4" then
direct_strategy = "ipv4_only"
elseif direct_dns_query_strategy == "UseIPv6" then
direct_strategy = "ipv6_only"
end
table.insert(outbounds, {
type = "direct",
tag = "direct",
routing_mark = 255,
})
local direct_dns_shunt = uci:get(appname, "@global[0]", "direct_dns_shunt") or ""
if #direct_dns_shunt > 0 then
local dns_server = {}
string.gsub(direct_dns_shunt, '[^' .. "\r\n" .. ']+', function(w)
if w:find("#") == 1 then return end
local domain = sys.exec(string.format("echo -n $(echo %s | awk -F ' ' '{print $1}')", w))
local dns = sys.exec(string.format("echo -n $(echo %s | awk -F ' ' '{print $2}')", w))
if domain ~= "" and dns ~= "" then
local new_dns_server = parseDNS(dns)
if new_dns_server then
if not dns_server[dns] then
dns_server[dns] = {}
end
if not dns_server[dns].server then
dns_server[dns].server = new_dns_server
dns_server[dns].server.tag = dns
dns_server[dns].server.detour = "direct"
end
if not dns_server[dns].rule then
dns_server[dns].rule = {
action = "route",
server = dns,
domain = {},
domain_suffix = {},
domain_keyword = {}
}
end
if domain:find("full:") == 1 then
table.insert(dns_server[dns].rule.domain, domain:sub(1 + #"full:"))
elseif domain:find("domain:") == 1 then
table.insert(dns_server[dns].rule.domain_suffix, domain:sub(1 + #"domain:"))
else
table.insert(dns_server[dns].rule.domain_keyword, domain)
end
end
end
end)
for k, v in pairs(dns_server) do
table.insert(dns.servers, v.server)
if #v.rule.domain == 0 then v.rule.domain = nil end
if #v.rule.domain_suffix == 0 then v.rule.domain_suffix = nil end
if #v.rule.domain_keyword == 0 then v.rule.domain_keyword = nil end
table.insert(dns.rules, v.rule)
end
end
if direct_dns_udp_server then
table.insert(dns.servers, {
tag = "direct",
type = "udp",
server = direct_dns_udp_server,
server_port = tonumber(direct_dns_udp_port) or 53,
detour = "direct"
})
local node_domain = {}
local nodes_domain_text = sys.exec('uci show passwall2 | grep ".address=" | cut -d "\'" -f 2 | grep "[a-zA-Z]$" | sort -u')
string.gsub(nodes_domain_text, '[^' .. "\r\n" .. ']+', function(w)
w = (w or ""):lower()
table.insert(node_domain, w)
end)
if #node_domain > 0 then
table.insert(dns.rules, {
action = "route",
server = "direct",
domain = node_domain
})
end
route.default_domain_resolver = {
server = "direct",
strategy = direct_strategy
}
end
if default_dns_udp_server then
table.insert(dns.servers, {
tag = "default",
type = "udp",
server = default_dns_udp_server,
server_port = tonumber(default_dns_udp_port) or 53,
detour = "direct"
})
dns.final = "default"
else
dns.final = "direct"
end
local dns_in_inbound = {
type = "direct",
tag = "dns-in",
listen = "127.0.0.1",
listen_port = tonumber(dns_listen_port),
}
table.insert(inbounds, dns_in_inbound)
route.rules = {}
table.insert(route.rules, {
action = "hijack-dns",
inbound = dns_in_inbound.tag
})
table.insert(route.rules, {
action = "sniff",
inbound = dns_in_inbound.tag
})
route.final = "direct"
local config = {
log = {
disabled = true,
level = "debug",
timestamp = true,
},
dns = dns,
inbounds = inbounds,
outbounds = outbounds,
route = route
}
return jsonc.stringify(config, 1)
end
_G.gen_config = gen_config
_G.gen_front_dns_config = gen_front_dns_config
_G.gen_proto_config = gen_proto_config
_G.geo_convert_srs = geo_convert_srs
@@ -51,35 +51,6 @@ for i, v in ipairs(cipherSuites) do
end
]]--
function parseDNS(str)
local result_dns_server
-- [proto]://[ip]
-- [proto]://[ip]:[port]
-- https://[ip]/[path]
-- https://[ip]:[port]/[path]
local _a = api.parseURL(str)
if _a then
if _a.protocol == "tcp" or _a.protocol == "udp" or _a.protocol == "https" then
result_dns_server = {
address = str
}
if _a.protocol == "udp" then
result_dns_server.address = _a.hostname
end
if _a.port then
result_dns_server.port = _a.port
else
if _a.protocol == "https" then
result_dns_server.port = 443
else
result_dns_server.port = 53
end
end
end
end
return result_dns_server
end
function gen_outbound(flag, node, tag, proxy_table)
local result = nil
if node then
@@ -2186,157 +2157,7 @@ function gen_proto_config(var)
return jsonc.stringify(config, 1)
end
function gen_front_dns_config(var)
local dns_listen_port = var["dns_listen_port"]
local direct_dns_udp_server = var["direct_dns_udp_server"]
local direct_dns_udp_port = var["direct_dns_udp_port"]
local default_dns_udp_server = var["default_dns_udp_server"]
local default_dns_udp_port = var["default_dns_udp_port"]
local queryStrategy = "UseIP"
local dns = {
tag = "dns-global-direct",
disableCache = false,
disableFallback = true,
disableFallbackIfMatch = true,
queryStrategy = queryStrategy,
servers = {}
}
local inbounds = {}
local outbounds = {}
local routing = {
rules = {}
}
table.insert(outbounds, {
tag = "direct",
protocol = "freedom",
settings = {
domainStrategy = queryStrategy
},
streamSettings = {
sockopt = {
mark = 255
}
}
})
if default_dns_udp_server then
table.insert(dns.servers, {
tag = "default",
address = default_dns_udp_server,
port = tonumber(default_dns_udp_port) or 53,
queryStrategy = queryStrategy,
})
end
local direct_dns_shunt = uci:get(appname, "@global[0]", "direct_dns_shunt") or ""
if #direct_dns_shunt > 0 then
local dns_server = {}
string.gsub(direct_dns_shunt, '[^' .. "\r\n" .. ']+', function(w)
if w:find("#") == 1 then return end
local domain = sys.exec(string.format("echo -n $(echo %s | awk -F ' ' '{print $1}')", w))
local dns = sys.exec(string.format("echo -n $(echo %s | awk -F ' ' '{print $2}')", w))
if domain ~= "" and dns ~= "" then
local new_dns_server = parseDNS(dns)
if new_dns_server then
if not dns_server[dns] then
dns_server[dns] = {}
end
dns_server[dns].tag = dns
dns_server[dns].queryStrategy = queryStrategy
dns_server[dns].address = new_dns_server.address
dns_server[dns].port = new_dns_server.port
dns_server[dns].finalQuery = true
if not dns_server[dns].domains then
dns_server[dns].domains = {}
end
table.insert(dns_server[dns].domains, domain)
end
end
end)
for k, v in pairs(dns_server) do
table.insert(dns.servers, v)
table.insert(routing.rules, {
inboundTag = {
v.tag
},
outboundTag = "direct"
})
end
end
if direct_dns_udp_server then
local node_domain = {}
local nodes_domain_text = sys.exec('uci show passwall2 | grep ".address=" | cut -d "\'" -f 2 | grep "[a-zA-Z]$" | sort -u')
string.gsub(nodes_domain_text, '[^' .. "\r\n" .. ']+', function(w)
w = (w or ""):lower()
table.insert(node_domain, "full:" .. w)
end)
if #node_domain > 0 then
table.insert(dns.servers, {
tag = "dns-in-vpslist",
address = direct_dns_udp_server,
port = tonumber(direct_dns_udp_port) or 53,
queryStrategy = queryStrategy,
domains = node_domain,
finalQuery = true,
disableCache = false,
serveStale = true,
})
end
end
table.insert(inbounds, {
tag = "dns-in",
listen = "127.0.0.1",
port = tonumber(dns_listen_port),
protocol = "dokodemo-door",
settings = {
address = "0.0.0.0",
network = "tcp,udp"
}
})
table.insert(outbounds, {
tag = "dns-out",
protocol = "dns",
proxySettings = {
tag = "direct"
},
settings = {
address = direct_dns_udp_server,
port = tonumber(direct_dns_udp_port) or 53,
network = "udp",
nonIPQuery = "skip",
blockTypes = {
65
}
}
})
table.insert(routing.rules, {
inboundTag = {
"dns-in"
},
outboundTag = "dns-out"
})
local config = {
log = {
dnsLog = true,
loglevel = "debug"
},
dns = dns,
inbounds = inbounds,
outbounds = outbounds,
routing = routing
}
return jsonc.stringify(config, 1)
end
_G.gen_config = gen_config
_G.gen_front_dns_config = gen_front_dns_config
_G.gen_proto_config = gen_proto_config
if arg[1] then
-6
View File
@@ -121,12 +121,6 @@ msgstr "0 به معنای عدم استفاده است"
msgid "Current node: %s"
msgstr "گره فعلی: %s"
msgid "Direct domain DNS routing"
msgstr "مسیریابی مستقیم DNS دامنه"
msgid "Please note that the program will not start if the format is incorrect!"
msgstr "لطفا توجه داشته باشید که اگر قالب نادرست باشد، برنامه شروع نخواهد شد!"
msgid "IP:Port mode acceptable, multi value split with english comma."
msgstr "حالت IP:Port قابل قبول است، مقادیر متعدد را با کاما انگلیسی جدا کنید."
-6
View File
@@ -118,12 +118,6 @@ msgstr "0 — отключить функцию"
msgid "Current node: %s"
msgstr "Текущий узел: %s"
msgid "Direct domain DNS routing"
msgstr "Прямая маршрутизация DNS домена"
msgid "Please note that the program will not start if the format is incorrect!"
msgstr "Обратите внимание, что программа не запустится, если формат указан неверно!"
msgid "IP:Port mode acceptable, multi value split with english comma."
msgstr "Допустим формат IP:Port. Несколько значений указывайте через запятую."
-6
View File
@@ -118,12 +118,6 @@ msgstr "0为不使用"
msgid "Current node: %s"
msgstr "当前节点:%s"
msgid "Direct domain DNS routing"
msgstr "直连域名 DNS 分流"
msgid "Please note that the program will not start if the format is incorrect!"
msgstr "请注意,格式不正确将无法启动!"
msgid "IP:Port mode acceptable, multi value split with english comma."
msgstr "接受 IP:Port 形式的输入,多个以英文逗号分隔。"
-6
View File
@@ -118,12 +118,6 @@ msgstr "0為不使用"
msgid "Current node: %s"
msgstr "當前節點:%s"
msgid "Direct domain DNS routing"
msgstr "直連網域 DNS 分流"
msgid "Please note that the program will not start if the format is incorrect!"
msgstr "請注意,格式不正確將無法啟動!"
msgid "IP:Port mode acceptable, multi value split with english comma."
msgstr "接受 IP:Port 形式的輸入,多個以英文逗号分隔。"
@@ -655,58 +655,13 @@ run_global() {
set_cache_var "ACL_GLOBAL_redir_port" "$REDIR_PORT"
}
run_front_dns() {
local switch=0
direct_dns_shunt=$(config_t_get global direct_dns_shunt)
direct_dns_shunt=$(echo "${direct_dns_shunt}" | grep -v "^#")
[ -n "${direct_dns_shunt}" ] && switch=1
[ "${switch}" == "1" ] && {
local config_file="${TMP_PATH}/direct_dns.json"
local log_file="${TMP_PATH}/direct_dns.log"
log_file="/dev/null"
local listen_port=$(get_new_port 10553)
json_init
json_add_string "dns_listen_port" "${listen_port}"
json_add_string "direct_dns_udp_server" "${DIRECT_DNS_UDP_SERVER}"
json_add_string "direct_dns_udp_port" "${DIRECT_DNS_UDP_PORT}"
json_add_string "direct_dns_query_strategy" "${DIRECT_DNS_QUERY_STRATEGY}"
[ -n "${ACL_GLOBAL_node}" ] && [ -n "${TUN_DNS_PORT}" ] && {
json_add_string "default_dns_udp_server" "127.0.0.1"
json_add_string "default_dns_udp_port" "${TUN_DNS_PORT}"
}
local _json_arg="$(json_dump)"
local prefer_core=""
[ -n "${XRAY_BIN}" ] && prefer_core="xray"
[ -n "${SINGBOX_BIN}" ] && prefer_core="sing-box"
if [ "${prefer_core}" = "xray" ]; then
lua $UTIL_XRAY gen_front_dns_config "${_json_arg}" > $config_file
ln_run 0 "$XRAY_BIN" "xray" "${log_file}" run -c "$config_file"
elif [ "${prefer_core}" = "sing-box" ]; then
lua $UTIL_SINGBOX gen_front_dns_config "${_json_arg}" > $config_file
ln_run 0 "$SINGBOX_BIN" "sing-box" "${log_file}" run -c "$config_file"
else
return 1
fi
FRONT_DNS_SERVER="127.0.0.1"
FRONT_DNS_PORT="${listen_port}"
}
}
run_global_dnsmasq() {
[ -z "${ACL_GLOBAL_node}" ] && [ -z "${FRONT_DNS_PORT}" ] && return
[ -z "${ACL_GLOBAL_node}" ] && return
local RUN_NEW_DNSMASQ=1
RUN_NEW_DNSMASQ=${DNS_REDIRECT}
DNSMASQ_DEFAULT_DNS="${AUTO_DNS}"
DNSMASQ_LOCAL_DNS="${LOCAL_DNS:-${AUTO_DNS}}"
DNSMASQ_TUN_DNS="${TUN_DNS}"
[ -n "${FRONT_DNS_PORT}" ] && {
DNSMASQ_DEFAULT_DNS="${FRONT_DNS_SERVER}#${FRONT_DNS_PORT}"
DNSMASQ_LOCAL_DNS="${DNSMASQ_DEFAULT_DNS}"
DNSMASQ_TUN_DNS="${DNSMASQ_DEFAULT_DNS}"
}
if [ "${RUN_NEW_DNSMASQ}" == "0" ]; then
#The old logic will be removed in the future.
#Run a copy dnsmasq instance, DNS hijack that don't need a proxy devices.
@@ -1194,7 +1149,6 @@ start() {
fi
mkdir -p ${GLOBAL_ACL_PATH}
[ "$ENABLED_DEFAULT_ACL" == 1 ] && run_global
run_front_dns
run_global_dnsmasq
[ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start
set_cache_var "USE_TABLES" "$USE_TABLES"