🎨 Sync 2024-12-17 00:34

This commit is contained in:
github-actions[bot] 2024-12-17 00:34:44 +08:00
parent 8ff91a9d07
commit 358351d427
30 changed files with 672 additions and 739 deletions

View File

@ -166,13 +166,13 @@ end
function get_now_use_node() function get_now_use_node()
local path = "/tmp/etc/passwall/acl/default" local path = "/tmp/etc/passwall/acl/default"
local e = {} local e = {}
local data, code, msg = nixio.fs.readfile(path .. "/TCP.id") local tcp_node = api.get_cache_var("GLOBAL_TCP_node")
if data then if tcp_node then
e["TCP"] = util.trim(data) e["TCP"] = tcp_node
end end
local data, code, msg = nixio.fs.readfile(path .. "/UDP.id") local udp_node = api.get_cache_var("GLOBAL_UDP_node")
if data then if udp_node then
e["UDP"] = util.trim(data) e["UDP"] = udp_node
end end
luci.http.prepare_content("application/json") luci.http.prepare_content("application/json")
luci.http.write_json(e) luci.http.write_json(e)
@ -269,8 +269,8 @@ function connect_status()
local chn_list = uci:get(appname, "@global[0]", "chn_list") or "direct" local chn_list = uci:get(appname, "@global[0]", "chn_list") or "direct"
local gfw_list = uci:get(appname, "@global[0]", "use_gfw_list") or "1" local gfw_list = uci:get(appname, "@global[0]", "use_gfw_list") or "1"
local proxy_mode = uci:get(appname, "@global[0]", "tcp_proxy_mode") or "proxy" local proxy_mode = uci:get(appname, "@global[0]", "tcp_proxy_mode") or "proxy"
local socks_server = luci.sys.exec("[ -f /tmp/etc/passwall/acl/default/TCP_SOCKS_server ] && echo -n $(cat /tmp/etc/passwall/acl/default/TCP_SOCKS_server) || echo -n ''") local socks_server = api.get_cache_var("GLOBAL_TCP_SOCKS_server")
if socks_server ~= "" then if socks_server and socks_server ~= "" then
if (chn_list == "proxy" and gfw_list == "0" and proxy_mode ~= "proxy" and baidu ~= nil) or (chn_list == "0" and gfw_list == "0" and proxy_mode == "proxy") then if (chn_list == "proxy" and gfw_list == "0" and proxy_mode ~= "proxy" and baidu ~= nil) or (chn_list == "0" and gfw_list == "0" and proxy_mode == "proxy") then
-- 中国列表+百度 or 全局 -- 中国列表+百度 or 全局
url = "-x socks5h://" .. socks_server .. " " .. url url = "-x socks5h://" .. socks_server .. " " .. url
@ -374,8 +374,8 @@ function clear_all_nodes()
uci:delete(appname, t[".name"]) uci:delete(appname, t[".name"])
end) end)
uci:foreach(appname, "acl_rule", function(t) uci:foreach(appname, "acl_rule", function(t)
uci:set(appname, t[".name"], "tcp_node", "default") uci:set(appname, t[".name"], "tcp_node", "nil")
uci:set(appname, t[".name"], "udp_node", "default") uci:set(appname, t[".name"], "udp_node", "nil")
end) end)
uci:foreach(appname, "nodes", function(node) uci:foreach(appname, "nodes", function(node)
uci:delete(appname, node['.name']) uci:delete(appname, node['.name'])
@ -413,10 +413,20 @@ function delete_select_nodes()
end) end)
uci:foreach(appname, "acl_rule", function(t) uci:foreach(appname, "acl_rule", function(t)
if t["tcp_node"] == w then if t["tcp_node"] == w then
uci:set(appname, t[".name"], "tcp_node", "default") uci:set(appname, t[".name"], "tcp_node", "nil")
end end
if t["udp_node"] == w then if t["udp_node"] == w then
uci:set(appname, t[".name"], "udp_node", "default") uci:set(appname, t[".name"], "udp_node", "nil")
end
end)
uci:foreach(appname, "nodes", function(t)
if t["preproxy_node"] == w then
uci:delete(appname, t[".name"], "preproxy_node")
uci:delete(appname, t[".name"], "chain_proxy")
end
if t["to_node"] == w then
uci:delete(appname, t[".name"], "to_node")
uci:delete(appname, t[".name"], "chain_proxy")
end end
end) end)
uci:delete(appname, w) uci:delete(appname, w)

View File

@ -21,9 +21,8 @@ o.default = 1
o.rmempty = false o.rmempty = false
local auto_switch_tip local auto_switch_tip
local current_node_file = string.format("/tmp/etc/%s/id/socks_%s", appname, arg[1]) local current_node = api.get_cache_var("socks_" .. arg[1])
local current_node = luci.sys.exec(string.format("[ -f '%s' ] && echo -n $(cat %s)", current_node_file, current_node_file)) if current_node then
if current_node and current_node ~= "" and current_node ~= "nil" then
local n = uci:get_all(appname, current_node) local n = uci:get_all(appname, current_node)
if n then if n then
if tonumber(m:get(arg[1], "enable_autoswitch") or 0) == 1 then if tonumber(m:get(arg[1], "enable_autoswitch") or 0) == 1 then

View File

@ -646,12 +646,26 @@ o.default = 0
o = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay") o = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay")
o.default = 0 o.default = 0
o = s:option(ListValue, option_name("to_node"), translate("Landing node"), translate("Only support a layer of proxy.")) o = s:option(ListValue, option_name("chain_proxy"), translate("Chain Proxy"))
o.default = ""
o:value("", translate("Close(Not use)")) o:value("", translate("Close(Not use)"))
o:value("1", translate("Preproxy Node"))
o:value("2", translate("Landing Node"))
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
if not v:find("_") then
o:depends({ [option_name("protocol")] = v })
end
end
o = s:option(ListValue, option_name("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "1" })
o = s:option(ListValue, option_name("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "2" })
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
if v.type == "Xray" then if v.type == "Xray" and v.id ~= arg[1] then
o:value(v.id, v.remark) s.fields[option_name("preproxy_node")]:value(v.id, v.remark)
s.fields[option_name("to_node")]:value(v.id, v.remark)
end end
end end
@ -659,7 +673,7 @@ for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
if not v:find("_") then if not v:find("_") then
s.fields[option_name("tcpMptcp")]:depends({ [option_name("protocol")] = v }) s.fields[option_name("tcpMptcp")]:depends({ [option_name("protocol")] = v })
s.fields[option_name("tcpNoDelay")]:depends({ [option_name("protocol")] = v }) s.fields[option_name("tcpNoDelay")]:depends({ [option_name("protocol")] = v })
s.fields[option_name("to_node")]:depends({ [option_name("protocol")] = v }) s.fields[option_name("chain_proxy")]:depends({ [option_name("protocol")] = v })
end end
end end

View File

@ -677,18 +677,27 @@ o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(ListValue, option_name("to_node"), translate("Landing node"), translate("Only support a layer of proxy.")) o = s:option(ListValue, option_name("chain_proxy"), translate("Chain Proxy"))
o.default = ""
o:value("", translate("Close(Not use)")) o:value("", translate("Close(Not use)"))
for k, v in pairs(nodes_table) do o:value("1", translate("Preproxy Node"))
if v.type == "sing-box" then o:value("2", translate("Landing Node"))
o:value(v.id, v.remark)
end
end
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
if not v:find("_") then if not v:find("_") then
o:depends({ [option_name("protocol")] = v }) o:depends({ [option_name("protocol")] = v })
end end
end end
o = s:option(ListValue, option_name("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "1" })
o = s:option(ListValue, option_name("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "2" })
for k, v in pairs(nodes_table) do
if v.type == "sing-box" and v.id ~= arg[1] then
s.fields[option_name("preproxy_node")]:value(v.id, v.remark)
s.fields[option_name("to_node")]:value(v.id, v.remark)
end
end
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)

View File

@ -19,6 +19,7 @@ OPENWRT_BOARD = nil
CACHE_PATH = "/tmp/etc/" .. appname .. "_tmp" CACHE_PATH = "/tmp/etc/" .. appname .. "_tmp"
LOG_FILE = "/tmp/log/" .. appname .. ".log" LOG_FILE = "/tmp/log/" .. appname .. ".log"
TMP_PATH = "/tmp/etc/" .. appname TMP_PATH = "/tmp/etc/" .. appname
TMP_IFACE_PATH = TMP_PATH .. "/iface"
function log(...) function log(...)
local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ")
@ -29,6 +30,16 @@ function log(...)
end end
end end
function set_cache_var(key, val)
sys.call(string.format('/usr/share/passwall/app.sh set_cache_var %s "%s"', key, val))
end
function get_cache_var(key)
local val = sys.exec(string.format('echo -n $(/usr/share/passwall/app.sh get_cache_var %s)', key))
if val == "" then val = nil end
return val
end
function exec_call(cmd) function exec_call(cmd)
local process = io.popen(cmd .. '; echo -e "\n$?"') local process = io.popen(cmd .. '; echo -e "\n$?"')
local lines = {} local lines = {}
@ -98,8 +109,8 @@ end
function curl_proxy(url, file, args) function curl_proxy(url, file, args)
--使用代理 --使用代理
local socks_server = luci.sys.exec("[ -f /tmp/etc/passwall/acl/default/TCP_SOCKS_server ] && echo -n $(cat /tmp/etc/passwall/acl/default/TCP_SOCKS_server) || echo -n ''") local socks_server = get_cache_var("GLOBAL_TCP_SOCKS_server")
if socks_server ~= "" then if socks_server and socks_server ~= "" then
if not args then args = {} end if not args then args = {} end
local tmp_args = clone(args) local tmp_args = clone(args)
tmp_args[#tmp_args + 1] = "-x socks5h://" .. socks_server tmp_args[#tmp_args + 1] = "-x socks5h://" .. socks_server

View File

@ -688,7 +688,7 @@ function gen_config_server(node)
bind_interface = node.outbound_node_iface, bind_interface = node.outbound_node_iface,
routing_mark = 255, routing_mark = 255,
} }
sys.call("mkdir -p /tmp/etc/passwall/iface && touch /tmp/etc/passwall/iface/" .. node.outbound_node_iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.outbound_node_iface))
else else
local outbound_node_t = uci:get_all("passwall", node.outbound_node) local outbound_node_t = uci:get_all("passwall", node.outbound_node)
if node.outbound_node == "_socks" or node.outbound_node == "_http" then if node.outbound_node == "_socks" or node.outbound_node == "_http" then
@ -880,6 +880,7 @@ function gen_config(var)
local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name) local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name)
if not node or not outbound or not outbounds_table then return nil end if not node or not outbound or not outbounds_table then return nil end
local default_outTag = outbound.tag local default_outTag = outbound.tag
local last_insert_outbound
if node.shadowtls == "1" then if node.shadowtls == "1" then
local _node = { local _node = {
@ -896,14 +897,31 @@ function gen_config(var)
} }
local shadowtls_outbound = gen_outbound(nil, _node, outbound.tag .. "_shadowtls") local shadowtls_outbound = gen_outbound(nil, _node, outbound.tag .. "_shadowtls")
if shadowtls_outbound then if shadowtls_outbound then
table.insert(outbounds_table, shadowtls_outbound) last_insert_outbound = shadowtls_outbound
outbound.detour = outbound.tag .. "_shadowtls" outbound.detour = outbound.tag .. "_shadowtls"
outbound.server = nil outbound.server = nil
outbound.server_port = nil outbound.server_port = nil
end end
end end
if node.to_node then if node.chain_proxy == "1" and node.preproxy_node then
if outbound["_flag_proxy_tag"] and outbound["_flag_proxy_tag"] ~= "nil" then
--Ignore
else
local preproxy_node = uci:get_all(appname, node.preproxy_node)
if preproxy_node then
local preproxy_outbound = gen_outbound(nil, preproxy_node)
if preproxy_outbound then
preproxy_outbound.tag = preproxy_node[".name"] .. ":" .. preproxy_node.remarks
outbound.tag = preproxy_outbound.tag .. " -> " .. outbound.tag
outbound.detour = preproxy_outbound.tag
last_insert_outbound = preproxy_outbound
default_outTag = outbound.tag
end
end
end
end
if node.chain_proxy == "2" and node.to_node then
local to_node = uci:get_all(appname, node.to_node) local to_node = uci:get_all(appname, node.to_node)
if to_node then if to_node then
local to_outbound = gen_outbound(nil, to_node) local to_outbound = gen_outbound(nil, to_node)
@ -921,7 +939,7 @@ function gen_config(var)
end end
end end
end end
return default_outTag return default_outTag, last_insert_outbound
end end
if node.protocol == "_shunt" then if node.protocol == "_shunt" then
@ -1006,8 +1024,11 @@ function gen_config(var)
local _outbound = gen_outbound(flag, _node, rule_name, { tag = use_proxy and preproxy_tag or nil }) local _outbound = gen_outbound(flag, _node, rule_name, { tag = use_proxy and preproxy_tag or nil })
if _outbound then if _outbound then
_outbound.tag = _outbound.tag .. ":" .. _node.remarks _outbound.tag = _outbound.tag .. ":" .. _node.remarks
rule_outboundTag = set_outbound_detour(_node, _outbound, outbounds, rule_name) rule_outboundTag, last_insert_outbound = set_outbound_detour(_node, _outbound, outbounds, rule_name)
table.insert(outbounds, _outbound) table.insert(outbounds, _outbound)
if last_insert_outbound then
table.insert(outbounds, last_insert_outbound)
end
end end
end end
elseif _node.protocol == "_iface" then elseif _node.protocol == "_iface" then
@ -1020,7 +1041,7 @@ function gen_config(var)
} }
table.insert(outbounds, _outbound) table.insert(outbounds, _outbound)
rule_outboundTag = _outbound.tag rule_outboundTag = _outbound.tag
sys.call("touch /tmp/etc/passwall/iface/" .. _node.iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, _node.iface))
end end
end end
end end
@ -1197,14 +1218,17 @@ function gen_config(var)
} }
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
COMMON.default_outbound_tag = outbound.tag COMMON.default_outbound_tag = outbound.tag
sys.call("touch /tmp/etc/passwall/iface/" .. node.iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.iface))
end end
else else
local outbound = gen_outbound(flag, node) local outbound = gen_outbound(flag, node)
if outbound then if outbound then
outbound.tag = outbound.tag .. ":" .. node.remarks outbound.tag = outbound.tag .. ":" .. node.remarks
COMMON.default_outbound_tag = set_outbound_detour(node, outbound, outbounds) COMMON.default_outbound_tag, last_insert_outbound = set_outbound_detour(node, outbound, outbounds)
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
if last_insert_outbound then
table.insert(outbounds, last_insert_outbound)
end
end end
end end
end end
@ -1452,6 +1476,9 @@ function gen_config(var)
tag = "block" tag = "block"
}) })
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
if (not value["_flag_proxy_tag"] or value["_flag_proxy_tag"] == "nil") and not value.detour and value["_id"] and value.server and value.server_port then
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
end
for k, v in pairs(config.outbounds[index]) do for k, v in pairs(config.outbounds[index]) do
if k:find("_") == 1 then if k:find("_") == 1 then
config.outbounds[index][k] = nil config.outbounds[index][k] = nil

View File

