mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-07-30 02:31:47 +08:00
update 2026-05-18 23:19:08
This commit is contained in:
parent
e6696f2057
commit
53eda83da8
@ -262,6 +262,13 @@ if load_balancing_options then -- [[ Load balancing Start ]]
|
||||
o.default = "2"
|
||||
o.placeholder = "2"
|
||||
o.description = translate("The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them.")
|
||||
|
||||
o = s:option(Value, _n("tolerance"), translate("Failure Tolerance (%)"))
|
||||
o:depends({ [_n("balancingStrategy")] = "leastLoad" })
|
||||
o.datatype = "uinteger"
|
||||
o.default = "10"
|
||||
o.placeholder = "10"
|
||||
o.description = translate("The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate.")
|
||||
end -- [[ 负载均衡 End ]]
|
||||
|
||||
if load_iface_options then -- [[ 自定义接口 Start ]]
|
||||
|
||||
@ -1072,7 +1072,13 @@ function gen_config(var)
|
||||
type = _node.balancingStrategy,
|
||||
settings = {
|
||||
expected = _node.expected and tonumber(_node.expected) and tonumber(_node.expected) or 2,
|
||||
maxRTT = "1s"
|
||||
maxRTT = "1s",
|
||||
tolerance = (function(t)
|
||||
t = tonumber(t) or 0
|
||||
if t < 1 then return nil end
|
||||
if t > 100 then t = 100 end
|
||||
return t / 100
|
||||
end)(_node.tolerance)
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@ -535,6 +535,12 @@ msgstr "优选节点数量"
|
||||
msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them."
|
||||
msgstr "负载均衡器选出最优节点的个数,流量将在这几个节点中随机分配。"
|
||||
|
||||
msgid "Failure Tolerance (%)"
|
||||
msgstr "测速失败率容忍度(%)"
|
||||
|
||||
msgid "The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate."
|
||||
msgstr "最多可接受的测速失败率,例如 1 表示允许 1% 的测速失败率。"
|
||||
|
||||
msgid "Shunt"
|
||||
msgstr "分流"
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall2
|
||||
PKG_VERSION:=26.5.1
|
||||
PKG_VERSION:=26.5.18
|
||||
PKG_RELEASE:=1
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ function index()
|
||||
entry({"admin", "services", appname, "socks_config"}, cbi(appname .. "/client/socks_config")).leaf = true
|
||||
entry({"admin", "services", appname, "acl"}, cbi(appname .. "/client/acl"), _("Access control"), 98).leaf = true
|
||||
entry({"admin", "services", appname, "acl_config"}, cbi(appname .. "/client/acl_config")).leaf = true
|
||||
entry({"admin", "services", appname, "log"}, form(appname .. "/client/log"), _("Watch Logs"), 999).leaf = true
|
||||
entry({"admin", "services", appname, "log"}, form(appname .. "/client/log"), _("Runtime Logs"), 999).leaf = true
|
||||
|
||||
--[[ Server ]]
|
||||
entry({"admin", "services", appname, "server"}, cbi(appname .. "/server/index"), _("Server-Side"), 99).leaf = true
|
||||
@ -452,13 +452,17 @@ function delete_select_nodes()
|
||||
if t["node"] == w then
|
||||
uci:delete(appname, t[".name"])
|
||||
end
|
||||
local changed = false
|
||||
local auto_switch_node_list = uci:get(appname, t[".name"], "autoswitch_backup_node") or {}
|
||||
for i = #auto_switch_node_list, 1, -1 do
|
||||
if w == auto_switch_node_list[i] then
|
||||
table.remove(auto_switch_node_list, i)
|
||||
changed = true
|
||||
end
|
||||
end
|
||||
uci:set_list(appname, t[".name"], "autoswitch_backup_node", auto_switch_node_list)
|
||||
if changed then
|
||||
uci:set_list(appname, t[".name"], "autoswitch_backup_node", auto_switch_node_list)
|
||||
end
|
||||
end)
|
||||
uci:foreach(appname, "haproxy_config", function(t)
|
||||
if t["lbss"] == w then
|
||||
|
||||
@ -21,27 +21,50 @@ local function _n(name)
|
||||
end
|
||||
|
||||
o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
|
||||
o:depends({ [_n("realms")] = false })
|
||||
|
||||
o = s:option(Value, _n("port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ [_n("realms")] = false })
|
||||
|
||||
o = s:option(Value, _n("hop"), translate("Port hopping range"))
|
||||
o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("realms")] = false })
|
||||
|
||||
o = s:option(Value, _n("hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
|
||||
o.datatype = "or(uinteger,portrange)"
|
||||
o.placeholder = "30"
|
||||
o.default = "30"
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("realms")] = false })
|
||||
|
||||
o = s:option(Value, _n("obfs"), translate("Obfs Password"))
|
||||
o = s:option(Flag, _n("realms"), translate("Realms"))
|
||||
o.default = "0"
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, _n("realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("realms")] = "1" })
|
||||
|
||||
o = s:option(DynamicList, _n("realm_stun"), translate("Realm STUN"))
|
||||
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("realms")] = "1" })
|
||||
|
||||
o = s:option(Value, _n("auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, _n("obfs_password"), translate("Obfs Password"))
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("obfs_type")] = "salamander" })
|
||||
|
||||
o = s:option(Flag, _n("fast_open"), translate("Fast Open"))
|
||||
o.default = "0"
|
||||
|
||||
|
||||
@ -164,28 +164,66 @@ if load_balancing_options then -- [[ Load balancing Start ]]
|
||||
|
||||
-- Fallback Node
|
||||
o = s:option(ListValue, _n("fallback_node"), translate("Fallback Node"))
|
||||
o.group = {"",""}
|
||||
o:value("", translate("Close(Not use)"))
|
||||
o:value("_direct", translate("Direct Connection"))
|
||||
o:depends({ [_n("protocol")] = "_balancing" })
|
||||
o.template = appname .. "/cbi/nodes_listvalue"
|
||||
o.group = {""}
|
||||
local function check_fallback_chain(fb)
|
||||
for k, v in pairs(fallback_list) do
|
||||
if v.fallback == fb then
|
||||
fallback_list[k] = nil
|
||||
check_fallback_chain(v.id)
|
||||
-- Maximum number of fallback nesting layers
|
||||
local MAX_FALLBACK_DEPTH = 3
|
||||
-- Check if a loop will form.
|
||||
local function will_loop(start_id, target_id, depth)
|
||||
depth = depth or 0
|
||||
-- Recursion stops after the maximum depth is exceeded.
|
||||
if depth >= MAX_FALLBACK_DEPTH then
|
||||
return false
|
||||
end
|
||||
for _, v in ipairs(fallback_list) do
|
||||
if v.id == target_id then
|
||||
local fb = v.fallback
|
||||
-- No fallback
|
||||
if not fb or fb == "" or fb == "_direct" then
|
||||
return false
|
||||
end
|
||||
-- Loopback detected
|
||||
if fb == start_id then
|
||||
return true
|
||||
end
|
||||
-- Continue recursive checking
|
||||
return will_loop(start_id, fb, depth + 1)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
-- Check the fallback chain and remove the balancer node that would form a closed loop.
|
||||
if is_balancer then
|
||||
check_fallback_chain(arg[1])
|
||||
-- Get fallback chain depth
|
||||
local function get_fallback_depth(id, depth)
|
||||
depth = depth or 0
|
||||
if depth >= MAX_FALLBACK_DEPTH then
|
||||
return depth
|
||||
end
|
||||
for _, v in ipairs(fallback_list) do
|
||||
if v.id == id then
|
||||
local fb = v.fallback
|
||||
if not fb or fb == "" or fb == "_direct" then
|
||||
return depth
|
||||
end
|
||||
return get_fallback_depth(fb, depth + 1)
|
||||
end
|
||||
end
|
||||
return depth
|
||||
end
|
||||
for i, v in ipairs(fallback_list) do
|
||||
o:value(v.id, v.remark)
|
||||
o.group[#o.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
|
||||
for _, v in ipairs(fallback_list) do
|
||||
local depth = get_fallback_depth(v.id)
|
||||
-- Once the maximum number of nested doll layers is exceeded, further selection of the balancer is not allowed.
|
||||
if depth < MAX_FALLBACK_DEPTH
|
||||
and not will_loop(arg[1], v.id)
|
||||
then
|
||||
o:value(v.id, v.remark)
|
||||
o.group[#o.group + 1] = (v.group and v.group ~= "") and v.group or translate("default")
|
||||
end
|
||||
end
|
||||
for k1, v1 in pairs(node_list) do
|
||||
if k1 == "socks_list" or k1 == "normal_list" then
|
||||
if k1 == "socks_list" or k1 == "normal_list" or k1 == "urltest_list" then
|
||||
for i, v in ipairs(v1) do
|
||||
o:value(v.id, v.remark)
|
||||
o.group[#o.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
|
||||
@ -221,6 +259,13 @@ if load_balancing_options then -- [[ Load balancing Start ]]
|
||||
o.default = "2"
|
||||
o.placeholder = "2"
|
||||
o.description = translate("The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them.")
|
||||
|
||||
o = s:option(Value, _n("tolerance"), translate("Failure Tolerance (%)"))
|
||||
o:depends({ [_n("balancingStrategy")] = "leastLoad" })
|
||||
o.datatype = "uinteger"
|
||||
o.default = "10"
|
||||
o.placeholder = "10"
|
||||
o.description = translate("The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate.")
|
||||
end -- [[ Load balancing End ]]
|
||||
|
||||
if load_iface_options then -- [[ Custom Interface Start ]]
|
||||
@ -299,11 +344,9 @@ o.placeholder = "30"
|
||||
o.default = "30"
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
@ -313,9 +356,11 @@ o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s~120s)")
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
@ -43,6 +43,8 @@ local security_list = { "none", "auto", "aes-128-gcm", "chacha20-poly1305", "zer
|
||||
|
||||
local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'")
|
||||
|
||||
local singbox_version = api.get_app_version("sing-box"):match("[^v]+")
|
||||
|
||||
o = s:option(ListValue, _n("protocol"), translate("Protocol"))
|
||||
o:value("socks", "Socks")
|
||||
o:value("http", "HTTP")
|
||||
@ -388,19 +390,32 @@ end
|
||||
if singbox_tags:find("with_quic") then
|
||||
o = s:option(Value, _n("hysteria2_hop"), translate("Port hopping range"))
|
||||
o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(Second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
|
||||
o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
|
||||
o.datatype = "or(uinteger,portrange)"
|
||||
o.placeholder = "30"
|
||||
o.default = "30"
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o = s:option(Flag, _n("hysteria2_realms"), translate("Realms"))
|
||||
o.default = "0"
|
||||
if api.compare_versions(singbox_version, ">=", "1.14.0") then
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
else
|
||||
o:depends({ [_n("protocol")] = "__hide"})
|
||||
end
|
||||
|
||||
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
|
||||
o:depends({ [_n("hysteria2_realms")] = "1" })
|
||||
|
||||
o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
|
||||
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
|
||||
o:depends({ [_n("hysteria2_realms")] = "1" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
@ -410,8 +425,20 @@ if singbox_tags:find("with_quic") then
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s~120s)")
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
o = s:option(Value, _n("hysteria2_keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Example:") .. "10s (2s~60s)")
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
o = s:option(Flag, _n("hysteria2_disable_mtu_discovery"), translate("Disable MTU detection"))
|
||||
o.default = "0"
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
end
|
||||
|
||||
@ -506,7 +533,7 @@ o.default = "0"
|
||||
o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
|
||||
o:depends({ [_n("protocol")] = "naive" })
|
||||
|
||||
o = s:option(TextValue, _n("ech_config"), translate("ECH Config"))
|
||||
@ -818,10 +845,14 @@ local protocols = s.fields[_n("protocol")].keylist
|
||||
if #protocols > 0 then
|
||||
for i, v in ipairs(protocols) do
|
||||
if not v:find("^_") then
|
||||
s.fields[_n("address")]:depends({ [_n("protocol")] = v })
|
||||
s.fields[_n("port")]:depends({ [_n("protocol")] = v })
|
||||
s.fields[_n("domain_resolver")]:depends({ [_n("protocol")] = v })
|
||||
s.fields[_n("domain_strategy")]:depends({ [_n("protocol")] = v })
|
||||
local depends_condition = { [_n("protocol")] = v }
|
||||
if v == "hysteria2" then
|
||||
depends_condition[_n("hysteria2_realms")] = false
|
||||
end
|
||||
s.fields[_n("address")]:depends(depends_condition)
|
||||
s.fields[_n("port")]:depends(depends_condition)
|
||||
s.fields[_n("domain_resolver")]:depends(depends_condition)
|
||||
s.fields[_n("domain_strategy")]:depends(depends_condition)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -836,6 +867,7 @@ if not load_shunt_options then
|
||||
o:value("1", translate("Preproxy Node"))
|
||||
end
|
||||
o:value("2", translate("Landing Node"))
|
||||
o:depends({ [_n("hysteria2_realms")] = false })
|
||||
|
||||
o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
|
||||
o1:depends({ [_n("chain_proxy")] = "1" })
|
||||
|
||||
@ -22,17 +22,38 @@ o = s:option(Flag, _n("custom"), translate("Use Custom Config"))
|
||||
|
||||
o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Value, _n("obfs"), translate("Obfs Password"))
|
||||
o = s:option(Flag, _n("realms"), translate("Realms"))
|
||||
o.default = "0"
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Value, _n("realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("realms")] = "1" })
|
||||
|
||||
o = s:option(DynamicList, _n("realm_stun"), translate("Realm STUN"))
|
||||
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("realms")] = "1" })
|
||||
|
||||
o = s:option(Value, _n("auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Value, _n("obfs_password"), translate("Obfs Password"))
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("obfs_type")] = "salamander" })
|
||||
|
||||
o = s:option(Flag, _n("udp"), translate("UDP"))
|
||||
o.default = "1"
|
||||
o.rewrite_option = o.option
|
||||
|
||||
@ -129,6 +129,14 @@ o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
|
||||
|
||||
o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control"))
|
||||
o.default = 0
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
@ -139,14 +147,6 @@ o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwid
|
||||
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwidth")] = false })
|
||||
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
|
||||
|
||||
---- [[ TLS ]]
|
||||
o = s:option(Flag, _n("tls"), translate("TLS"))
|
||||
o.default = 0
|
||||
|
||||
@ -58,6 +58,7 @@ o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Flag, _n("auth"), translate("Auth"))
|
||||
@ -157,10 +158,29 @@ if singbox_tags:find("with_quic") then
|
||||
end
|
||||
|
||||
if singbox_tags:find("with_quic") then
|
||||
o = s:option(Flag, _n("hysteria2_realms"), translate("Realms"))
|
||||
o.default = "0"
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
|
||||
o:depends({ [_n("hysteria2_realms")] = "1" })
|
||||
|
||||
o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
|
||||
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
|
||||
o:depends({ [_n("hysteria2_realms")] = "1" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
|
||||
|
||||
o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Client BBR Flow Control"), translate("Commands the client to use the BBR flow control algorithm"))
|
||||
o.default = 0
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
@ -170,14 +190,6 @@ if singbox_tags:find("with_quic") then
|
||||
|
||||
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwidth")] = false })
|
||||
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("hysteria2_obfs_type")] = "salamander" })
|
||||
end
|
||||
|
||||
o = s:option(ListValue, _n("d_protocol"), translate("Destination protocol"))
|
||||
@ -324,7 +336,7 @@ o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
|
||||
o:depends({ [_n("protocol")] = "naive" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false })
|
||||
|
||||
o = s:option(TextValue, _n("ech_key"), translate("ECH Key"))
|
||||
o.default = ""
|
||||
|
||||
@ -31,7 +31,11 @@ local type_table = {}
|
||||
for filename in fs.dir(types_dir) do
|
||||
table.insert(type_table, filename)
|
||||
end
|
||||
table.sort(type_table)
|
||||
table.sort(type_table, function(a, b)
|
||||
if a == "socks.lua" then return true end
|
||||
if b == "socks.lua" then return false end
|
||||
return a < b
|
||||
end)
|
||||
|
||||
for index, value in ipairs(type_table) do
|
||||
local p_func = loadfile(types_dir .. value)
|
||||
|
||||
@ -377,11 +377,13 @@ function is_special_node(e)
|
||||
end
|
||||
|
||||
function is_ip(val)
|
||||
val = trim(val):lower()
|
||||
local str = val:match("%[(.-)%]") or val
|
||||
return datatypes.ipaddr(str) or false
|
||||
end
|
||||
|
||||
function is_ipv6(val)
|
||||
val = trim(val):lower()
|
||||
local str = val:match("%[(.-)%]") or val
|
||||
return datatypes.ip6addr(str) or false
|
||||
end
|
||||
@ -497,9 +499,10 @@ function get_valid_nodes()
|
||||
end
|
||||
end
|
||||
local port = e.port or e.hysteria_hop or e.hysteria2_hop
|
||||
if port and e.address then
|
||||
local is_realm = (e.type == "Hysteria2" or e.protocol == 'hysteria2') and e.hysteria2_realms or nil
|
||||
if (port and e.address) or is_realm then
|
||||
local address = e.address
|
||||
if is_ip(address) or datatypes.hostname(address) then
|
||||
if is_ip(address) or datatypes.hostname(address) or is_realm then
|
||||
if (e.type == "sing-box" or e.type == "Xray") and e.protocol then
|
||||
local protocol = e.protocol
|
||||
if protocol == "vmess" then
|
||||
@ -526,10 +529,13 @@ function get_valid_nodes()
|
||||
type_name = type_name .. " " .. protocol
|
||||
end
|
||||
if is_ipv6(address) then address = get_ipv6_full(address) end
|
||||
type_name = is_realm and type_name .. " Realm" or type_name
|
||||
e["remark"] = trim("%s:[%s]" % {type_name, e.remarks})
|
||||
if show_node_info == "1" then
|
||||
port = port:gsub(":", "-")
|
||||
e["remark"] = trim("%s:[%s] %s:%s" % {type_name, e.remarks, address, port})
|
||||
port = (port or ""):gsub(":", "-")
|
||||
if not is_realm then
|
||||
e["remark"] = trim("%s:[%s] %s:%s" % {type_name, e.remarks, address, port})
|
||||
end
|
||||
end
|
||||
e.node_type = "normal"
|
||||
if not e.group or e.group == "" then
|
||||
@ -619,7 +625,10 @@ function get_node_remarks(n)
|
||||
end
|
||||
type_name = type_name .. " " .. protocol
|
||||
end
|
||||
remarks = trim("%s:[%s]" % {type_name, n.remarks})
|
||||
if (n.type == "Hysteria2" or n.protocol == 'hysteria2') and n.hysteria2_realms then
|
||||
type_name = type_name .. " Realm"
|
||||
end
|
||||
remarks = trim("%s:[%s]" % {type_name, n.remarks})
|
||||
end
|
||||
end
|
||||
return remarks
|
||||
@ -1204,7 +1213,7 @@ function to_move(app_name,file)
|
||||
}
|
||||
end
|
||||
|
||||
local flag = sys.call('pgrep -af "passwall2/.*'.. app_name ..'" >/dev/null')
|
||||
local flag = sys.call('busybox pgrep -af "passwall2/.*'.. app_name ..'" >/dev/null')
|
||||
if flag == 0 then
|
||||
sys.call("/etc/init.d/passwall2 stop")
|
||||
end
|
||||
@ -1587,4 +1596,30 @@ function get_dnsmasq_server_domain()
|
||||
end
|
||||
end
|
||||
return dnsmasq_server_t
|
||||
end
|
||||
end
|
||||
|
||||
function parse_realm_uri(uri)
|
||||
if type(uri) ~= "string" then return nil end
|
||||
-- realm://token@server/realm_id?query
|
||||
local token, server_url, realm_id, query = trim(uri):match("^realm://([^@]+)@([^/]+)/([^?]*)%??(.*)$")
|
||||
if not token or not server_url or not realm_id then return nil end
|
||||
realm_id = realm_id:gsub("/+$", "")
|
||||
local realm = {
|
||||
token = token,
|
||||
server_url = server_url,
|
||||
realm_id = realm_id
|
||||
}
|
||||
-- 解析 query 中的 stun=
|
||||
if query and query ~= "" then
|
||||
local stun_servers = {}
|
||||
for key, value in query:gmatch("([^&=?]+)=([^&]+)") do
|
||||
if key == "stun" and value ~= "" then
|
||||
stun_servers[#stun_servers + 1] = value
|
||||
end
|
||||
end
|
||||
if #stun_servers > 0 then
|
||||
realm.stun_servers = stun_servers
|
||||
end
|
||||
end
|
||||
return realm
|
||||
end
|
||||
|
||||
@ -5,15 +5,24 @@ local jsonc = api.jsonc
|
||||
|
||||
function gen_config_server(node)
|
||||
local config = {
|
||||
listen = ":" .. node.port,
|
||||
listen = (function()
|
||||
if node.hysteria2_realms and node.hysteria2_realm_url then
|
||||
local url = node.hysteria2_realm_url:gsub("/+$", "")
|
||||
if node.port then
|
||||
url = url .. (url:find("?") and "&lport=" or "?lport=") .. node.port
|
||||
end
|
||||
return url
|
||||
end
|
||||
return ":" .. (node.port or "0")
|
||||
end)(),
|
||||
tls = {
|
||||
cert = node.tls_certificateFile,
|
||||
key = node.tls_keyFile,
|
||||
},
|
||||
obfs = (node.hysteria2_obfs) and {
|
||||
obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and {
|
||||
type = "salamander",
|
||||
salamander = {
|
||||
password = node.hysteria2_obfs
|
||||
password = node.hysteria2_obfs_password
|
||||
}
|
||||
} or nil,
|
||||
auth = {
|
||||
@ -26,6 +35,9 @@ function gen_config_server(node)
|
||||
} or nil,
|
||||
ignoreClientBandwidth = (node.hysteria2_ignoreClientBandwidth == "1") and true or false,
|
||||
disableUDP = (node.hysteria2_udp == "0") and true or false,
|
||||
realm = (node.hysteria2_realms and node.hysteria2_realm_stun) and {
|
||||
stunServers = node.hysteria2_realm_stun
|
||||
} or nil
|
||||
}
|
||||
return config
|
||||
end
|
||||
@ -51,14 +63,23 @@ function gen_config(var)
|
||||
if api.is_ipv6(server_host) then
|
||||
server_host = api.get_ipv6_full(server_host)
|
||||
end
|
||||
local server = server_host .. ":" .. server_port
|
||||
|
||||
if (node.hysteria2_hop) then
|
||||
server = server .. "," .. string.gsub(node.hysteria2_hop, ":", "-")
|
||||
local server = server_host .. (server_port and ":" .. server_port or "")
|
||||
|
||||
if node.hysteria2_hop then
|
||||
server = server .. (server_port and "," or ":") .. string.gsub(node.hysteria2_hop, ":", "-")
|
||||
end
|
||||
|
||||
local config = {
|
||||
server = server,
|
||||
server = (function()
|
||||
if node.hysteria2_realms and node.hysteria2_realm_url then
|
||||
return node.hysteria2_realm_url:gsub("/+$", "")
|
||||
end
|
||||
return server
|
||||
end)(),
|
||||
realm = (node.hysteria2_realms and node.hysteria2_realm_stun) and {
|
||||
stunServers = node.hysteria2_realm_stun
|
||||
} or nil,
|
||||
transport = {
|
||||
type = "udp",
|
||||
udp = node.hysteria2_hop and (function()
|
||||
@ -83,10 +104,10 @@ function gen_config(var)
|
||||
return udp
|
||||
end)() or nil
|
||||
},
|
||||
obfs = (node.hysteria2_obfs) and {
|
||||
obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and {
|
||||
type = "salamander",
|
||||
salamander = {
|
||||
password = node.hysteria2_obfs
|
||||
password = node.hysteria2_obfs_password
|
||||
}
|
||||
} or nil,
|
||||
auth = node.hysteria2_auth_password,
|
||||
|
||||
@ -134,8 +134,8 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
local run_socks_instance = true
|
||||
if proxy_table ~= nil and type(proxy_table) == "table" then
|
||||
proxy_tag = proxy_table.tag or nil
|
||||
fragment = proxy_table.fragment or nil
|
||||
record_fragment = proxy_table.record_fragment or nil
|
||||
fragment = (proxy_table.fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil
|
||||
record_fragment = (proxy_table.record_fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil
|
||||
run_socks_instance = proxy_table.run_socks_instance
|
||||
end
|
||||
|
||||
@ -250,7 +250,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
enabled = true,
|
||||
disable_sni = (node.tls_disable_sni == "1") and true or false, -- Do not send the server name in ClientHello.
|
||||
server_name = node.tls_serverName, -- Used to verify the hostname on the returned certificate, unless the settings are insecure. It is also included in ClientHello to support virtual hosts, unless it is an IP address.
|
||||
insecure = (node.tls_allowInsecure == "1") and true or false, -- Accepts any server certificate.
|
||||
insecure = node.tls_allowInsecure == "1" or (node.tls_pinSHA256 and node.tls_pinSHA256 ~= ""), -- Accepts any server certificate. (Also compatible with xray's pinnedPeerCertSha256)
|
||||
alpn = alpn, -- A list of supported application layer protocols, arranged in order of priority. If both peers support ALPN, the protocol selected will be one of these protocols; otherwise, the connection will fail.
|
||||
--max_version = "1.3",
|
||||
fragment = fragment,
|
||||
@ -506,6 +506,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
table.insert(server_ports, range)
|
||||
end
|
||||
end
|
||||
result.server_port = nil
|
||||
end
|
||||
protocol_table = {
|
||||
server_ports = next(server_ports) and server_ports or nil,
|
||||
@ -519,9 +520,9 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
obfs = node.hysteria_obfs,
|
||||
auth = (node.hysteria_auth_type == "base64") and node.hysteria_auth_password or nil,
|
||||
auth_str = (node.hysteria_auth_type == "string") and node.hysteria_auth_password or nil,
|
||||
recv_window_conn = tonumber(node.hysteria_recv_window_conn),
|
||||
recv_window = tonumber(node.hysteria_recv_window),
|
||||
disable_mtu_discovery = (node.hysteria_disable_mtu_discovery == "1") and true or false,
|
||||
recv_window_conn = tonumber(node.hysteria_recv_window_conn), --1.14 将变更为 stream_receive_window
|
||||
recv_window = tonumber(node.hysteria_recv_window), --1.14 将变更为 connection_receive_window
|
||||
disable_mtu_discovery = (node.hysteria_disable_mtu_discovery == "1") and true or false, --1.14 将变更为 disable_path_mtu_discovery
|
||||
tls = tls
|
||||
}
|
||||
end
|
||||
@ -545,13 +546,12 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
heartbeat = (tonumber(node.tuic_heartbeat) or 3) .. "s",
|
||||
tls = tls
|
||||
}
|
||||
if node.tuic_alpn and node.tuic_alpn ~= "default" then
|
||||
local alpn = {}
|
||||
string.gsub(node.tuic_alpn, '[^,]+', function(w)
|
||||
table.insert(alpn, w)
|
||||
end)
|
||||
if #alpn > 0 then protocol_table.tls.alpn = alpn end
|
||||
end
|
||||
node.tuic_alpn = (node.tuic_alpn and node.tuic_alpn ~= "default") and node.tuic_alpn or "h3"
|
||||
local alpn = {}
|
||||
string.gsub(node.tuic_alpn, '[^,]+', function(w)
|
||||
table.insert(alpn, w)
|
||||
end)
|
||||
if #alpn > 0 then protocol_table.tls.alpn = alpn end
|
||||
end
|
||||
|
||||
if node.protocol == "hysteria2" then
|
||||
@ -563,6 +563,10 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
table.insert(server_ports, range)
|
||||
end
|
||||
end
|
||||
result.server_port = nil
|
||||
end
|
||||
if node.hysteria2_realms then
|
||||
server_ports = {}
|
||||
end
|
||||
local interval, interval_max
|
||||
if next(server_ports) then
|
||||
@ -595,7 +599,29 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
password = node.hysteria2_obfs_password
|
||||
} or nil,
|
||||
password = node.hysteria2_auth_password or nil,
|
||||
tls = tls
|
||||
idle_timeout = (function(t)
|
||||
if not version_ge_1_14_0 then return nil end
|
||||
t = tonumber(tostring(t or "30"):match("^%d+"))
|
||||
return (t and t >= 4 and t <= 120) and t or 30
|
||||
end)(node.hysteria2_idle_timeout),
|
||||
keep_alive_period = (function(t)
|
||||
if not version_ge_1_14_0 then return nil end
|
||||
t = tonumber(tostring(t or "0"):match("^%d+"))
|
||||
return (t and t >= 2 and t <= 60) and t or nil
|
||||
end)(node.hysteria2_keep_alive_period),
|
||||
disable_path_mtu_discovery = version_ge_1_14_0 and (tonumber(node.hysteria2_disable_mtu_discovery) == 1) or nil,
|
||||
tls = tls,
|
||||
realm = node.hysteria2_realms and (function()
|
||||
result.server = nil
|
||||
result.server_port = nil
|
||||
local realm = api.parse_realm_uri(node.hysteria2_realm_url)
|
||||
if realm then
|
||||
realm.server_url = realm.server_url and "https://" .. realm.server_url or nil
|
||||
realm.stun_servers = realm.stun_servers or node.hysteria2_realm_stun
|
||||
return realm
|
||||
end
|
||||
return nil
|
||||
end)() or nil
|
||||
}
|
||||
end
|
||||
|
||||
@ -881,10 +907,10 @@ function gen_config_server(node)
|
||||
auth_str = (node.hysteria_auth_type == "string") and node.hysteria_auth_password or nil,
|
||||
}
|
||||
},
|
||||
recv_window_conn = node.hysteria_recv_window_conn and tonumber(node.hysteria_recv_window_conn) or nil,
|
||||
recv_window_client = node.hysteria_recv_window_client and tonumber(node.hysteria_recv_window_client) or nil,
|
||||
max_conn_client = node.hysteria_max_conn_client and tonumber(node.hysteria_max_conn_client) or nil,
|
||||
disable_mtu_discovery = (node.hysteria_disable_mtu_discovery == "1") and true or false,
|
||||
recv_window_conn = node.hysteria_recv_window_conn and tonumber(node.hysteria_recv_window_conn) or nil, --1.14 to stream_receive_window
|
||||
recv_window_client = node.hysteria_recv_window_client and tonumber(node.hysteria_recv_window_client) or nil, --1.14 to connection_receive_window
|
||||
max_conn_client = node.hysteria_max_conn_client and tonumber(node.hysteria_max_conn_client) or nil, --1.14 to max_concurrent_streams
|
||||
disable_mtu_discovery = (node.hysteria_disable_mtu_discovery == "1") and true or false, --1.14 to disable_path_mtu_discover
|
||||
tls = tls
|
||||
}
|
||||
end
|
||||
@ -928,7 +954,17 @@ function gen_config_server(node)
|
||||
}
|
||||
},
|
||||
ignore_client_bandwidth = (node.hysteria2_ignore_client_bandwidth == "1") and true or false,
|
||||
tls = tls
|
||||
tls = tls,
|
||||
realm = node.hysteria2_realms and (function()
|
||||
local realm = api.parse_realm_uri(node.hysteria2_realm_url)
|
||||
if realm then
|
||||
realm.server_url = realm.server_url and "https://" .. realm.server_url or nil
|
||||
realm.stun_servers = realm.stun_servers or node.hysteria2_realm_stun
|
||||
realm.stun_domain_resolver = "direct"
|
||||
return realm
|
||||
end
|
||||
return nil
|
||||
end)() or nil
|
||||
}
|
||||
end
|
||||
|
||||
@ -1312,7 +1348,6 @@ function gen_config(var)
|
||||
else
|
||||
ut_nodes = _node.urltest_node
|
||||
end
|
||||
if #ut_nodes == 0 then return nil end
|
||||
local valid_nodes = {}
|
||||
for i = 1, #(ut_nodes or {}) do
|
||||
local ut_node_id = ut_nodes[i]
|
||||
@ -2051,7 +2086,7 @@ function gen_config(var)
|
||||
string.gsub(direct_ipset, '[^' .. "," .. ']+', function(w)
|
||||
sys.call("ipset -q -F " .. w)
|
||||
end)
|
||||
local ipset_prefix_name = "passwall2_" .. node_id .. "_"
|
||||
local ipset_prefix_name = "psw2_" .. node_id .. "_"
|
||||
local ipset_list = sys.exec("ipset list | grep 'Name: ' | grep '" .. ipset_prefix_name .. "' | awk '{print $2}'")
|
||||
string.gsub(ipset_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||
sys.call("ipset -q -F " .. w)
|
||||
@ -2070,7 +2105,7 @@ function gen_config(var)
|
||||
end)
|
||||
local family = "inet"
|
||||
local table_name = "passwall2"
|
||||
local nftset_prefix_name = "passwall2_" .. node_id .. "_"
|
||||
local nftset_prefix_name = "psw2_" .. node_id .. "_"
|
||||
local nftset_list = sys.exec("nft -a list sets | grep -E '" .. nftset_prefix_name .. "' | awk -F 'set ' '{print $2}' | awk '{print $1}'")
|
||||
string.gsub(nftset_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||
sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, w))
|
||||
@ -2138,7 +2173,7 @@ function gen_config(var)
|
||||
if not value.detour and value.server then
|
||||
value.detour = "direct"
|
||||
end
|
||||
if value.server and not api.datatypes.hostname(value.server) then
|
||||
if (value.server and not api.datatypes.hostname(value.server)) and not value.realm then
|
||||
value.domain_resolver = nil
|
||||
end
|
||||
for k, v in pairs(config.outbounds[index]) do
|
||||
|
||||
@ -794,6 +794,9 @@ function gen_config_server(node)
|
||||
config.outbounds[index][k] = nil
|
||||
end
|
||||
end
|
||||
if value.protocol == "freedom" and api.compare_versions(xray_version, "<", "26.5.3") then -- Todo is to remove it
|
||||
value.settings = nil
|
||||
end
|
||||
end
|
||||
|
||||
return config
|
||||
@ -1049,10 +1052,10 @@ function gen_config(var)
|
||||
if #valid_nodes == 0 then return nil end
|
||||
|
||||
-- fallback node
|
||||
local fallback_node_tag = nil
|
||||
local fallback_node_id = _node.fallback_node
|
||||
if not fallback_node_id or fallback_node_id == "" then fallback_node_id = nil end
|
||||
if fallback_node_id then
|
||||
fallback_node_id = (fallback_node_id and fallback_node_id ~= "") and fallback_node_id or nil
|
||||
local fallback_node_tag = (fallback_node_id == "_direct") and "direct" or "blackhole"
|
||||
if fallback_node_id and fallback_node_id ~= "_direct" then
|
||||
local is_new_node = true
|
||||
for _, outbound in ipairs(outbounds) do
|
||||
if string.sub(outbound.tag, 1, #fallback_node_id) == fallback_node_id then
|
||||
@ -1082,7 +1085,13 @@ function gen_config(var)
|
||||
type = _node.balancingStrategy,
|
||||
settings = {
|
||||
expected = _node.expected and tonumber(_node.expected) and tonumber(_node.expected) or 2,
|
||||
maxRTT = "1s"
|
||||
maxRTT = "1s",
|
||||
tolerance = (function(t)
|
||||
t = tonumber(t) or 0
|
||||
if t < 1 then return nil end
|
||||
if t > 100 then t = 100 end
|
||||
return t / 100
|
||||
end)(_node.tolerance)
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1264,9 +1273,9 @@ function gen_config(var)
|
||||
interface = node.iface
|
||||
}
|
||||
},
|
||||
settings = {
|
||||
settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check
|
||||
finalRules = {{ action = "allow" }}
|
||||
}
|
||||
} or nil
|
||||
}
|
||||
sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.iface))
|
||||
end
|
||||
@ -1806,7 +1815,7 @@ function gen_config(var)
|
||||
string.gsub(direct_ipset, '[^' .. "," .. ']+', function(w)
|
||||
sys.call("ipset -q -F " .. w)
|
||||
end)
|
||||
local ipset_prefix_name = "passwall2_" .. node_id .. "_"
|
||||
local ipset_prefix_name = "psw2_" .. node_id .. "_"
|
||||
local ipset_list = sys.exec("ipset list | grep 'Name: ' | grep '" .. ipset_prefix_name .. "' | awk '{print $2}'")
|
||||
string.gsub(ipset_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||
sys.call("ipset -q -F " .. w)
|
||||
@ -1825,7 +1834,7 @@ function gen_config(var)
|
||||
end)
|
||||
local family = "inet"
|
||||
local table_name = "passwall2"
|
||||
local nftset_prefix_name = "passwall2_" .. node_id .. "_"
|
||||
local nftset_prefix_name = "psw2_" .. node_id .. "_"
|
||||
local nftset_list = sys.exec("nft -a list sets | grep -E '" .. nftset_prefix_name .. "' | awk -F 'set ' '{print $2}' | awk '{print $1}'")
|
||||
string.gsub(nftset_list, '[^' .. "\r\n" .. ']+', function(w)
|
||||
sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, w))
|
||||
@ -2080,7 +2089,12 @@ function gen_proto_config(var)
|
||||
end
|
||||
|
||||
table.insert(outbounds, {
|
||||
protocol = "freedom", tag = "direct", settings = {finalRules = {{ action = "allow" }}}, sockopt = {mark = 255}
|
||||
protocol = "freedom",
|
||||
tag = "direct",
|
||||
settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check
|
||||
finalRules = {{ action = "allow" }}
|
||||
} or nil,
|
||||
sockopt = {mark = 255}
|
||||
})
|
||||
|
||||
local config = {
|
||||
|
||||
@ -35,22 +35,48 @@ local appname = api.appname
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var shunt_list = JSON.parse('<%=self.shunt_list%>');
|
||||
const shunt_list = JSON.parse('<%=self.shunt_list%>');
|
||||
|
||||
function go() {
|
||||
var _status = document.getElementsByClassName('_status');
|
||||
for (var i = 0; i < _status.length; i++) {
|
||||
var id = _status[i].getAttribute("socks_id");
|
||||
function to_edit_node(btn) {
|
||||
if (!btn) return;
|
||||
const idReg = /^cbid\..*\..*node$/;
|
||||
let hidden_select = null;
|
||||
const container = btn.closest('#cbi-<%=appname%>-global') || btn.closest('#cbi-<%=appname%>-socks');
|
||||
if (!container) return null;
|
||||
const selects = container.querySelectorAll('select[id^="cbid."][id*="."][id$="node"]');
|
||||
for (const sel of selects) {
|
||||
if ( idReg.test(sel.id) && getComputedStyle(sel).display === "none" && (sel.compareDocumentPosition(btn) & Node.DOCUMENT_POSITION_FOLLOWING)) {
|
||||
hidden_select = sel;
|
||||
}
|
||||
}
|
||||
if (!hidden_select) return;
|
||||
let node_select_value = hidden_select?.options[0]?.value;
|
||||
if (!node_select_value || node_select_value.indexOf("_default") === 0 || node_select_value.indexOf("_direct") === 0 || node_select_value.indexOf("_blackhole") === 0) {
|
||||
return;
|
||||
}
|
||||
let to_url = '<%=api.url("node_config")%>/' + node_select_value;
|
||||
if (node_select_value.indexOf("Socks_") === 0) {
|
||||
to_url = '<%=api.url("socks_config")%>/' + node_select_value.substring("Socks_".length);
|
||||
}
|
||||
location.href = to_url;
|
||||
}
|
||||
|
||||
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
async function go() {
|
||||
const _status = document.getElementsByClassName('_status');
|
||||
for (let i = 0; i < _status.length; i++) {
|
||||
const id = _status[i].getAttribute("socks_id");
|
||||
XHR.get('<%=api.url("socks_status")%>', {
|
||||
index: i,
|
||||
id: id
|
||||
},
|
||||
function(x, result) {
|
||||
var index = result.index;
|
||||
var div = '';
|
||||
var div1 = '<font style="font-weight:bold;" color="green">✓</font> ';
|
||||
var div2 = '<font style="font-weight:bold;" color="red">X</font> ';
|
||||
|
||||
const index = result.index;
|
||||
let div = '';
|
||||
const div1 = '<font style="font-weight:bold;" color="green">✓</font> ';
|
||||
const div2 = '<font style="font-weight:bold;" color="red">X</font> ';
|
||||
|
||||
if (result.socks_status) {
|
||||
div += div1;
|
||||
} else {
|
||||
@ -67,83 +93,112 @@ local appname = api.appname
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
var global_id = null;
|
||||
var global = document.getElementById("cbi-<%=appname%>-global");
|
||||
let global_id = null;
|
||||
const global = document.getElementById("cbi-<%=appname%>-global");
|
||||
if (global) {
|
||||
var node = global.getElementsByClassName("cbi-section-node")[0];
|
||||
var node_id = node.getAttribute("id");
|
||||
global_id = node_id;
|
||||
var all_node = node.querySelectorAll("[id]");
|
||||
var reg1 = /^cbid\..*node\.main$/;
|
||||
// Add an "Edit" placeholder to the routing rule node in advance to ensure left alignment of the node list.
|
||||
document.querySelectorAll('.td[data-widget="nodes_listvalue"][data-name="_node"] > div').forEach(container => {
|
||||
if (!container.querySelector('.shunt-node-placeholder')) {
|
||||
const placeholder = document.createElement('div');
|
||||
placeholder.className = 'shunt-node-placeholder';
|
||||
placeholder.style.cssText = 'display:inline-flex; width:40px; flex-shrink:0;';
|
||||
container.appendChild(placeholder);
|
||||
}
|
||||
});
|
||||
|
||||
for (var i = 0; i < all_node.length; i++) {
|
||||
var el = all_node[i];
|
||||
await delay(100);
|
||||
|
||||
const node = global.getElementsByClassName("cbi-section-node")[0];
|
||||
const node_id = node.getAttribute("id");
|
||||
global_id = node_id;
|
||||
const all_node = node.querySelectorAll("[id]");
|
||||
const reg1 = /^cbid\..*node\.main$/;
|
||||
//const reg1 = /^cbid\..*\.(node)\.main$/;
|
||||
|
||||
for (let i = 0; i < all_node.length; i++) {
|
||||
const el = all_node[i];
|
||||
if (!reg1.test(el.id)) continue;
|
||||
|
||||
var node_select = el;
|
||||
const node_select = el;
|
||||
if (!node_select) continue;
|
||||
var cbid = el.id.replace(/\.main$/, "");
|
||||
var hidden_select = document.getElementById(cbid);
|
||||
var node_select_value = hidden_select ? hidden_select.options[0].value : "";
|
||||
const cbid = el.id.replace(/\.main$/, "");
|
||||
const hidden_select = document.getElementById(cbid);
|
||||
const node_select_value = hidden_select?.options[0]?.value;
|
||||
if (!node_select_value || node_select_value.indexOf("_default") === 0 || node_select_value.indexOf("_direct") === 0 || node_select_value.indexOf("_blackhole") === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var to_url = '<%=api.url("node_config")%>/' + node_select_value;
|
||||
if (node_select_value.indexOf("Socks_") === 0) {
|
||||
to_url = '<%=api.url("socks_config")%>/' + node_select_value.substring("Socks_".length);
|
||||
}
|
||||
var html = '<a href="#" onclick="location.href=\'' + to_url + '\'"><%:Edit%></a>';
|
||||
let html = '<a href="#" onclick="return to_edit_node(this);"><%:Edit%></a>';
|
||||
|
||||
var m = cbid.match(/\.node$/);
|
||||
const m = cbid.match(/\.node$/);
|
||||
if (m) {
|
||||
html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_redir_log")%>?id=default&name=' + 'global' + '\', \'_blank\')"><%:Log%></a>';
|
||||
}
|
||||
|
||||
node_select.insertAdjacentHTML("beforeend",
|
||||
'<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">'
|
||||
+ html + '</div>'
|
||||
);
|
||||
html = '<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">' + html + '</div>'
|
||||
|
||||
const placeholder = node_select.parentElement.querySelector('.shunt-node-placeholder');
|
||||
if (placeholder) {
|
||||
placeholder.innerHTML = html;
|
||||
} else {
|
||||
node_select.insertAdjacentHTML("beforeend", html);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var socks = document.getElementById("cbi-<%=appname%>-socks");
|
||||
const socks = document.getElementById("cbi-<%=appname%>-socks");
|
||||
if (socks) {
|
||||
var socks_enabled_dom = document.getElementById(global_id + "-socks_enabled");
|
||||
socks_enabled_dom.parentNode.removeChild(socks_enabled_dom);
|
||||
var descr = socks.getElementsByClassName("cbi-section-descr")[0];
|
||||
descr.outerHTML = socks_enabled_dom.outerHTML;
|
||||
rows = socks.getElementsByClassName("cbi-section-table-row");
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
const socks_enabled_dom = document.getElementById(global_id + "-socks_enabled");
|
||||
const descr = socks.getElementsByClassName("cbi-section-descr")[0];
|
||||
descr.replaceWith(socks_enabled_dom);
|
||||
const rows = socks.getElementsByClassName("cbi-section-table-row");
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
try {
|
||||
var row = rows[i];
|
||||
var id = row.id;
|
||||
const row = rows[i];
|
||||
const id = row.id;
|
||||
if (!id) continue;
|
||||
var dom_id = id + "-node";
|
||||
var cbid = dom_id.replace("cbi-", "cbid-").replace(new RegExp("-", 'g'), ".");
|
||||
let dom_id = id + "-node";
|
||||
const cbid = dom_id.replace("cbi-", "cbid-").replace(new RegExp("-", 'g'), ".");
|
||||
dom_id = cbid + ".main";
|
||||
var node_select = document.getElementById(dom_id);
|
||||
const node_select = document.getElementById(dom_id);
|
||||
if (!node_select) continue;
|
||||
|
||||
var hidden_select = document.getElementById(cbid);;
|
||||
var node_select_value = hidden_select ? hidden_select.options[0].value : "";
|
||||
if (node_select_value && node_select_value != "") {
|
||||
var to_url = '<%=api.url("node_config")%>/' + node_select_value;
|
||||
var html = '<a href="#" onclick="location.href=\'' + to_url + '\'"><%:Edit%></a>';
|
||||
html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_socks_log")%>?name=' + id.replace("cbi-<%=appname%>-", "") + '\', \'_blank\')"><%:Log%></a>';
|
||||
let html = '<a href="#" onclick="return to_edit_node(this);"><%:Edit%></a>';
|
||||
html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_socks_log")%>?name=' + id.replace("cbi-<%=appname%>-", "") + '\', \'_blank\')"><%:Log%></a>';
|
||||
|
||||
node_select.insertAdjacentHTML("afterend",
|
||||
'<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">'
|
||||
+ html + '</div>'
|
||||
);
|
||||
}
|
||||
node_select.insertAdjacentHTML("afterend",
|
||||
'<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">'
|
||||
+ html + '</div>'
|
||||
);
|
||||
} catch(err) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(function () {
|
||||
let lastCount = 0;
|
||||
let stableTimes = 0;
|
||||
const STABLE_THRESHOLD = 5;
|
||||
function waitStable() {
|
||||
const list = document.querySelectorAll('[id^="cbid.<%=appname%>."][id$="node.main"]');
|
||||
const count = list.length;
|
||||
if (count === lastCount && count > 0) {
|
||||
stableTimes++;
|
||||
} else {
|
||||
stableTimes = 0;
|
||||
lastCount = count;
|
||||
}
|
||||
if (stableTimes >= STABLE_THRESHOLD) {
|
||||
go();
|
||||
return;
|
||||
}
|
||||
requestAnimationFrame(waitStable);
|
||||
}
|
||||
waitStable();
|
||||
})();
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => setTimeout(() => {
|
||||
const hiddenSelect = document.getElementById("cbid.<%=appname%>.<%=self.global_cfgid%>.node");
|
||||
let o_val = hiddenSelect.value
|
||||
@ -184,8 +239,6 @@ local appname = api.appname
|
||||
shunt_taboption.appendChild(shunt_option_list);
|
||||
}
|
||||
}
|
||||
go();
|
||||
}, 100));
|
||||
//setTimeout("go()", 1000);
|
||||
//]]>
|
||||
</script>
|
||||
@ -602,10 +602,10 @@ local current_node = map:get(section)
|
||||
|
||||
if (v_type === "Hysteria2") {
|
||||
v_password = opt.get("hysteria2_auth_password");
|
||||
var dom_obfs = opt.get("hysteria2_obfs");
|
||||
var dom_obfs = opt.get("hysteria2_obfs_password");
|
||||
if (dom_obfs && dom_obfs.value != "") {
|
||||
params += "&obfs=" + "salamander";
|
||||
params += opt.query("obfs-password", "hysteria2_obfs");
|
||||
params += opt.query("obfs-password", "hysteria2_obfs_password");
|
||||
}
|
||||
params += opt.query("mport", "hysteria2_hop");
|
||||
} else {
|
||||
@ -1621,7 +1621,8 @@ local current_node = map:get(section)
|
||||
dom_prefix = "hysteria2_"
|
||||
opt.set(dom_prefix + 'auth_password', decodeURIComponent(password));
|
||||
if (queryParam["obfs-password"] || queryParam["obfs_password"]) {
|
||||
opt.set(dom_prefix + 'obfs', queryParam["obfs-password"] || queryParam["obfs_password"]);
|
||||
opt.set(dom_prefix + 'obfs_type', "salamander");
|
||||
opt.set(dom_prefix + 'obfs_password', queryParam["obfs-password"] || queryParam["obfs_password"]);
|
||||
}
|
||||
opt.set(dom_prefix + 'hop', queryParam.mport || "");
|
||||
}
|
||||
@ -1678,7 +1679,7 @@ local current_node = map:get(section)
|
||||
}
|
||||
opt.set(dom_prefix + 'tuic_congestion_control', queryParam.congestion_control || 'cubic');
|
||||
opt.set(dom_prefix + 'tuic_udp_relay_mode', queryParam.udp_relay_mode || 'native');
|
||||
opt.set(dom_prefix + 'tuic_alpn', queryParam.alpn || 'default');
|
||||
opt.set(dom_prefix + 'tuic_alpn', queryParam.alpn || 'h3');
|
||||
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
|
||||
opt.set(dom_prefix + 'tls_disable_sni', queryParam.disable_sni === "1");
|
||||
opt.set(
|
||||
|
||||
@ -911,7 +911,11 @@ table td, .table .td {
|
||||
} else {
|
||||
port_s = o["hysteria_hop"] || o["hysteria2_hop"];
|
||||
}
|
||||
str += type + ":" + remarks;
|
||||
if ((o.type === "Hysteria2" || o.protocol === 'hysteria2') && o.hysteria2_realms) {
|
||||
str += type + " Realm:" + remarks;
|
||||
} else {
|
||||
str += type + ":" + remarks;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
@ -46,8 +46,8 @@ msgstr "لیست قوانین"
|
||||
msgid "Access control"
|
||||
msgstr "کنترل دسترسی"
|
||||
|
||||
msgid "Watch Logs"
|
||||
msgstr "مشاهده گزارشها"
|
||||
msgid "Runtime Logs"
|
||||
msgstr "گزارشهای زمان اجرا"
|
||||
|
||||
msgid "Node Config"
|
||||
msgstr "پیکربندی گره"
|
||||
@ -437,6 +437,12 @@ msgstr "تعداد گرههای ترجیحی"
|
||||
msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them."
|
||||
msgstr "توزیعکننده بار تعداد بهینهای از گرهها را انتخاب میکند و ترافیک به طور تصادفی بین آنها توزیع میشود."
|
||||
|
||||
msgid "Failure Tolerance (%)"
|
||||
msgstr "تحمل شکست (%)"
|
||||
|
||||
msgid "The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate."
|
||||
msgstr "حداکثر نرخ شکست قابل قبول در تست سرعت. برای مثال، عدد ۱ به معنای مجاز بودن نرخ شکست ۱٪ است.
|
||||
|
||||
msgid "Shunt"
|
||||
msgstr "شنت (Shunt)"
|
||||
|
||||
|
||||
@ -46,8 +46,8 @@ msgstr "Список правил"
|
||||
msgid "Access control"
|
||||
msgstr "Контроль доступа"
|
||||
|
||||
msgid "Watch Logs"
|
||||
msgstr "Просмотр журнала"
|
||||
msgid "Runtime Logs"
|
||||
msgstr "Журналы выполнения"
|
||||
|
||||
msgid "Node Config"
|
||||
msgstr "Параметры узла"
|
||||
@ -433,6 +433,12 @@ msgstr "Количество предпочтительных узлов"
|
||||
msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them."
|
||||
msgstr "Балансировщик выбирает указанное количество наилучших узлов и распределяет трафик между ними случайным образом."
|
||||
|
||||
msgid "Failure Tolerance (%)"
|
||||
msgstr "Допуск на отказ (%)"
|
||||
|
||||
msgid "The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate."
|
||||
msgstr "Максимально допустимый процент отказов при проверке скорости. Например, 1 означает допустимый процент отказов в 1%."
|
||||
|
||||
msgid "Shunt"
|
||||
msgstr "Shunt (разделение трафика)"
|
||||
|
||||
|
||||
@ -46,8 +46,8 @@ msgstr "规则列表"
|
||||
msgid "Access control"
|
||||
msgstr "访问控制"
|
||||
|
||||
msgid "Watch Logs"
|
||||
msgstr "查看日志"
|
||||
msgid "Runtime Logs"
|
||||
msgstr "运行日志"
|
||||
|
||||
msgid "Node Config"
|
||||
msgstr "节点配置"
|
||||
@ -433,6 +433,12 @@ msgstr "优选节点数量"
|
||||
msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them."
|
||||
msgstr "负载均衡器选出最优节点的个数,流量将在这几个节点中随机分配。"
|
||||
|
||||
msgid "Failure Tolerance (%)"
|
||||
msgstr "测速失败率容忍度(%)"
|
||||
|
||||
msgid "The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate."
|
||||
msgstr "最多可接受的测速失败率,例如 1 表示允许 1% 的测速失败率。"
|
||||
|
||||
msgid "Shunt"
|
||||
msgstr "分流"
|
||||
|
||||
|
||||
@ -46,8 +46,8 @@ msgstr "規則列表"
|
||||
msgid "Access control"
|
||||
msgstr "訪問控制"
|
||||
|
||||
msgid "Watch Logs"
|
||||
msgstr "查看日誌"
|
||||
msgid "Runtime Logs"
|
||||
msgstr "運行日誌"
|
||||
|
||||
msgid "Node Config"
|
||||
msgstr "節點配置"
|
||||
@ -433,6 +433,12 @@ msgstr "優選節點數量"
|
||||
msgid "The load balancer selects the optimal number of nodes, and traffic is randomly distributed among them."
|
||||
msgstr "負載均衡器選出最優節點的個數,流量將在這几個節點中随機分配。"
|
||||
|
||||
msgid "Failure Tolerance (%)"
|
||||
msgstr "測速失敗率容忍度(%)"
|
||||
|
||||
msgid "The maximum acceptable speed test failure rate. For example, 1 means allowing a 1% failure rate."
|
||||
msgstr "最多可接受的測速失敗率,例如 1 表示允許 1% 的測速失敗率。"
|
||||
|
||||
msgid "Shunt"
|
||||
msgstr "分流"
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
if [ "$ACTION" = "ifupdate" ]; then
|
||||
USE_TABLES=$(get_cache_var "USE_TABLES")
|
||||
[ -n "$USE_TABLES" ] && ${APP_PATH}/${USE_TABLES}.sh update_wan_sets >/dev/null 2>&1 &
|
||||
[ -n "$USE_TABLES" ] && { ${APP_PATH}/${USE_TABLES}.sh update_wan_sets >/dev/null 2>&1 & }
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ run_xray() {
|
||||
json_add_string "loglevel" "${loglevel}"
|
||||
|
||||
[ -n "$flag" ] && {
|
||||
pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
busybox pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
json_add_string "flag" "${flag}"
|
||||
}
|
||||
[ -n "$socks_address" ] && [ -n "$socks_port" ] && {
|
||||
@ -112,12 +112,12 @@ run_xray() {
|
||||
local direct_ipset_conf=${GLOBAL_ACL_PATH}/dns_${flag}_direct.conf
|
||||
[ -n "$(echo ${flag} | grep '^acl')" ] && direct_ipset_conf=${TMP_ACL_PATH}/${sid}/dns_${flag}_direct.conf
|
||||
if [ "${nftflag}" = "1" ]; then
|
||||
local direct_nftset4="passwall2_${node}_white"
|
||||
local direct_nftset6="passwall2_${node}_white6"
|
||||
local direct_nftset4="psw2_${node}_white"
|
||||
local direct_nftset6="psw2_${node}_white6"
|
||||
local direct_nftset="4#inet#passwall2#${direct_nftset4},6#inet#passwall2#${direct_nftset6}"
|
||||
else
|
||||
local direct_ipset4="passwall2_${node}_white"
|
||||
local direct_ipset6="passwall2_${node}_white6"
|
||||
local direct_ipset4="psw2_${node}_white"
|
||||
local direct_ipset6="psw2_${node}_white6"
|
||||
local direct_ipset="${direct_ipset4},${direct_ipset6}"
|
||||
fi
|
||||
run_ipset_dns_server listen_port=${direct_dnsmasq_listen_port} server_dns=${AUTO_DNS} ipset="${direct_ipset}" nftset="${direct_nftset}" config_file=${direct_ipset_conf}
|
||||
@ -225,7 +225,7 @@ run_singbox() {
|
||||
json_add_string "loglevel" "${loglevel}"
|
||||
|
||||
[ -n "$flag" ] && {
|
||||
pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
busybox pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
json_add_string "flag" "${flag}"
|
||||
}
|
||||
[ -n "$socks_address" ] && [ -n "$socks_port" ] && {
|
||||
@ -251,12 +251,12 @@ run_singbox() {
|
||||
local direct_ipset_conf=${GLOBAL_ACL_PATH}/dns_${flag}_direct.conf
|
||||
[ -n "$(echo ${flag} | grep '^acl')" ] && direct_ipset_conf=${TMP_ACL_PATH}/${sid}/dns_${flag}_direct.conf
|
||||
if [ "${nftflag}" = "1" ]; then
|
||||
local direct_nftset4="passwall2_${node}_white"
|
||||
local direct_nftset6="passwall2_${node}_white6"
|
||||
local direct_nftset4="psw2_${node}_white"
|
||||
local direct_nftset6="psw2_${node}_white6"
|
||||
local direct_nftset="4#inet#passwall2#${direct_nftset4},6#inet#passwall2#${direct_nftset6}"
|
||||
else
|
||||
local direct_ipset4="passwall2_${node}_white"
|
||||
local direct_ipset6="passwall2_${node}_white6"
|
||||
local direct_ipset4="psw2_${node}_white"
|
||||
local direct_ipset6="psw2_${node}_white6"
|
||||
local direct_ipset="${direct_ipset4},${direct_ipset6}"
|
||||
fi
|
||||
run_ipset_dns_server listen_port=${direct_dnsmasq_listen_port} server_dns=${AUTO_DNS} ipset="${direct_ipset}" nftset="${direct_nftset}" config_file=${direct_ipset_conf}
|
||||
@ -386,6 +386,10 @@ run_socks() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "${error_msg}" ] && [ "$(config_n_get $node hysteria2_realms)" = "1" ]; then
|
||||
unset error_msg
|
||||
fi
|
||||
|
||||
[ -n "${error_msg}" ] && {
|
||||
[ "$bind" != "127.0.0.1" ] && log 1 "$(i18n "Socks node: [%s]%s, start failed %s:%s %s" "${remarks}" "${tmp}" "${bind}" "${socks_port}" "${error_msg}")"
|
||||
return 1
|
||||
@ -555,7 +559,7 @@ socks_node_switch() {
|
||||
[ -s "$pf" ] && kill -9 "$(head -n1 "$pf")" >/dev/null 2>&1
|
||||
done
|
||||
|
||||
pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1 && !/acl\/|acl_/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
busybox pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1 && !/acl\/|acl_/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
for prefix in "" "HTTP_" "HTTP2"; do
|
||||
rm -rf "$TMP_PATH/${prefix}SOCKS_${flag}"*
|
||||
done
|
||||
@ -791,7 +795,7 @@ start_socks() {
|
||||
|
||||
# Auto switch logic
|
||||
local enable_autoswitch=$(config_n_get $id enable_autoswitch 0)
|
||||
[ "$enable_autoswitch" = "1" ] && $APP_PATH/socks_auto_switch.sh ${id} > /dev/null 2>&1 &
|
||||
[ "$enable_autoswitch" = "1" ] && { $APP_PATH/socks_auto_switch.sh ${id} > /dev/null 2>&1 & }
|
||||
done
|
||||
}
|
||||
}
|
||||
@ -805,14 +809,14 @@ clean_crontab() {
|
||||
sed -i "/$(echo "lua ${APP_PATH}/rule_update.lua log" | sed 's#\/#\\\/#g')/d" /etc/crontabs/root >/dev/null 2>&1
|
||||
sed -i "/$(echo "lua ${APP_PATH}/subscribe.lua start" | sed 's#\/#\\\/#g')/d" /etc/crontabs/root >/dev/null 2>&1
|
||||
|
||||
pgrep -af "${CONFIG}/" | awk '/tasks\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
busybox pgrep -af "${CONFIG}/" | awk '/tasks\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
rm -rf /tmp/lock/${CONFIG}_tasks.lock
|
||||
}
|
||||
|
||||
start_crontab() {
|
||||
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then
|
||||
start_daemon=$(config_t_get global_delay start_daemon 0)
|
||||
[ "$start_daemon" = "1" ] && $APP_PATH/monitor.sh > /dev/null 2>&1 &
|
||||
[ "$start_daemon" = "1" ] && { $APP_PATH/monitor.sh > /dev/null 2>&1 & }
|
||||
fi
|
||||
|
||||
[ -f "/tmp/lock/${CONFIG}_cron.lock" ] && {
|
||||
@ -982,11 +986,11 @@ run_ipset_chinadns_ng() {
|
||||
|
||||
[ -n "${ipset}" ] && {
|
||||
set_names=$ipset
|
||||
vps_set_names="passwall2_vps,passwall2_vps6"
|
||||
vps_set_names="psw2_vps,psw2_vps6"
|
||||
}
|
||||
[ -n "${nftset}" ] && {
|
||||
set_names=$(echo ${nftset} | awk -F, '{printf "%s,%s", substr($1,3), substr($2,3)}' | sed 's/#/@/g')
|
||||
vps_set_names="inet@passwall2@passwall2_vps,inet@passwall2@passwall2_vps6"
|
||||
vps_set_names="inet@passwall2@psw2_vps,inet@passwall2@psw2_vps6"
|
||||
}
|
||||
cat <<-EOF > $config_file
|
||||
bind-addr 127.0.0.1
|
||||
@ -1162,7 +1166,7 @@ acl_app() {
|
||||
}
|
||||
|
||||
start() {
|
||||
pgrep -f /tmp/etc/passwall2/bin > /dev/null 2>&1 && {
|
||||
busybox pgrep -f /tmp/etc/passwall2/bin > /dev/null 2>&1 && {
|
||||
#log_i18n 0 "The program has started. Please stop it and then restart it!"
|
||||
stop
|
||||
}
|
||||
@ -1241,8 +1245,8 @@ stop() {
|
||||
kill -9 "$pid" >/dev/null 2>&1
|
||||
fi
|
||||
done
|
||||
pgrep -f "sleep.*(6s|9s|58s)" | xargs kill -9 >/dev/null 2>&1
|
||||
pgrep -af "${CONFIG}/" | awk '! /app\.sh|subscribe\.lua|rule_update\.lua|tasks\.sh|server_app\.lua|ujail/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
busybox pgrep -f "sleep.*(6s|9s|58s)" | xargs kill -9 >/dev/null 2>&1
|
||||
busybox pgrep -af "${CONFIG}/" | awk '! /app\.sh|subscribe\.lua|rule_update\.lua|tasks\.sh|server_app\.lua|ujail/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
unset V2RAY_LOCATION_ASSET
|
||||
unset XRAY_LOCATION_ASSET
|
||||
unset SS_SYSTEM_DNS_RESOLVER_FORCE_BUILTIN
|
||||
|
||||
@ -8,7 +8,8 @@ listen_port=$2
|
||||
server_address=$3
|
||||
server_port=$4
|
||||
|
||||
pgrep -af "${CONFIG}/" | grep -E 'app\.sh.*(start|stop)|nftables\.sh|iptables\.sh|subscribe\.lua' >/dev/null && {
|
||||
busybox pgrep -af "${CONFIG}/" | grep -E 'app\.sh.*(start|stop)|nftables\.sh|iptables\.sh|subscribe\.lua' >/dev/null && {
|
||||
# No detection during specific task execution
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
@ -274,7 +274,7 @@ function add_rule(var)
|
||||
if address == "engage.cloudflareclient.com" then return end
|
||||
if datatypes.hostname(address) then
|
||||
set_domain_dns(address, fwd_dns)
|
||||
set_domain_ipset(address, setflag_4 .. "passwall2_vps," .. setflag_6 .. "passwall2_vps6")
|
||||
set_domain_ipset(address, setflag_4 .. "psw2_vps," .. setflag_6 .. "psw2_vps6")
|
||||
end
|
||||
end
|
||||
process_address(t.address)
|
||||
|
||||
@ -3,17 +3,17 @@
|
||||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
MY_PATH=$DIR/iptables.sh
|
||||
UTILS_PATH=$DIR/utils.sh
|
||||
IPSET_LOCAL="passwall2_local"
|
||||
IPSET_PROXY_LAN="passwall2_proxy_lan"
|
||||
IPSET_LAN="passwall2_lan"
|
||||
IPSET_VPS="passwall2_vps"
|
||||
IPSET_WAN="passwall2_wan"
|
||||
IPSET_LOCAL="psw2_local"
|
||||
IPSET_PROXY_LAN="psw2_proxy_lan"
|
||||
IPSET_LAN="psw2_lan"
|
||||
IPSET_VPS="psw2_vps"
|
||||
IPSET_WAN="psw2_wan"
|
||||
|
||||
IPSET_LOCAL6="passwall2_local6"
|
||||
IPSET_PROXY_LAN6="passwall2_proxy_lan6"
|
||||
IPSET_LAN6="passwall2_lan6"
|
||||
IPSET_VPS6="passwall2_vps6"
|
||||
IPSET_WAN6="passwall2_wan6"
|
||||
IPSET_LOCAL6="psw2_local6"
|
||||
IPSET_PROXY_LAN6="psw2_proxy_lan6"
|
||||
IPSET_LAN6="psw2_lan6"
|
||||
IPSET_VPS6="psw2_vps6"
|
||||
IPSET_WAN6="psw2_wan6"
|
||||
|
||||
FWMARK="0x50535732"
|
||||
|
||||
@ -194,8 +194,8 @@ gen_shunt_list() {
|
||||
for shunt_id in $shunt_ids; do
|
||||
local shunt_node=$(config_n_get ${node} "${shunt_id}")
|
||||
[ -n "$shunt_node" ] && {
|
||||
local ipset_v4="passwall2_${node}_${shunt_id}"
|
||||
local ipset_v6="passwall2_${node}_${shunt_id}6"
|
||||
local ipset_v4="psw2_${node}_${shunt_id}"
|
||||
local ipset_v6="psw2_${node}_${shunt_id}6"
|
||||
ipset -! create $ipset_v4 nethash maxelem 1048576
|
||||
ipset -! create $ipset_v6 nethash family inet6 maxelem 1048576
|
||||
local outbound="redirect"
|
||||
@ -219,22 +219,14 @@ gen_shunt_list() {
|
||||
}
|
||||
local direct_ipset4=$(get_cache_var "node_${node}_direct_ipset4")
|
||||
[ -n "${direct_ipset4}" ] && {
|
||||
ipset -! create ${direct_ipset4} nethash maxelem 1048576 timeout 259200
|
||||
ipset -! create ${direct_ipset4} iphash maxelem 1048576 timeout 259200
|
||||
_SHUNT_LIST4="${_SHUNT_LIST4} ${direct_ipset4}:direct"
|
||||
}
|
||||
local direct_ipset6=$(get_cache_var "node_${node}_direct_ipset6")
|
||||
[ -n "${direct_ipset6}" ] && {
|
||||
ipset -! create ${direct_ipset6} nethash family inet6 maxelem 1048576 timeout 259200
|
||||
ipset -! create ${direct_ipset6} iphash family inet6 maxelem 1048576 timeout 259200
|
||||
_SHUNT_LIST6="${_SHUNT_LIST6} ${direct_ipset6}:direct"
|
||||
}
|
||||
[ "${preloading}" = "1" ] && [ -n "$default_node" ] && {
|
||||
local ipset_v4="passwall2_${node}_default"
|
||||
local ipset_v6="passwall2_${node}_default6"
|
||||
ipset -! create $ipset_v4 nethash maxelem 1048576
|
||||
ipset -! create $ipset_v6 nethash family inet6 maxelem 1048576
|
||||
_SHUNT_LIST4="${_SHUNT_LIST4} ${ipset_v4}:${default_outbound}"
|
||||
_SHUNT_LIST6="${_SHUNT_LIST6} ${ipset_v6}:${default_outbound}"
|
||||
}
|
||||
}
|
||||
[ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\"
|
||||
[ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\"
|
||||
@ -618,6 +610,8 @@ filter_direct_node_list() {
|
||||
}
|
||||
|
||||
update_wan_sets() {
|
||||
[ -z "$(command -v get_wan_ips)" ] && . "$UTILS_PATH"
|
||||
|
||||
local WAN_IP=$(get_wan_ips ip4)
|
||||
[ -n "$WAN_IP" ] && {
|
||||
ipset -F "$IPSET_WAN"
|
||||
@ -641,13 +635,13 @@ add_firewall_rule() {
|
||||
ipset -! create $IPSET_LOCAL nethash maxelem 1048576
|
||||
ipset -! create $IPSET_PROXY_LAN nethash maxelem 1048576
|
||||
ipset -! create $IPSET_LAN nethash maxelem 1048576
|
||||
ipset -! create $IPSET_VPS nethash maxelem 1048576
|
||||
ipset -! create $IPSET_VPS iphash maxelem 1048576
|
||||
ipset -! create $IPSET_WAN nethash maxelem 1048576
|
||||
|
||||
ipset -! create $IPSET_LOCAL6 nethash family inet6 maxelem 1048576
|
||||
ipset -! create $IPSET_PROXY_LAN6 nethash family inet6 maxelem 1048576
|
||||
ipset -! create $IPSET_LAN6 nethash family inet6 maxelem 1048576
|
||||
ipset -! create $IPSET_VPS6 nethash family inet6 maxelem 1048576
|
||||
ipset -! create $IPSET_VPS6 iphash family inet6 maxelem 1048576
|
||||
ipset -! create $IPSET_WAN6 nethash family inet6 maxelem 1048576
|
||||
|
||||
get_local_ips ip4 | sed "s/^/add $IPSET_LOCAL /" | ipset -! -R
|
||||
@ -1025,7 +1019,7 @@ del_firewall_rule() {
|
||||
|
||||
flush_ipset() {
|
||||
log_i18n 0 "Clear %s." "IPSet"
|
||||
for _name in $(ipset list | grep "Name: " | grep "passwall2_" | awk '{print $2}'); do
|
||||
for _name in $(ipset list | grep "Name: " | grep "psw2_" | awk '{print $2}'); do
|
||||
destroy_ipset ${_name}
|
||||
done
|
||||
}
|
||||
@ -1105,7 +1099,7 @@ start() {
|
||||
}
|
||||
|
||||
stop() {
|
||||
[ -z "$(command -v log_i18n)" ] && . /usr/share/passwall2/utils.sh
|
||||
[ -z "$(command -v log_i18n)" ] && . "$UTILS_PATH"
|
||||
del_firewall_rule
|
||||
destroy_ipset $IPSET_PROXY_LAN
|
||||
destroy_ipset $IPSET_PROXY_LAN6
|
||||
|
||||
@ -18,7 +18,7 @@ while [ "$ENABLED" -eq 1 ]; do
|
||||
for filename in $(ls ${TMP_SCRIPT_FUNC_PATH} | grep -v "^_"); do
|
||||
cmd=$(cat ${TMP_SCRIPT_FUNC_PATH}/${filename})
|
||||
cmd_check=$(echo $cmd | awk -F '>' '{print $1}')
|
||||
icount=$(pgrep -f "$(echo $cmd_check)" | wc -l)
|
||||
icount=$(busybox pgrep -f "$(echo $cmd_check)" | wc -l)
|
||||
if [ $icount = 0 ]; then
|
||||
#echo "${cmd} crashed, restarting." >> /tmp/log/passwall2.log
|
||||
eval $(echo "nohup ${cmd} 2>&1 &") >/dev/null 2>&1 &
|
||||
|
||||
@ -4,17 +4,17 @@ DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
MY_PATH=$DIR/nftables.sh
|
||||
UTILS_PATH=$DIR/utils.sh
|
||||
NFTABLE_NAME="inet passwall2"
|
||||
NFTSET_LOCAL="passwall2_local"
|
||||
NFTSET_PROXY_LAN="passwall2_proxy_lan"
|
||||
NFTSET_LAN="passwall2_lan"
|
||||
NFTSET_VPS="passwall2_vps"
|
||||
NFTSET_WAN="passwall2_wan"
|
||||
NFTSET_LOCAL="psw2_local"
|
||||
NFTSET_PROXY_LAN="psw2_proxy_lan"
|
||||
NFTSET_LAN="psw2_lan"
|
||||
NFTSET_VPS="psw2_vps"
|
||||
NFTSET_WAN="psw2_wan"
|
||||
|
||||
NFTSET_LOCAL6="passwall2_local6"
|
||||
NFTSET_PROXY_LAN6="passwall2_proxy_lan6"
|
||||
NFTSET_LAN6="passwall2_lan6"
|
||||
NFTSET_VPS6="passwall2_vps6"
|
||||
NFTSET_WAN6="passwall2_wan6"
|
||||
NFTSET_LOCAL6="psw2_local6"
|
||||
NFTSET_PROXY_LAN6="psw2_proxy_lan6"
|
||||
NFTSET_LAN6="psw2_lan6"
|
||||
NFTSET_VPS6="psw2_vps6"
|
||||
NFTSET_WAN6="psw2_wan6"
|
||||
|
||||
FWMARK="0x50535732"
|
||||
|
||||
@ -231,8 +231,8 @@ gen_shunt_list() {
|
||||
for shunt_id in $shunt_ids; do
|
||||
local shunt_node=$(config_n_get ${node} "${shunt_id}")
|
||||
[ -n "$shunt_node" ] && {
|
||||
local nftset_v4="passwall2_${node}_${shunt_id}"
|
||||
local nftset_v6="passwall2_${node}_${shunt_id}6"
|
||||
local nftset_v4="psw2_${node}_${shunt_id}"
|
||||
local nftset_v6="psw2_${node}_${shunt_id}6"
|
||||
gen_nftset $nftset_v4 ipv4_addr 0 0
|
||||
gen_nftset $nftset_v6 ipv6_addr 0 0
|
||||
local outbound="redirect"
|
||||
@ -263,14 +263,6 @@ gen_shunt_list() {
|
||||
gen_nftset $direct_nftset6 ipv6_addr 0 0
|
||||
_SHUNT_LIST6="${_SHUNT_LIST6} ${direct_nftset6}:direct"
|
||||
}
|
||||
[ "${preloading}" = "1" ] && [ -n "$default_node" ] && {
|
||||
local nftset_v4="passwall2_${node}_default"
|
||||
local nftset_v6="passwall2_${node}_default6"
|
||||
gen_nftset $nftset_v4 ipv4_addr 0 0
|
||||
gen_nftset $nftset_v6 ipv6_addr 0 0
|
||||
_SHUNT_LIST4="${_SHUNT_LIST4} ${nftset_v4}:${default_outbound}"
|
||||
_SHUNT_LIST6="${_SHUNT_LIST6} ${nftset_v6}:${default_outbound}"
|
||||
}
|
||||
}
|
||||
[ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\"
|
||||
[ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\"
|
||||
@ -681,6 +673,8 @@ mwan3_start() {
|
||||
}
|
||||
|
||||
update_wan_sets() {
|
||||
[ -z "$(command -v get_wan_ips)" ] && . "$UTILS_PATH"
|
||||
|
||||
local WAN_IP=$(get_wan_ips ip4)
|
||||
[ -n "$WAN_IP" ] && {
|
||||
nft flush set $NFTABLE_NAME $NFTSET_WAN
|
||||
@ -1073,7 +1067,7 @@ del_firewall_rule() {
|
||||
|
||||
flush_nftset() {
|
||||
log_i18n 0 "Clear %s." "NFTSet"
|
||||
for _name in $(nft -a list sets | grep -E "passwall2_" | awk -F 'set ' '{print $2}' | awk '{print $1}'); do
|
||||
for _name in $(nft -a list sets | grep -E "psw2_" | awk -F 'set ' '{print $2}' | awk '{print $1}'); do
|
||||
destroy_nftset ${_name}
|
||||
done
|
||||
}
|
||||
@ -1116,7 +1110,7 @@ start() {
|
||||
}
|
||||
|
||||
stop() {
|
||||
[ -z "$(command -v log_i18n)" ] && . /usr/share/passwall2/utils.sh
|
||||
[ -z "$(command -v log_i18n)" ] && . "$UTILS_PATH"
|
||||
del_firewall_rule
|
||||
destroy_nftset $NFTSET_PROXY_LAN
|
||||
destroy_nftset $NFTSET_PROXY_LAN6
|
||||
|
||||
@ -6,7 +6,7 @@ APP_FILE=${APP_PATH}/app.sh
|
||||
flag=0
|
||||
|
||||
check_process() {
|
||||
while pgrep -af "${CONFIG}/" | grep -E 'app\.sh.*(start|stop)|nftables\.sh|iptables\.sh|subscribe\.lua' >/dev/null; do
|
||||
while busybox pgrep -af "${CONFIG}/" | grep -E 'app\.sh.*(start|stop)|nftables\.sh|iptables\.sh|subscribe\.lua' >/dev/null; do
|
||||
sleep 6s
|
||||
done
|
||||
}
|
||||
@ -63,7 +63,7 @@ test_node() {
|
||||
# Kill the SS plugin process
|
||||
local pid_file="/tmp/etc/${CONFIG}/test_node_${node_id}_plugin.pid"
|
||||
[ -s "$pid_file" ] && kill -9 "$(head -n 1 "$pid_file")" >/dev/null 2>&1
|
||||
pgrep -af "test_node_${node_id}" | awk '! /socks_auto_switch\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
busybox pgrep -af "test_node_${node_id}" | awk '! /socks_auto_switch\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
rm -rf /tmp/etc/${CONFIG}/test_node_${node_id}*.*
|
||||
if [ "${_proxy_status}" -eq 200 ]; then
|
||||
return 0
|
||||
|
||||
@ -1688,22 +1688,19 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
local insecure = params.allowinsecure or params.insecure
|
||||
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0")
|
||||
result.hysteria2_hop = params.mport
|
||||
if params["obfs-password"] or params["obfs_password"] then
|
||||
result.hysteria2_obfs_type = "salamander"
|
||||
result.hysteria2_obfs_password = params["obfs-password"] or params["obfs_password"]
|
||||
end
|
||||
|
||||
if (sub_hysteria2_type == "sing-box" and has_singbox) or (sub_hysteria2_type == "xray" and has_xray) then
|
||||
local is_singbox = sub_hysteria2_type == "sing-box" and has_singbox
|
||||
result.type = is_singbox and 'sing-box' or 'Xray'
|
||||
result.protocol = "hysteria2"
|
||||
if params["obfs-password"] or params["obfs_password"] then
|
||||
result.hysteria2_obfs_type = "salamander"
|
||||
result.hysteria2_obfs_password = params["obfs-password"] or params["obfs_password"]
|
||||
end
|
||||
result.use_finalmask = (params.fm and params.fm ~= "") and "1" or nil
|
||||
result.finalmask = (params.fm and params.fm ~= "") and api.base64Encode(params.fm) or nil
|
||||
elseif has_hysteria2 then
|
||||
result.type = "Hysteria2"
|
||||
if params["obfs-password"] or params["obfs_password"] then
|
||||
result.hysteria2_obfs = params["obfs-password"] or params["obfs_password"]
|
||||
end
|
||||
else
|
||||
log(2, i18n.translatef("Skipping the %s node is due to incompatibility with the %s core program or incorrect node usage type settings.", "Hysteria2", "Hysteria2"))
|
||||
return nil
|
||||
@ -1761,7 +1758,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
end
|
||||
result.tls_serverName = params.sni
|
||||
result.tls_disable_sni = params.disable_sni
|
||||
result.tuic_alpn = params.alpn or "default"
|
||||
result.tuic_alpn = params.alpn or "h3"
|
||||
result.tuic_congestion_control = params.congestion_control or "cubic"
|
||||
result.tuic_udp_relay_mode = params.udp_relay_mode or "native"
|
||||
local insecure = params.allowinsecure or params.insecure or params.allow_insecure
|
||||
@ -2049,12 +2046,12 @@ local function select_node(nodes, config, parentConfig)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- First priority: Type + Notes + IP + Port
|
||||
-- First priority: Type + Notes + IP + Port + Group
|
||||
if not server then
|
||||
for index, node in pairs(nodes) do
|
||||
if config.currentNode.type and config.currentNode.remarks and config.currentNode.address and config.currentNode.port then
|
||||
if node.type and node.remarks and node.address and node.port then
|
||||
if node.type == config.currentNode.type and node.remarks == config.currentNode.remarks and (node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port) then
|
||||
if node.type == config.currentNode.type and node.remarks == config.currentNode.remarks and (node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port) and node.group == config.currentNode.group then
|
||||
if config.log == nil or config.log == true then
|
||||
log(log_level, i18n.translatef("Update [%s]", config.remarks) .. " " .. i18n.translatef("First Matching node:") .. " " .. node.remarks)
|
||||
end
|
||||
@ -2065,12 +2062,12 @@ local function select_node(nodes, config, parentConfig)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Second priority: Type + IP + Port
|
||||
-- Second priority: Type + IP + Port + Group
|
||||
if not server then
|
||||
for index, node in pairs(nodes) do
|
||||
if config.currentNode.type and config.currentNode.address and config.currentNode.port then
|
||||
if node.type and node.address and node.port then
|
||||
if node.type == config.currentNode.type and (node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port) then
|
||||
if node.type == config.currentNode.type and (node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port) and node.group == config.currentNode.group then
|
||||
if config.log == nil or config.log == true then
|
||||
log(log_level, i18n.translatef("Update [%s]", config.remarks) .. " " .. i18n.translatef("Second Matching node:") .. " " .. node.remarks)
|
||||
end
|
||||
@ -2081,12 +2078,12 @@ local function select_node(nodes, config, parentConfig)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Third priority: IP + Port
|
||||
-- Third priority: IP + Port + Group
|
||||
if not server then
|
||||
for index, node in pairs(nodes) do
|
||||
if config.currentNode.address and config.currentNode.port then
|
||||
if node.address and node.port then
|
||||
if node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port then
|
||||
if node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port and node.group == config.currentNode.group then
|
||||
if config.log == nil or config.log == true then
|
||||
log(log_level, i18n.translatef("Update [%s]", config.remarks) .. " " .. i18n.translatef("Third Matching node:") .. " " .. node.remarks)
|
||||
end
|
||||
@ -2097,12 +2094,12 @@ local function select_node(nodes, config, parentConfig)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Fourth priority: IP
|
||||
-- Fourth priority: IP + Group
|
||||
if not server then
|
||||
for index, node in pairs(nodes) do
|
||||
if config.currentNode.address then
|
||||
if node.address then
|
||||
if node.address == config.currentNode.address then
|
||||
if node.address == config.currentNode.address and node.group == config.currentNode.group then
|
||||
if config.log == nil or config.log == true then
|
||||
log(log_level, i18n.translatef("Update [%s]", config.remarks) .. " " .. i18n.translatef("Fourth Matching node:") .. " " .. node.remarks)
|
||||
end
|
||||
@ -2113,12 +2110,12 @@ local function select_node(nodes, config, parentConfig)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Fifth priority: remarks
|
||||
-- Fifth priority: remarks + Group
|
||||
if not server then
|
||||
for index, node in pairs(nodes) do
|
||||
if config.currentNode.remarks then
|
||||
if node.remarks then
|
||||
if node.remarks == config.currentNode.remarks then
|
||||
if node.remarks == config.currentNode.remarks and node.group == config.currentNode.group then
|
||||
if config.log == nil or config.log == true then
|
||||
log(log_level, i18n.translatef("Update [%s]", config.remarks) .. " " .. i18n.translatef("Fifth Matching node:") .. " " .. node.remarks)
|
||||
end
|
||||
|
||||
@ -22,7 +22,7 @@ do
|
||||
stop_interval_mode=$(expr "$stop_interval_mode" \* 60)
|
||||
if [ -n "$stop_week_mode" ]; then
|
||||
[ "$stop_week_mode" = "8" ] && {
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$stop_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG stop > /dev/null 2>&1 &
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$stop_interval_mode")" -eq 0 ] && { /etc/init.d/$CONFIG stop > /dev/null 2>&1 & }
|
||||
}
|
||||
fi
|
||||
|
||||
@ -31,7 +31,7 @@ do
|
||||
start_interval_mode=$(expr "$start_interval_mode" \* 60)
|
||||
if [ -n "$start_week_mode" ]; then
|
||||
[ "$start_week_mode" = "8" ] && {
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$start_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG start > /dev/null 2>&1 &
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$start_interval_mode")" -eq 0 ] && { /etc/init.d/$CONFIG start > /dev/null 2>&1 & }
|
||||
}
|
||||
fi
|
||||
|
||||
@ -40,7 +40,7 @@ do
|
||||
restart_interval_mode=$(expr "$restart_interval_mode" \* 60)
|
||||
if [ -n "$restart_week_mode" ]; then
|
||||
[ "$restart_week_mode" = "8" ] && {
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$restart_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG restart > /dev/null 2>&1 &
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$restart_interval_mode")" -eq 0 ] && { /etc/init.d/$CONFIG restart > /dev/null 2>&1 & }
|
||||
}
|
||||
fi
|
||||
|
||||
@ -50,7 +50,7 @@ do
|
||||
hourupdate=$(expr "$hourupdate" \* 60)
|
||||
if [ "$autoupdate" = "1" ]; then
|
||||
[ "$weekupdate" = "8" ] && {
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$hourupdate")" -eq 0 ] && lua $APP_PATH/rule_update.lua log all cron > /dev/null 2>&1 &
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$hourupdate")" -eq 0 ] && { lua $APP_PATH/rule_update.lua log all cron > /dev/null 2>&1 & }
|
||||
}
|
||||
fi
|
||||
|
||||
@ -73,7 +73,7 @@ do
|
||||
hour_update=$(expr "$hour_update" \* 60)
|
||||
cfgids=$(echo -n $(cat ${TMP_SUB_PATH}/${name}) | sed 's# #,#g')
|
||||
[ "$week_update" = "8" ] && {
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$hour_update")" -eq 0 ] && lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 &
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$hour_update")" -eq 0 ] && { lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 & }
|
||||
}
|
||||
|
||||
done
|
||||
|
||||
@ -49,11 +49,13 @@ url_test_node() {
|
||||
local _tmp_port=$(get_new_port 48900 tcp,udp)
|
||||
NO_REC_PROCESS=1 /usr/share/${CONFIG}/app.sh run_socks flag="url_test_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=url_test_${node_id}.json
|
||||
sleep 2s
|
||||
local curlx="socks5h://127.0.0.1:${_tmp_port}"
|
||||
local url=$(config_t_get global_other url_test_url https://www.google.com/generate_204)
|
||||
result=$(curl --connect-timeout 3 -o /dev/null -I -skL -w "%{http_code}:%{time_starttransfer}" -x $curlx "${url}")
|
||||
pgrep -af "url_test_${node_id}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
rm -rf /tmp/etc/${CONFIG}/*url_test_${node_id}*.json
|
||||
local probeUrl=$(config_t_get global_other url_test_url https://www.google.com/generate_204)
|
||||
result=$(curl --connect-timeout 3 --max-time 5 -o /dev/null -I -skL -w "%{http_code}:%{time_pretransfer}" -x ${curlx} "${probeUrl}")
|
||||
# End the SS plugin process
|
||||
local pid_file="/tmp/etc/${CONFIG}/url_test_${node_id}_plugin.pid"
|
||||
[ -s "$pid_file" ] && kill -9 "$(head -n 1 "$pid_file")" >/dev/null 2>&1
|
||||
busybox pgrep -af "url_test_${node_id}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
rm -rf /tmp/etc/${CONFIG}/*url_test_${node_id}*.*
|
||||
}
|
||||
echo $result
|
||||
}
|
||||
|
||||
@ -412,7 +412,7 @@ run_process_queue() {
|
||||
for filename in $(ls ${TMP_PROCESS_LIST_PATH}); do
|
||||
cmd=$(cat ${TMP_PROCESS_LIST_PATH}/${filename})
|
||||
cmd_check=$(echo $cmd | awk -F '>' '{print $1}')
|
||||
icount=$(pgrep -f "$(echo $cmd_check)" | wc -l)
|
||||
icount=$(busybox pgrep -f "$(echo $cmd_check)" | wc -l)
|
||||
if [ $icount = 0 ]; then
|
||||
eval $(echo "nohup ${cmd} 2>&1 &") >/dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
Loading…
Reference in New Issue
Block a user