luci: shunt added xray balancer support

- optimized pre-proxy settings (https://github.com/xiaorouji/openwrt-passwall/issues/2234)
This commit is contained in:
Tianhe Y 2023-03-31 13:44:00 +08:00 committed by sbwml
parent eadb44a03a
commit ee7ded80e5
7 changed files with 363 additions and 240 deletions

View File

@ -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:value("0", translate("Switch it"))
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"))

View File

@ -100,74 +100,106 @@ if current_node and current_node ~= "" and current_node ~= "nil" then
end
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
local normal_list = {}
local shunt_list = {}
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
end
if v.protocol and v.protocol == "_shunt" then
shunt_list[#shunt_list + 1] = v
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
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)
local id = e[".name"]
local node_option = vid .. "-" .. id .. "_node"
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:value("nil", translate("Close"))
o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection"))
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
o:value(v1.id, v1["remark"])
o:value(v1.id, v1.remark)
if v1.protocol ~= "_balancing" then
pt:depends(node_option, v1.id)
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
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)
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:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
for k1, v1 in pairs(normal_list) do
o:value(v1.id, v1["remark"])
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
o.cfgvalue = get_cfgvalue(v.id, id)
o.write = get_write(v.id, id)
local id = "main_node"
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:depends("tcp_node", v.id)
o:value("nil", translate("Close"))
local id = "default_proxy_tag"
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."))
for k1, v1 in pairs(normal_list) do
o:value(v1.id, v1["remark"])
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)
if v1.protocol ~= "_balancing" then
o:depends(vid .. "-default_node", v1.id)
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
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.default = 1070

View File

