luci-app-passwall2: sync upstream

This commit is contained in:
actions 2024-02-26 23:00:12 +08:00
parent ec56aacd33
commit 407d3e0fa9
6 changed files with 179 additions and 127 deletions

View File

@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2 PKG_NAME:=luci-app-passwall2
PKG_VERSION:=1.26-3 PKG_VERSION:=1.27-1
PKG_RELEASE:= PKG_RELEASE:=
PKG_CONFIG_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \

View File

@ -54,7 +54,8 @@ for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" then if e.node_type == "normal" then
nodes_table[#nodes_table + 1] = { nodes_table[#nodes_table + 1] = {
id = e[".name"], id = e[".name"],
remarks = e["remark"] remarks = e["remark"],
type = e["type"]
} }
end end
if e.protocol == "_balancing" then if e.protocol == "_balancing" then
@ -80,11 +81,13 @@ local o = s:option(ListValue, option_name("balancingStrategy"), translate("Balan
o:depends({ [option_name("protocol")] = "_balancing" }) o:depends({ [option_name("protocol")] = "_balancing" })
o:value("random") o:value("random")
o:value("leastPing") o:value("leastPing")
o.default = "random" o:value("leastLoad")
o.default = "leastLoad"
-- 探测地址 -- 探测地址
local o = s:option(Flag, option_name("useCustomProbeUrl"), translate("Use Custome Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL.")) local o = s:option(Flag, option_name("useCustomProbeUrl"), translate("Use Custome Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL."))
o:depends({ [option_name("balancingStrategy")] = "leastPing" }) o:depends({ [option_name("balancingStrategy")] = "leastPing" })
o:depends({ [option_name("balancingStrategy")] = "leastLoad" })
local o = s:option(Value, option_name("probeUrl"), translate("Probe URL")) local o = s:option(Value, option_name("probeUrl"), translate("Probe URL"))
o:depends({ [option_name("useCustomProbeUrl")] = true }) o:depends({ [option_name("useCustomProbeUrl")] = true })
@ -94,6 +97,7 @@ o.description = translate("The URL used to detect the connection status.")
-- 探测间隔 -- 探测间隔
local o = s:option(Value, option_name("probeInterval"), translate("Probe Interval")) local o = s:option(Value, option_name("probeInterval"), translate("Probe Interval"))
o:depends({ [option_name("balancingStrategy")] = "leastPing" }) o:depends({ [option_name("balancingStrategy")] = "leastPing" })
o:depends({ [option_name("balancingStrategy")] = "leastLoad" })
o.default = "1m" o.default = "1m"
o.description = translate("The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.") o.description = translate("The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.")
@ -523,4 +527,21 @@ o.default = 0
o = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay") o = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay")
o.default = 0 o.default = 0
o = s:option(ListValue, option_name("to_node"), translate("Landing node"), translate("Only support a layer of proxy."))
o.default = ""
o:value("", translate("Close(Not use)"))
for k, v in pairs(nodes_table) do
if v.type == "Xray" then
o:value(v.id, v.remarks)
end
end
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
if not v:find("_") then
s.fields[option_name("tcpMptcp")]:depends({ [option_name("protocol")] = v })
s.fields[option_name("tcpNoDelay")]:depends({ [option_name("protocol")] = v })
s.fields[option_name("to_node")]:depends({ [option_name("protocol")] = v })
end
end
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)

View File

@ -65,13 +65,13 @@ o.default = "eth1"
o:depends({ [option_name("protocol")] = "_iface" }) o:depends({ [option_name("protocol")] = "_iface" })
local nodes_table = {} local nodes_table = {}
local balancers_table = {}
local iface_table = {} local iface_table = {}
for k, e in ipairs(api.get_valid_nodes()) do for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" then if e.node_type == "normal" then
nodes_table[#nodes_table + 1] = { nodes_table[#nodes_table + 1] = {
id = e[".name"], id = e[".name"],
remarks = e["remark"] remarks = e["remark"],
type = e["type"]
} }
end end
if e.protocol == "_iface" then if e.protocol == "_iface" then
@ -89,9 +89,6 @@ if #nodes_table > 0 then
o = s:option(Value, option_name("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not.")) o = s:option(Value, option_name("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not."))
o:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true }) o:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true })
for k, v in pairs(balancers_table) do
o:value(v.id, v.remarks)
end
for k, v in pairs(iface_table) do for k, v in pairs(iface_table) do
o:value(v.id, v.remarks) o:value(v.id, v.remarks)
end end
@ -110,9 +107,6 @@ uci:foreach(appname, "shunt_rules", function(e)
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [option_name("protocol")] = "_shunt" })
if #nodes_table > 0 then if #nodes_table > 0 then
for k, v in pairs(balancers_table) do
o:value(v.id, v.remarks)
end
for k, v in pairs(iface_table) do for k, v in pairs(iface_table) do
o:value(v.id, v.remarks) o:value(v.id, v.remarks)
end end
@ -142,9 +136,6 @@ o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole")) o:value("_blackhole", translate("Blackhole"))
if #nodes_table > 0 then if #nodes_table > 0 then
for k, v in pairs(balancers_table) do
o:value(v.id, v.remarks)
end
for k, v in pairs(iface_table) do for k, v in pairs(iface_table) do
o:value(v.id, v.remarks) o:value(v.id, v.remarks)
end end
@ -631,4 +622,18 @@ o:value("prefer_ipv6")
o:value("ipv4_only") o:value("ipv4_only")
o:value("ipv6_only") o:value("ipv6_only")
o = s:option(ListValue, option_name("to_node"), translate("Landing node"), translate("Only support a layer of proxy."))
o.default = ""
o:value("", translate("Close(Not use)"))
for k, v in pairs(nodes_table) do
if v.type == "sing-box" then
o:value(v.id, v.remarks)
end
end
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
if not v:find("_") then
o:depends({ [option_name("protocol")] = v })
end
end
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)