@ -417,7 +417,7 @@ function gen_config_server(node)
} }
} }
} }
sys.call("mkdir -p /tmp/etc/passwall/iface && touch /tmp/etc/passwall/iface/" .. node.outbound_node_iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.outbound_node_iface))
else else
local outbound_node_t = uci:get_all("passwall", node.outbound_node) local outbound_node_t = uci:get_all("passwall", node.outbound_node)
if node.outbound_node == "_socks" or node.outbound_node == "_http" then if node.outbound_node == "_socks" or node.outbound_node == "_http" then
@ -780,9 +780,30 @@ function gen_config(var)
local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name) local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name)
if not node or not outbound or not outbounds_table then return nil end if not node or not outbound or not outbounds_table then return nil end
local default_out_tag = outbound.tag local default_outTag = outbound.tag
local last_insert_outbound
if node.to_node then if node.chain_proxy == "1" and node.preproxy_node then
if outbound["_flag_proxy_tag"] and outbound["_flag_proxy_tag"] ~= "nil" then
--Ignore
else
local preproxy_node = uci:get_all(appname, node.preproxy_node)
if preproxy_node then
local preproxy_outbound = gen_outbound(nil, preproxy_node)
if preproxy_outbound then
preproxy_outbound.tag = preproxy_node[".name"] .. ":" .. preproxy_node.remarks
outbound.tag = preproxy_outbound.tag .. " -> " .. outbound.tag
outbound.proxySettings = {
tag = preproxy_outbound.tag,
transportLayer = true
}
last_insert_outbound = preproxy_outbound
default_outTag = outbound.tag
end
end
end
end
if node.chain_proxy == "2" and node.to_node then
local to_node = uci:get_all(appname, node.to_node) local to_node = uci:get_all(appname, node.to_node)
if to_node then if to_node then
local to_outbound = gen_outbound(nil, to_node) local to_outbound = gen_outbound(nil, to_node)
@ -799,11 +820,11 @@ function gen_config(var)
transportLayer = true transportLayer = true
} }
table.insert(outbounds_table, to_outbound) table.insert(outbounds_table, to_outbound)
default_out_tag = to_outbound.tag default_outTag = to_outbound.tag
end end
end end
end end
return default_out_tag return default_outTag, last_insert_outbound
end end
if node.protocol == "_shunt" then if node.protocol == "_shunt" then
@ -901,12 +922,15 @@ function gen_config(var)
local outbound_tag local outbound_tag
if outbound then if outbound then
outbound.tag = outbound.tag .. ":" .. _node.remarks outbound.tag = outbound.tag .. ":" .. _node.remarks
outbound_tag = set_outbound_detour(_node, outbound, outbounds, rule_name) outbound_tag, last_insert_outbound = set_outbound_detour(_node, outbound, outbounds, rule_name)
if rule_name == "default" then if rule_name == "default" then
table.insert(outbounds, 1, outbound) table.insert(outbounds, 1, outbound)
else else
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
end end
if last_insert_outbound then
table.insert(outbounds, last_insert_outbound)
end
end end
return outbound_tag, nil return outbound_tag, nil
elseif _node.protocol == "_balancing" then elseif _node.protocol == "_balancing" then
@ -926,7 +950,7 @@ function gen_config(var)
} }
outbound_tag = outbound.tag outbound_tag = outbound.tag
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
sys.call("touch /tmp/etc/passwall/iface/" .. _node.iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, _node.iface))
end end
return outbound_tag, nil return outbound_tag, nil
end end
@ -1075,14 +1099,17 @@ function gen_config(var)
} }
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
COMMON.default_outbound_tag = outbound.tag COMMON.default_outbound_tag = outbound.tag
sys.call("touch /tmp/etc/passwall/iface/" .. node.iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.iface))
end end
else else
local outbound = gen_outbound(flag, node, nil, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.fragment == "1" or nil }) local outbound = gen_outbound(flag, node, nil, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.fragment == "1" or nil })
if outbound then if outbound then
outbound.tag = outbound.tag .. ":" .. node.remarks outbound.tag = outbound.tag .. ":" .. node.remarks
COMMON.default_outbound_tag = set_outbound_detour(node, outbound, outbounds) COMMON.default_outbound_tag, last_insert_outbound = set_outbound_detour(node, outbound, outbounds)
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
if last_insert_outbound then
table.insert(outbounds, last_insert_outbound)
end
end end
routing = { routing = {
domainStrategy = "AsIs", domainStrategy = "AsIs",
@ -1369,6 +1396,9 @@ function gen_config(var)
end end
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
if (not value["_flag_proxy_tag"] or value["_flag_proxy_tag"] == "nil") and value["_id"] and value.server and value.server_port then
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
end
for k, v in pairs(config.outbounds[index]) do for k, v in pairs(config.outbounds[index]) do
if k:find("_") == 1 then if k:find("_") == 1 then
config.outbounds[index][k] = nil config.outbounds[index][k] = nil

View File

@ -221,6 +221,10 @@ table td, .table .td {
dom.title = "当前TCP节点"; dom.title = "当前TCP节点";
//var v = "<a style='color: red'>当前TCP节点</a>" + document.getElementById("cbid.passwall." + id + ".remarks").value; //var v = "<a style='color: red'>当前TCP节点</a>" + document.getElementById("cbid.passwall." + id + ".remarks").value;
//document.getElementById("cbi-passwall-" + id + "-remarks").innerHTML = v; //document.getElementById("cbi-passwall-" + id + "-remarks").innerHTML = v;
var tds = dom.getElementsByTagName("td")
for (var j = 0; j < tds.length; j++) {
tds[j].classList.add("_now_use");
}
} }
} }
id = result["UDP"]; id = result["UDP"];
@ -229,6 +233,10 @@ table td, .table .td {
if (dom) { if (dom) {
dom.classList.add("_now_use"); dom.classList.add("_now_use");
dom.title = "当前UDP节点"; dom.title = "当前UDP节点";
var tds = dom.getElementsByTagName("td")
for (var j = 0; j < tds.length; j++) {
tds[j].classList.add("_now_use");
}
} }
} }
} }
@ -295,8 +303,6 @@ table td, .table .td {
); );
} }
} }
get_now_use_node();
/* 自动Ping */ /* 自动Ping */
if (auto_detection_time == "icmp" || auto_detection_time == "tcping") { if (auto_detection_time == "icmp" || auto_detection_time == "tcping") {
@ -417,6 +423,8 @@ table td, .table .td {
console.error(err); console.error(err);
} }
} }
get_now_use_node();
if (true) { if (true) {
var str = ""; var str = "";

View File

@ -1720,7 +1720,10 @@ msgstr "延迟ms"
msgid "If is domain name, The requested domain name will be resolved to IP before connect." msgid "If is domain name, The requested domain name will be resolved to IP before connect."
msgstr "如果是域名,域名将在请求发出之前解析为 IP。" msgstr "如果是域名,域名将在请求发出之前解析为 IP。"
msgid "Landing node" msgid "Chain Proxy"
msgstr "链式代理"
msgid "Landing Node"
msgstr "落地节点" msgstr "落地节点"
msgid "Only support a layer of proxy." msgid "Only support a layer of proxy."

View File

@ -9,7 +9,6 @@ CONFIG=passwall
TMP_PATH=/tmp/etc/$CONFIG TMP_PATH=/tmp/etc/$CONFIG
TMP_BIN_PATH=$TMP_PATH/bin TMP_BIN_PATH=$TMP_PATH/bin
TMP_SCRIPT_FUNC_PATH=$TMP_PATH/script_func TMP_SCRIPT_FUNC_PATH=$TMP_PATH/script_func
TMP_ID_PATH=$TMP_PATH/id
TMP_ROUTE_PATH=$TMP_PATH/route TMP_ROUTE_PATH=$TMP_PATH/route
TMP_ACL_PATH=$TMP_PATH/acl TMP_ACL_PATH=$TMP_PATH/acl
TMP_IFACE_PATH=$TMP_PATH/iface TMP_IFACE_PATH=$TMP_PATH/iface
@ -373,6 +372,20 @@ get_geoip() {
fi fi
} }
set_cache_var() {
local key="${1}"
shift 1
local val="$@"
[ -n "${key}" ] && [ -n "${val}" ] && echo "${key}=\"${val}\"" >> $TMP_PATH/var
}
get_cache_var() {
local key="${1}"
[ -n "${key}" ] && [ -s "$TMP_PATH/var" ] && {
echo $(cat $TMP_PATH/var | grep "^${key}=" | awk -F '=' '{print $2}' | tail -n 1 | awk -F'"' '{print $2}')
}
}
run_ipt2socks() { run_ipt2socks() {
local flag proto tcp_tproxy local_port socks_address socks_port socks_username socks_password log_file local flag proto tcp_tproxy local_port socks_address socks_port socks_username socks_password log_file
local _extra_param="" local _extra_param=""
@ -712,6 +725,8 @@ run_socks() {
fi fi
} }
unset http_flag unset http_flag
[ "${server_host}" != "127.0.0.1" ] && [ "$type" != "sing-box" ] && [ "$type" != "xray" ] && echo "${node}" >> $TMP_PATH/direct_node_list
} }
run_redir() { run_redir() {
@ -1064,11 +1079,12 @@ run_redir() {
[ "$tcp_node_socks" = "1" ] && { [ "$tcp_node_socks" = "1" ] && {
TCP_SOCKS_server="127.0.0.1:$tcp_node_socks_port" TCP_SOCKS_server="127.0.0.1:$tcp_node_socks_port"
echo "${TCP_SOCKS_server}" > ${GLOBAL_ACL_PATH}/TCP_SOCKS_server set_cache_var "GLOBAL_TCP_SOCKS_server" "${TCP_SOCKS_server}"
} }
;; ;;
esac esac
unset tcp_node_socks_flag tcp_node_http_flag unset tcp_node_socks_flag tcp_node_http_flag
[ "$type" != "sing-box" ] && [ "$type" != "xray" ] && echo "${node}" >> $TMP_PATH/direct_node_list
return 0 return 0
} }
@ -1083,7 +1099,7 @@ start_redir() {
local port=$(echo $(get_new_port $current_port $proto)) local port=$(echo $(get_new_port $current_port $proto))
eval ${proto}_REDIR=$port eval ${proto}_REDIR=$port
run_redir node=$node proto=${proto} bind=0.0.0.0 local_port=$port config_file=$config_file log_file=$log_file run_redir node=$node proto=${proto} bind=0.0.0.0 local_port=$port config_file=$config_file log_file=$log_file
echo $node > ${GLOBAL_ACL_PATH}/${proto}.id set_cache_var "GLOBAL_${proto}_node" "$node"
else else
[ "${proto}" = "UDP" ] && [ "$TCP_UDP" = "1" ] && return [ "${proto}" = "UDP" ] && [ "$TCP_UDP" = "1" ] && return
echolog "${proto}节点没有选择或为空,不代理${proto}" echolog "${proto}节点没有选择或为空,不代理${proto}"
@ -1111,7 +1127,7 @@ start_socks() {
local http_port=$(config_n_get $id http_port 0) local http_port=$(config_n_get $id http_port 0)
local http_config_file="HTTP2SOCKS_${id}.json" local http_config_file="HTTP2SOCKS_${id}.json"
run_socks flag=$id node=$node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file run_socks flag=$id node=$node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file
echo $node > $TMP_ID_PATH/socks_${id} set_cache_var "socks_${id}" "$node"
#自动切换逻辑 #自动切换逻辑
local enable_autoswitch=$(config_n_get $id enable_autoswitch 0) local enable_autoswitch=$(config_n_get $id enable_autoswitch 0)
@ -1145,7 +1161,9 @@ socks_node_switch() {
local http_config_file="HTTP2SOCKS_${flag}.json" local http_config_file="HTTP2SOCKS_${flag}.json"
LOG_FILE="/dev/null" LOG_FILE="/dev/null"
run_socks flag=$flag node=$new_node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file run_socks flag=$flag node=$new_node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file
echo $new_node > $TMP_ID_PATH/socks_${flag} set_cache_var "socks_${flag}" "$new_node"
local USE_TABLES=$(get_cache_var "USE_TABLES")
[ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh filter_direct_node_list
} }
} }
@ -1582,7 +1600,7 @@ start_dns() {
-TCP_NODE ${TCP_NODE} -DEFAULT_PROXY_MODE ${TCP_PROXY_MODE} -NO_PROXY_IPV6 ${DNSMASQ_FILTER_PROXY_IPV6:-0} -NFTFLAG ${nftflag:-0} \ -TCP_NODE ${TCP_NODE} -DEFAULT_PROXY_MODE ${TCP_PROXY_MODE} -NO_PROXY_IPV6 ${DNSMASQ_FILTER_PROXY_IPV6:-0} -NFTFLAG ${nftflag:-0} \
-NO_LOGIC_LOG ${NO_LOGIC_LOG:-0} -NO_LOGIC_LOG ${NO_LOGIC_LOG:-0}
ln_run "$(first_type dnsmasq)" "dnsmasq_default" "/dev/null" -C ${GLOBAL_DNSMASQ_CONF} -x ${GLOBAL_ACL_PATH}/dnsmasq.pid ln_run "$(first_type dnsmasq)" "dnsmasq_default" "/dev/null" -C ${GLOBAL_DNSMASQ_CONF} -x ${GLOBAL_ACL_PATH}/dnsmasq.pid
echo "${GLOBAL_DNSMASQ_PORT}" > ${GLOBAL_ACL_PATH}/var_redirect_dns_port set_cache_var "ACL_default_dns_port" "${GLOBAL_DNSMASQ_PORT}"
DNS_REDIRECT_PORT=${GLOBAL_DNSMASQ_PORT} DNS_REDIRECT_PORT=${GLOBAL_DNSMASQ_PORT}
fi fi
} }
@ -1624,7 +1642,7 @@ delete_ip2route() {
start_haproxy() { start_haproxy() {
[ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && return [ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && return
haproxy_path=${TMP_PATH}/haproxy haproxy_path=$TMP_PATH/haproxy
haproxy_conf="config.cfg" haproxy_conf="config.cfg"
lua $APP_PATH/haproxy.lua -path ${haproxy_path} -conf ${haproxy_conf} -dns ${LOCAL_DNS} lua $APP_PATH/haproxy.lua -path ${haproxy_path} -conf ${haproxy_conf} -dns ${LOCAL_DNS}
ln_run "$(first_type haproxy)" haproxy "/dev/null" -f "${haproxy_path}/${haproxy_conf}" ln_run "$(first_type haproxy)" haproxy "/dev/null" -f "${haproxy_path}/${haproxy_conf}"
@ -1782,7 +1800,7 @@ acl_app() {
-TCP_NODE $tcp_node -DEFAULT_PROXY_MODE ${tcp_proxy_mode} -NO_PROXY_IPV6 ${dnsmasq_filter_proxy_ipv6:-0} -NFTFLAG ${nftflag:-0} \ -TCP_NODE $tcp_node -DEFAULT_PROXY_MODE ${tcp_proxy_mode} -NO_PROXY_IPV6 ${dnsmasq_filter_proxy_ipv6:-0} -NFTFLAG ${nftflag:-0} \
-NO_LOGIC_LOG 1 -NO_LOGIC_LOG 1
ln_run "$(first_type dnsmasq)" "dnsmasq_${sid}" "/dev/null" -C ${dnsmasq_conf} -x ${acl_path}/dnsmasq.pid ln_run "$(first_type dnsmasq)" "dnsmasq_${sid}" "/dev/null" -C ${dnsmasq_conf} -x ${acl_path}/dnsmasq.pid
echo "${dnsmasq_port}" > ${acl_path}/var_redirect_dns_port set_cache_var "ACL_${sid}_dns_port" "${dnsmasq_port}"
eval node_${tcp_node}_$(echo -n "${tcp_proxy_mode}${remote_dns}" | md5sum | cut -d " " -f1)=${dnsmasq_port} eval node_${tcp_node}_$(echo -n "${tcp_proxy_mode}${remote_dns}" | md5sum | cut -d " " -f1)=${dnsmasq_port}
} }
_redir_port=$(eval echo \${node_${tcp_node}_redir_port}) _redir_port=$(eval echo \${node_${tcp_node}_redir_port})
@ -1795,7 +1813,7 @@ acl_app() {
_dns_port=$(eval echo \${node_${tcp_node}_$(echo -n "${remote_dns}" | md5sum | cut -d " " -f1)}) _dns_port=$(eval echo \${node_${tcp_node}_$(echo -n "${remote_dns}" | md5sum | cut -d " " -f1)})
run_dns ${_dns_port} run_dns ${_dns_port}
else else
[ -n "${_dnsmasq_port}" ] && echo "${_dnsmasq_port}" > ${acl_path}/var_redirect_dns_port [ -n "${_dnsmasq_port}" ] && set_cache_var "ACL_${sid}_dns_port" "${_dnsmasq_port}"
fi fi
else else
socks_port=$(get_new_port $(expr $socks_port + 1)) socks_port=$(get_new_port $(expr $socks_port + 1))
@ -1833,10 +1851,10 @@ acl_app() {
fi fi
run_dns ${_dns_port} run_dns ${_dns_port}
fi fi
echo "${tcp_node}" > ${acl_path}/var_tcp_node set_cache_var "ACL_${sid}_tcp_node" "${tcp_node}"
} }
fi fi
echo "${tcp_port}" > ${acl_path}/var_tcp_port set_cache_var "ACL_${sid}_tcp_port" "${tcp_port}"
} }
[ "$udp_node" != "nil" ] && { [ "$udp_node" != "nil" ] && {
[ "$udp_node" = "tcp" ] && udp_node=$tcp_node [ "$udp_node" = "tcp" ] && udp_node=$tcp_node
@ -1885,12 +1903,11 @@ acl_app() {
run_ipt2socks flag=acl_${udp_node} local_port=$redir_port socks_address=127.0.0.1 socks_port=$socks_port log_file=$log_file run_ipt2socks flag=acl_${udp_node} local_port=$redir_port socks_address=127.0.0.1 socks_port=$socks_port log_file=$log_file
fi fi
fi fi
echo "${udp_node}" > ${acl_path}/var_udp_node set_cache_var "ACL_${sid}_udp_node" "${udp_node}"
fi fi
} }
fi fi
echo "${udp_port}" > ${acl_path}/var_udp_port set_cache_var "ACL_${sid}_udp_port" "${udp_port}"
udp_flag=1
} }
unset enabled sid remarks sources interface use_global_config tcp_node udp_node use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode filter_proxy_ipv6 dns_mode remote_dns v2ray_dns_mode remote_dns_doh dns_client_ip unset enabled sid remarks sources interface use_global_config tcp_node udp_node use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode filter_proxy_ipv6 dns_mode remote_dns v2ray_dns_mode remote_dns_doh dns_client_ip
unset _ip _mac _iprange _ipset _ip_or_mac source_list tcp_port udp_port config_file _extra_param unset _ip _mac _iprange _ipset _ip_or_mac source_list tcp_port udp_port config_file _extra_param
@ -1951,9 +1968,19 @@ start() {
start_dns start_dns
} }
[ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start [ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start
[ ! -s "${GLOBAL_ACL_PATH}/var_redirect_dns_port" ] && { set_cache_var "USE_TABLES" "$USE_TABLES"
lua $APP_PATH/helper_dnsmasq.lua logic_restart -LOG 1 [ -z $(get_cache_var "ACL_default_dns_port") ] && lua $APP_PATH/helper_dnsmasq.lua logic_restart -LOG 1
} if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then
bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables)
set_cache_var "bak_bridge_nf_ipt" "$bridge_nf_ipt"
sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1
[ "$PROXY_IPV6" == "1" ] && {
bridge_nf_ip6t=$(sysctl -e -n net.bridge.bridge-nf-call-ip6tables)
set_cache_var "bak_bridge_nf_ip6t" "$bridge_nf_ip6t"
sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1
}
fi
start_crontab start_crontab
echolog "运行完成!\n" echolog "运行完成!\n"
} }
@ -1972,10 +1999,12 @@ stop() {
source $APP_PATH/helper_smartdns.sh del source $APP_PATH/helper_smartdns.sh del
rm -rf $GLOBAL_DNSMASQ_CONF rm -rf $GLOBAL_DNSMASQ_CONF
rm -rf $GLOBAL_DNSMASQ_CONF_PATH rm -rf $GLOBAL_DNSMASQ_CONF_PATH
[ ! -s "${GLOBAL_ACL_PATH}/var_redirect_dns_port" ] && lua $APP_PATH/helper_dnsmasq.lua restart -LOG 0 [ -z $(get_cache_var "ACL_default_dns_port") ] && lua $APP_PATH/helper_dnsmasq.lua restart -LOG 0
[ -s "$TMP_PATH/bridge_nf_ipt" ] && sysctl -w net.bridge.bridge-nf-call-iptables=$(cat $TMP_PATH/bridge_nf_ipt) >/dev/null 2>&1 bak_bridge_nf_ipt=$(get_cache_var "bak_bridge_nf_ipt")
[ -s "$TMP_PATH/bridge_nf_ip6t" ] && sysctl -w net.bridge.bridge-nf-call-ip6tables=$(cat $TMP_PATH/bridge_nf_ip6t) >/dev/null 2>&1 [ -n "${bak_bridge_nf_ipt}" ] && sysctl -w net.bridge.bridge-nf-call-iptables=${bak_bridge_nf_ipt} >/dev/null 2>&1
rm -rf ${TMP_PATH} bak_bridge_nf_ip6t=$(get_cache_var "bak_bridge_nf_ip6t")
[ -n "${bak_bridge_nf_ip6t}" ] && sysctl -w net.bridge.bridge-nf-call-ip6tables=${bak_bridge_nf_ip6t} >/dev/null 2>&1
rm -rf $TMP_PATH
rm -rf /tmp/lock/${CONFIG}_socks_auto_switch* rm -rf /tmp/lock/${CONFIG}_socks_auto_switch*
echolog "清空并关闭相关程序和缓存完成。" echolog "清空并关闭相关程序和缓存完成。"
exit 0 exit 0
@ -2069,7 +2098,7 @@ DNSMASQ_FILTER_PROXY_IPV6=${FILTER_PROXY_IPV6}
export V2RAY_LOCATION_ASSET=$(config_t_get global_rules v2ray_location_asset "/usr/share/v2ray/") export V2RAY_LOCATION_ASSET=$(config_t_get global_rules v2ray_location_asset "/usr/share/v2ray/")
export XRAY_LOCATION_ASSET=$V2RAY_LOCATION_ASSET export XRAY_LOCATION_ASSET=$V2RAY_LOCATION_ASSET
mkdir -p /tmp/etc $TMP_PATH $TMP_BIN_PATH $TMP_SCRIPT_FUNC_PATH $TMP_ID_PATH $TMP_ROUTE_PATH $TMP_ACL_PATH $TMP_IFACE_PATH $TMP_PATH2 mkdir -p /tmp/etc $TMP_PATH $TMP_BIN_PATH $TMP_SCRIPT_FUNC_PATH $TMP_ROUTE_PATH $TMP_ACL_PATH $TMP_PATH2
arg1=$1 arg1=$1
shift shift
@ -2092,6 +2121,12 @@ socks_node_switch)
echolog) echolog)
echolog $@ echolog $@
;; ;;
get_cache_var)
get_cache_var $@
;;
set_cache_var)
set_cache_var $@
;;
stop) stop)
stop stop
;; ;;

