luci: add Sing-Box node a layer chain proxy logic

Can set it in the node configuration, no need to use shunt mode.
This commit is contained in:
xiaorouji 2024-02-26 18:11:46 +08:00 committed by sbwml
parent 5d55b4dc02
commit c71368fa9d
3 changed files with 88 additions and 93 deletions

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

@ -875,6 +875,53 @@ function gen_config(var)
table.insert(inbounds, inbound) table.insert(inbounds, inbound)
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 = {}
@ -903,34 +950,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
@ -1002,27 +1029,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
@ -1201,46 +1208,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.protocol == "_iface" then
if node.iface then if node.iface then
outbound = { local outbound = {
type = "direct", type = "direct",
tag = node_id, tag = node_id,
bind_interface = node.iface, bind_interface = node.iface,
routing_mark = 255, routing_mark = 255,
} }
table.insert(outbounds, outbound)
default_outTag = outbound.tag
route.final = default_outTag
sys.call("touch /tmp/etc/passwall/iface/" .. node.iface) sys.call("touch /tmp/etc/passwall/iface/" .. node.iface)
end end
else else
outbound = gen_outbound(flag, node) local outbound = gen_outbound(flag, node)
if outbound then if outbound then
if node.shadowtls == "1" then default_outTag = set_outbound_detour(node, outbound, outbounds)
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
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
route.final = default_outTag route.final = default_outTag
end end

View File

@ -1569,3 +1569,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 "仅支持一层代理。"