View File

@ -872,6 +872,54 @@ function gen_config(var)
node.address = server_host node.address = server_host
node.port = server_port node.port = server_port
end end
local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name)
if not node or not outbound or not outbounds_table then return nil end
local default_outTag = outbound.tag
if node.shadowtls == "1" then
local _node = {
type = "sing-box",
protocol = "shadowtls",
shadowtls_version = node.shadowtls_version,
password = (node.shadowtls_version == "2" or node.shadowtls_version == "3") and node.shadowtls_password or nil,
address = node.address,
port = node.port,
tls = "1",
tls_serverName = node.shadowtls_serverName,
utls = node.shadowtls_utls,
fingerprint = node.shadowtls_fingerprint
}
local shadowtls_outbound = gen_outbound(nil, _node, outbound.tag .. "_shadowtls")
if shadowtls_outbound then
table.insert(outbounds_table, shadowtls_outbound)
outbound.detour = outbound.tag .. "_shadowtls"
outbound.server = nil
outbound.server_port = nil
end
end
if node.to_node then
local to_node = uci:get_all(appname, node.to_node)
if to_node then
local to_outbound = gen_outbound(nil, to_node)
if to_outbound then
if shunt_rule_name then
to_outbound.tag = outbound.tag
outbound.tag = node[".name"]
else
to_outbound.tag = outbound.tag .. " -> " .. to_outbound.tag
end
to_outbound.detour = outbound.tag
table.insert(outbounds_table, to_outbound)
default_outTag = to_outbound.tag
end
end
end
return default_outTag
end
if node.protocol == "_shunt" then if node.protocol == "_shunt" then
local rules = {} local rules = {}
@ -900,34 +948,14 @@ function gen_config(var)
elseif preproxy_node and api.is_normal_node(preproxy_node) then elseif preproxy_node and api.is_normal_node(preproxy_node) then
local preproxy_outbound = gen_outbound(flag, preproxy_node, preproxy_tag) local preproxy_outbound = gen_outbound(flag, preproxy_node, preproxy_tag)
if preproxy_outbound then if preproxy_outbound then
if preproxy_node.shadowtls == "1" then set_outbound_detour(preproxy_node, preproxy_outbound, outbounds, preproxy_tag)
local _node = {
type = "sing-box",
protocol = "shadowtls",
shadowtls_version = preproxy_node.shadowtls_version,
password = (preproxy_node.shadowtls_version == "2" or preproxy_node.shadowtls_version == "3") and preproxy_node.shadowtls_password or nil,
address = preproxy_node.address,
port = preproxy_node.port,
tls = "1",
tls_serverName = preproxy_node.shadowtls_serverName,
utls = preproxy_node.shadowtls_utls,
fingerprint = preproxy_node.shadowtls_fingerprint
}
local shadowtls_outbound = gen_outbound(flag, _node, preproxy_tag .. "_shadowtls")
if shadowtls_outbound then
table.insert(outbounds, shadowtls_outbound)
preproxy_outbound.detour = preproxy_outbound.tag .. "_shadowtls"
preproxy_outbound.server = nil
preproxy_outbound.server_port = nil
end
end
table.insert(outbounds, preproxy_outbound) table.insert(outbounds, preproxy_outbound)
else else
preproxy_enabled = false preproxy_enabled = false
end end
end end
local function gen_shunt_node(rule_name, _node_id, as_proxy) local function gen_shunt_node(rule_name, _node_id)
if not rule_name then return nil, nil end if not rule_name then return nil, nil end
if not _node_id then _node_id = node[rule_name] or "nil" end if not _node_id then _node_id = node[rule_name] or "nil" end
local rule_outboundTag local rule_outboundTag
@ -999,27 +1027,7 @@ function gen_config(var)
end end
local _outbound = gen_outbound(flag, _node, rule_name, { proxy = proxy and 1 or 0, tag = proxy and preproxy_tag or nil }) local _outbound = gen_outbound(flag, _node, rule_name, { proxy = proxy and 1 or 0, tag = proxy and preproxy_tag or nil })
if _outbound then if _outbound then
if _node.shadowtls == "1" then set_outbound_detour(_node, _outbound, outbounds, rule_name)
local shadowtls_node = {
type = "sing-box",
protocol = "shadowtls",
shadowtls_version = _node.shadowtls_version,
password = (_node.shadowtls_version == "2" or _node.shadowtls_version == "3") and _node.shadowtls_password or nil,
address = _node.address,
port = _node.port,
tls = "1",
tls_serverName = _node.shadowtls_serverName,
utls = _node.shadowtls_utls,
fingerprint = _node.shadowtls_fingerprint
}
local shadowtls_outbound = gen_outbound(flag, shadowtls_node, rule_name .. "_shadowtls", { proxy = proxy and 1 or 0, tag = proxy and preproxy_tag or nil })
if shadowtls_outbound then
table.insert(outbounds, shadowtls_outbound)
_outbound.detour = _outbound.tag .. "_shadowtls"
_outbound.server = nil
_outbound.server_port = nil
end
end
table.insert(outbounds, _outbound) table.insert(outbounds, _outbound)
rule_outboundTag = rule_name rule_outboundTag = rule_name
end end
@ -1196,46 +1204,23 @@ function gen_config(var)
for index, value in ipairs(rules) do for index, value in ipairs(rules) do
table.insert(route.rules, rules[index]) table.insert(route.rules, rules[index])
end end
else elseif node.protocol == "_iface" then
local outbound = nil if node.iface then
if node.protocol == "_iface" then local outbound = {
if node.iface then type = "direct",
outbound = { tag = node_id,
type = "direct", bind_interface = node.iface,
tag = node_id, routing_mark = 255,
bind_interface = node.iface, }
routing_mark = 255, table.insert(outbounds, outbound)
}
sys.call("touch /tmp/etc/passwall2/iface/" .. node.iface)
end
else
outbound = gen_outbound(flag, node)
if outbound then
if node.shadowtls == "1" then
local shadowtls_node = {
type = "sing-box",
protocol = "shadowtls",
shadowtls_version = node.shadowtls_version,
password = (node.shadowtls_version == "2" or node.shadowtls_version == "3") and node.shadowtls_password or nil,
address = node.address,
port = node.port,
tls = "1",
tls_serverName = node.shadowtls_serverName,
utls = node.shadowtls_utls,
fingerprint = node.shadowtls_fingerprint
}
local shadowtls_outbound = gen_outbound(flag, shadowtls_node, outbound.tag .. "_shadowtls")
if shadowtls_outbound then
table.insert(outbounds, shadowtls_outbound)
outbound.detour = outbound.tag .. "_shadowtls"
outbound.server = nil
outbound.server_port = nil
end
end
end
end
if outbound then
default_outTag = outbound.tag default_outTag = outbound.tag
route.final = default_outTag
sys.call("touch /tmp/etc/passwall2/iface/" .. node.iface)
end
else
local outbound = gen_outbound(flag, node)
if outbound then
default_outTag = set_outbound_detour(node, outbound, outbounds)
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
route.final = default_outTag route.final = default_outTag
end end