View File

@ -90,8 +90,8 @@ end
function logic_restart(var) function logic_restart(var)
local LOG = var["-LOG"] local LOG = var["-LOG"]
local file = io.open(api.TMP_PATH .. "/default_DNS", "r") local DEFAULT_DNS = api.get_cache_var("DEFAULT_DNS")
if file then if DEFAULT_DNS then
backup_servers() backup_servers()
--sys.call("sed -i '/list server/d' /etc/config/dhcp >/dev/null 2>&1") --sys.call("sed -i '/list server/d' /etc/config/dhcp >/dev/null 2>&1")
local dns_table = {} local dns_table = {}
@ -646,9 +646,7 @@ function add_rule(var)
end end
if FLAG == "default" then if FLAG == "default" then
local f_out = io.open("/tmp/etc/passwall/default_DNS", "a") api.set_cache_var("DEFAULT_DNS", DEFAULT_DNS)
f_out:write(DEFAULT_DNS)
f_out:close()
end end
end end
if #conf_lines > 0 then if #conf_lines > 0 then

View File

@ -214,11 +214,11 @@ load_acl() {
[ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS [ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS
[ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS [ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
[ -s "${TMP_ACL_PATH}/${sid}/var_tcp_node" ] && tcp_node=$(cat ${TMP_ACL_PATH}/${sid}/var_tcp_node) [ -n $(get_cache_var "ACL_${sid}_tcp_node") ] && tcp_node=$(get_cache_var "ACL_${sid}_tcp_node")
[ -s "${TMP_ACL_PATH}/${sid}/var_udp_node" ] && udp_node=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_node) [ -n $(get_cache_var "ACL_${sid}_udp_node") ] && udp_node=$(get_cache_var "ACL_${sid}_udp_node")
[ -s "${TMP_ACL_PATH}/${sid}/var_tcp_port" ] && tcp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_tcp_port) [ -n $(get_cache_var "ACL_${sid}_tcp_port") ] && tcp_port=$(get_cache_var "ACL_${sid}_tcp_port")
[ -s "${TMP_ACL_PATH}/${sid}/var_udp_port" ] && udp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_port) [ -n $(get_cache_var "ACL_${sid}_udp_port") ] && udp_port=$(get_cache_var "ACL_${sid}_udp_port")
[ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) [ -n $(get_cache_var "ACL_${sid}_dns_port") ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
use_shunt_tcp=0 use_shunt_tcp=0
use_shunt_udp=0 use_shunt_udp=0
@ -640,7 +640,6 @@ load_acl() {
} }
echolog " - ${msg2}" echolog " - ${msg2}"
udp_flag=1
} }
fi fi
$ipt_m -A PSW $(comment "默认") -p udp -j RETURN $ipt_m -A PSW $(comment "默认") -p udp -j RETURN
@ -663,111 +662,50 @@ filter_vpsip() {
echolog " - [$?]加入所有IPv6节点到ipset[$IPSET_VPSLIST6]直连完成" echolog " - [$?]加入所有IPv6节点到ipset[$IPSET_VPSLIST6]直连完成"
} }
filter_server_port() {
local address=${1}
local port=${2}
local stream=${3}
stream=$(echo ${3} | tr 'A-Z' 'a-z')
local _is_tproxy ipt_tmp
ipt_tmp=$ipt_n
_is_tproxy=${is_tproxy}
[ "$stream" == "udp" ] && _is_tproxy="TPROXY"
[ -n "${_is_tproxy}" ] && ipt_tmp=$ipt_m
for _ipt in 4 6; do
[ "$_ipt" == "4" ] && _ipt=$ipt_tmp
[ "$_ipt" == "6" ] && _ipt=$ip6t_m
$_ipt -n -L PSW_OUTPUT | grep -q "${address}:${port}"
if [ $? -ne 0 ]; then
$_ipt -I PSW_OUTPUT $(comment "${address}:${port}") -p $stream -d $address --dport $port -j RETURN 2>/dev/null
fi
done
}
filter_node() { filter_node() {
local proxy_node=${1} local node=${1}
local stream=$(echo ${2} | tr 'A-Z' 'a-z') local stream=${2}
local proxy_port=${3} if [ -n "$node" ] && [ "$node" != "nil" ]; then
local address=$(config_n_get $node address)
filter_rules() { local port=$(config_n_get $node port)
local node=${1} [ -z "$address" ] && [ -z "$port" ] && {
local stream=${2}
local _proxy=${3}
local _port=${4}
local _is_tproxy ipt_tmp msg msg2
if [ -n "$node" ] && [ "$node" != "nil" ]; then
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
local address=$(config_n_get $node address)
local port=$(config_n_get $node port)
[ -z "$address" ] && [ -z "$port" ] && {
echolog " - 节点配置不正常,略过"
return 1
}
ipt_tmp=$ipt_n
_is_tproxy=${is_tproxy}
[ "$stream" == "udp" ] && _is_tproxy="TPROXY"
if [ -n "${_is_tproxy}" ]; then
ipt_tmp=$ipt_m
msg="TPROXY"
else
msg="REDIRECT"
fi
else
echolog " - 节点配置不正常,略过"
return 1 return 1
fi
local ADD_INDEX=$FORCE_INDEX
for _ipt in 4 6; do
[ "$_ipt" == "4" ] && _ipt=$ipt_tmp && _set_name=$IPSET_VPSLIST
[ "$_ipt" == "6" ] && _ipt=$ip6t_m && _set_name=$IPSET_VPSLIST6
$_ipt -n -L PSW_OUTPUT | grep -q "${address}:${port}"
if [ $? -ne 0 ]; then
local dst_rule="-j PSW_RULE"
msg2="按规则路由(${msg})"
[ "$_ipt" == "$ipt_m" -o "$_ipt" == "$ip6t_m" ] || {
dst_rule=$(REDIRECT $_port)
msg2="套娃使用(${msg}:${port} -> ${_port})"
}
[ -n "$_proxy" ] && [ "$_proxy" == "1" ] && [ -n "$_port" ] || {
ADD_INDEX=$(RULE_LAST_INDEX "$_ipt" PSW_OUTPUT "$_set_name" $FORCE_INDEX)
dst_rule=" -j RETURN"
msg2="直连代理"
}
$_ipt -I PSW_OUTPUT $ADD_INDEX $(comment "${address}:${port}") -p $stream -d $address --dport $port $dst_rule 2>/dev/null
else
msg2="已配置过的节点,"
fi
done
msg="[$?]$(echo ${2} | tr 'a-z' 'A-Z')${msg2}使用链${ADD_INDEX},节点(${type}${address}:${port}"
#echolog " - ${msg}"
}
local proxy_protocol=$(config_n_get $proxy_node protocol)
local proxy_type=$(echo $(config_n_get $proxy_node type nil) | tr 'A-Z' 'a-z')
[ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 1
if [ "$proxy_protocol" == "_balancing" ]; then
#echolog " - 多节点负载均衡(${proxy_type}..."
proxy_node=$(config_n_get $proxy_node balancing_node)
for _node in $proxy_node; do
filter_rules "$_node" "$stream"
done
elif [ "$proxy_protocol" == "_shunt" ]; then
#echolog " - 按请求目的地址分流(${proxy_type}..."
local preproxy_enabled=$(config_n_get $proxy_node preproxy_enabled 0)
[ "$preproxy_enabled" == "1" ] && {
local preproxy_node=$(config_n_get $proxy_node main_node nil)
[ "$preproxy_node" != "nil" ] && {
local preproxy_node_address=$(config_n_get $preproxy_node address)
if [ -n "$preproxy_node_address" ]; then
filter_rules $preproxy_node $stream
else
preproxy_enabled=0
fi
}
} }
local default_node=$(config_n_get $proxy_node default_node _direct) filter_server_port $address $port $stream
if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then filter_server_port $address $port $stream
local default_proxy_tag=$(config_n_get $proxy_node default_proxy_tag nil)
[ "$default_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && default_proxy_tag="nil"
[ "$default_proxy_tag" == "nil" ] && filter_rules $default_node $stream
fi
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
for shunt_id in $shunt_ids; do
local shunt_node=$(config_n_get $proxy_node "${shunt_id}" nil)
[ "$shunt_node" == "nil" -o "$shunt_node" == "_default" -o "$shunt_node" == "_direct" -o "$shunt_node" == "_blackhole" ] && continue
local shunt_node_address=$(config_n_get $shunt_node address)
[ -z "$shunt_node_address" ] && continue
local shunt_proxy_tag=$(config_n_get $proxy_node "${shunt_id}_proxy_tag" nil)
[ "$shunt_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && shunt_proxy_tag="nil"
[ "$shunt_proxy_tag" == "nil" ] && filter_rules $shunt_node $stream
done
else
#echolog " - 普通节点(${proxy_type}..."
filter_rules "$proxy_node" "$stream"
fi fi
} }
filter_direct_node_list() {
[ ! -s "$TMP_PATH/direct_node_list" ] && return
for _node_id in $(cat $TMP_PATH/direct_node_list | awk '!seen[$0]++'); do
filter_node "$_node_id" TCP
filter_node "$_node_id" UDP
unset _node_id
done
}
add_firewall_rule() { add_firewall_rule() {
echolog "开始加载防火墙规则..." echolog "开始加载防火墙规则..."
ipset -! create $IPSET_LOCALLIST nethash maxelem 1048576 ipset -! create $IPSET_LOCALLIST nethash maxelem 1048576
@ -1075,44 +1013,8 @@ add_firewall_rule() {
ip -6 route add local ::/0 dev lo table 100 ip -6 route add local ::/0 dev lo table 100
[ "$TCP_UDP" = "1" ] && [ "$UDP_NODE" = "nil" ] && UDP_NODE=$TCP_NODE [ "$TCP_UDP" = "1" ] && [ "$UDP_NODE" = "nil" ] && UDP_NODE=$TCP_NODE
# 过滤Socks节点
[ "$SOCKS_ENABLED" = "1" ] && {
local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
#echolog "分析 Socks 服务所使用节点..."
local id enabled node port msg num
for id in $ids; do
enabled=$(config_n_get $id enabled 0)
[ "$enabled" == "1" ] || continue
node=$(config_n_get $id node nil)
port=$(config_n_get $id port 0)
msg="Socks 服务 [:${port}]"
if [ "$node" == "nil" ] || [ "$port" == "0" ]; then
msg="${msg} 未配置完全,略过"
else
filter_node $node TCP > /dev/null 2>&1 &
filter_node $node UDP > /dev/null 2>&1 &
fi
#echolog " - ${msg}"
done
}
[ "$ENABLED_DEFAULT_ACL" == 1 ] && { [ "$ENABLED_DEFAULT_ACL" == 1 ] && {
# 处理轮换节点的分流或套娃
local node port stream switch
for stream in TCP UDP; do
eval "node=\${${stream}_NODE}"
eval "port=\${${stream}_REDIR_PORT}"
#echolog "分析 $stream 代理自动切换..."
[ "$stream" == "UDP" ] && [ "$node" == "tcp" ] && {
eval "node=\${TCP_NODE}"
eval "port=\${TCP_REDIR_PORT}"
}
if [ "$node" != "nil" ] && [ "$(config_get_type $node nil)" != "nil" ]; then
filter_node $node $stream $port > /dev/null 2>&1 &
fi
done
local ipt_tmp=$ipt_n local ipt_tmp=$ipt_n
if [ -n "${is_tproxy}" ]; then if [ -n "${is_tproxy}" ]; then
ipt_tmp=$ipt_m ipt_tmp=$ipt_m
@ -1315,24 +1217,18 @@ add_firewall_rule() {
# 加载ACLS # 加载ACLS
load_acl load_acl
for iface in $(ls ${TMP_IFACE_PATH}); do filter_direct_node_list
$ipt_n -I PSW_OUTPUT -o $iface -j RETURN
$ipt_m -I PSW_OUTPUT -o $iface -j RETURN [ -d "${TMP_IFACE_PATH}" ] && {
done for iface in $(ls ${TMP_IFACE_PATH}); do
$ipt_n -I PSW_OUTPUT -o $iface -j RETURN
$ipt_m -I PSW_OUTPUT -o $iface -j RETURN
done
}
$ipt_n -I PREROUTING $(comment "PSW") -m mark --mark 1 -j RETURN $ipt_n -I PREROUTING $(comment "PSW") -m mark --mark 1 -j RETURN
$ip6t_n -I PREROUTING $(comment "PSW") -m mark --mark 1 -j RETURN $ip6t_n -I PREROUTING $(comment "PSW") -m mark --mark 1 -j RETURN
[ -n "${is_tproxy}" -o -n "${udp_flag}" ] && {
bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables)
echo -n $bridge_nf_ipt > $TMP_PATH/bridge_nf_ipt
sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1
[ "$PROXY_IPV6" == "1" ] && {
bridge_nf_ip6t=$(sysctl -e -n net.bridge.bridge-nf-call-ip6tables)
echo -n $bridge_nf_ip6t > $TMP_PATH/bridge_nf_ip6t
sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1
}
}
echolog "防火墙规则加载完成!" echolog "防火墙规则加载完成!"
} }
@ -1528,6 +1424,9 @@ get_wan_ip)
get_wan6_ip) get_wan6_ip)
get_wan6_ip get_wan6_ip
;; ;;
filter_direct_node_list)
filter_direct_node_list
;;
stop) stop)
stop stop
;; ;;