@ -133,9 +133,10 @@ iface:depends("protocol", "_iface")
local nodes_table = {}
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] = {
id = e[".name"],
protocol = e["protocol"],
remarks = e["remark"]
}
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>"))
for k, v in pairs(nodes_table) do balancing_node:value(v.id, v.remarks) end
balancing_node:depends("protocol", "_balancing")
local balancingStrategy = s:option(ListValue, "balancingStrategy", translate("Balancing Strategy"))
balancingStrategy:depends("protocol", "_balancing")
balancingStrategy:value("random")
balancingStrategy:value("leastPing")
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"))
probeInterval:depends("balancingStrategy", "leastPing")
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.")
-- 分流
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)
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))
@ -166,15 +189,15 @@ uci:foreach(appname, "shunt_rules", function(e)
o:depends("protocol", "_shunt")
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")))
_proxy_tag:value("nil", translate("Close"))
_proxy_tag:value("default", translate("Default"))
_proxy_tag:value("main", translate("Default Preproxy"))
_proxy_tag.default = "nil"
local pt = s:option(ListValue, e[".name"] .. "_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 k, v in pairs(nodes_table) do
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
@ -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")
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."))
o:value("nil", translate("Close"))
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."))
dpt:value("nil", translate("Close"))
dpt:value("main", translate("Preproxy Node"))
dpt.default = "nil"
for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
o:depends("default_node", v.id)
if v.protocol ~= "_balancing" then
dpt:depends("default_node", v.id)
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:value("AsIs")

View File

@ -215,7 +215,7 @@ local function stop()
ip6t("-F PSW-SERVER 2>/dev/null")
ip6t("-X PSW-SERVER 2>/dev/null")
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 flush chain inet fw4 PSW-SERVER 2>/dev/null")
cmd("nft delete chain inet fw4 PSW-SERVER 2>/dev/null")

View File

@ -91,8 +91,7 @@ function gen_outbound(flag, node, tag, proxy_table)
config_file, --config file
(proxy == 1 and relay_port) and tostring(relay_port) or "" --relay port
)
)
)
))
node = {}
node.protocol = "socks"
node.transport = "tcp"
@ -596,96 +595,124 @@ function gen_config(var)
end
end
if node.protocol == "_shunt" then
local rules = {}
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
local function get_balancer_tag(_node_id)
return "balancer-" .. _node_id:sub(1, 8)
end
uci:foreach(appname, "shunt_rules", function(e)
local name = e[".name"]
if name and e.remarks then
local _node_id = node[name] or "nil"
local proxy_tag = node[name .. "_proxy_tag"] or "nil"
local outboundTag
if _node_id == "_direct" then
outboundTag = "direct"
elseif _node_id == "_blackhole" then
outboundTag = "blackhole"
elseif _node_id == "_default" then
outboundTag = "default"
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)
local function gen_balancer(_node, loopbackTag)
local blc_nodes = _node.balancing_node
local length = #blc_nodes
local valid_nodes = {}
for i = 1, length do
local blc_node_id = blc_nodes[i]
local blc_node_tag = "blc-" .. blc_node_id:sub(1, 8)
local is_new_blc_node = true
for _, outbound in ipairs(outbounds) do
if outbound.tag == blc_node_tag then
is_new_blc_node = false
valid_nodes[#valid_nodes + 1] = blc_node_tag
break
end
end
if new_outbound then
new_outbound["tag"] = name
table.insert(outbounds, new_outbound)
outboundTag = name
if is_new_blc_node then
local blc_node = uci:get_all(appname, blc_node_id)
local outbound = gen_outbound(flag, blc_node, blc_node_tag)
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
if proxy_tag ~= "nil" then
local pre_proxy = nil
if _node.type ~= "V2ray" and _node.type ~= "Xray" then
pre_proxy = true
@ -694,10 +721,9 @@ function gen_config(var)
pre_proxy = true
end
if pre_proxy then
if proxy_tag ~= "nil" then
new_port = get_new_port()
table.insert(inbounds, {
tag = "proxy_" .. name,
tag = "proxy_" .. rule_name,
listen = "127.0.0.1",
port = new_port,
protocol = "dokodemo-door",
@ -710,21 +736,69 @@ function gen_config(var)
_node.port = new_port
table.insert(rules, 1, {
type = "field",
inboundTag = {"proxy_" .. name},
outboundTag = proxy_tag
inboundTag = {"proxy_" .. rule_name},
outboundTag = is_balancing_proxy and nil or proxy_tag,
balancerTag = is_balancing_proxy and get_balancer_tag(proxy_node_id) or nil
})
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
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生成等效OutboundTagloopback + 规则路由至)的代码,可能用上
--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
return rule_outboundTag, rule_balancerTag
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
outboundTag = default_outboundTag
end
@ -735,45 +809,36 @@ function gen_config(var)
table.insert(protocols, w)
end)
end
local _domain = nil
if e.domain_list then
local _domain = {}
_domain = {}
string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w)
table.insert(_domain, w)
end)
table.insert(rules, {
type = "field",
outboundTag = outboundTag,
domain = _domain,
protocol = protocols
})
end
local _ip = nil
if e.ip_list then
local _ip = {}
_ip = {}
string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w)
table.insert(_ip, w)
end)
end
table.insert(rules, {
type = "field",
outboundTag = outboundTag,
balancerTag = balancerTag,
domain = _domain,
ip = _ip,
protocol = protocols
})
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)
if default_outboundTag then
if default_outboundTag or default_balancerTag then
table.insert(rules, {
type = "field",
outboundTag = default_outboundTag,
balancerTag = default_balancerTag,
network = "tcp,udp"
})
end
@ -781,31 +846,16 @@ function gen_config(var)
routing = {
domainStrategy = node.domainStrategy or "AsIs",
domainMatcher = node.domainMatcher or "hybrid",
balancers = #balancers > 0 and balancers or nil,
rules = rules
}
elseif node.protocol == "_balancing" then
if node.balancing_node then
local nodes = node.balancing_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
local balancer = gen_balancer(node)
routing = {
balancers = {{
tag = "balancer",
selector = nodes,
strategy = {type = node.balancingStrategy or "random"}
}},
balancers = { balancer },
rules = {
{type = "field", network = "tcp,udp", balancerTag = "balancer"}
{ type = "field", network = "tcp,udp", balancerTag = balancer.tag }
}
}
end

View File

@ -352,6 +352,18 @@ msgstr "V2ray 负载均衡"
msgid "Balancing Strategy"
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"
msgstr "探测间隔"
@ -370,6 +382,12 @@ msgstr "V2ray 分流"
msgid "Preproxy"
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"
msgstr "直连"
@ -661,8 +679,8 @@ msgstr "切掉它"
msgid "Applying to the default node"
msgstr "应用于默认节点"
msgid "Applying to the default preproxy node"
msgstr "应用于默认前置节点"
msgid "Applying to the preproxy node"
msgstr "应用于前置代理节点"
msgid "Add nodes to the standby node list by keywords"
msgstr "通过关键字添加节点到备用节点列表"