View File

@ -245,6 +245,11 @@ function gen_outbound(flag, node, tag, proxy_table)
reserved = (node.protocol == "wireguard" and node.wireguard_reserved) and node.wireguard_reserved or nil reserved = (node.protocol == "wireguard" and node.wireguard_reserved) and node.wireguard_reserved or nil
} }
} }
if node.protocol == "wireguard" then
result.settings.kernelMode = false
end
local alpn = {} local alpn = {}
if node.alpn and node.alpn ~= "default" then if node.alpn and node.alpn ~= "default" then
string.gsub(node.alpn, '[^' .. "," .. ']+', function(w) string.gsub(node.alpn, '[^' .. "," .. ']+', function(w)
@ -658,7 +663,7 @@ function gen_config(var)
selector = valid_nodes, selector = valid_nodes,
strategy = { type = _node.balancingStrategy or "random" } strategy = { type = _node.balancingStrategy or "random" }
} }
if _node.balancingStrategy == "leastPing" then if _node.balancingStrategy == "leastPing" or _node.balancingStrategy == "leastLoad" then
if not observatory then if not observatory then
observatory = { observatory = {
subjectSelector = { "blc-" }, subjectSelector = { "blc-" },
@ -685,6 +690,34 @@ function gen_config(var)
return balancer, rule return balancer, rule
end end
local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name)
if not node or not outbound or not outbounds_table then return nil end
local default_outTag = outbound.tag
if node.to_node then
local to_node = uci:get_all(appname, node.to_node)
if to_node then
local to_outbound = gen_outbound(nil, to_node)
if to_outbound then
if shunt_rule_name then
to_outbound.tag = outbound.tag
outbound.tag = node[".name"]
else
to_outbound.tag = outbound.tag .. " -> " .. to_outbound.tag
end
to_outbound.proxySettings = {
tag = outbound.tag,
transportLayer = true
}
table.insert(outbounds_table, to_outbound)
default_outTag = to_outbound.tag
end
end
end
return default_outTag
end
for k, v in pairs(nodes) do for k, v in pairs(nodes) do
if server_host and server_port then if server_host and server_port then
v.address = server_host v.address = server_host
@ -722,6 +755,7 @@ function gen_config(var)
elseif preproxy_node and api.is_normal_node(preproxy_node) then elseif preproxy_node and api.is_normal_node(preproxy_node) then
local preproxy_outbound = gen_outbound(flag, preproxy_node, preproxy_tag, { fragment = xray_settings.fragment == "1" or nil }) local preproxy_outbound = gen_outbound(flag, preproxy_node, preproxy_tag, { fragment = xray_settings.fragment == "1" or nil })
if preproxy_outbound then if preproxy_outbound then
set_outbound_detour(preproxy_node, preproxy_outbound, outbounds, preproxy_tag)
table.insert(outbounds, preproxy_outbound) table.insert(outbounds, preproxy_outbound)
else else
preproxy_enabled = false preproxy_enabled = false
@ -737,7 +771,7 @@ function gen_config(var)
end end
end end
local function gen_shunt_node(rule_name, _node_id, as_proxy) local function gen_shunt_node(rule_name, _node_id)
if not rule_name then return nil, nil end if not rule_name then return nil, nil end
if not _node_id then _node_id = node[rule_name] or "nil" end if not _node_id then _node_id = node[rule_name] or "nil" end
local rule_outboundTag local rule_outboundTag
@ -831,6 +865,7 @@ function gen_config(var)
end end
local _outbound = gen_outbound(flag, _node, rule_name, proxy_table) local _outbound = gen_outbound(flag, _node, rule_name, proxy_table)
if _outbound then if _outbound then
set_outbound_detour(_node, _outbound, outbounds, rule_name)
table.insert(outbounds, _outbound) table.insert(outbounds, _outbound)
if proxy then preproxy_used = true end if proxy then preproxy_used = true end
rule_outboundTag = rule_name rule_outboundTag = rule_name
@ -991,39 +1026,39 @@ function gen_config(var)
} }
} }
end end
else elseif node.protocol == "_iface" then
local outbound = nil if node.iface then
if node.protocol == "_iface" then local outbound = {
if node.iface then protocol = "freedom",
outbound = { tag = "outbound",
protocol = "freedom", streamSettings = {
tag = "outbound", sockopt = {
streamSettings = { mark = 255,
sockopt = { interface = node.iface
mark = 255,
interface = node.iface
}
} }
} }
sys.call("touch /tmp/etc/passwall2/iface/" .. node.iface) }
end table.insert(outbounds, outbound)
else sys.call("touch /tmp/etc/passwall2/iface/" .. node.iface)
outbound = gen_outbound(flag, node, nil, { fragment = xray_settings.fragment == "1" or nil }) end
else
local outbound = gen_outbound(flag, node, nil, { fragment = xray_settings.fragment == "1" or nil })
if outbound then
local default_outTag = set_outbound_detour(node, outbound, outbounds)
table.insert(outbounds, outbound)
routing = {
domainStrategy = "AsIs",
domainMatcher = "hybrid",
rules = {}
}
table.insert(routing.rules, {
_flag = "default",
type = "field",
outboundTag = default_outTag,
network = "tcp,udp"
})
end end
if outbound then table.insert(outbounds, outbound) end
routing = {
domainStrategy = "AsIs",
domainMatcher = "hybrid",
rules = {}
}
table.insert(routing.rules, {
_flag = "default",
type = "field",
outboundTag = node_id,
network = "tcp,udp"
})
end end
end end
if remote_dns_udp_server then if remote_dns_udp_server then

View File

@ -1482,3 +1482,9 @@ msgstr "分片间隔ms"
msgid "If is domain name, The requested domain name will be resolved to IP before connect." msgid "If is domain name, The requested domain name will be resolved to IP before connect."
msgstr "如果是域名,域名将在请求发出之前解析为 IP。" msgstr "如果是域名,域名将在请求发出之前解析为 IP。"
msgid "Landing node"
msgstr "落地节点"
msgid "Only support a layer of proxy."
msgstr "仅支持一层代理。"