View File

@ -274,11 +274,11 @@ load_acl() {
[ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS [ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS
[ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS [ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
[ -s "${TMP_ACL_PATH}/${sid}/var_tcp_node" ] && tcp_node=$(cat ${TMP_ACL_PATH}/${sid}/var_tcp_node) [ -n $(get_cache_var "ACL_${sid}_tcp_node") ] && tcp_node=$(get_cache_var "ACL_${sid}_tcp_node")
[ -s "${TMP_ACL_PATH}/${sid}/var_udp_node" ] && udp_node=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_node) [ -n $(get_cache_var "ACL_${sid}_udp_node") ] && udp_node=$(get_cache_var "ACL_${sid}_udp_node")
[ -s "${TMP_ACL_PATH}/${sid}/var_tcp_port" ] && tcp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_tcp_port) [ -n $(get_cache_var "ACL_${sid}_tcp_port") ] && tcp_port=$(get_cache_var "ACL_${sid}_tcp_port")
[ -s "${TMP_ACL_PATH}/${sid}/var_udp_port" ] && udp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_port) [ -n $(get_cache_var "ACL_${sid}_udp_port") ] && udp_port=$(get_cache_var "ACL_${sid}_udp_port")
[ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) [ -n $(get_cache_var "ACL_${sid}_dns_port") ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
use_shunt_tcp=0 use_shunt_tcp=0
use_shunt_udp=0 use_shunt_udp=0
@ -702,7 +702,6 @@ load_acl() {
} }
echolog " - ${msg2}" echolog " - ${msg2}"
udp_flag=1
} }
fi fi
} }
@ -732,109 +731,48 @@ filter_vpsip() {
echolog " - [$?]加入所有IPv6节点到nftset[$NFTSET_VPSLIST6]直连完成" echolog " - [$?]加入所有IPv6节点到nftset[$NFTSET_VPSLIST6]直连完成"
} }
filter_server_port() {
local address=${1}
local port=${2}
local stream=${3}
stream=$(echo ${3} | tr 'A-Z' 'a-z')
local _is_tproxy
_is_tproxy=${is_tproxy}
[ "$stream" == "udp" ] && _is_tproxy="TPROXY"
for _ipt in 4 6; do
[ "$_ipt" == "4" ] && _ip_type=ip
[ "$_ipt" == "6" ] && _ip_type=ip6
nft "list chain $NFTABLE_NAME $nft_output_chain" 2>/dev/null | grep -q "${address}:${port}"
if [ $? -ne 0 ]; then
nft "insert rule $NFTABLE_NAME $nft_output_chain meta l4proto $stream $_ip_type daddr $address $stream dport $port return comment \"${address}:${port}\"" 2>/dev/null
fi
done
}
filter_node() { filter_node() {
local proxy_node=${1} local node=${1}
local stream=$(echo ${2} | tr 'A-Z' 'a-z') local stream=${2}
local proxy_port=${3} if [ -n "$node" ] && [ "$node" != "nil" ]; then
local address=$(config_n_get $node address)
filter_rules() { local port=$(config_n_get $node port)
local node=${1} [ -z "$address" ] && [ -z "$port" ] && {
local stream=${2}
local _proxy=${3}
local _port=${4}
local _is_tproxy msg msg2
if [ -n "$node" ] && [ "$node" != "nil" ]; then
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
local address=$(config_n_get $node address)
local port=$(config_n_get $node port)
[ -z "$address" ] && [ -z "$port" ] && {
echolog " - 节点配置不正常,略过"
return 1
}
_is_tproxy=${is_tproxy}
[ "$stream" == "udp" ] && _is_tproxy="TPROXY"
if [ -n "${_is_tproxy}" ]; then
msg="TPROXY"
else
msg="REDIRECT"
fi
else
echolog " - 节点配置不正常,略过"
return 1 return 1
fi
local ADD_INDEX=$FORCE_INDEX
for _ipt in 4 6; do
[ "$_ipt" == "4" ] && _ip_type=ip && _set_name=$NFTSET_VPSLIST
[ "$_ipt" == "6" ] && _ip_type=ip6 && _set_name=$NFTSET_VPSLIST6
nft "list chain $NFTABLE_NAME $nft_output_chain" 2>/dev/null | grep -q "${address}:${port}"
if [ $? -ne 0 ]; then
local dst_rule="jump PSW_RULE"
msg2="按规则路由(${msg})"
[ -n "${is_tproxy}" ] || {
dst_rule=$(REDIRECT $_port)
msg2="套娃使用(${msg}:${port} -> ${_port})"
}
[ -n "$_proxy" ] && [ "$_proxy" == "1" ] && [ -n "$_port" ] || {
ADD_INDEX=$(RULE_LAST_INDEX "$NFTABLE_NAME" $nft_output_chain $_set_name $FORCE_INDEX)
dst_rule="return"
msg2="直连代理"
}
nft "insert rule $NFTABLE_NAME $nft_output_chain position $ADD_INDEX meta l4proto $stream $_ip_type daddr $address $stream dport $port $dst_rule comment \"${address}:${port}\"" 2>/dev/null
else
msg2="已配置过的节点,"
fi
done
msg="[$?]$(echo ${2} | tr 'a-z' 'A-Z')${msg2}使用链${ADD_INDEX},节点(${type}${address}:${port}"
#echolog " - ${msg}"
}
local proxy_protocol=$(config_n_get $proxy_node protocol)
local proxy_type=$(echo $(config_n_get $proxy_node type nil) | tr 'A-Z' 'a-z')
[ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 1
if [ "$proxy_protocol" == "_balancing" ]; then
#echolog " - 多节点负载均衡(${proxy_type}..."
proxy_node=$(config_n_get $proxy_node balancing_node)
for _node in $proxy_node; do
filter_rules "$_node" "$stream"
done
elif [ "$proxy_protocol" == "_shunt" ]; then
#echolog " - 按请求目的地址分流(${proxy_type}..."
local preproxy_enabled=$(config_n_get $proxy_node preproxy_enabled 0)
[ "$preproxy_enabled" == "1" ] && {
local preproxy_node=$(config_n_get $proxy_node main_node nil)
[ "$preproxy_node" != "nil" ] && {
local preproxy_node_address=$(config_n_get $preproxy_node address)
if [ -n "$preproxy_node_address" ]; then
filter_rules $preproxy_node $stream
else
preproxy_enabled=0
fi
}
} }
local default_node=$(config_n_get $proxy_node default_node _direct) filter_server_port $address $port $stream
if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then filter_server_port $address $port $stream
local default_proxy_tag=$(config_n_get $proxy_node default_proxy_tag nil)
[ "$default_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && default_proxy_tag="nil"
[ "$default_proxy_tag" == "nil" ] && filter_rules $default_node $stream
fi
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
for shunt_id in $shunt_ids; do
local shunt_node=$(config_n_get $proxy_node "${shunt_id}" nil)
[ "$shunt_node" == "nil" -o "$shunt_node" == "_default" -o "$shunt_node" == "_direct" -o "$shunt_node" == "_blackhole" ] && continue
local shunt_node_address=$(config_n_get $shunt_node address)
[ -z "$shunt_node_address" ] && continue
local shunt_proxy_tag=$(config_n_get $proxy_node "${shunt_id}_proxy_tag" nil)
[ "$shunt_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && shunt_proxy_tag="nil"
[ "$shunt_proxy_tag" == "nil" ] && filter_rules $shunt_node $stream
done
else
#echolog " - 普通节点(${proxy_type}..."
filter_rules "$proxy_node" "$stream"
fi fi
} }
filter_direct_node_list() {
[ ! -s "$TMP_PATH/direct_node_list" ] && return
for _node_id in $(cat $TMP_PATH/direct_node_list | awk '!seen[$0]++'); do
filter_node "$_node_id" TCP
filter_node "$_node_id" UDP
unset _node_id
done
}
add_firewall_rule() { add_firewall_rule() {
echolog "开始加载防火墙规则..." echolog "开始加载防火墙规则..."
gen_nft_tables gen_nft_tables
@ -1140,44 +1078,8 @@ add_firewall_rule() {
} }
[ "$TCP_UDP" = "1" ] && [ "$UDP_NODE" = "nil" ] && UDP_NODE=$TCP_NODE [ "$TCP_UDP" = "1" ] && [ "$UDP_NODE" = "nil" ] && UDP_NODE=$TCP_NODE
# 过滤Socks节点
[ "$SOCKS_ENABLED" = "1" ] && {
local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
#echolog "分析 Socks 服务所使用节点..."
local id enabled node port msg num
for id in $ids; do
enabled=$(config_n_get $id enabled 0)
[ "$enabled" == "1" ] || continue
node=$(config_n_get $id node nil)
port=$(config_n_get $id port 0)
msg="Socks 服务 [:${port}]"
if [ "$node" == "nil" ] || [ "$port" == "0" ]; then
msg="${msg} 未配置完全,略过"
else
filter_node $node TCP > /dev/null 2>&1 &
filter_node $node UDP > /dev/null 2>&1 &
fi
#echolog " - ${msg}"
done
}
[ "$ENABLED_DEFAULT_ACL" == 1 ] && { [ "$ENABLED_DEFAULT_ACL" == 1 ] && {
# 处理轮换节点的分流或套娃
local node port stream switch
for stream in TCP UDP; do
eval "node=\${${stream}_NODE}"
eval "port=\${${stream}_REDIR_PORT}"
#echolog "分析 $stream 代理自动切换..."
[ "$stream" == "UDP" ] && [ "$node" == "tcp" ] && {
eval "node=\${TCP_NODE}"
eval "port=\${TCP_REDIR_PORT}"
}
if [ "$node" != "nil" ] && [ "$(config_get_type $node nil)" != "nil" ]; then
filter_node $node $stream $port > /dev/null 2>&1 &
fi
done
msg="【路由器本机】," msg="【路由器本机】,"
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
@ -1373,21 +1275,15 @@ add_firewall_rule() {
# 加载ACLS # 加载ACLS
load_acl load_acl
for iface in $(ls ${TMP_IFACE_PATH}); do filter_direct_node_list
nft "insert rule $NFTABLE_NAME $nft_output_chain oif $iface counter return"
nft "insert rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 oif $iface counter return"
done
[ -n "${is_tproxy}" -o -n "${udp_flag}" ] && { [ -d "${TMP_IFACE_PATH}" ] && {
bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables) for iface in $(ls ${TMP_IFACE_PATH}); do
echo -n $bridge_nf_ipt > $TMP_PATH/bridge_nf_ipt nft "insert rule $NFTABLE_NAME $nft_output_chain oif $iface counter return"
sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1 nft "insert rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 oif $iface counter return"
[ "$PROXY_IPV6" == "1" ] && { done
bridge_nf_ip6t=$(sysctl -e -n net.bridge.bridge-nf-call-ip6tables)
echo -n $bridge_nf_ip6t > $TMP_PATH/bridge_nf_ip6t
sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1
}
} }
echolog "防火墙规则加载完成!" echolog "防火墙规则加载完成!"
} }
@ -1534,6 +1430,9 @@ get_wan_ip)
get_wan6_ip) get_wan6_ip)
get_wan6_ip get_wan6_ip
;; ;;
filter_direct_node_list)
filter_direct_node_list
;;
stop) stop)
stop stop
;; ;;

