update 2023-03-31 16:22:05
This commit is contained in:
parent
a84d617d3a
commit
43d8292cb6
|
@ -6,8 +6,8 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=4.61
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=4.62
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
|
||||
|
|
|
@ -15,7 +15,7 @@ local k, v
|
|||
local com = require "luci.passwall.com"
|
||||
for k, v in pairs(com) do
|
||||
o = s:option(Value, k:gsub("%-","_") .. "_file", translatef("%s App Path", v.name))
|
||||
o.default = v.default_path or ("/usr/bin/"..k)
|
||||
o.default = v.default_path or ("/usr/bin/" .. k)
|
||||
o.rmempty = false
|
||||
end
|
||||
|
||||
|
|
|
@ -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"))
|
||||
|
||||
|
|
|
@ -100,75 +100,107 @@ 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"])
|
||||
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)
|
||||
o:value(v1.id, v1.remark)
|
||||
if v1.protocol ~= "_balancing" then
|
||||
pt:depends(node_option, v1.id)
|
||||
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)
|
||||
|
||||
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
|
||||
tcp_node_socks_port.datatype = "port"
|
||||
|
|
|
@ -45,11 +45,29 @@ o = s:option(Value, "console_port", translate("Console Port"), translate(
|
|||
o.default = "1188"
|
||||
o:depends("balancing_enable", true)
|
||||
|
||||
---- Health Check Type
|
||||
o = s:option(ListValue, "health_check_type", translate("Health Check Type"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("passwall_logic", translate("Availability test") .. string.format("(passwall %s)", translate("Inner implement")))
|
||||
o:depends("balancing_enable", true)
|
||||
|
||||
---- Health Check Inter
|
||||
o = s:option(Value, "health_check_inter", translate("Health Check Inter"), translate("Units:seconds"))
|
||||
o.default = "10"
|
||||
o:depends("balancing_enable", true)
|
||||
|
||||
o = s:option(DummyValue, "health_check_tips", " ")
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
return string.format('<span style="color: red">%s</span>', translate("When the availability test is used, the load balancing node will be converted into a Socks node. when node list set customizing, must be a Socks node, otherwise the health check will be invalid."))
|
||||
end
|
||||
o:depends("health_check_type", "passwall_logic")
|
||||
|
||||
-- [[ Balancing Settings ]]--
|
||||
s = m:section(TypedSection, "haproxy_config", "",
|
||||
"<font color='red'>" ..
|
||||
translate("Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group.") ..
|
||||
"\n" .. translate("Note that the node configuration parameters for load balancing must be consistent, otherwise problems can arise!") ..
|
||||
"\n" .. translate("Note that the node configuration parameters for load balancing must be consistent when use TCP health check type, otherwise it cannot be used normally!") ..
|
||||
"</font>")
|
||||
s.template = "cbi/tblsection"
|
||||
s.sortable = true
|
||||
|
|
|
@ -46,7 +46,7 @@ local x_ss_encrypt_method_list = {
|
|||
"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"
|
||||
}
|
||||
|
||||
local security_list = {"none", "auto", "aes-128-gcm", "chacha20-poly1305", "zero"}
|
||||
local security_list = { "none", "auto", "aes-128-gcm", "chacha20-poly1305", "zero" }
|
||||
|
||||
local header_type_list = {
|
||||
"none", "srtp", "utp", "wechat-video", "dtls", "wireguard"
|
||||
|
@ -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,26 +217,26 @@ 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")
|
||||
domainStrategy:value("IPIfNonMatch")
|
||||
domainStrategy:value("IPOnDemand")
|
||||
domainStrategy.default = "IPOnDemand"
|
||||
domainStrategy.description = "<br /><ul><li>" .. translate("'AsIs': Only use domain for routing. Default value.")
|
||||
.. "</li><li>" .. translate("'IPIfNonMatch': When no rule matches current domain, resolves it into IP addresses (A or AAAA records) and try all rules again.")
|
||||
.. "</li><li>" .. translate("'IPOnDemand': As long as there is a IP-based rule, resolves the domain into IP immediately.")
|
||||
.. "</li></ul>"
|
||||
.. "</li><li>" .. translate("'IPIfNonMatch': When no rule matches current domain, resolves it into IP addresses (A or AAAA records) and try all rules again.")
|
||||
.. "</li><li>" .. translate("'IPOnDemand': As long as there is a IP-based rule, resolves the domain into IP immediately.")
|
||||
.. "</li></ul>"
|
||||
domainStrategy:depends("protocol", "_shunt")
|
||||
|
||||
domainMatcher = s:option(ListValue, "domainMatcher", translate("Domain matcher"))
|
||||
|
@ -808,7 +831,7 @@ h2_path:depends("transport", "h2")
|
|||
h2_path:depends("ss_transport", "h2")
|
||||
|
||||
h2_health_check = s:option(Flag, "h2_health_check", translate("Health check"))
|
||||
h2_health_check:depends({ type = "Xray", transport = "h2"})
|
||||
h2_health_check:depends({ type = "Xray", transport = "h2" })
|
||||
|
||||
h2_read_idle_timeout = s:option(Value, "h2_read_idle_timeout", translate("Idle timeout"))
|
||||
h2_read_idle_timeout.default = "10"
|
||||
|
@ -843,10 +866,10 @@ grpc_serviceName:depends("transport", "grpc")
|
|||
grpc_mode = s:option(ListValue, "grpc_mode", "gRPC " .. translate("Transfer mode"))
|
||||
grpc_mode:value("gun")
|
||||
grpc_mode:value("multi")
|
||||
grpc_mode:depends({ type = "Xray", transport = "grpc"})
|
||||
grpc_mode:depends({ type = "Xray", transport = "grpc" })
|
||||
|
||||
grpc_health_check = s:option(Flag, "grpc_health_check", translate("Health check"))
|
||||
grpc_health_check:depends({ type = "Xray", transport = "grpc"})
|
||||
grpc_health_check:depends({ type = "Xray", transport = "grpc" })
|
||||
|
||||
grpc_idle_timeout = s:option(Value, "grpc_idle_timeout", translate("Idle timeout"))
|
||||
grpc_idle_timeout.default = "10"
|
||||
|
@ -862,7 +885,7 @@ grpc_permit_without_stream:depends("grpc_health_check", true)
|
|||
|
||||
grpc_initial_windows_size = s:option(Value, "grpc_initial_windows_size", translate("Initial Windows Size"))
|
||||
grpc_initial_windows_size.default = "0"
|
||||
grpc_initial_windows_size:depends({ type = "Xray", transport = "grpc"})
|
||||
grpc_initial_windows_size:depends({ type = "Xray", transport = "grpc" })
|
||||
|
||||
-- [[ Trojan-Go Shadowsocks2 ]] --
|
||||
ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks secondary encryption"))
|
||||
|
@ -932,6 +955,9 @@ hysteria_hop_interval:depends("type", "Hysteria")
|
|||
hysteria_disable_mtu_discovery = s:option(Flag, "hysteria_disable_mtu_discovery", translate("Disable MTU detection"))
|
||||
hysteria_disable_mtu_discovery:depends("type", "Hysteria")
|
||||
|
||||
hysteria_lazy_start = s:option(Flag, "hysteria_lazy_start", translate("Lazy Start"))
|
||||
hysteria_lazy_start:depends("type", "Hysteria")
|
||||
|
||||
protocol.validate = function(self, value)
|
||||
if value == "_shunt" or value == "_balancing" then
|
||||
address.rmempty = true
|
||||
|
|
|
@ -44,14 +44,14 @@ local function ln_run(s, d, command, output)
|
|||
end
|
||||
d = TMP_BIN_PATH .. "/" .. d
|
||||
cmd(string.format('[ ! -f "%s" ] && ln -s %s %s 2>/dev/null', d, s, d))
|
||||
return string.format("%s >%s 2>&1 &", d .. " " ..command, output)
|
||||
return string.format("%s >%s 2>&1 &", d .. " " .. command, output)
|
||||
end
|
||||
|
||||
local function gen_include()
|
||||
cmd(string.format("echo '#!/bin/sh' > /tmp/etc/%s.include", CONFIG))
|
||||
if nft_flag == "1" then
|
||||
cmd("echo \"\" > " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft")
|
||||
local nft_cmd="for chain in $(nft -a list chains |grep -E \"chain PSW-SERVER\" |awk -F ' ' '{print$2}'); do\n nft list chain inet fw4 ${chain} >> " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft\n done"
|
||||
local nft_cmd = "for chain in $(nft -a list chains |grep -E \"chain PSW-SERVER\" |awk -F ' ' '{print$2}'); do\n nft list chain inet fw4 ${chain} >> " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft\n done"
|
||||
cmd(nft_cmd)
|
||||
end
|
||||
local function extract_rules(n, a)
|
||||
|
@ -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")
|
||||
|
|
|
@ -77,6 +77,7 @@ function gen_config(var)
|
|||
hop_interval = (node.hysteria_hop_interval) and tonumber(node.hysteria_hop_interval) or nil,
|
||||
disable_mtu_discovery = (node.hysteria_disable_mtu_discovery) and true or false,
|
||||
fast_open = (node.fast_open == "1") and true or false,
|
||||
lazy_start = (node.hysteria_lazy_start) and true or false,
|
||||
socks5 = (local_socks_address and local_socks_port) and {
|
||||
listen = local_socks_address .. ":" .. local_socks_port,
|
||||
timeout = 300,
|
||||
|
|
|
@ -90,9 +90,8 @@ function gen_outbound(flag, node, tag, proxy_table)
|
|||
new_port, --socks port
|
||||
config_file, --config file
|
||||
(proxy == 1 and relay_port) and tostring(relay_port) or "" --relay port
|
||||
)
|
||||
)
|
||||
)
|
||||
))
|
||||
node = {}
|
||||
node.protocol = "socks"
|
||||
node.transport = "tcp"
|
||||
|
@ -257,7 +256,7 @@ function gen_config_server(node)
|
|||
local settings = nil
|
||||
local routing = nil
|
||||
local outbounds = {
|
||||
{protocol = "freedom", tag = "direct"}, {protocol = "blackhole", tag = "blocked"}
|
||||
{ protocol = "freedom", tag = "direct" }, { protocol = "blackhole", tag = "blocked" }
|
||||
}
|
||||
|
||||
if node.protocol == "vmess" or node.protocol == "vless" then
|
||||
|
@ -596,184 +595,250 @@ function gen_config(var)
|
|||
end
|
||||
end
|
||||
|
||||
if node.protocol == "_shunt" then
|
||||
local rules = {}
|
||||
local function get_balancer_tag(_node_id)
|
||||
return "balancer-" .. _node_id:sub(1, 8)
|
||||
end
|
||||
|
||||
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
|
||||
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 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"
|
||||
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
|
||||
|
||||
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)
|
||||
break
|
||||
end
|
||||
end
|
||||
if new_outbound then
|
||||
new_outbound["tag"] = name
|
||||
table.insert(outbounds, new_outbound)
|
||||
outboundTag = name
|
||||
else
|
||||
local pre_proxy = nil
|
||||
if _node.type ~= "V2ray" and _node.type ~= "Xray" then
|
||||
pre_proxy = true
|
||||
end
|
||||
if _node.type == "Xray" and _node.tlsflow == "xtls-rprx-vision" then
|
||||
pre_proxy = true
|
||||
end
|
||||
if pre_proxy then
|
||||
if proxy_tag ~= "nil" then
|
||||
new_port = get_new_port()
|
||||
table.insert(inbounds, {
|
||||
tag = "proxy_" .. name,
|
||||
listen = "127.0.0.1",
|
||||
port = new_port,
|
||||
protocol = "dokodemo-door",
|
||||
settings = {network = "tcp,udp", address = _node.address, port = tonumber(_node.port)}
|
||||
})
|
||||
if _node.tls_serverName == nil then
|
||||
_node.tls_serverName = _node.address
|
||||
end
|
||||
_node.address = "127.0.0.1"
|
||||
_node.port = new_port
|
||||
table.insert(rules, 1, {
|
||||
type = "field",
|
||||
inboundTag = {"proxy_" .. name},
|
||||
outboundTag = proxy_tag
|
||||
})
|
||||
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 })
|
||||
if _outbound then
|
||||
table.insert(outbounds, _outbound)
|
||||
outboundTag = name
|
||||
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
|
||||
end
|
||||
if outboundTag then
|
||||
if outboundTag == "default" then
|
||||
outboundTag = default_outboundTag
|
||||
|
||||
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
|
||||
local protocols = nil
|
||||
if e["protocol"] and e["protocol"] ~= "" then
|
||||
protocols = {}
|
||||
string.gsub(e["protocol"], '[^' .. " " .. ']+', function(w)
|
||||
table.insert(protocols, w)
|
||||
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
|
||||
end
|
||||
if _node.type == "Xray" and _node.tlsflow == "xtls-rprx-vision" then
|
||||
pre_proxy = true
|
||||
end
|
||||
if pre_proxy then
|
||||
new_port = get_new_port()
|
||||
table.insert(inbounds, {
|
||||
tag = "proxy_" .. rule_name,
|
||||
listen = "127.0.0.1",
|
||||
port = new_port,
|
||||
protocol = "dokodemo-door",
|
||||
settings = {network = "tcp,udp", address = _node.address, port = tonumber(_node.port)}
|
||||
})
|
||||
if _node.tls_serverName == nil then
|
||||
_node.tls_serverName = _node.address
|
||||
end
|
||||
_node.address = "127.0.0.1"
|
||||
_node.port = new_port
|
||||
table.insert(rules, 1, {
|
||||
type = "field",
|
||||
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, 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)
|
||||
if proxy_tag == preproxy_tag then preproxy_used = true end
|
||||
rule_outboundTag = rule_name
|
||||
end
|
||||
end
|
||||
if e.domain_list then
|
||||
local _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
|
||||
})
|
||||
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 e.ip_list then
|
||||
local _ip = {}
|
||||
string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||
table.insert(_ip, w)
|
||||
end)
|
||||
table.insert(rules, {
|
||||
type = "field",
|
||||
outboundTag = outboundTag,
|
||||
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
|
||||
})
|
||||
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
|
||||
return rule_outboundTag, rule_balancerTag
|
||||
end
|
||||
|
||||
--[[此处只要前置代理设置选择了节点,即使全部规则都没使用,仍会先尝试生成,生成有效配置才真正开启功能,会造成配置文件里面会有多余未使用的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
|
||||
local protocols = nil
|
||||
if e["protocol"] and e["protocol"] ~= "" then
|
||||
protocols = {}
|
||||
string.gsub(e["protocol"], '[^' .. " " .. ']+', function(w)
|
||||
table.insert(protocols, w)
|
||||
end)
|
||||
end
|
||||
local _domain = nil
|
||||
if e.domain_list then
|
||||
_domain = {}
|
||||
string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||
table.insert(_domain, w)
|
||||
end)
|
||||
end
|
||||
local _ip = nil
|
||||
if e.ip_list then
|
||||
_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
|
||||
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
|
||||
|
|
|
@ -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 "直连"
|
||||
|
||||
|
@ -490,6 +508,9 @@ msgstr "QUIC 连接接收窗口"
|
|||
msgid "Disable MTU detection"
|
||||
msgstr "禁用 MTU 检测"
|
||||
|
||||
msgid "Lazy Start"
|
||||
msgstr "延迟启动"
|
||||
|
||||
msgid "Encrypt Method"
|
||||
msgstr "加密"
|
||||
|
||||
|
@ -658,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 "通过关键字添加节点到备用节点列表"
|
||||
|
@ -691,11 +712,23 @@ msgstr "在浏览器输入路由IP加端口访问,如:192.168.1.1:1188"
|
|||
msgid "Haproxy Port"
|
||||
msgstr "负载均衡端口"
|
||||
|
||||
msgid "Health Check Type"
|
||||
msgstr "健康检查类型"
|
||||
|
||||
msgid "Inner implement"
|
||||
msgstr "内置实现"
|
||||
|
||||
msgid "Health Check Inter"
|
||||
msgstr "健康检查节点间隔时间"
|
||||
|
||||
msgid "When the availability test is used, the load balancing node will be converted into a Socks node. when node list set customizing, must be a Socks node, otherwise the health check will be invalid."
|
||||
msgstr "当使用可用性测试时,负载均衡节点将转换成Socks节点。下面的节点列表自定义时必须为Socks节点,否则健康检查将无效。"
|
||||
|
||||
msgid "Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group."
|
||||
msgstr "添加节点,指定出口功能是为多WAN用户准备的。负载比重范围1-256。多个主服务器可以负载均衡,备用只有在主服务器离线时才会启用!可以设置多个组,负载均衡端口相同则为一组。"
|
||||
|
||||
msgid "Note that the node configuration parameters for load balancing must be consistent, otherwise problems can arise!"
|
||||
msgstr "注意,负载均衡的节点配置参数必须一致,否则会出问题!"
|
||||
msgid "Note that the node configuration parameters for load balancing must be consistent when use TCP health check type, otherwise it cannot be used normally!"
|
||||
msgstr "注意,当使用TCP健康检查时负载均衡的节点配置参数必须一致,否则无法正常使用!"
|
||||
|
||||
msgid "Node"
|
||||
msgstr "节点"
|
||||
|
|
|
@ -17,10 +17,24 @@ function get_ip_port_from(str)
|
|||
return result_ip, result_port
|
||||
end
|
||||
|
||||
local new_port
|
||||
local function get_new_port()
|
||||
if new_port then
|
||||
new_port = tonumber(sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port %s tcp)", appname, new_port + 1)))
|
||||
else
|
||||
new_port = tonumber(sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port auto tcp)", appname)))
|
||||
end
|
||||
return new_port
|
||||
end
|
||||
|
||||
local var = api.get_args(arg)
|
||||
local haproxy_path = var["-path"]
|
||||
local haproxy_conf = var["-conf"]
|
||||
|
||||
local health_check_type = uci:get(appname, "@global_haproxy[0]", "health_check_type") or "tcp"
|
||||
local health_check_inter = uci:get(appname, "@global_haproxy[0]", "health_check_inter") or "10"
|
||||
health_check_inter = tonumber(health_check_inter) * 1000
|
||||
|
||||
log("HAPROXY 负载均衡...")
|
||||
fs.mkdir(haproxy_path)
|
||||
local haproxy_file = haproxy_path .. "/" .. haproxy_conf
|
||||
|
@ -30,9 +44,9 @@ local f_out = io.open(haproxy_file, "a")
|
|||
local haproxy_config = [[
|
||||
global
|
||||
log 127.0.0.1 local2
|
||||
chroot %s
|
||||
maxconn 60000
|
||||
stats socket %s/haproxy.sock
|
||||
%s
|
||||
daemon
|
||||
|
||||
defaults
|
||||
|
@ -57,31 +71,59 @@ resolvers mydns
|
|||
nameserver dns1 127.0.0.1:53
|
||||
resolve_retries 3
|
||||
timeout retry 3s
|
||||
hold valid 10s
|
||||
hold valid 30s
|
||||
|
||||
]]
|
||||
|
||||
f_out:write(string.format(haproxy_config, haproxy_path, haproxy_path))
|
||||
f_out:write(string.format(haproxy_config, haproxy_path, health_check_type == "passwall_logic" and string.format([[
|
||||
external-check
|
||||
insecure-fork-wanted
|
||||
]]) or ""
|
||||
))
|
||||
|
||||
local listens = {}
|
||||
|
||||
uci:foreach(appname, "haproxy_config", function(t)
|
||||
if t.enabled == "1" then
|
||||
local server_remark
|
||||
local server_address
|
||||
local server_port
|
||||
local lbss = t.lbss
|
||||
local listen_port = tonumber(t.haproxy_port) or 0
|
||||
local server_node = uci:get_all(appname, lbss)
|
||||
if server_node and server_node.address and server_node.port then
|
||||
server_remark = server_node.address .. ":" .. server_node.port
|
||||
server_address = server_node.address
|
||||
server_port = server_node.port
|
||||
if health_check_type == "passwall_logic" then
|
||||
if server_node.type ~= "Socks" then
|
||||
local relay_port = server_node.port
|
||||
new_port = get_new_port()
|
||||
local config_file = string.format("haproxy_%s_%s.json", t[".name"], new_port)
|
||||
sys.call(string.format('/usr/share/%s/app.sh run_socks "%s"> /dev/null',
|
||||
appname,
|
||||
string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s",
|
||||
new_port, --flag
|
||||
server_node[".name"], --node
|
||||
"127.0.0.1", --bind
|
||||
new_port, --socks port
|
||||
config_file --config file
|
||||
)
|
||||
)
|
||||
)
|
||||
server_address = "127.0.0.1"
|
||||
server_port = new_port
|
||||
end
|
||||
end
|
||||
else
|
||||
server_address, server_port = get_ip_port_from(lbss)
|
||||
server_remark = server_address .. ":" .. server_port
|
||||
end
|
||||
if server_address and server_port and listen_port > 0 then
|
||||
if not listens[listen_port] then
|
||||
listens[listen_port] = {}
|
||||
end
|
||||
t.server_remark = server_remark
|
||||
t.server_address = server_address
|
||||
t.server_port = server_port
|
||||
table.insert(listens[listen_port], t)
|
||||
|
@ -109,12 +151,19 @@ listen %s
|
|||
balance roundrobin
|
||||
]], port, port))
|
||||
|
||||
for i, o in ipairs(listens[port]) do
|
||||
local server = o.server_address .. ":" .. o.server_port
|
||||
local remark = server:gsub("%[", ""):gsub("%]", "")
|
||||
if health_check_type == "passwall_logic" then
|
||||
f_out:write(string.format([[
|
||||
server %s %s weight %s check resolvers mydns inter 1500 rise 1 fall 3 %s
|
||||
]], remark, server, o.lbweight, o.backup == "1" and "backup" or ""))
|
||||
option external-check
|
||||
external-check command "/usr/share/passwall/haproxy_check.sh"
|
||||
]], port, port))
|
||||
end
|
||||
|
||||
for i, o in ipairs(listens[port]) do
|
||||
local remark = o.server_remark
|
||||
local server = o.server_address .. ":" .. o.server_port
|
||||
f_out:write(string.format([[
|
||||
server %s %s weight %s check resolvers mydns inter %s rise 1 fall 3 %s
|
||||
]], remark, server, o.lbweight, health_check_inter, o.backup == "1" and "backup" or ""))
|
||||
|
||||
if o.export ~= "0" then
|
||||
sys.call(string.format("/usr/share/passwall/app.sh add_ip2route %s %s", o.server_address, o.export))
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
listen_address=$1
|
||||
listen_port=$2
|
||||
server_address=$3
|
||||
server_port=$4
|
||||
status=$(/usr/bin/curl -I -o /dev/null -skL -x socks5h://${server_address}:${server_port} --connect-timeout 3 --retry 3 -w %{http_code} "https://www.google.com/generate_204")
|
||||
case "$status" in
|
||||
204|\
|
||||
200)
|
||||
status=200
|
||||
;;
|
||||
esac
|
||||
return_code=1
|
||||
if [ "$status" = "200" ]; then
|
||||
return_code=0
|
||||
fi
|
||||
exit ${return_code}
|
Loading…
Reference in New Issue