luci: shunt added xray balancer support
- optimized pre-proxy settings (https://github.com/xiaorouji/openwrt-passwall/issues/2234)
This commit is contained in:
parent
eadb44a03a
commit
ee7ded80e5
@ -59,7 +59,7 @@ o = s:option(Flag, "restore_switch", "TCP " .. translate("Restore Switch"), tran
|
|||||||
o = s:option(ListValue, "shunt_logic", "TCP " .. translate("If the main node is V2ray/Xray shunt"))
|
o = s:option(ListValue, "shunt_logic", "TCP " .. translate("If the main node is V2ray/Xray shunt"))
|
||||||
o:value("0", translate("Switch it"))
|
o:value("0", translate("Switch it"))
|
||||||
o:value("1", translate("Applying to the default node"))
|
o:value("1", translate("Applying to the default node"))
|
||||||
o:value("2", translate("Applying to the default preproxy node"))
|
o:value("2", translate("Applying to the preproxy node"))
|
||||||
|
|
||||||
m:append(Template(appname .. "/auto_switch/footer"))
|
m:append(Template(appname .. "/auto_switch/footer"))
|
||||||
|
|
||||||
|
@ -100,74 +100,106 @@ if current_node and current_node ~= "" and current_node ~= "nil" then
|
|||||||
end
|
end
|
||||||
tcp_node:value("nil", translate("Close"))
|
tcp_node:value("nil", translate("Close"))
|
||||||
|
|
||||||
|
---- UDP Node
|
||||||
|
udp_node = s:taboption("Main", ListValue, "udp_node", "<a style='color: red'>" .. translate("UDP Node") .. "</a>")
|
||||||
|
udp_node:value("nil", translate("Close"))
|
||||||
|
udp_node:value("tcp", translate("Same as the tcp node"))
|
||||||
|
|
||||||
-- 分流
|
-- 分流
|
||||||
if (has_v2ray or has_xray) and #nodes_table > 0 then
|
if (has_v2ray or has_xray) and #nodes_table > 0 then
|
||||||
local normal_list = {}
|
local normal_list = {}
|
||||||
local shunt_list = {}
|
local shunt_list = {}
|
||||||
for k, v in pairs(nodes_table) do
|
for k, v in pairs(nodes_table) do
|
||||||
if v.node_type == "normal" then
|
if v.node_type == "normal" or v.protocol == "_balancing" then
|
||||||
normal_list[#normal_list + 1] = v
|
normal_list[#normal_list + 1] = v
|
||||||
end
|
end
|
||||||
if v.protocol and v.protocol == "_shunt" then
|
if v.protocol and v.protocol == "_shunt" then
|
||||||
shunt_list[#shunt_list + 1] = v
|
shunt_list[#shunt_list + 1] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function get_cfgvalue(shunt_node_id, rule_id)
|
||||||
|
return function(self, section)
|
||||||
|
return m:get(shunt_node_id, rule_id) or "nil"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function get_write(shunt_node_id, rule_id)
|
||||||
|
return function(self, section, value)
|
||||||
|
m:set(shunt_node_id, rule_id, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for k, v in pairs(shunt_list) do
|
for k, v in pairs(shunt_list) do
|
||||||
|
local vid = v.id:sub(1, 8)
|
||||||
|
o = s:taboption("Main", ListValue, vid .. "-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("tcp_node", v.id)
|
||||||
|
o:value("nil", translate("Close"))
|
||||||
|
for k1, v1 in pairs(normal_list) do
|
||||||
|
o:value(v1.id, v1.remark)
|
||||||
|
end
|
||||||
|
o.cfgvalue = get_cfgvalue(v.id, "main_node")
|
||||||
|
o.write = get_write(v.id, "main_node")
|
||||||
|
|
||||||
|
local dialerProxy = s:taboption("Main", Flag, vid .. "-dialerProxy", translate("dialerProxy"))
|
||||||
|
if v.type == "Xray" then
|
||||||
|
dialerProxy:depends("tcp_node", v.id)
|
||||||
|
else --主设置界面没有type判断,只能判断本分流节点类型是Xray就添加对本分流节点的依赖,但不是的话就没有依赖,会全部显示,所以添加一个不存在的依赖以达到隐藏的目的
|
||||||
|
dialerProxy:depends("tcp_node", "xray_shunt")
|
||||||
|
end
|
||||||
|
dialerProxy.cfgvalue = get_cfgvalue(v.id, "dialerProxy")
|
||||||
|
dialerProxy.write = get_write(v.id, "dialerProxy")
|
||||||
|
|
||||||
uci:foreach(appname, "shunt_rules", function(e)
|
uci:foreach(appname, "shunt_rules", function(e)
|
||||||
local id = e[".name"]
|
local id = e[".name"]
|
||||||
|
local node_option = vid .. "-" .. id .. "_node"
|
||||||
if id and e.remarks then
|
if id and e.remarks then
|
||||||
o = s:taboption("Main", ListValue, v.id .. "." .. id .. "_node", string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", id), e.remarks))
|
o = s:taboption("Main", ListValue, node_option, string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", id), e.remarks))
|
||||||
o:depends("tcp_node", v.id)
|
o:depends("tcp_node", v.id)
|
||||||
o:value("nil", translate("Close"))
|
o:value("nil", translate("Close"))
|
||||||
o:value("_default", translate("Default"))
|
o:value("_default", translate("Default"))
|
||||||
o:value("_direct", translate("Direct Connection"))
|
o:value("_direct", translate("Direct Connection"))
|
||||||
o:value("_blackhole", translate("Blackhole"))
|
o:value("_blackhole", translate("Blackhole"))
|
||||||
|
local pt = s:taboption("Main", ListValue, vid .. "-".. id .. "_proxy_tag", string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
|
||||||
|
pt:value("nil", translate("Close"))
|
||||||
|
pt:value("main", translate("Preproxy Node"))
|
||||||
|
pt.default = "nil"
|
||||||
for k1, v1 in pairs(normal_list) do
|
for k1, v1 in pairs(normal_list) do
|
||||||
o:value(v1.id, v1["remark"])
|
o:value(v1.id, v1.remark)
|
||||||
|
if v1.protocol ~= "_balancing" then
|
||||||
|
pt:depends(node_option, v1.id)
|
||||||
end
|
end
|
||||||
o.cfgvalue = function(self, section)
|
|
||||||
return m:get(v.id, id) or "nil"
|
|
||||||
end
|
|
||||||
o.write = function(self, section, value)
|
|
||||||
m:set(v.id, id, value)
|
|
||||||
end
|
end
|
||||||
|
o.cfgvalue = get_cfgvalue(v.id, id)
|
||||||
|
o.write = get_write(v.id, id)
|
||||||
|
pt.cfgvalue = get_cfgvalue(v.id, id .. "_proxy_tag")
|
||||||
|
pt.write = get_write(v.id, id .. "_proxy_tag")
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local id = "default_node"
|
local id = "default_node"
|
||||||
o = s:taboption("Main", ListValue, v.id .. "." .. id, string.format('* <a style="color:red">%s</a>', translate("Default")))
|
o = s:taboption("Main", ListValue, vid .. "-" .. id, string.format('* <a style="color:red">%s</a>', translate("Default")))
|
||||||
o:depends("tcp_node", v.id)
|
o:depends("tcp_node", v.id)
|
||||||
o:value("_direct", translate("Direct Connection"))
|
o:value("_direct", translate("Direct Connection"))
|
||||||
o:value("_blackhole", translate("Blackhole"))
|
o:value("_blackhole", translate("Blackhole"))
|
||||||
for k1, v1 in pairs(normal_list) do
|
for k1, v1 in pairs(normal_list) do
|
||||||
o:value(v1.id, v1["remark"])
|
o:value(v1.id, v1["remark"])
|
||||||
end
|
end
|
||||||
o.cfgvalue = function(self, section)
|
o.cfgvalue = get_cfgvalue(v.id, id)
|
||||||
return m:get(v.id, id) or "nil"
|
o.write = get_write(v.id, id)
|
||||||
end
|
|
||||||
o.write = function(self, section, value)
|
|
||||||
m:set(v.id, id, value)
|
|
||||||
end
|
|
||||||
|
|
||||||
local id = "main_node"
|
local id = "default_proxy_tag"
|
||||||
o = s:taboption("Main", ListValue, v.id .. "." .. id, string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
|
o = s:taboption("Main", ListValue, vid .. "-" .. id, string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
|
||||||
o:depends("tcp_node", v.id)
|
|
||||||
o:value("nil", translate("Close"))
|
|
||||||
for k1, v1 in pairs(normal_list) do
|
for k1, v1 in pairs(normal_list) do
|
||||||
o:value(v1.id, v1["remark"])
|
if v1.protocol ~= "_balancing" then
|
||||||
end
|
o:depends(vid .. "-default_node", v1.id)
|
||||||
o.cfgvalue = function(self, section)
|
|
||||||
return m:get(v.id, id) or "nil"
|
|
||||||
end
|
|
||||||
o.write = function(self, section, value)
|
|
||||||
m:set(v.id, id, value)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
o:value("nil", translate("Close"))
|
||||||
|
o:value("main", translate("Preproxy Node"))
|
||||||
|
o.cfgvalue = get_cfgvalue(v.id, id)
|
||||||
|
o.write = get_write(v.id, id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
udp_node = s:taboption("Main", ListValue, "udp_node", "<a style='color: red'>" .. translate("UDP Node") .. "</a>")
|
|
||||||
udp_node:value("nil", translate("Close"))
|
|
||||||
udp_node:value("tcp", translate("Same as the tcp node"))
|
|
||||||
|
|
||||||
tcp_node_socks_port = s:taboption("Main", Value, "tcp_node_socks_port", translate("TCP Node") .. " Socks " .. translate("Listen Port"))
|
tcp_node_socks_port = s:taboption("Main", Value, "tcp_node_socks_port", translate("TCP Node") .. " Socks " .. translate("Listen Port"))
|
||||||
tcp_node_socks_port.default = 1070
|
tcp_node_socks_port.default = 1070
|
||||||
|
@ -133,9 +133,10 @@ iface:depends("protocol", "_iface")
|
|||||||
|
|
||||||
local nodes_table = {}
|
local nodes_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" or e.protocol == "_balancing" then
|
||||||
nodes_table[#nodes_table + 1] = {
|
nodes_table[#nodes_table + 1] = {
|
||||||
id = e[".name"],
|
id = e[".name"],
|
||||||
|
protocol = e["protocol"],
|
||||||
remarks = e["remark"]
|
remarks = e["remark"]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@ -145,17 +146,39 @@ end
|
|||||||
local balancing_node = s:option(DynamicList, "balancing_node", translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>"))
|
local balancing_node = s:option(DynamicList, "balancing_node", translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>"))
|
||||||
for k, v in pairs(nodes_table) do balancing_node:value(v.id, v.remarks) end
|
for k, v in pairs(nodes_table) do balancing_node:value(v.id, v.remarks) end
|
||||||
balancing_node:depends("protocol", "_balancing")
|
balancing_node:depends("protocol", "_balancing")
|
||||||
|
|
||||||
local balancingStrategy = s:option(ListValue, "balancingStrategy", translate("Balancing Strategy"))
|
local balancingStrategy = s:option(ListValue, "balancingStrategy", translate("Balancing Strategy"))
|
||||||
balancingStrategy:depends("protocol", "_balancing")
|
balancingStrategy:depends("protocol", "_balancing")
|
||||||
balancingStrategy:value("random")
|
balancingStrategy:value("random")
|
||||||
balancingStrategy:value("leastPing")
|
balancingStrategy:value("leastPing")
|
||||||
balancingStrategy.default = "random"
|
balancingStrategy.default = "random"
|
||||||
|
-- 探测地址
|
||||||
|
local useCustomProbeUrl = s:option(Flag, "useCustomProbeUrl", translate("Use Custome Probe URL"))
|
||||||
|
useCustomProbeUrl:depends("balancingStrategy", "leastPing")
|
||||||
|
useCustomProbeUrl.description = "By default the built-in probe URL will be used, enable this option to use a custom probe URL."
|
||||||
|
local probeUrl = s:option(Value, "probeUrl", translate("Probe URL"))
|
||||||
|
probeUrl:depends("useCustomProbeUrl", true)
|
||||||
|
probeUrl.default = "https://www.google.com/generate_204"
|
||||||
|
probeUrl.description = translate("The URL used to detect the connection status.")
|
||||||
|
-- 探测间隔
|
||||||
local probeInterval = s:option(Value, "probeInterval", translate("Probe Interval"))
|
local probeInterval = s:option(Value, "probeInterval", translate("Probe Interval"))
|
||||||
probeInterval:depends("balancingStrategy", "leastPing")
|
probeInterval:depends("balancingStrategy", "leastPing")
|
||||||
probeInterval.default = "1m"
|
probeInterval.default = "1m"
|
||||||
probeInterval.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.")
|
probeInterval.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.")
|
||||||
|
|
||||||
-- 分流
|
-- 分流
|
||||||
|
if #nodes_table > 0 then
|
||||||
|
o = s:option(ListValue, "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("protocol", "_shunt")
|
||||||
|
o:value("nil", translate("Close"))
|
||||||
|
dialerProxy = s:option(Flag, "dialerProxy", translate("dialerProxy"))
|
||||||
|
dialerProxy:depends({ type = "Xray", protocol = "_shunt" , })
|
||||||
|
for k, v in pairs(nodes_table) do
|
||||||
|
o:value(v.id, v.remarks)
|
||||||
|
--dialerProxy:depends({ type = "Xray", main_node = v.id })
|
||||||
|
end
|
||||||
|
o.default = "nil"
|
||||||
|
end
|
||||||
uci:foreach(appname, "shunt_rules", function(e)
|
uci:foreach(appname, "shunt_rules", function(e)
|
||||||
if e[".name"] and e.remarks then
|
if e[".name"] and e.remarks then
|
||||||
o = s:option(ListValue, e[".name"], string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks))
|
o = s:option(ListValue, e[".name"], string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks))
|
||||||
@ -166,15 +189,15 @@ uci:foreach(appname, "shunt_rules", function(e)
|
|||||||
o:depends("protocol", "_shunt")
|
o:depends("protocol", "_shunt")
|
||||||
|
|
||||||
if #nodes_table > 0 then
|
if #nodes_table > 0 then
|
||||||
_proxy_tag = s:option(ListValue, e[".name"] .. "_proxy_tag", string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
|
local pt = s:option(ListValue, e[".name"] .. "_proxy_tag", string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
|
||||||
_proxy_tag:value("nil", translate("Close"))
|
pt:value("nil", translate("Close"))
|
||||||
_proxy_tag:value("default", translate("Default"))
|
pt:value("main", translate("Preproxy Node"))
|
||||||
_proxy_tag:value("main", translate("Default Preproxy"))
|
pt.default = "nil"
|
||||||
_proxy_tag.default = "nil"
|
|
||||||
|
|
||||||
for k, v in pairs(nodes_table) do
|
for k, v in pairs(nodes_table) do
|
||||||
o:value(v.id, v.remarks)
|
o:value(v.id, v.remarks)
|
||||||
_proxy_tag:depends(e[".name"], v.id)
|
if v.protocol ~= "_balancing" then
|
||||||
|
pt:depends(e[".name"], v.id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -194,16 +217,16 @@ for k, v in pairs(nodes_table) do default_node:value(v.id, v.remarks) end
|
|||||||
default_node:depends("protocol", "_shunt")
|
default_node:depends("protocol", "_shunt")
|
||||||
|
|
||||||
if #nodes_table > 0 then
|
if #nodes_table > 0 then
|
||||||
o = s:option(ListValue, "main_node", string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
|
local dpt = s:option(ListValue, "default_proxy_tag", string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
|
||||||
o:value("nil", translate("Close"))
|
dpt:value("nil", translate("Close"))
|
||||||
|
dpt:value("main", translate("Preproxy Node"))
|
||||||
|
dpt.default = "nil"
|
||||||
for k, v in pairs(nodes_table) do
|
for k, v in pairs(nodes_table) do
|
||||||
o:value(v.id, v.remarks)
|
if v.protocol ~= "_balancing" then
|
||||||
o:depends("default_node", v.id)
|
dpt:depends("default_node", v.id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
dialerProxy = s:option(Flag, "dialerProxy", translate("dialerProxy"))
|
|
||||||
dialerProxy:depends({ type = "Xray", protocol = "_shunt"})
|
|
||||||
|
|
||||||
domainStrategy = s:option(ListValue, "domainStrategy", translate("Domain Strategy"))
|
domainStrategy = s:option(ListValue, "domainStrategy", translate("Domain Strategy"))
|
||||||
domainStrategy:value("AsIs")
|
domainStrategy:value("AsIs")
|
||||||
|
@ -215,7 +215,7 @@ local function stop()
|
|||||||
ip6t("-F PSW-SERVER 2>/dev/null")
|
ip6t("-F PSW-SERVER 2>/dev/null")
|
||||||
ip6t("-X PSW-SERVER 2>/dev/null")
|
ip6t("-X PSW-SERVER 2>/dev/null")
|
||||||
else
|
else
|
||||||
nft_cmd="handles=$(nft -a list chain inet fw4 input | grep -E \"PSW-SERVER\" | awk -F '# handle ' '{print$2}')\n for handle in $handles; do\n nft delete rule inet fw4 input handle ${handle} 2>/dev/null\n done"
|
local nft_cmd = "handles=$(nft -a list chain inet fw4 input | grep -E \"PSW-SERVER\" | awk -F '# handle ' '{print$2}')\n for handle in $handles; do\n nft delete rule inet fw4 input handle ${handle} 2>/dev/null\n done"
|
||||||
cmd(nft_cmd)
|
cmd(nft_cmd)
|
||||||
cmd("nft flush chain inet fw4 PSW-SERVER 2>/dev/null")
|
cmd("nft flush chain inet fw4 PSW-SERVER 2>/dev/null")
|
||||||
cmd("nft delete chain inet fw4 PSW-SERVER 2>/dev/null")
|
cmd("nft delete chain inet fw4 PSW-SERVER 2>/dev/null")
|
||||||
|
@ -91,8 +91,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
|||||||
config_file, --config file
|
config_file, --config file
|
||||||
(proxy == 1 and relay_port) and tostring(relay_port) or "" --relay port
|
(proxy == 1 and relay_port) and tostring(relay_port) or "" --relay port
|
||||||
)
|
)
|
||||||
)
|
))
|
||||||
)
|
|
||||||
node = {}
|
node = {}
|
||||||
node.protocol = "socks"
|
node.protocol = "socks"
|
||||||
node.transport = "tcp"
|
node.transport = "tcp"
|
||||||
@ -596,96 +595,124 @@ function gen_config(var)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if node.protocol == "_shunt" then
|
local function get_balancer_tag(_node_id)
|
||||||
local rules = {}
|
return "balancer-" .. _node_id:sub(1, 8)
|
||||||
|
|
||||||
local default_node_id = node.default_node or "_direct"
|
|
||||||
local default_outboundTag
|
|
||||||
if default_node_id == "_direct" then
|
|
||||||
default_outboundTag = "direct"
|
|
||||||
elseif default_node_id == "_blackhole" then
|
|
||||||
default_outboundTag = "blackhole"
|
|
||||||
else
|
|
||||||
local default_node = uci:get_all(appname, default_node_id)
|
|
||||||
local main_node_id = node.main_node or "nil"
|
|
||||||
local proxy = 0
|
|
||||||
local proxy_tag
|
|
||||||
if main_node_id ~= "nil" then
|
|
||||||
local main_node = uci:get_all(appname, main_node_id)
|
|
||||||
if main_node and api.is_normal_node(main_node) and main_node_id ~= default_node_id then
|
|
||||||
local main_node_outbound = gen_outbound(flag, main_node, "main")
|
|
||||||
if main_node_outbound then
|
|
||||||
table.insert(outbounds, main_node_outbound)
|
|
||||||
proxy = 1
|
|
||||||
proxy_tag = "main"
|
|
||||||
local pre_proxy = nil
|
|
||||||
if default_node.type ~= "V2ray" and default_node.type ~= "Xray" then
|
|
||||||
pre_proxy = true
|
|
||||||
end
|
|
||||||
if default_node.type == "Xray" and default_node.tlsflow == "xtls-rprx-vision" then
|
|
||||||
pre_proxy = true
|
|
||||||
end
|
|
||||||
if pre_proxy then
|
|
||||||
proxy_tag = nil
|
|
||||||
new_port = get_new_port()
|
|
||||||
table.insert(inbounds, {
|
|
||||||
tag = "proxy_default",
|
|
||||||
listen = "127.0.0.1",
|
|
||||||
port = new_port,
|
|
||||||
protocol = "dokodemo-door",
|
|
||||||
settings = {network = "tcp,udp", address = default_node.address, port = tonumber(default_node.port)}
|
|
||||||
})
|
|
||||||
if default_node.tls_serverName == nil then
|
|
||||||
default_node.tls_serverName = default_node.address
|
|
||||||
end
|
|
||||||
default_node.address = "127.0.0.1"
|
|
||||||
default_node.port = new_port
|
|
||||||
table.insert(rules, 1, {
|
|
||||||
type = "field",
|
|
||||||
inboundTag = {"proxy_default"},
|
|
||||||
outboundTag = "main"
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if default_node and api.is_normal_node(default_node) then
|
|
||||||
local default_outbound = gen_outbound(flag, default_node, "default", { proxy = proxy, tag = proxy_tag, dialerProxy = node.dialerProxy })
|
|
||||||
if default_outbound then
|
|
||||||
table.insert(outbounds, default_outbound)
|
|
||||||
default_outboundTag = "default"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
uci:foreach(appname, "shunt_rules", function(e)
|
local function gen_balancer(_node, loopbackTag)
|
||||||
local name = e[".name"]
|
local blc_nodes = _node.balancing_node
|
||||||
if name and e.remarks then
|
local length = #blc_nodes
|
||||||
local _node_id = node[name] or "nil"
|
local valid_nodes = {}
|
||||||
local proxy_tag = node[name .. "_proxy_tag"] or "nil"
|
for i = 1, length do
|
||||||
local outboundTag
|
local blc_node_id = blc_nodes[i]
|
||||||
if _node_id == "_direct" then
|
local blc_node_tag = "blc-" .. blc_node_id:sub(1, 8)
|
||||||
outboundTag = "direct"
|
local is_new_blc_node = true
|
||||||
elseif _node_id == "_blackhole" then
|
for _, outbound in ipairs(outbounds) do
|
||||||
outboundTag = "blackhole"
|
if outbound.tag == blc_node_tag then
|
||||||
elseif _node_id == "_default" then
|
is_new_blc_node = false
|
||||||
outboundTag = "default"
|
valid_nodes[#valid_nodes + 1] = blc_node_tag
|
||||||
else
|
|
||||||
if _node_id ~= "nil" then
|
|
||||||
local _node = uci:get_all(appname, _node_id)
|
|
||||||
if _node and api.is_normal_node(_node) then
|
|
||||||
local new_outbound
|
|
||||||
for index, value in ipairs(outbounds) do
|
|
||||||
if value["_flag_tag"] == _node_id and value["_flag_proxy_tag"] == proxy_tag then
|
|
||||||
new_outbound = api.clone(value)
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if new_outbound then
|
if is_new_blc_node then
|
||||||
new_outbound["tag"] = name
|
local blc_node = uci:get_all(appname, blc_node_id)
|
||||||
table.insert(outbounds, new_outbound)
|
local outbound = gen_outbound(flag, blc_node, blc_node_tag)
|
||||||
outboundTag = name
|
if outbound then
|
||||||
|
table.insert(outbounds, outbound)
|
||||||
|
valid_nodes[#valid_nodes + 1] = blc_node_tag
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local balancer, rule
|
||||||
|
if #valid_nodes > 0 then
|
||||||
|
local balancerTag = get_balancer_tag(_node[".name"])
|
||||||
|
balancer = {
|
||||||
|
tag = balancerTag,
|
||||||
|
selector = valid_nodes,
|
||||||
|
strategy = { type = _node.balancingStrategy or "random" }
|
||||||
|
}
|
||||||
|
if _node.balancingStrategy == "leastPing" then
|
||||||
|
if not observatory then
|
||||||
|
observatory = {
|
||||||
|
subjectSelector = { "blc-" },
|
||||||
|
probeUrl = _node.useCustomProbeUrl == true and _node.probeUrl or nil,
|
||||||
|
probeInterval = _node.probeInterval or "1m",
|
||||||
|
enableConcurrency = node.type == "Xray" and true or nil --这里只判断顶层节点(分流总节点/单独的负载均衡节点)类型为Xray,就可以启用并发
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if loopbackTag and loopbackTag ~= "" then
|
||||||
|
local inboundTag = loopbackTag .. "-in"
|
||||||
|
table.insert(outbounds, {
|
||||||
|
protocol = "loopback",
|
||||||
|
tag = loopbackTag,
|
||||||
|
settings = { inboundTag = inboundTag }
|
||||||
|
})
|
||||||
|
rule = {
|
||||||
|
type = "field",
|
||||||
|
inboundTag = { inboundTag },
|
||||||
|
balancerTag = balancerTag
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return balancer, rule
|
||||||
|
end
|
||||||
|
|
||||||
|
if node.protocol == "_shunt" then
|
||||||
|
local rules = {}
|
||||||
|
local balancers = {}
|
||||||
|
|
||||||
|
local preproxy_enabled = false
|
||||||
|
local preproxy_tag = "main"
|
||||||
|
local preproxy_node_id = node[preproxy_tag .. "_node"] or "nil"
|
||||||
|
|
||||||
|
local function gen_shunt_node(rule_name, _node_id, as_proxy)
|
||||||
|
if not rule_name then return nil, nil end
|
||||||
|
if not _node_id then _node_id = node[rule_name] or "nil" end
|
||||||
|
local rule_outboundTag
|
||||||
|
local rule_balancerTag
|
||||||
|
if _node_id == "_direct" then
|
||||||
|
rule_outboundTag = "direct"
|
||||||
|
elseif _node_id == "_blackhole" then
|
||||||
|
rule_outboundTag = "blackhole"
|
||||||
|
elseif _node_id == "_default" and rule_name ~= "default" then
|
||||||
|
rule_outboundTag = "default"
|
||||||
|
elseif _node_id ~= "nil" then
|
||||||
|
local _node = uci:get_all(appname, _node_id)
|
||||||
|
if not _node then return nil, nil end
|
||||||
|
|
||||||
|
if api.is_normal_node(_node) then --这一块根据代理设置的修改方向还需要修改
|
||||||
|
local proxy_tag = node[rule_name .. "_proxy_tag"] or "nil"
|
||||||
|
if proxy_tag == preproxy_tag and not preproxy_enabled then proxy_tag = "nil" end
|
||||||
|
local proxy_node_id = proxy_tag ~= "nil" and node[proxy_tag .. "_node"] or "nil" --为了适配之前默认节点也可用作前置代理的写法,只设一个的话直接用preproxy_node_id
|
||||||
|
if _node_id == proxy_node_id then proxy_tag = "nil" end --规则启用了前置代理,但规则本身节点和前置代理节点是同一个,则前置代理设置无效
|
||||||
|
local proxy_node = uci:get_all(appname, proxy_node_id) --前置代理节点
|
||||||
|
local is_balancing_proxy
|
||||||
|
if proxy_node and proxy_node.protocol == "_balancing" then
|
||||||
|
is_balancing_proxy = true
|
||||||
|
local blc_nodes = proxy_node.balancing_node
|
||||||
|
for _, blc_node_id in ipairs(blc_nodes) do
|
||||||
|
if _node_id == blc_node_id then
|
||||||
|
proxy_tag = "nil"
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local copied_outbound
|
||||||
|
for index, value in ipairs(outbounds) do
|
||||||
|
if value["_flag_tag"] == _node_id and value["_flag_proxy_tag"] == proxy_tag then
|
||||||
|
copied_outbound = api.clone(value)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if copied_outbound then
|
||||||
|
copied_outbound.tag = rule_name
|
||||||
|
table.insert(outbounds, copied_outbound)
|
||||||
|
rule_outboundTag = rule_name
|
||||||
else
|
else
|
||||||
|
if proxy_tag ~= "nil" then
|
||||||
local pre_proxy = nil
|
local pre_proxy = nil
|
||||||
if _node.type ~= "V2ray" and _node.type ~= "Xray" then
|
if _node.type ~= "V2ray" and _node.type ~= "Xray" then
|
||||||
pre_proxy = true
|
pre_proxy = true
|
||||||
@ -694,10 +721,9 @@ function gen_config(var)
|
|||||||
pre_proxy = true
|
pre_proxy = true
|
||||||
end
|
end
|
||||||
if pre_proxy then
|
if pre_proxy then
|
||||||
if proxy_tag ~= "nil" then
|
|
||||||
new_port = get_new_port()
|
new_port = get_new_port()
|
||||||
table.insert(inbounds, {
|
table.insert(inbounds, {
|
||||||
tag = "proxy_" .. name,
|
tag = "proxy_" .. rule_name,
|
||||||
listen = "127.0.0.1",
|
listen = "127.0.0.1",
|
||||||
port = new_port,
|
port = new_port,
|
||||||
protocol = "dokodemo-door",
|
protocol = "dokodemo-door",
|
||||||
@ -710,21 +736,69 @@ function gen_config(var)
|
|||||||
_node.port = new_port
|
_node.port = new_port
|
||||||
table.insert(rules, 1, {
|
table.insert(rules, 1, {
|
||||||
type = "field",
|
type = "field",
|
||||||
inboundTag = {"proxy_" .. name},
|
inboundTag = {"proxy_" .. rule_name},
|
||||||
outboundTag = proxy_tag
|
outboundTag = is_balancing_proxy and nil or proxy_tag,
|
||||||
|
balancerTag = is_balancing_proxy and get_balancer_tag(proxy_node_id) or nil
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local _outbound = gen_outbound(flag, _node, name, { proxy = (proxy_tag ~= "nil") and 1 or 0, tag = (proxy_tag ~= "nil") and proxy_tag or nil, dialerProxy = node.dialerProxy })
|
local _outbound = gen_outbound(flag, _node, rule_name, { proxy = (proxy_tag ~= "nil") and 1 or 0, tag = (proxy_tag ~= "nil") and proxy_tag or nil, dialerProxy = node.dialerProxy })
|
||||||
if _outbound then
|
if _outbound then
|
||||||
table.insert(outbounds, _outbound)
|
table.insert(outbounds, _outbound)
|
||||||
outboundTag = name
|
if proxy_tag == preproxy_tag then preproxy_used = true end
|
||||||
|
rule_outboundTag = rule_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif _node.protocol == "_balancing" then
|
||||||
|
local is_new_balancer = true
|
||||||
|
for _, v in ipairs(balancers) do
|
||||||
|
if v["_flag_tag"] == _node_id then
|
||||||
|
is_new_balancer = false
|
||||||
|
rule_balancerTag = v.tag
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if is_new_balancer then --注释掉的是给需要用作前置代理的balancer生成等效OutboundTag(loopback + 规则路由至)的代码,可能用上
|
||||||
|
--local loopbackTag = as_proxy == true and rule_name or nil
|
||||||
|
local balancer = gen_balancer(_node) --local balancer, rule = gen_balancer(_node)
|
||||||
|
if balancer then
|
||||||
|
table.insert(balancers, balancer)
|
||||||
|
--if rule then table.insert(rules, rule) end
|
||||||
|
rule_balancerTag = balancer.tag
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return rule_outboundTag, rule_balancerTag
|
||||||
end
|
end
|
||||||
if outboundTag then
|
|
||||||
|
--[[此处只要前置代理设置选择了节点,即使全部规则都没使用,仍会先尝试生成,生成有效配置才真正开启功能,会造成配置文件里面会有多余未使用的outbound,
|
||||||
|
如果放到最后,判断节点有使用前置代理才生成又不能提前检测前置代理节点能否正确生成配置项,主要是负载均衡类型节点不好处理,生成的配置项多,
|
||||||
|
只能先读取分流规则和默认的 proxy_tag,有启用前置代理的,就生成前置代理配置]]
|
||||||
|
if preproxy_node_id ~= "nil" then
|
||||||
|
local preproxy_node = uci:get_all(appname, preproxy_node_id)
|
||||||
|
if preproxy_node and api.is_normal_node(preproxy_node) then
|
||||||
|
local preproxy_outbound = gen_outbound(flag, preproxy_node, preproxy_tag)
|
||||||
|
if preproxy_outbound then
|
||||||
|
table.insert(outbounds, preproxy_outbound)
|
||||||
|
preproxy_enabled = true
|
||||||
|
end
|
||||||
|
elseif preproxy_node and preproxy_node.protocol == "_balancing" then
|
||||||
|
local preproxy_balancer, preproxy_rule = gen_balancer(preproxy_node, preproxy_tag)
|
||||||
|
if preproxy_balancer and preproxy_rule then
|
||||||
|
table.insert(balancers, preproxy_balancer)
|
||||||
|
table.insert(rules, preproxy_rule)
|
||||||
|
preproxy_enabled = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local default_node_id = node.default_node or "_direct"
|
||||||
|
local default_outboundTag, default_balancerTag = gen_shunt_node("default", default_node_id)
|
||||||
|
|
||||||
|
uci:foreach(appname, "shunt_rules", function(e)
|
||||||
|
local outboundTag, balancerTag = gen_shunt_node(e[".name"])
|
||||||
|
if outboundTag or balancerTag and e.remarks then
|
||||||
if outboundTag == "default" then
|
if outboundTag == "default" then
|
||||||
outboundTag = default_outboundTag
|
outboundTag = default_outboundTag
|
||||||
end
|
end
|
||||||
@ -735,45 +809,36 @@ function gen_config(var)
|
|||||||
table.insert(protocols, w)
|
table.insert(protocols, w)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
local _domain = nil
|
||||||
if e.domain_list then
|
if e.domain_list then
|
||||||
local _domain = {}
|
_domain = {}
|
||||||
string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w)
|
string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||||
table.insert(_domain, w)
|
table.insert(_domain, w)
|
||||||
end)
|
end)
|
||||||
table.insert(rules, {
|
|
||||||
type = "field",
|
|
||||||
outboundTag = outboundTag,
|
|
||||||
domain = _domain,
|
|
||||||
protocol = protocols
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
local _ip = nil
|
||||||
if e.ip_list then
|
if e.ip_list then
|
||||||
local _ip = {}
|
_ip = {}
|
||||||
string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w)
|
string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||||
table.insert(_ip, w)
|
table.insert(_ip, w)
|
||||||
end)
|
end)
|
||||||
|
end
|
||||||
table.insert(rules, {
|
table.insert(rules, {
|
||||||
type = "field",
|
type = "field",
|
||||||
outboundTag = outboundTag,
|
outboundTag = outboundTag,
|
||||||
|
balancerTag = balancerTag,
|
||||||
|
domain = _domain,
|
||||||
ip = _ip,
|
ip = _ip,
|
||||||
protocol = protocols
|
protocol = protocols
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
if not e.domain_list and not e.ip_list and protocols then
|
|
||||||
table.insert(rules, {
|
|
||||||
type = "field",
|
|
||||||
outboundTag = outboundTag,
|
|
||||||
protocol = protocols
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
if default_outboundTag then
|
if default_outboundTag or default_balancerTag then
|
||||||
table.insert(rules, {
|
table.insert(rules, {
|
||||||
type = "field",
|
type = "field",
|
||||||
outboundTag = default_outboundTag,
|
outboundTag = default_outboundTag,
|
||||||
|
balancerTag = default_balancerTag,
|
||||||
network = "tcp,udp"
|
network = "tcp,udp"
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
@ -781,31 +846,16 @@ function gen_config(var)
|
|||||||
routing = {
|
routing = {
|
||||||
domainStrategy = node.domainStrategy or "AsIs",
|
domainStrategy = node.domainStrategy or "AsIs",
|
||||||
domainMatcher = node.domainMatcher or "hybrid",
|
domainMatcher = node.domainMatcher or "hybrid",
|
||||||
|
balancers = #balancers > 0 and balancers or nil,
|
||||||
rules = rules
|
rules = rules
|
||||||
}
|
}
|
||||||
elseif node.protocol == "_balancing" then
|
elseif node.protocol == "_balancing" then
|
||||||
if node.balancing_node then
|
if node.balancing_node then
|
||||||
local nodes = node.balancing_node
|
local balancer = gen_balancer(node)
|
||||||
local length = #nodes
|
|
||||||
for i = 1, length do
|
|
||||||
local node = uci:get_all(appname, nodes[i])
|
|
||||||
local outbound = gen_outbound(flag, node)
|
|
||||||
if outbound then table.insert(outbounds, outbound) end
|
|
||||||
end
|
|
||||||
if node.balancingStrategy == "leastPing" then
|
|
||||||
observatory = {
|
|
||||||
subjectSelector = nodes,
|
|
||||||
probeInterval = node.probeInterval or "1m"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
routing = {
|
routing = {
|
||||||
balancers = {{
|
balancers = { balancer },
|
||||||
tag = "balancer",
|
|
||||||
selector = nodes,
|
|
||||||
strategy = {type = node.balancingStrategy or "random"}
|
|
||||||
}},
|
|
||||||
rules = {
|
rules = {
|
||||||
{type = "field", network = "tcp,udp", balancerTag = "balancer"}
|
{ type = "field", network = "tcp,udp", balancerTag = balancer.tag }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -352,6 +352,18 @@ msgstr "V2ray 负载均衡"
|
|||||||
msgid "Balancing Strategy"
|
msgid "Balancing Strategy"
|
||||||
msgstr "负载均衡策略"
|
msgstr "负载均衡策略"
|
||||||
|
|
||||||
|
msgid "Use Custome Probe URL"
|
||||||
|
msgstr "使用自定义探测网址"
|
||||||
|
|
||||||
|
msgid "By default the built-in probe URL will be used, enable this option to use a custom probe URL."
|
||||||
|
msgstr "默认使用内置的探测网址,启用此选项以使用自定义探测网址。"
|
||||||
|
|
||||||
|
msgid "Probe URL"
|
||||||
|
msgstr "探测网址"
|
||||||
|
|
||||||
|
msgid "The URL used to detect the connection status."
|
||||||
|
msgstr "用于检测连接状态的网址。"
|
||||||
|
|
||||||
msgid "Probe Interval"
|
msgid "Probe Interval"
|
||||||
msgstr "探测间隔"
|
msgstr "探测间隔"
|
||||||
|
|
||||||
@ -370,6 +382,12 @@ msgstr "V2ray 分流"
|
|||||||
msgid "Preproxy"
|
msgid "Preproxy"
|
||||||
msgstr "前置代理"
|
msgstr "前置代理"
|
||||||
|
|
||||||
|
msgid "Preproxy Node"
|
||||||
|
msgstr "前置代理节点"
|
||||||
|
|
||||||
|
msgid "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."
|
||||||
|
msgstr "设置用作前置代理的节点。每条规则(包括<code>默认</code>)都有独立开关控制本规则是否使用前置代理。"
|
||||||
|
|
||||||
msgid "Direct Connection"
|
msgid "Direct Connection"
|
||||||
msgstr "直连"
|
msgstr "直连"
|
||||||
|
|
||||||
@ -661,8 +679,8 @@ msgstr "切掉它"
|
|||||||
msgid "Applying to the default node"
|
msgid "Applying to the default node"
|
||||||
msgstr "应用于默认节点"
|
msgstr "应用于默认节点"
|
||||||
|
|
||||||
msgid "Applying to the default preproxy node"
|
msgid "Applying to the preproxy node"
|
||||||
msgstr "应用于默认前置节点"
|
msgstr "应用于前置代理节点"
|
||||||
|
|
||||||
msgid "Add nodes to the standby node list by keywords"
|
msgid "Add nodes to the standby node list by keywords"
|
||||||
msgstr "通过关键字添加节点到备用节点列表"
|
msgstr "通过关键字添加节点到备用节点列表"
|
||||||
|
Loading…
Reference in New Issue
Block a user