View File

@ -82,9 +82,8 @@ test_auto_switch() {
local b_nodes=$1 local b_nodes=$1
local now_node=$2 local now_node=$2
[ -z "$now_node" ] && { [ -z "$now_node" ] && {
local f="/tmp/etc/$CONFIG/id/socks_${id}" if [ -n $(/usr/share/${CONFIG}/app.sh get_cache_var "socks_${id}") ]; then
if [ -f "${f}" ]; then now_node=$(/usr/share/${CONFIG}/app.sh get_cache_var "socks_${id}")
now_node=$(cat ${f})
else else
#echolog "自动切换检测:未知错误" #echolog "自动切换检测:未知错误"
return 1 return 1

View File

@ -327,6 +327,23 @@ do
} }
end end
else else
--前置代理节点
local currentNode = uci:get_all(appname, node_id) or nil
if currentNode and currentNode.preproxy_node then
CONFIG[#CONFIG + 1] = {
log = true,
id = node_id,
remarks = "节点[" .. node_id .. "]前置代理节点",
currentNode = uci:get_all(appname, currentNode.preproxy_node) or nil,
set = function(o, server)
uci:set(appname, node_id, "preproxy_node", server)
o.newNodeId = server
end,
delete = function(o)
uci:delete(appname, node_id, "preproxy_node")
end
}
end
--落地节点 --落地节点
local currentNode = uci:get_all(appname, node_id) or nil local currentNode = uci:get_all(appname, node_id) or nil
if currentNode and currentNode.to_node then if currentNode and currentNode.to_node then

View File

@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2 PKG_NAME:=luci-app-passwall2
PKG_VERSION:=24.12.14 PKG_VERSION:=24.12.16
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_CONFIG_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \

View File

@ -158,9 +158,9 @@ end
function get_now_use_node() function get_now_use_node()
local e = {} local e = {}
local data, code, msg = nixio.fs.readfile("/tmp/etc/passwall2/acl/default/global.id") local node = api.get_cache_var("GLOBAL_node")
if data then if node then
e["global"] = util.trim(data) e["global"] = node
end end
luci.http.prepare_content("application/json") luci.http.prepare_content("application/json")
luci.http.write_json(e) luci.http.write_json(e)
@ -328,7 +328,7 @@ function clear_all_nodes()
uci:delete(appname, t[".name"]) uci:delete(appname, t[".name"])
end) end)
uci:foreach(appname, "acl_rule", function(t) uci:foreach(appname, "acl_rule", function(t)
uci:set(appname, t[".name"], "node", "default") uci:set(appname, t[".name"], "node", "nil")
end) end)
uci:foreach(appname, "nodes", function(node) uci:foreach(appname, "nodes", function(node)
uci:delete(appname, node['.name']) uci:delete(appname, node['.name'])
@ -363,7 +363,17 @@ function delete_select_nodes()
end) end)
uci:foreach(appname, "acl_rule", function(t) uci:foreach(appname, "acl_rule", function(t)
if t["node"] == w then if t["node"] == w then
uci:set(appname, t[".name"], "node", "default") uci:set(appname, t[".name"], "node", "nil")
end
end)
uci:foreach(appname, "nodes", function(t)
if t["preproxy_node"] == w then
uci:delete(appname, t[".name"], "preproxy_node")
uci:delete(appname, t[".name"], "chain_proxy")
end
if t["to_node"] == w then
uci:delete(appname, t[".name"], "to_node")
uci:delete(appname, t[".name"], "chain_proxy")
end end
end) end)
uci:delete(appname, w) uci:delete(appname, w)

View File

@ -22,9 +22,8 @@ o.default = 1
o.rmempty = false o.rmempty = false
local auto_switch_tip local auto_switch_tip
local current_node_file = string.format("/tmp/etc/%s/id/socks_%s", appname, arg[1]) local current_node = api.get_cache_var("socks_" .. arg[1])
local current_node = luci.sys.exec(string.format("[ -f '%s' ] && echo -n $(cat %s)", current_node_file, current_node_file)) if current_node then
if current_node and current_node ~= "" and current_node ~= "nil" then
local n = uci:get_all(appname, current_node) local n = uci:get_all(appname, current_node)
if n then if n then
if tonumber(m:get(arg[1], "enable_autoswitch") or 0) == 1 then if tonumber(m:get(arg[1], "enable_autoswitch") or 0) == 1 then

View File

@ -647,12 +647,26 @@ o.default = 0
o = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay") o = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay")
o.default = 0 o.default = 0
o = s:option(ListValue, option_name("to_node"), translate("Landing node"), translate("Only support a layer of proxy.")) o = s:option(ListValue, option_name("chain_proxy"), translate("Chain Proxy"))
o.default = ""
o:value("", translate("Close(Not use)")) o:value("", translate("Close(Not use)"))
o:value("1", translate("Preproxy Node"))
o:value("2", translate("Landing Node"))
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
if not v:find("_") then
o:depends({ [option_name("protocol")] = v })
end
end
o = s:option(ListValue, option_name("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "1" })
o = s:option(ListValue, option_name("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "2" })
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
if v.type == "Xray" then if v.type == "Xray" and v.id ~= arg[1] then
o:value(v.id, v.remark) s.fields[option_name("preproxy_node")]:value(v.id, v.remark)
s.fields[option_name("to_node")]:value(v.id, v.remark)
end end
end end
@ -660,7 +674,7 @@ for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
if not v:find("_") then if not v:find("_") then
s.fields[option_name("tcpMptcp")]:depends({ [option_name("protocol")] = v }) s.fields[option_name("tcpMptcp")]:depends({ [option_name("protocol")] = v })
s.fields[option_name("tcpNoDelay")]:depends({ [option_name("protocol")] = v }) s.fields[option_name("tcpNoDelay")]:depends({ [option_name("protocol")] = v })
s.fields[option_name("to_node")]:depends({ [option_name("protocol")] = v }) s.fields[option_name("chain_proxy")]:depends({ [option_name("protocol")] = v })
end end
end end

View File

@ -684,18 +684,27 @@ o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(ListValue, option_name("to_node"), translate("Landing node"), translate("Only support a layer of proxy.")) o = s:option(ListValue, option_name("chain_proxy"), translate("Chain Proxy"))
o.default = ""
o:value("", translate("Close(Not use)")) o:value("", translate("Close(Not use)"))
for k, v in pairs(nodes_table) do o:value("1", translate("Preproxy Node"))
if v.type == "sing-box" then o:value("2", translate("Landing Node"))
o:value(v.id, v.remark)
end
end
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
if not v:find("_") then if not v:find("_") then
o:depends({ [option_name("protocol")] = v }) o:depends({ [option_name("protocol")] = v })
end end
end end
o = s:option(ListValue, option_name("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "1" })
o = s:option(ListValue, option_name("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "2" })
for k, v in pairs(nodes_table) do
if v.type == "sing-box" and v.id ~= arg[1] then
s.fields[option_name("preproxy_node")]:value(v.id, v.remark)
s.fields[option_name("to_node")]:value(v.id, v.remark)
end
end
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)

View File

@ -17,6 +17,8 @@ DISTRIB_ARCH = nil
LOG_FILE = "/tmp/log/passwall2.log" LOG_FILE = "/tmp/log/passwall2.log"
CACHE_PATH = "/tmp/etc/passwall2_tmp" CACHE_PATH = "/tmp/etc/passwall2_tmp"
TMP_PATH = "/tmp/etc/" .. appname
TMP_IFACE_PATH = TMP_PATH .. "/iface"
function log(...) function log(...)
local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ")
@ -27,6 +29,15 @@ function log(...)
end end
end end
function set_cache_var(key, val)
sys.call(string.format('/usr/share/passwall2/app.sh set_cache_var %s "%s"', key, val))
end
function get_cache_var(key)
local val = sys.exec(string.format('echo -n $(/usr/share/passwall2/app.sh get_cache_var %s)', key))
if val == "" then val = nil end
return val
end
function exec_call(cmd) function exec_call(cmd)
local process = io.popen(cmd .. '; echo -e "\n$?"') local process = io.popen(cmd .. '; echo -e "\n$?"')
local lines = {} local lines = {}
@ -96,8 +107,8 @@ end
function curl_proxy(url, file, args) function curl_proxy(url, file, args)
--使用代理 --使用代理
local socks_server = luci.sys.exec("[ -f /tmp/etc/passwall2/acl/default/SOCKS_server ] && echo -n $(cat /tmp/etc/passwall2/acl/default/SOCKS_server) || echo -n ''") local socks_server = get_cache_var("GLOBAL_SOCKS_server")
if socks_server ~= "" then if socks_server and socks_server ~= "" then
if not args then args = {} end if not args then args = {} end
local tmp_args = clone(args) local tmp_args = clone(args)
tmp_args[#tmp_args + 1] = "-x socks5h://" .. socks_server tmp_args[#tmp_args + 1] = "-x socks5h://" .. socks_server

View File

@ -685,7 +685,7 @@ function gen_config_server(node)
bind_interface = node.outbound_node_iface, bind_interface = node.outbound_node_iface,
routing_mark = 255, routing_mark = 255,
} }
sys.call("mkdir -p /tmp/etc/passwall2/iface && touch /tmp/etc/passwall2/iface/" .. node.outbound_node_iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.outbound_node_iface))
else else
local outbound_node_t = uci:get_all("passwall2", node.outbound_node) local outbound_node_t = uci:get_all("passwall2", node.outbound_node)
if node.outbound_node == "_socks" or node.outbound_node == "_http" then if node.outbound_node == "_socks" or node.outbound_node == "_http" then
@ -871,6 +871,7 @@ function gen_config(var)
local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name) local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name)
if not node or not outbound or not outbounds_table then return nil end if not node or not outbound or not outbounds_table then return nil end
local default_outTag = outbound.tag local default_outTag = outbound.tag
local last_insert_outbound
if node.shadowtls == "1" then if node.shadowtls == "1" then
local _node = { local _node = {
@ -887,14 +888,31 @@ function gen_config(var)
} }
local shadowtls_outbound = gen_outbound(nil, _node, outbound.tag .. "_shadowtls") local shadowtls_outbound = gen_outbound(nil, _node, outbound.tag .. "_shadowtls")
if shadowtls_outbound then if shadowtls_outbound then
table.insert(outbounds_table, shadowtls_outbound) last_insert_outbound = shadowtls_outbound
outbound.detour = outbound.tag .. "_shadowtls" outbound.detour = outbound.tag .. "_shadowtls"
outbound.server = nil outbound.server = nil
outbound.server_port = nil outbound.server_port = nil
end end
end end
if node.to_node then if node.chain_proxy == "1" and node.preproxy_node then
if outbound["_flag_proxy_tag"] and outbound["_flag_proxy_tag"] ~= "nil" then
--Ignore
else
local preproxy_node = uci:get_all(appname, node.preproxy_node)
if preproxy_node then
local preproxy_outbound = gen_outbound(nil, preproxy_node)
if preproxy_outbound then
preproxy_outbound.tag = preproxy_node[".name"] .. ":" .. preproxy_node.remarks
outbound.tag = preproxy_outbound.tag .. " -> " .. outbound.tag
outbound.detour = preproxy_outbound.tag
last_insert_outbound = preproxy_outbound
default_outTag = outbound.tag
end
end
end
end
if node.chain_proxy == "2" and node.to_node then
local to_node = uci:get_all(appname, node.to_node) local to_node = uci:get_all(appname, node.to_node)
if to_node then if to_node then
local to_outbound = gen_outbound(nil, to_node) local to_outbound = gen_outbound(nil, to_node)
@ -912,7 +930,7 @@ function gen_config(var)
end end
end end
end end
return default_outTag return default_outTag, last_insert_outbound
end end
if node.protocol == "_shunt" then if node.protocol == "_shunt" then
@ -997,8 +1015,11 @@ function gen_config(var)
local _outbound = gen_outbound(flag, _node, rule_name, { tag = use_proxy and preproxy_tag or nil }) local _outbound = gen_outbound(flag, _node, rule_name, { tag = use_proxy and preproxy_tag or nil })
if _outbound then if _outbound then
_outbound.tag = _outbound.tag .. ":" .. _node.remarks _outbound.tag = _outbound.tag .. ":" .. _node.remarks
rule_outboundTag = set_outbound_detour(_node, _outbound, outbounds, rule_name) rule_outboundTag, last_insert_outbound = set_outbound_detour(_node, _outbound, outbounds, rule_name)
table.insert(outbounds, _outbound) table.insert(outbounds, _outbound)
if last_insert_outbound then
table.insert(outbounds, last_insert_outbound)
end
end end
end end
elseif _node.protocol == "_iface" then elseif _node.protocol == "_iface" then
@ -1011,7 +1032,7 @@ function gen_config(var)
} }
table.insert(outbounds, _outbound) table.insert(outbounds, _outbound)
rule_outboundTag = _outbound.tag rule_outboundTag = _outbound.tag
sys.call("touch /tmp/etc/passwall2/iface/" .. _node.iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, _node.iface))
end end
end end
end end
@ -1186,14 +1207,17 @@ function gen_config(var)
} }
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
COMMON.default_outbound_tag = outbound.tag COMMON.default_outbound_tag = outbound.tag
sys.call("touch /tmp/etc/passwall2/iface/" .. node.iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.iface))
end end
else else
local outbound = gen_outbound(flag, node) local outbound = gen_outbound(flag, node)
if outbound then if outbound then
outbound.tag = outbound.tag .. ":" .. node.remarks outbound.tag = outbound.tag .. ":" .. node.remarks
COMMON.default_outbound_tag = set_outbound_detour(node, outbound, outbounds) COMMON.default_outbound_tag, last_insert_outbound = set_outbound_detour(node, outbound, outbounds)
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
if last_insert_outbound then
table.insert(outbounds, last_insert_outbound)
end
end end
end end
end end
@ -1444,6 +1468,9 @@ function gen_config(var)
tag = "block" tag = "block"
}) })
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
if (not value["_flag_proxy_tag"] or value["_flag_proxy_tag"] == "nil") and not value.detour and value["_id"] and value.server and value.server_port then
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
end
for k, v in pairs(config.outbounds[index]) do for k, v in pairs(config.outbounds[index]) do
if k:find("_") == 1 then if k:find("_") == 1 then
config.outbounds[index][k] = nil config.outbounds[index][k] = nil

