diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua index 6140f7bcb..9f0868a80 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua @@ -49,7 +49,9 @@ o:depends({ [option_name("protocol")] = "_iface" }) local nodes_table = {} local balancers_table = {} +local fallback_table = {} local iface_table = {} +local is_balancer = nil for k, e in ipairs(api.get_valid_nodes()) do if e.node_type == "normal" then nodes_table[#nodes_table + 1] = { @@ -63,6 +65,15 @@ for k, e in ipairs(api.get_valid_nodes()) do id = e[".name"], remark = e["remark"] } + if e[".name"] ~= arg[1] then + fallback_table[#fallback_table + 1] = { + id = e[".name"], + remark = e["remark"], + fallback = e["fallback_node"] + } + else + is_balancer = true + end end if e.protocol == "_iface" then iface_table[#iface_table + 1] = { @@ -90,23 +101,35 @@ for k, v in pairs(nodes_table) do o:value(v.id, v.remark) end local o = s:option(ListValue, option_name("balancingStrategy"), translate("Balancing Strategy")) o:depends({ [option_name("protocol")] = "_balancing" }) o:value("random") +o:value("roundRobin") o:value("leastPing") -o:value("leastLoad") -o.default = "leastLoad" +o.default = "leastPing" -- Fallback Node if api.compare_versions(api.get_app_version("xray"), ">=", "1.8.10") then local o = s:option(ListValue, option_name("fallback_node"), translate("Fallback Node")) - o:depends({ [option_name("protocol")] = "_balancing" }) + o:depends({ [option_name("balancingStrategy")] = "leastPing" }) o:value("",translate("Null")) o.default = "" + local function check_fallback_chain(fb) + for k, v in pairs(fallback_table) do + if v.fallback == fb then + fallback_table[k] = nil + check_fallback_chain(v.id) + end + end + end + -- 检查fallback链,去掉会形成闭环的balancer节点 + if is_balancer then + check_fallback_chain(arg[1]) + end + for k, v in pairs(fallback_table) do o:value(v.id, v.remark) end for k, v in pairs(nodes_table) do o:value(v.id, v.remark) end end -- 探测地址 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")] = "leastLoad" }) local o = s:option(Value, option_name("probeUrl"), translate("Probe URL")) o:depends({ [option_name("useCustomProbeUrl")] = true }) @@ -116,7 +139,6 @@ o.description = translate("The URL used to detect the connection status.") -- 探测间隔 local o = s:option(Value, option_name("probeInterval"), translate("Probe Interval")) o:depends({ [option_name("balancingStrategy")] = "leastPing" }) -o:depends({ [option_name("balancingStrategy")] = "leastLoad" }) 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 ns, us, ms, s, m, h, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.") diff --git a/luci-app-passwall/luasrc/passwall/util_xray.lua b/luci-app-passwall/luasrc/passwall/util_xray.lua index 9c1e13541..7121f2fb4 100644 --- a/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -564,6 +564,8 @@ function gen_config(var) if node_id then local node = uci:get_all(appname, node_id) + local balancers = {} + local rules = {} if node then if server_host and server_port then node.address = server_host @@ -682,25 +684,32 @@ function gen_config(var) end if is_new_node then local fallback_node = uci:get_all(appname, fallback_node_id) - local outbound = gen_outbound(flag, fallback_node, fallback_node_id, { fragment = xray_settings.fragment == "1" or nil }) - if outbound then - table.insert(outbounds, outbound) + if fallback_node.protocol ~= "_balancing" then + local outbound = gen_outbound(flag, fallback_node, fallback_node_id, { fragment = xray_settings.fragment == "1" or nil }) + if outbound then + table.insert(outbounds, outbound) + else + fallback_node_id = nil + end else - fallback_node_id = nil + local valid = gen_balancer(fallback_node) + if not valid then + fallback_node_id = nil + end end end end - local balancer, rule + local valid = nil if #valid_nodes > 0 then local balancerTag = get_balancer_tag(_node[".name"]) - balancer = { + table.insert(balancers, { tag = balancerTag, selector = valid_nodes, fallbackTag = fallback_node_id, strategy = { type = _node.balancingStrategy or "random" } - } - if _node.balancingStrategy == "leastPing" or _node.balancingStrategy == "leastLoad" then + }) + if _node.balancingStrategy == "leastPing" then if not observatory then observatory = { subjectSelector = { "blc-" }, @@ -717,13 +726,10 @@ function gen_config(var) tag = loopbackTag, settings = { inboundTag = inboundTag } }) - rule = { - type = "field", - inboundTag = { inboundTag }, - balancerTag = balancerTag - } + table.insert(rules, { type = "field", inboundTag = { inboundTag }, balancerTag = balancerTag }) + valid = true end - return balancer, rule + return valid end local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name) @@ -755,9 +761,6 @@ function gen_config(var) end if node.protocol == "_shunt" then - local rules = {} - local balancers = {} - local preproxy_enabled = node.preproxy_enabled == "1" local preproxy_tag = "main" local preproxy_node_id = node["main_node"] @@ -793,11 +796,8 @@ function gen_config(var) end elseif preproxy_node and preproxy_node.protocol == "_balancing" then preproxy_is_balancer = true - 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) - else + local valid = gen_balancer(preproxy_node, preproxy_tag) + if not valid then preproxy_enabled = false end end @@ -913,11 +913,9 @@ function gen_config(var) end end if is_new_balancer then - local balancer, rule = gen_balancer(_node) - if balancer then - table.insert(balancers, balancer) - table.insert(rules, rule) - rule_balancerTag = balancer.tag + local valid = gen_balancer(_node) + if valid then + rule_balancerTag = get_balancer_tag(_node_id) end end elseif _node.protocol == "_iface" then @@ -1043,13 +1041,13 @@ function gen_config(var) } elseif node.protocol == "_balancing" then if node.balancing_node then - local balancer, rule = gen_balancer(node) + local valid = gen_balancer(node) + if valid then + table.insert(rules, { type = "field", network = "tcp,udp", balancerTag = get_balancer_tag(node_id) }) + end routing = { - balancers = { balancer }, - rules = { - { type = "field", network = "tcp,udp", balancerTag = balancer.tag }, - rule - } + balancers = balancers, + rules = rules } end elseif node.protocol == "_iface" then