View File

@ -183,8 +183,7 @@ function gen_outbound(flag, node, tag, proxy_table)
} or nil, } or nil,
wsSettings = (node.transport == "ws") and { wsSettings = (node.transport == "ws") and {
path = node.ws_path or "/", path = node.ws_path or "/",
headers = (node.ws_host ~= nil) and host = node.ws_host or nil,
{Host = node.ws_host} or nil,
maxEarlyData = tonumber(node.ws_maxEarlyData) or nil, maxEarlyData = tonumber(node.ws_maxEarlyData) or nil,
earlyDataHeaderName = (node.ws_earlyDataHeaderName) and node.ws_earlyDataHeaderName or nil, earlyDataHeaderName = (node.ws_earlyDataHeaderName) and node.ws_earlyDataHeaderName or nil,
heartbeatPeriod = tonumber(node.ws_heartbeatPeriod) or nil heartbeatPeriod = tonumber(node.ws_heartbeatPeriod) or nil
@ -416,7 +415,7 @@ function gen_config_server(node)
} }
} }
} }
sys.call("mkdir -p /tmp/etc/passwall2/iface && touch /tmp/etc/passwall2/iface/" .. node.outbound_node_iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.outbound_node_iface))
else else
local outbound_node_t = uci:get_all("passwall2", node.outbound_node) local outbound_node_t = uci:get_all("passwall2", node.outbound_node)
if node.outbound_node == "_socks" or node.outbound_node == "_http" then if node.outbound_node == "_socks" or node.outbound_node == "_http" then
@ -483,7 +482,7 @@ function gen_config_server(node)
header = {type = node.mkcp_guise} header = {type = node.mkcp_guise}
} or nil, } or nil,
wsSettings = (node.transport == "ws") and { wsSettings = (node.transport == "ws") and {
headers = (node.ws_host) and {Host = node.ws_host} or nil, host = node.ws_host or nil,
path = node.ws_path path = node.ws_path
} or nil, } or nil,
httpSettings = (node.transport == "h2") and { httpSettings = (node.transport == "h2") and {
@ -782,8 +781,29 @@ function gen_config(var)
local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name) local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name)
if not node or not outbound or not outbounds_table then return nil end if not node or not outbound or not outbounds_table then return nil end
local default_outTag = outbound.tag local default_outTag = outbound.tag
local last_insert_outbound
if node.to_node then if node.chain_proxy == "1" and node.preproxy_node then
if outbound["_flag_proxy_tag"] and outbound["_flag_proxy_tag"] ~= "nil" then
--Ignore
else
local preproxy_node = uci:get_all(appname, node.preproxy_node)
if preproxy_node then
local preproxy_outbound = gen_outbound(nil, preproxy_node)
if preproxy_outbound then
preproxy_outbound.tag = preproxy_node[".name"] .. ":" .. preproxy_node.remarks
outbound.tag = preproxy_outbound.tag .. " -> " .. outbound.tag
outbound.proxySettings = {
tag = preproxy_outbound.tag,
transportLayer = true
}
last_insert_outbound = preproxy_outbound
default_outTag = outbound.tag
end
end
end
end
if node.chain_proxy == "2" and node.to_node then
local to_node = uci:get_all(appname, node.to_node) local to_node = uci:get_all(appname, node.to_node)
if to_node then if to_node then
local to_outbound = gen_outbound(nil, to_node) local to_outbound = gen_outbound(nil, to_node)
@ -804,7 +824,7 @@ function gen_config(var)
end end
end end
end end
return default_outTag return default_outTag, last_insert_outbound
end end
if node then if node then
@ -906,12 +926,15 @@ function gen_config(var)
local outbound_tag local outbound_tag
if outbound then if outbound then
outbound.tag = outbound.tag .. ":" .. _node.remarks outbound.tag = outbound.tag .. ":" .. _node.remarks
outbound_tag = set_outbound_detour(_node, outbound, outbounds, rule_name) outbound_tag, last_insert_outbound = set_outbound_detour(_node, outbound, outbounds, rule_name)
if rule_name == "default" then if rule_name == "default" then
table.insert(outbounds, 1, outbound) table.insert(outbounds, 1, outbound)
else else
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
end end
if last_insert_outbound then
table.insert(outbounds, last_insert_outbound)
end
end end
return outbound_tag, nil return outbound_tag, nil
end end
@ -932,7 +955,7 @@ function gen_config(var)
} }
outbound_tag = outbound.tag outbound_tag = outbound.tag
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
sys.call("touch /tmp/etc/passwall2/iface/" .. _node.iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, _node.iface))
end end
return outbound_tag, nil return outbound_tag, nil
end end
@ -1098,14 +1121,17 @@ function gen_config(var)
} }
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
COMMON.default_outbound_tag = outbound.tag COMMON.default_outbound_tag = outbound.tag
sys.call("touch /tmp/etc/passwall2/iface/" .. node.iface) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.iface))
end end
else else
local outbound = gen_outbound(flag, node, nil, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.fragment == "1" or nil }) local outbound = gen_outbound(flag, node, nil, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.fragment == "1" or nil })
if outbound then if outbound then
outbound.tag = outbound.tag .. ":" .. node.remarks outbound.tag = outbound.tag .. ":" .. node.remarks
COMMON.default_outbound_tag = set_outbound_detour(node, outbound, outbounds) COMMON.default_outbound_tag, last_insert_outbound = set_outbound_detour(node, outbound, outbounds)
table.insert(outbounds, outbound) table.insert(outbounds, outbound)
if last_insert_outbound then
table.insert(outbounds, last_insert_outbound)
end
routing = { routing = {
domainStrategy = "AsIs", domainStrategy = "AsIs",
domainMatcher = "hybrid", domainMatcher = "hybrid",
@ -1523,6 +1549,9 @@ function gen_config(var)
end end
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
if (not value["_flag_proxy_tag"] or value["_flag_proxy_tag"] == "nil") and value["_id"] and value.server and value.server_port then
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
end
for k, v in pairs(config.outbounds[index]) do for k, v in pairs(config.outbounds[index]) do
if k:find("_") == 1 then if k:find("_") == 1 then
config.outbounds[index][k] = nil config.outbounds[index][k] = nil

View File

@ -223,22 +223,18 @@ table td, .table .td {
function get_now_use_node() { function get_now_use_node() {
XHR.get('<%=api.url("get_now_use_node")%>', null, XHR.get('<%=api.url("get_now_use_node")%>', null,
function(x, result) { function(x, result) {
var id = result["TCP"]; var id = result["global"];
if (id) { if (id) {
var dom = document.getElementById("cbi-passwall2-" + id); var dom = document.getElementById("cbi-passwall2-" + id);
if (dom) { if (dom) {
dom.classList.add("_now_use"); dom.classList.add("_now_use");
dom.title = "当前TCP节点"; dom.title = "当前节点";
//var v = "<a style='color: red'>当前TCP节点:</a>" + document.getElementById("cbid.passwall2." + id + ".remarks").value; //var v = "<a style='color: red'>当前节点:</a>" + document.getElementById("cbid.passwall2." + id + ".remarks").value;
//document.getElementById("cbi-passwall2-" + id + "-remarks").innerHTML = v; //document.getElementById("cbi-passwall2-" + id + "-remarks").innerHTML = v;
} var tds = dom.getElementsByTagName("td")
} for (var j = 0; j < tds.length; j++) {
id = result["UDP"]; tds[j].classList.add("_now_use");
if (id) { }
var dom = document.getElementById("cbi-passwall2-" + id);
if (dom) {
dom.classList.add("_now_use");
dom.title = "当前UDP节点";
} }
} }
} }
@ -305,9 +301,7 @@ table td, .table .td {
); );
} }
} }
get_now_use_node();
/* 自动Ping */ /* 自动Ping */
if (auto_detection_time == "icmp" || auto_detection_time == "tcping") { if (auto_detection_time == "icmp" || auto_detection_time == "tcping") {
var nodes = []; var nodes = [];
@ -427,7 +421,9 @@ table td, .table .td {
console.error(err); console.error(err);
} }
} }
get_now_use_node();
if (true) { if (true) {
var str = ""; var str = "";
for (var add_from in node_list) { for (var add_from in node_list) {

View File

@ -1570,7 +1570,10 @@ msgstr "延迟ms"
msgid "If is domain name, The requested domain name will be resolved to IP before connect." msgid "If is domain name, The requested domain name will be resolved to IP before connect."
msgstr "如果是域名,域名将在请求发出之前解析为 IP。" msgstr "如果是域名,域名将在请求发出之前解析为 IP。"
msgid "Landing node" msgid "Chain Proxy"
msgstr "链式代理"
msgid "Landing Node"
msgstr "落地节点" msgstr "落地节点"
msgid "Only support a layer of proxy." msgid "Only support a layer of proxy."

View File

@ -8,7 +8,6 @@ CONFIG=passwall2
TMP_PATH=/tmp/etc/$CONFIG TMP_PATH=/tmp/etc/$CONFIG
TMP_BIN_PATH=$TMP_PATH/bin TMP_BIN_PATH=$TMP_PATH/bin
TMP_SCRIPT_FUNC_PATH=$TMP_PATH/script_func TMP_SCRIPT_FUNC_PATH=$TMP_PATH/script_func
TMP_ID_PATH=$TMP_PATH/id
TMP_ROUTE_PATH=$TMP_PATH/route TMP_ROUTE_PATH=$TMP_PATH/route
TMP_ACL_PATH=$TMP_PATH/acl TMP_ACL_PATH=$TMP_PATH/acl
TMP_IFACE_PATH=$TMP_PATH/iface TMP_IFACE_PATH=$TMP_PATH/iface
@ -324,6 +323,19 @@ get_singbox_geoip() {
fi fi
} }
set_cache_var() {
local key="${1}"
shift 1
local val="$@"
[ -n "${key}" ] && [ -n "${val}" ] && echo "${key}=\"${val}\"" >> $TMP_PATH/var
}
get_cache_var() {
local key="${1}"
[ -n "${key}" ] && [ -s "$TMP_PATH/var" ] && {
echo $(cat $TMP_PATH/var | grep "^${key}=" | awk -F '=' '{print $2}' | tail -n 1 | awk -F'"' '{print $2}')
}
}
run_xray() { run_xray() {
local flag node redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password local flag node redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password
local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy dns_cache write_ipset_direct local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy dns_cache write_ipset_direct
@ -654,6 +666,8 @@ run_socks() {
fi fi
} }
unset http_flag unset http_flag
[ "${server_host}" != "127.0.0.1" ] && [ "$type" != "sing-box" ] && [ "$type" != "xray" ] && echo "${node}" >> $TMP_PATH/direct_node_list
} }
socks_node_switch() { socks_node_switch() {
@ -680,7 +694,9 @@ socks_node_switch() {
local http_config_file="HTTP2SOCKS_${flag}.json" local http_config_file="HTTP2SOCKS_${flag}.json"
LOG_FILE="/dev/null" LOG_FILE="/dev/null"
run_socks flag=$flag node=$new_node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file run_socks flag=$flag node=$new_node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file
echo $new_node > $TMP_ID_PATH/socks_${flag} set_cache_var "socks_${flag}" "$new_node"
local USE_TABLES=$(get_cache_var "USE_TABLES")
[ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh filter_direct_node_list
} }
} }
@ -689,7 +705,7 @@ run_global() {
TYPE=$(echo $(config_n_get $NODE type nil) | tr 'A-Z' 'a-z') TYPE=$(echo $(config_n_get $NODE type nil) | tr 'A-Z' 'a-z')
[ "$TYPE" = "nil" ] && return 1 [ "$TYPE" = "nil" ] && return 1
mkdir -p $TMP_ACL_PATH/default mkdir -p $TMP_ACL_PATH/default
echo $NODE > $TMP_ACL_PATH/default/global.id set_cache_var "GLOBAL_node" "$NODE"
if [ $PROXY_IPV6 == "1" ]; then if [ $PROXY_IPV6 == "1" ]; then
echolog "开启实验性IPv6透明代理(TProxy)请确认您的节点及类型支持IPv6" echolog "开启实验性IPv6透明代理(TProxy)请确认您的节点及类型支持IPv6"
@ -737,7 +753,7 @@ run_global() {
node_socks_bind="127.0.0.1" node_socks_bind="127.0.0.1"
[ "${node_socks_bind_local}" != "1" ] && node_socks_bind="0.0.0.0" [ "${node_socks_bind_local}" != "1" ] && node_socks_bind="0.0.0.0"
V2RAY_ARGS="${V2RAY_ARGS} socks_address=${node_socks_bind} socks_port=${node_socks_port}" V2RAY_ARGS="${V2RAY_ARGS} socks_address=${node_socks_bind} socks_port=${node_socks_port}"
echo "127.0.0.1:$node_socks_port" > $TMP_ACL_PATH/default/SOCKS_server set_cache_var "GLOBAL_SOCKS_server" "127.0.0.1:$node_socks_port"
node_http_port=$(config_t_get global node_http_port 0) node_http_port=$(config_t_get global node_http_port 0)
[ "$node_http_port" != "0" ] && V2RAY_ARGS="${V2RAY_ARGS} http_port=${node_http_port}" [ "$node_http_port" != "0" ] && V2RAY_ARGS="${V2RAY_ARGS} http_port=${node_http_port}"
@ -781,7 +797,7 @@ start_socks() {
local http_port=$(config_n_get $id http_port 0) local http_port=$(config_n_get $id http_port 0)
local http_config_file="HTTP2SOCKS_${id}.json" local http_config_file="HTTP2SOCKS_${id}.json"
run_socks flag=$id node=$node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file run_socks flag=$id node=$node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file
echo $node > $TMP_ID_PATH/socks_${id} set_cache_var "socks_${id}" "$node"
#自动切换逻辑 #自动切换逻辑
local enable_autoswitch=$(config_n_get $id enable_autoswitch 0) local enable_autoswitch=$(config_n_get $id enable_autoswitch 0)
@ -947,7 +963,7 @@ delete_ip2route() {
start_haproxy() { start_haproxy() {
[ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && return [ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && return
haproxy_path=${TMP_PATH}/haproxy haproxy_path=$TMP_PATH/haproxy
haproxy_conf="config.cfg" haproxy_conf="config.cfg"
lua $APP_PATH/haproxy.lua -path ${haproxy_path} -conf ${haproxy_conf} -dns ${LOCAL_DNS} lua $APP_PATH/haproxy.lua -path ${haproxy_path} -conf ${haproxy_conf} -dns ${LOCAL_DNS}
ln_run "$(first_type haproxy)" haproxy "/dev/null" -f "${haproxy_path}/${haproxy_conf}" ln_run "$(first_type haproxy)" haproxy "/dev/null" -f "${haproxy_path}/${haproxy_conf}"
@ -1013,7 +1029,7 @@ run_copy_dnsmasq() {
node_servers=$(uci show "${CONFIG}" | grep -E "(.address=|.download_address=)" | cut -d "'" -f 2) node_servers=$(uci show "${CONFIG}" | grep -E "(.address=|.download_address=)" | cut -d "'" -f 2)
hosts_foreach "node_servers" host_from_url | grep '[a-zA-Z]$' | sort -u | grep -v "engage.cloudflareclient.com" | gen_dnsmasq_items settype="${set_type}" setnames="${setflag_4}passwall2_vpslist,${setflag_6}passwall2_vpslist6" dnss="${LOCAL_DNS:-${AUTO_DNS}}" outf="${dnsmasq_conf_path}/10-vpslist_host.conf" ipsetoutf="${dnsmasq_conf_path}/ipset.conf" hosts_foreach "node_servers" host_from_url | grep '[a-zA-Z]$' | sort -u | grep -v "engage.cloudflareclient.com" | gen_dnsmasq_items settype="${set_type}" setnames="${setflag_4}passwall2_vpslist,${setflag_6}passwall2_vpslist6" dnss="${LOCAL_DNS:-${AUTO_DNS}}" outf="${dnsmasq_conf_path}/10-vpslist_host.conf" ipsetoutf="${dnsmasq_conf_path}/ipset.conf"
ln_run "$(first_type dnsmasq)" "dnsmasq_${flag}" "/dev/null" -C $dnsmasq_conf -x $TMP_ACL_PATH/$flag/dnsmasq.pid ln_run "$(first_type dnsmasq)" "dnsmasq_${flag}" "/dev/null" -C $dnsmasq_conf -x $TMP_ACL_PATH/$flag/dnsmasq.pid
echo "${listen_port}" > $TMP_ACL_PATH/$flag/var_redirect_dns_port set_cache_var "ACL_${flag}_dns_port" "${listen_port}"
} }
run_ipset_chinadns_ng() { run_ipset_chinadns_ng() {
@ -1157,10 +1173,10 @@ acl_app() {
filter_node $node TCP > /dev/null 2>&1 & filter_node $node TCP > /dev/null 2>&1 &
filter_node $node UDP > /dev/null 2>&1 & filter_node $node UDP > /dev/null 2>&1 &
fi fi
echo "${node}" > $TMP_ACL_PATH/$sid/var_node set_cache_var "ACL_${sid}_node" "${node}"
} }
fi fi
echo "${redir_port}" > $TMP_ACL_PATH/$sid/var_port set_cache_var "ACL_${sid}_redir_port" "${redir_port}"
} }
unset enabled sid remarks sources interface node direct_dns_query_strategy remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy unset enabled sid remarks sources interface node direct_dns_query_strategy remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy
unset _ip _mac _iprange _ipset _ip_or_mac source_list config_file unset _ip _mac _iprange _ipset _ip_or_mac source_list config_file
@ -1219,13 +1235,14 @@ start() {
fi fi
[ "$ENABLED_DEFAULT_ACL" == 1 ] && run_global [ "$ENABLED_DEFAULT_ACL" == 1 ] && run_global
[ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start [ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start
set_cache_var "USE_TABLES" "$USE_TABLES"
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then
bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables) bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables)
echo -n $bridge_nf_ipt > $TMP_PATH/bridge_nf_ipt set_cache_var "origin_bridge_nf_ipt" "$bridge_nf_ipt"
sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1 sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" == "1" ] && {
bridge_nf_ip6t=$(sysctl -e -n net.bridge.bridge-nf-call-ip6tables) bridge_nf_ip6t=$(sysctl -e -n net.bridge.bridge-nf-call-ip6tables)
echo -n $bridge_nf_ip6t > $TMP_PATH/bridge_nf_ip6t set_cache_var "origin_bridge_nf_ip6t" "$bridge_nf_ip6t"
sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1 sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1
} }
fi fi
@ -1244,9 +1261,11 @@ stop() {
unset V2RAY_LOCATION_ASSET unset V2RAY_LOCATION_ASSET
unset XRAY_LOCATION_ASSET unset XRAY_LOCATION_ASSET
stop_crontab stop_crontab
[ -s "$TMP_PATH/bridge_nf_ipt" ] && sysctl -w net.bridge.bridge-nf-call-iptables=$(cat $TMP_PATH/bridge_nf_ipt) >/dev/null 2>&1 origin_bridge_nf_ipt=$(get_cache_var "origin_bridge_nf_ipt")
[ -s "$TMP_PATH/bridge_nf_ip6t" ] && sysctl -w net.bridge.bridge-nf-call-ip6tables=$(cat $TMP_PATH/bridge_nf_ip6t) >/dev/null 2>&1 [ -n "${origin_bridge_nf_ipt}" ] && sysctl -w net.bridge.bridge-nf-call-iptables=${origin_bridge_nf_ipt} >/dev/null 2>&1
rm -rf ${TMP_PATH} origin_bridge_nf_ip6t=$(get_cache_var "origin_bridge_nf_ip6t")
[ -n "${origin_bridge_nf_ip6t}" ] && sysctl -w net.bridge.bridge-nf-call-ip6tables=${origin_bridge_nf_ip6t} >/dev/null 2>&1
rm -rf $TMP_PATH
rm -rf /tmp/lock/${CONFIG}_socks_auto_switch* rm -rf /tmp/lock/${CONFIG}_socks_auto_switch*
echolog "清空并关闭相关程序和缓存完成。" echolog "清空并关闭相关程序和缓存完成。"
exit 0 exit 0
@ -1299,7 +1318,7 @@ SINGBOX_BIN=$(first_type $(config_t_get global_app singbox_file) sing-box)
export V2RAY_LOCATION_ASSET=$(config_t_get global_rules v2ray_location_asset "/usr/share/v2ray/") export V2RAY_LOCATION_ASSET=$(config_t_get global_rules v2ray_location_asset "/usr/share/v2ray/")
export XRAY_LOCATION_ASSET=$V2RAY_LOCATION_ASSET export XRAY_LOCATION_ASSET=$V2RAY_LOCATION_ASSET
mkdir -p /tmp/etc $TMP_PATH $TMP_BIN_PATH $TMP_SCRIPT_FUNC_PATH $TMP_ID_PATH $TMP_ROUTE_PATH $TMP_ACL_PATH $TMP_IFACE_PATH $TMP_PATH2 mkdir -p /tmp/etc $TMP_PATH $TMP_BIN_PATH $TMP_SCRIPT_FUNC_PATH $TMP_ROUTE_PATH $TMP_ACL_PATH $TMP_PATH2
arg1=$1 arg1=$1
shift shift
@ -1319,6 +1338,12 @@ socks_node_switch)
echolog) echolog)
echolog $@ echolog $@
;; ;;
get_cache_var)
get_cache_var $@
;;
set_cache_var)
set_cache_var $@
;;
stop) stop)
stop stop
;; ;;

View File

@ -292,9 +292,9 @@ load_acl() {
[ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS [ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
node_remark=$(config_n_get $NODE remarks) node_remark=$(config_n_get $NODE remarks)
[ -s "${TMP_ACL_PATH}/${sid}/var_node" ] && node=$(cat ${TMP_ACL_PATH}/${sid}/var_node) [ -n $(get_cache_var "ACL_${sid}_node") ] && node=$(get_cache_var "ACL_${sid}_node")
[ -s "${TMP_ACL_PATH}/${sid}/var_port" ] && redir_port=$(cat ${TMP_ACL_PATH}/${sid}/var_port) [ -n $(get_cache_var "ACL_${sid}_redir_port") ] && redir_port=$(get_cache_var "ACL_${sid}_redir_port")
[ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) [ -n $(get_cache_var "ACL_${sid}_dns_port") ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
[ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT} [ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT}
[ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks) [ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks)
@ -571,111 +571,50 @@ filter_vpsip() {
echolog " - [$?]加入所有IPv6节点到ipset[$IPSET_VPSLIST6]直连完成" echolog " - [$?]加入所有IPv6节点到ipset[$IPSET_VPSLIST6]直连完成"
} }
filter_server_port() {
local address=${1}
local port=${2}
local stream=${3}
stream=$(echo ${3} | tr 'A-Z' 'a-z')
local _is_tproxy ipt_tmp
ipt_tmp=$ipt_n
_is_tproxy=${is_tproxy}
[ "$stream" == "udp" ] && _is_tproxy="TPROXY"
[ -n "${_is_tproxy}" ] && ipt_tmp=$ipt_m
for _ipt in 4 6; do
[ "$_ipt" == "4" ] && _ipt=$ipt_tmp
[ "$_ipt" == "6" ] && _ipt=$ip6t_m
$_ipt -n -L PSW2_OUTPUT | grep -q "${address}:${port}"
if [ $? -ne 0 ]; then
$_ipt -I PSW2_OUTPUT $(comment "${address}:${port}") -p $stream -d $address --dport $port -j RETURN 2>/dev/null
fi
done
}
filter_node() { filter_node() {
local proxy_node=${1} local node=${1}
local stream=$(echo ${2} | tr 'A-Z' 'a-z') local stream=${2}
local proxy_port=${3} if [ -n "$node" ] && [ "$node" != "nil" ]; then
local address=$(config_n_get $node address)
filter_rules() { local port=$(config_n_get $node port)
local node=${1} [ -z "$address" ] && [ -z "$port" ] && {
local stream=${2}
local _proxy=${3}
local _port=${4}
local _is_tproxy ipt_tmp msg msg2
if [ -n "$node" ] && [ "$node" != "nil" ]; then
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
local address=$(config_n_get $node address)
local port=$(config_n_get $node port)
[ -z "$address" ] && [ -z "$port" ] && {
echolog " - 节点配置不正常,略过"
return 1
}
ipt_tmp=$ipt_n
_is_tproxy=${is_tproxy}
[ "$stream" == "udp" ] && _is_tproxy="TPROXY"
if [ -n "${_is_tproxy}" ]; then
ipt_tmp=$ipt_m
msg="TPROXY"
else
msg="REDIRECT"
fi
else
echolog " - 节点配置不正常,略过"
return 1 return 1
fi
local ADD_INDEX=$FORCE_INDEX
for _ipt in 4 6; do
[ "$_ipt" == "4" ] && _ipt=$ipt_tmp
[ "$_ipt" == "6" ] && _ipt=$ip6t_m
$_ipt -n -L PSW2_OUTPUT | grep -q "${address}:${port}"
if [ $? -ne 0 ]; then
local dst_rule="-j PSW2_RULE"
msg2="按规则路由(${msg})"
[ "$_ipt" == "$ipt_m" -o "$_ipt" == "$ip6t_m" ] || {
dst_rule=$(REDIRECT $_port)
msg2="套娃使用(${msg}:${port} -> ${_port})"
}
[ -n "$_proxy" ] && [ "$_proxy" == "1" ] && [ -n "$_port" ] || {
ADD_INDEX=$(RULE_LAST_INDEX "$_ipt" PSW2_OUTPUT "$IPSET_VPSLIST" $FORCE_INDEX)
dst_rule=" -j RETURN"
msg2="直连代理"
}
$_ipt -I PSW2_OUTPUT $ADD_INDEX $(comment "${address}:${port}") -p $stream -d $address --dport $port $dst_rule 2>/dev/null
else
msg2="已配置过的节点,"
fi
done
msg="[$?]$(echo ${2} | tr 'a-z' 'A-Z')${msg2}使用链${ADD_INDEX},节点(${type}${address}:${port}"
#echolog " - ${msg}"
}
local proxy_protocol=$(config_n_get $proxy_node protocol)
local proxy_type=$(echo $(config_n_get $proxy_node type nil) | tr 'A-Z' 'a-z')
[ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 1
if [ "$proxy_protocol" == "_balancing" ]; then
#echolog " - 多节点负载均衡(${proxy_type}..."
proxy_node=$(config_n_get $proxy_node balancing_node)
for _node in $proxy_node; do
filter_rules "$_node" "$stream"
done
elif [ "$proxy_protocol" == "_shunt" ]; then
#echolog " - 按请求目的地址分流(${proxy_type}..."
local preproxy_enabled=$(config_n_get $proxy_node preproxy_enabled 0)
[ "$preproxy_enabled" == "1" ] && {
local preproxy_node=$(config_n_get $proxy_node main_node nil)
[ "$preproxy_node" != "nil" ] && {
local preproxy_node_address=$(config_n_get $preproxy_node address)
if [ -n "$preproxy_node_address" ]; then
filter_rules $preproxy_node $stream
else
preproxy_enabled=0
fi
}
} }
local default_node=$(config_n_get $proxy_node default_node _direct) filter_server_port $address $port $stream
if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then filter_server_port $address $port $stream
local default_proxy_tag=$(config_n_get $proxy_node default_proxy_tag nil)
[ "$default_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && default_proxy_tag="nil"
[ "$default_proxy_tag" == "nil" ] && filter_rules $default_node $stream
fi
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
for shunt_id in $shunt_ids; do
local shunt_node=$(config_n_get $proxy_node "${shunt_id}" nil)
[ "$shunt_node" == "nil" -o "$shunt_node" == "_default" -o "$shunt_node" == "_direct" -o "$shunt_node" == "_blackhole" ] && continue
local shunt_node_address=$(config_n_get $shunt_node address)
[ -z "$shunt_node_address" ] && continue
local shunt_proxy_tag=$(config_n_get $proxy_node "${shunt_id}_proxy_tag" nil)
[ "$shunt_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && shunt_proxy_tag="nil"
[ "$shunt_proxy_tag" == "nil" ] && filter_rules $shunt_node $stream
done
else
#echolog " - 普通节点(${proxy_type}..."
filter_rules "$proxy_node" "$stream"
fi fi
} }
filter_direct_node_list() {
[ ! -s "$TMP_PATH/direct_node_list" ] && return
for _node_id in $(cat $TMP_PATH/direct_node_list | awk '!seen[$0]++'); do
filter_node "$_node_id" TCP
filter_node "$_node_id" UDP
unset _node_id
done
}
add_firewall_rule() { add_firewall_rule() {
echolog "开始加载防火墙规则..." echolog "开始加载防火墙规则..."
ipset -! create $IPSET_LOCALLIST nethash maxelem 1048576 ipset -! create $IPSET_LOCALLIST nethash maxelem 1048576
@ -866,36 +805,13 @@ add_firewall_rule() {
ip -6 rule add fwmark 1 table 100 ip -6 rule add fwmark 1 table 100
ip -6 route add local ::/0 dev lo table 100 ip -6 route add local ::/0 dev lo table 100
# 过滤Socks节点 filter_direct_node_list
[ "$SOCKS_ENABLED" = "1" ] && {
local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
#echolog "分析 Socks 服务所使用节点..."
local id enabled node port msg num
for id in $ids; do
enabled=$(config_n_get $id enabled 0)
[ "$enabled" == "1" ] || continue
node=$(config_n_get $id node nil)
port=$(config_n_get $id port 0)
msg="Socks 服务 [:${port}]"
if [ "$node" == "nil" ] || [ "$port" == "0" ]; then
msg="${msg} 未配置完全,略过"
else
filter_node $node TCP > /dev/null 2>&1 &
filter_node $node UDP > /dev/null 2>&1 &
fi
#echolog " - ${msg}"
done
}
[ "$ENABLED_DEFAULT_ACL" == 1 ] && { [ "$ENABLED_DEFAULT_ACL" == 1 ] && {
local ipt_tmp=$ipt_n local ipt_tmp=$ipt_n
[ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m [ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m
# 过滤节点
filter_node $NODE TCP > /dev/null 2>&1 &
filter_node $NODE UDP > /dev/null 2>&1 &
TCP_LOCALHOST_PROXY=$LOCALHOST_PROXY TCP_LOCALHOST_PROXY=$LOCALHOST_PROXY
UDP_LOCALHOST_PROXY=$LOCALHOST_PROXY UDP_LOCALHOST_PROXY=$LOCALHOST_PROXY
@ -972,10 +888,12 @@ add_firewall_rule() {
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -p tcp -j PSW2_OUTPUT" insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -p tcp -j PSW2_OUTPUT"
fi fi
for iface in $(ls ${TMP_IFACE_PATH}); do [ -d "${TMP_IFACE_PATH}" ] && {
$ipt_n -I PSW2_OUTPUT -o $iface -p tcp -j RETURN for iface in $(ls ${TMP_IFACE_PATH}); do
$ipt_m -I PSW2_OUTPUT -o $iface -p tcp -j RETURN $ipt_n -I PSW2_OUTPUT -o $iface -p tcp -j RETURN
done $ipt_m -I PSW2_OUTPUT -o $iface -p tcp -j RETURN
done
}
fi fi
# 加载路由器自身代理 UDP # 加载路由器自身代理 UDP
@ -996,10 +914,12 @@ add_firewall_rule() {
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -p udp -j PSW2_OUTPUT" insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -p udp -j PSW2_OUTPUT"
fi fi
for iface in $(ls ${TMP_IFACE_PATH}); do [ -d "${TMP_IFACE_PATH}" ] && {
$ipt_n -I PSW2_OUTPUT -o $iface -p udp -j RETURN for iface in $(ls ${TMP_IFACE_PATH}); do
$ipt_m -I PSW2_OUTPUT -o $iface -p udp -j RETURN $ipt_n -I PSW2_OUTPUT -o $iface -p udp -j RETURN
done $ipt_m -I PSW2_OUTPUT -o $iface -p udp -j RETURN
done
}
fi fi
$ipt_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN $ipt_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN
@ -1179,6 +1099,9 @@ get_wan_ip)
get_wan6_ip) get_wan6_ip)
get_wan6_ip get_wan6_ip
;; ;;
filter_direct_node_list)
filter_direct_node_list
;;
stop) stop)
stop stop
;; ;;

View File

@ -347,9 +347,9 @@ load_acl() {
[ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS [ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
node_remark=$(config_n_get $NODE remarks) node_remark=$(config_n_get $NODE remarks)
[ -s "${TMP_ACL_PATH}/${sid}/var_node" ] && node=$(cat ${TMP_ACL_PATH}/${sid}/var_node) [ -n $(get_cache_var "ACL_${sid}_node") ] && node=$(get_cache_var "ACL_${sid}_node")
[ -s "${TMP_ACL_PATH}/${sid}/var_port" ] && redir_port=$(cat ${TMP_ACL_PATH}/${sid}/var_port) [ -n $(get_cache_var "ACL_${sid}_redir_port") ] && redir_port=$(get_cache_var "ACL_${sid}_redir_port")
[ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) [ -n $(get_cache_var "ACL_${sid}_dns_port") ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
[ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT} [ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT}
[ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks) [ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks)
@ -634,109 +634,48 @@ filter_vpsip() {
echolog " - [$?]加入所有IPv6节点到nftset[$NFTSET_VPSLIST6]直连完成" echolog " - [$?]加入所有IPv6节点到nftset[$NFTSET_VPSLIST6]直连完成"
} }
filter_server_port() {
local address=${1}
local port=${2}
local stream=${3}
stream=$(echo ${3} | tr 'A-Z' 'a-z')
local _is_tproxy
_is_tproxy=${is_tproxy}
[ "$stream" == "udp" ] && _is_tproxy="TPROXY"
for _ipt in 4 6; do
[ "$_ipt" == "4" ] && _ip_type=ip
[ "$_ipt" == "6" ] && _ip_type=ip6
nft "list chain $NFTABLE_NAME $nft_output_chain" 2>/dev/null | grep -q "${address}:${port}"
if [ $? -ne 0 ]; then
nft "insert rule $NFTABLE_NAME $nft_output_chain meta l4proto $stream $_ip_type daddr $address $stream dport $port return comment \"${address}:${port}\"" 2>/dev/null
fi
done
}
filter_node() { filter_node() {
local proxy_node=${1} local node=${1}
local stream=$(echo ${2} | tr 'A-Z' 'a-z') local stream=${2}
local proxy_port=${3} if [ -n "$node" ] && [ "$node" != "nil" ]; then
local address=$(config_n_get $node address)
filter_rules() { local port=$(config_n_get $node port)
local node=${1} [ -z "$address" ] && [ -z "$port" ] && {
local stream=${2}
local _proxy=${3}
local _port=${4}
local _is_tproxy msg msg2
if [ -n "$node" ] && [ "$node" != "nil" ]; then
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
local address=$(config_n_get $node address)
local port=$(config_n_get $node port)
[ -z "$address" ] && [ -z "$port" ] && {
echolog " - 节点配置不正常,略过"
return 1
}
_is_tproxy=${is_tproxy}
[ "$stream" == "udp" ] && _is_tproxy="TPROXY"
if [ -n "${_is_tproxy}" ]; then
msg="TPROXY"
else
msg="REDIRECT"
fi
else
echolog " - 节点配置不正常,略过"
return 1 return 1
fi
local ADD_INDEX=$FORCE_INDEX
for _ipt in 4 6; do
[ "$_ipt" == "4" ] && _ip_type=ip && _set_name=$NFTSET_VPSLIST
[ "$_ipt" == "6" ] && _ip_type=ip6 && _set_name=$NFTSET_VPSLIST6
nft "list chain $NFTABLE_NAME $nft_output_chain" 2>/dev/null | grep -q "${address}:${port}"
if [ $? -ne 0 ]; then
local dst_rule="jump PSW2_RULE"
msg2="按规则路由(${msg})"
[ -n "${is_tproxy}" ] || {
dst_rule=$(REDIRECT $_port)
msg2="套娃使用(${msg}:${port} -> ${_port})"
}
[ -n "$_proxy" ] && [ "$_proxy" == "1" ] && [ -n "$_port" ] || {
ADD_INDEX=$(RULE_LAST_INDEX "$NFTABLE_NAME" $nft_output_chain $_set_name $FORCE_INDEX)
dst_rule="return"
msg2="直连代理"
}
nft "insert rule $NFTABLE_NAME $nft_output_chain position $ADD_INDEX meta l4proto $stream $_ip_type daddr $address $stream dport $port $dst_rule comment \"${address}:${port}\"" 2>/dev/null
else
msg2="已配置过的节点,"
fi
done
msg="[$?]$(echo ${2} | tr 'a-z' 'A-Z')${msg2}使用链${ADD_INDEX},节点(${type}${address}:${port}"
#echolog " - ${msg}"
}
local proxy_protocol=$(config_n_get $proxy_node protocol)
local proxy_type=$(echo $(config_n_get $proxy_node type nil) | tr 'A-Z' 'a-z')
[ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 1
if [ "$proxy_protocol" == "_balancing" ]; then
#echolog " - 多节点负载均衡(${proxy_type}..."
proxy_node=$(config_n_get $proxy_node balancing_node)
for _node in $proxy_node; do
filter_rules "$_node" "$stream"
done
elif [ "$proxy_protocol" == "_shunt" ]; then
#echolog " - 按请求目的地址分流(${proxy_type}..."
local preproxy_enabled=$(config_n_get $proxy_node preproxy_enabled 0)
[ "$preproxy_enabled" == "1" ] && {
local preproxy_node=$(config_n_get $proxy_node main_node nil)
[ "$preproxy_node" != "nil" ] && {
local preproxy_node_address=$(config_n_get $preproxy_node address)
if [ -n "$preproxy_node_address" ]; then
filter_rules $preproxy_node $stream
else
preproxy_enabled=0
fi
}
} }
local default_node=$(config_n_get $proxy_node default_node _direct) filter_server_port $address $port $stream
if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then filter_server_port $address $port $stream
local default_proxy_tag=$(config_n_get $proxy_node default_proxy_tag nil)
[ "$default_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && default_proxy_tag="nil"
[ "$default_proxy_tag" == "nil" ] && filter_rules $default_node $stream
fi
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
for shunt_id in $shunt_ids; do
local shunt_node=$(config_n_get $proxy_node "${shunt_id}" nil)
[ "$shunt_node" == "nil" -o "$shunt_node" == "_default" -o "$shunt_node" == "_direct" -o "$shunt_node" == "_blackhole" ] && continue
local shunt_node_address=$(config_n_get $shunt_node address)
[ -z "$shunt_node_address" ] && continue
local shunt_proxy_tag=$(config_n_get $proxy_node "${shunt_id}_proxy_tag" nil)
[ "$shunt_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && shunt_proxy_tag="nil"
[ "$shunt_proxy_tag" == "nil" ] && filter_rules $shunt_node $stream
done
else
#echolog " - 普通节点(${proxy_type}..."
filter_rules "$proxy_node" "$stream"
fi fi
} }
filter_direct_node_list() {
[ ! -s "$TMP_PATH/direct_node_list" ] && return
for _node_id in $(cat $TMP_PATH/direct_node_list | awk '!seen[$0]++'); do
filter_node "$_node_id" TCP
filter_node "$_node_id" UDP
unset _node_id
done
}
add_firewall_rule() { add_firewall_rule() {
echolog "开始加载防火墙规则..." echolog "开始加载防火墙规则..."
gen_nft_tables gen_nft_tables
@ -922,33 +861,10 @@ add_firewall_rule() {
ip -6 rule add fwmark 1 table 100 ip -6 rule add fwmark 1 table 100
ip -6 route add local ::/0 dev lo table 100 ip -6 route add local ::/0 dev lo table 100
} }
# 过滤Socks节点 filter_direct_node_list
[ "$SOCKS_ENABLED" = "1" ] && {
local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
#echolog "分析 Socks 服务所使用节点..."
local id enabled node port msg num
for id in $ids; do
enabled=$(config_n_get $id enabled 0)
[ "$enabled" == "1" ] || continue
node=$(config_n_get $id node nil)
port=$(config_n_get $id port 0)
msg="Socks 服务 [:${port}]"
if [ "$node" == "nil" ] || [ "$port" == "0" ]; then
msg="${msg} 未配置完全,略过"
else
filter_node $node TCP > /dev/null 2>&1 &
filter_node $node UDP > /dev/null 2>&1 &
fi
#echolog " - ${msg}"
done
}
[ "$ENABLED_DEFAULT_ACL" == 1 ] && { [ "$ENABLED_DEFAULT_ACL" == 1 ] && {
# 过滤节点
filter_node $NODE TCP > /dev/null 2>&1 &
filter_node $NODE UDP > /dev/null 2>&1 &
TCP_LOCALHOST_PROXY=$LOCALHOST_PROXY TCP_LOCALHOST_PROXY=$LOCALHOST_PROXY
UDP_LOCALHOST_PROXY=$LOCALHOST_PROXY UDP_LOCALHOST_PROXY=$LOCALHOST_PROXY
@ -1026,10 +942,12 @@ add_firewall_rule() {
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp iif lo counter return comment \"本机\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp iif lo counter return comment \"本机\""
} }
for iface in $(ls ${TMP_IFACE_PATH}); do [ -d "${TMP_IFACE_PATH}" ] && {
nft "insert rule $NFTABLE_NAME $nft_output_chain ip protocol tcp oif $iface counter return" for iface in $(ls ${TMP_IFACE_PATH}); do
nft "insert rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol tcp oif $iface counter return" nft "insert rule $NFTABLE_NAME $nft_output_chain ip protocol tcp oif $iface counter return"
done nft "insert rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol tcp oif $iface counter return"
done
}
fi fi
# 加载路由器自身代理 UDP # 加载路由器自身代理 UDP
@ -1049,10 +967,12 @@ add_firewall_rule() {
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo counter return comment \"本机\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo counter return comment \"本机\""
fi fi
for iface in $(ls ${TMP_IFACE_PATH}); do [ -d "${TMP_IFACE_PATH}" ] && {
nft "insert rule $NFTABLE_NAME $nft_output_chain ip protocol udp oif $iface counter return" for iface in $(ls ${TMP_IFACE_PATH}); do
nft "insert rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol udp oif $iface counter return" nft "insert rule $NFTABLE_NAME $nft_output_chain ip protocol udp oif $iface counter return"
done nft "insert rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol udp oif $iface counter return"
done
}
fi fi
nft "add rule $NFTABLE_NAME mangle_output oif lo counter return comment \"PSW2_OUTPUT_MANGLE\"" nft "add rule $NFTABLE_NAME mangle_output oif lo counter return comment \"PSW2_OUTPUT_MANGLE\""
@ -1065,16 +985,6 @@ add_firewall_rule() {
# 加载ACLS # 加载ACLS
load_acl load_acl
[ -n "${is_tproxy}" -o -n "${udp_flag}" ] && {
bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables)
echo -n $bridge_nf_ipt > $TMP_PATH/bridge_nf_ipt
sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1
[ "$PROXY_IPV6" == "1" ] && {
bridge_nf_ip6t=$(sysctl -e -n net.bridge.bridge-nf-call-ip6tables)
echo -n $bridge_nf_ip6t > $TMP_PATH/bridge_nf_ip6t
sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1
}
}
echolog "防火墙规则加载完成!" echolog "防火墙规则加载完成!"
} }
@ -1208,6 +1118,9 @@ get_wan_ip)
get_wan6_ip) get_wan6_ip)
get_wan6_ip get_wan6_ip
;; ;;
filter_direct_node_list)
filter_direct_node_list
;;
stop) stop)
stop stop
;; ;;

View File

@ -78,9 +78,8 @@ test_auto_switch() {
local b_nodes=$1 local b_nodes=$1
local now_node=$2 local now_node=$2
[ -z "$now_node" ] && { [ -z "$now_node" ] && {
local f="/tmp/etc/$CONFIG/id/socks_${id}" if [ -n $(/usr/share/${CONFIG}/app.sh get_cache_var "socks_${id}") ]; then
if [ -f "${f}" ]; then now_node=$(/usr/share/${CONFIG}/app.sh get_cache_var "socks_${id}")
now_node=$(cat ${f})
else else
#echolog "自动切换检测:未知错误" #echolog "自动切换检测:未知错误"
return 1 return 1

View File

@ -312,6 +312,23 @@ do
} }
end end
else else
--前置代理节点
local currentNode = uci:get_all(appname, node_id) or nil
if currentNode and currentNode.preproxy_node then
CONFIG[#CONFIG + 1] = {
log = true,
id = node_id,
remarks = "节点[" .. node_id .. "]前置代理节点",
currentNode = uci:get_all(appname, currentNode.preproxy_node) or nil,
set = function(o, server)
uci:set(appname, node_id, "preproxy_node", server)
o.newNodeId = server
end,
delete = function(o)
uci:delete(appname, node_id, "preproxy_node")
end
}
end
--落地节点 --落地节点
local currentNode = uci:get_all(appname, node_id) or nil local currentNode = uci:get_all(appname, node_id) or nil
if currentNode and currentNode.to_node then if currentNode and currentNode.to_node then