diff --git a/luci-app-passwall2/Makefile b/luci-app-passwall2/Makefile index a3e86ced5..0f9cb501d 100644 --- a/luci-app-passwall2/Makefile +++ b/luci-app-passwall2/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=24.12.14 +PKG_VERSION:=24.12.16 PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-passwall2/luasrc/controller/passwall2.lua b/luci-app-passwall2/luasrc/controller/passwall2.lua index 5521ece0f..3c6a951c6 100644 --- a/luci-app-passwall2/luasrc/controller/passwall2.lua +++ b/luci-app-passwall2/luasrc/controller/passwall2.lua @@ -158,9 +158,9 @@ end function get_now_use_node() local e = {} - local data, code, msg = nixio.fs.readfile("/tmp/etc/passwall2/acl/default/global.id") - if data then - e["global"] = util.trim(data) + local node = api.get_cache_var("GLOBAL_node") + if node then + e["global"] = node end luci.http.prepare_content("application/json") luci.http.write_json(e) @@ -328,7 +328,7 @@ function clear_all_nodes() uci:delete(appname, t[".name"]) end) uci:foreach(appname, "acl_rule", function(t) - uci:set(appname, t[".name"], "node", "default") + uci:set(appname, t[".name"], "node", "nil") end) uci:foreach(appname, "nodes", function(node) uci:delete(appname, node['.name']) @@ -363,7 +363,17 @@ function delete_select_nodes() end) uci:foreach(appname, "acl_rule", function(t) 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) uci:delete(appname, w) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua index 09352ed14..d47cea1e8 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua @@ -22,9 +22,8 @@ o.default = 1 o.rmempty = false local auto_switch_tip -local current_node_file = string.format("/tmp/etc/%s/id/socks_%s", appname, 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 and current_node ~= "" and current_node ~= "nil" then +local current_node = api.get_cache_var("socks_" .. arg[1]) +if current_node then local n = uci:get_all(appname, current_node) if n then if tonumber(m:get(arg[1], "enable_autoswitch") or 0) == 1 then diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua index e98ad96cf..53686de88 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua @@ -647,12 +647,26 @@ o.default = 0 o = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay") o.default = 0 -o = s:option(ListValue, option_name("to_node"), translate("Landing node"), translate("Only support a layer of proxy.")) -o.default = "" +o = s:option(ListValue, option_name("chain_proxy"), translate("Chain Proxy")) 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 - if v.type == "Xray" then - o:value(v.id, v.remark) + if v.type == "Xray" 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 @@ -660,7 +674,7 @@ for i, v in ipairs(s.fields[option_name("protocol")].keylist) do if not v:find("_") then s.fields[option_name("tcpMptcp")]: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 diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua index ce424b751..dd1aa88a3 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua @@ -684,18 +684,27 @@ o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "tuic" }) 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.default = "" +o = s:option(ListValue, option_name("chain_proxy"), translate("Chain Proxy")) o:value("", translate("Close(Not use)")) -for k, v in pairs(nodes_table) do - if v.type == "sing-box" then - o:value(v.id, v.remark) - end -end +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 + 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) diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua index 9491c885f..ddd5ca4a4 100644 --- a/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/luci-app-passwall2/luasrc/passwall2/api.lua @@ -17,6 +17,8 @@ DISTRIB_ARCH = nil LOG_FILE = "/tmp/log/passwall2.log" CACHE_PATH = "/tmp/etc/passwall2_tmp" +TMP_PATH = "/tmp/etc/" .. appname +TMP_IFACE_PATH = TMP_PATH .. "/iface" function log(...) local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") @@ -27,6 +29,15 @@ function log(...) 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) local process = io.popen(cmd .. '; echo -e "\n$?"') local lines = {} @@ -96,8 +107,8 @@ end 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 ''") - if socks_server ~= "" then + local socks_server = get_cache_var("GLOBAL_SOCKS_server") + if socks_server and socks_server ~= "" then if not args then args = {} end local tmp_args = clone(args) tmp_args[#tmp_args + 1] = "-x socks5h://" .. socks_server diff --git a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index 254485783..9d0bf93f1 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -685,7 +685,7 @@ function gen_config_server(node) bind_interface = node.outbound_node_iface, 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 local outbound_node_t = uci:get_all("passwall2", node.outbound_node) 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) if not node or not outbound or not outbounds_table then return nil end local default_outTag = outbound.tag + local last_insert_outbound if node.shadowtls == "1" then local _node = { @@ -887,14 +888,31 @@ function gen_config(var) } local shadowtls_outbound = gen_outbound(nil, _node, outbound.tag .. "_shadowtls") if shadowtls_outbound then - table.insert(outbounds_table, shadowtls_outbound) + last_insert_outbound = shadowtls_outbound outbound.detour = outbound.tag .. "_shadowtls" outbound.server = nil outbound.server_port = nil 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) if to_node then local to_outbound = gen_outbound(nil, to_node) @@ -912,7 +930,7 @@ function gen_config(var) end end end - return default_outTag + return default_outTag, last_insert_outbound end 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 }) if _outbound then _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) + if last_insert_outbound then + table.insert(outbounds, last_insert_outbound) + end end end elseif _node.protocol == "_iface" then @@ -1011,7 +1032,7 @@ function gen_config(var) } table.insert(outbounds, _outbound) 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 @@ -1186,14 +1207,17 @@ function gen_config(var) } table.insert(outbounds, outbound) 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 else local outbound = gen_outbound(flag, node) if outbound then 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) + if last_insert_outbound then + table.insert(outbounds, last_insert_outbound) + end end end end @@ -1444,6 +1468,9 @@ function gen_config(var) tag = "block" }) 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 if k:find("_") == 1 then config.outbounds[index][k] = nil diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua index b480b16bc..5f9118096 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -416,7 +416,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 local outbound_node_t = uci:get_all("passwall2", node.outbound_node) if node.outbound_node == "_socks" or node.outbound_node == "_http" then @@ -782,8 +782,29 @@ function gen_config(var) 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 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) if to_node then local to_outbound = gen_outbound(nil, to_node) @@ -804,7 +825,7 @@ function gen_config(var) end end end - return default_outTag + return default_outTag, last_insert_outbound end if node then @@ -906,12 +927,15 @@ function gen_config(var) local outbound_tag if outbound then 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 table.insert(outbounds, 1, outbound) else table.insert(outbounds, outbound) end + if last_insert_outbound then + table.insert(outbounds, last_insert_outbound) + end end return outbound_tag, nil end @@ -932,7 +956,7 @@ function gen_config(var) } outbound_tag = outbound.tag 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 return outbound_tag, nil end @@ -1098,14 +1122,17 @@ function gen_config(var) } table.insert(outbounds, outbound) 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 else local outbound = gen_outbound(flag, node, nil, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.fragment == "1" or nil }) if outbound then 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) + if last_insert_outbound then + table.insert(outbounds, last_insert_outbound) + end routing = { domainStrategy = "AsIs", domainMatcher = "hybrid", @@ -1523,6 +1550,9 @@ function gen_config(var) end 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 if k:find("_") == 1 then config.outbounds[index][k] = nil diff --git a/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm b/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm index 5f222ecfe..8d5e0abe9 100644 --- a/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm +++ b/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm @@ -223,22 +223,18 @@ table td, .table .td { function get_now_use_node() { XHR.get('<%=api.url("get_now_use_node")%>', null, function(x, result) { - var id = result["TCP"]; + var id = result["global"]; if (id) { var dom = document.getElementById("cbi-passwall2-" + id); if (dom) { dom.classList.add("_now_use"); - dom.title = "当前TCP节点"; - //var v = "当前TCP节点:" + document.getElementById("cbid.passwall2." + id + ".remarks").value; + dom.title = "当前节点"; + //var v = "当前节点:" + document.getElementById("cbid.passwall2." + id + ".remarks").value; //document.getElementById("cbi-passwall2-" + id + "-remarks").innerHTML = v; - } - } - id = result["UDP"]; - if (id) { - var dom = document.getElementById("cbi-passwall2-" + id); - if (dom) { - dom.classList.add("_now_use"); - dom.title = "当前UDP节点"; + var tds = dom.getElementsByTagName("td") + for (var j = 0; j < tds.length; j++) { + tds[j].classList.add("_now_use"); + } } } } @@ -305,9 +301,7 @@ table td, .table .td { ); } } - - get_now_use_node(); - + /* 自动Ping */ if (auto_detection_time == "icmp" || auto_detection_time == "tcping") { var nodes = []; @@ -427,7 +421,9 @@ table td, .table .td { console.error(err); } } - + + get_now_use_node(); + if (true) { var str = ""; for (var add_from in node_list) { diff --git a/luci-app-passwall2/po/zh-cn/passwall2.po b/luci-app-passwall2/po/zh-cn/passwall2.po index 67f48a1a7..0be850e18 100644 --- a/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/luci-app-passwall2/po/zh-cn/passwall2.po @@ -1570,7 +1570,10 @@ msgstr "延迟(ms)" msgid "If is domain name, The requested domain name will be resolved to IP before connect." msgstr "如果是域名,域名将在请求发出之前解析为 IP。" -msgid "Landing node" +msgid "Chain Proxy" +msgstr "链式代理" + +msgid "Landing Node" msgstr "落地节点" msgid "Only support a layer of proxy." diff --git a/luci-app-passwall2/root/usr/share/passwall2/app.sh b/luci-app-passwall2/root/usr/share/passwall2/app.sh index 7f555fd9a..cc7c1a2ca 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -8,7 +8,6 @@ CONFIG=passwall2 TMP_PATH=/tmp/etc/$CONFIG TMP_BIN_PATH=$TMP_PATH/bin TMP_SCRIPT_FUNC_PATH=$TMP_PATH/script_func -TMP_ID_PATH=$TMP_PATH/id TMP_ROUTE_PATH=$TMP_PATH/route TMP_ACL_PATH=$TMP_PATH/acl TMP_IFACE_PATH=$TMP_PATH/iface @@ -324,6 +323,19 @@ get_singbox_geoip() { 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() { 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 @@ -654,6 +666,8 @@ run_socks() { fi } unset http_flag + + [ "${server_host}" != "127.0.0.1" ] && [ "$type" != "sing-box" ] && [ "$type" != "xray" ] && echo "${node}" >> $TMP_PATH/direct_node_list } socks_node_switch() { @@ -680,7 +694,9 @@ socks_node_switch() { local http_config_file="HTTP2SOCKS_${flag}.json" 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 - 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" = "nil" ] && return 1 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 echolog "开启实验性IPv6透明代理(TProxy),请确认您的节点及类型支持IPv6!" @@ -737,7 +753,7 @@ run_global() { node_socks_bind="127.0.0.1" [ "${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}" - 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" != "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_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 - echo $node > $TMP_ID_PATH/socks_${id} + set_cache_var "socks_${id}" "$node" #自动切换逻辑 local enable_autoswitch=$(config_n_get $id enable_autoswitch 0) @@ -947,7 +963,7 @@ delete_ip2route() { start_haproxy() { [ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && return - haproxy_path=${TMP_PATH}/haproxy + haproxy_path=$TMP_PATH/haproxy haproxy_conf="config.cfg" 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}" @@ -1013,7 +1029,7 @@ run_copy_dnsmasq() { 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" 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() { @@ -1157,10 +1173,10 @@ acl_app() { filter_node $node TCP > /dev/null 2>&1 & filter_node $node UDP > /dev/null 2>&1 & fi - echo "${node}" > $TMP_ACL_PATH/$sid/var_node + set_cache_var "ACL_${sid}_node" "${node}" } 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 _ip _mac _iprange _ipset _ip_or_mac source_list config_file @@ -1219,13 +1235,14 @@ start() { fi [ "$ENABLED_DEFAULT_ACL" == 1 ] && run_global [ -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 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 [ "$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 + set_cache_var "origin_bridge_nf_ip6t" "$bridge_nf_ip6t" sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1 } fi @@ -1244,9 +1261,11 @@ stop() { unset V2RAY_LOCATION_ASSET unset XRAY_LOCATION_ASSET 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 - [ -s "$TMP_PATH/bridge_nf_ip6t" ] && sysctl -w net.bridge.bridge-nf-call-ip6tables=$(cat $TMP_PATH/bridge_nf_ip6t) >/dev/null 2>&1 - rm -rf ${TMP_PATH} + origin_bridge_nf_ipt=$(get_cache_var "origin_bridge_nf_ipt") + [ -n "${origin_bridge_nf_ipt}" ] && sysctl -w net.bridge.bridge-nf-call-iptables=${origin_bridge_nf_ipt} >/dev/null 2>&1 + 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* echolog "清空并关闭相关程序和缓存完成。" 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 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 shift @@ -1319,6 +1338,12 @@ socks_node_switch) echolog) echolog $@ ;; +get_cache_var) + get_cache_var $@ + ;; +set_cache_var) + set_cache_var $@ + ;; stop) stop ;; diff --git a/luci-app-passwall2/root/usr/share/passwall2/iptables.sh b/luci-app-passwall2/root/usr/share/passwall2/iptables.sh index 6dd34b2e8..7dc379168 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/iptables.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/iptables.sh @@ -292,9 +292,9 @@ load_acl() { [ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS node_remark=$(config_n_get $NODE remarks) - [ -s "${TMP_ACL_PATH}/${sid}/var_node" ] && node=$(cat ${TMP_ACL_PATH}/${sid}/var_node) - [ -s "${TMP_ACL_PATH}/${sid}/var_port" ] && redir_port=$(cat ${TMP_ACL_PATH}/${sid}/var_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}_node") ] && node=$(get_cache_var "ACL_${sid}_node") + [ -n $(get_cache_var "ACL_${sid}_redir_port") ] && redir_port=$(get_cache_var "ACL_${sid}_redir_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} [ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks) @@ -571,111 +571,50 @@ filter_vpsip() { 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() { - local proxy_node=${1} - local stream=$(echo ${2} | tr 'A-Z' 'a-z') - local proxy_port=${3} - - filter_rules() { - local node=${1} - 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 " - 节点配置不正常,略过" + local node=${1} + local stream=${2} + if [ -n "$node" ] && [ "$node" != "nil" ]; then + local address=$(config_n_get $node address) + local port=$(config_n_get $node port) + [ -z "$address" ] && [ -z "$port" ] && { 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) - if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then - 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" + filter_server_port $address $port $stream + filter_server_port $address $port $stream 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() { echolog "开始加载防火墙规则..." ipset -! create $IPSET_LOCALLIST nethash maxelem 1048576 @@ -866,36 +805,13 @@ add_firewall_rule() { ip -6 rule add fwmark 1 table 100 ip -6 route add local ::/0 dev lo table 100 - - # 过滤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 - } + + filter_direct_node_list [ "$ENABLED_DEFAULT_ACL" == 1 ] && { local ipt_tmp=$ipt_n [ -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 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" fi - for iface in $(ls ${TMP_IFACE_PATH}); do - $ipt_n -I PSW2_OUTPUT -o $iface -p tcp -j RETURN - $ipt_m -I PSW2_OUTPUT -o $iface -p tcp -j RETURN - done + [ -d "${TMP_IFACE_PATH}" ] && { + for iface in $(ls ${TMP_IFACE_PATH}); do + $ipt_n -I PSW2_OUTPUT -o $iface -p tcp -j RETURN + $ipt_m -I PSW2_OUTPUT -o $iface -p tcp -j RETURN + done + } fi # 加载路由器自身代理 UDP @@ -996,10 +914,12 @@ add_firewall_rule() { insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -p udp -j PSW2_OUTPUT" fi - for iface in $(ls ${TMP_IFACE_PATH}); do - $ipt_n -I PSW2_OUTPUT -o $iface -p udp -j RETURN - $ipt_m -I PSW2_OUTPUT -o $iface -p udp -j RETURN - done + [ -d "${TMP_IFACE_PATH}" ] && { + for iface in $(ls ${TMP_IFACE_PATH}); do + $ipt_n -I PSW2_OUTPUT -o $iface -p udp -j RETURN + $ipt_m -I PSW2_OUTPUT -o $iface -p udp -j RETURN + done + } fi $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 ;; +filter_direct_node_list) + filter_direct_node_list + ;; stop) stop ;; diff --git a/luci-app-passwall2/root/usr/share/passwall2/nftables.sh b/luci-app-passwall2/root/usr/share/passwall2/nftables.sh index 5f7f3a80e..c14c09f96 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/nftables.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/nftables.sh @@ -347,9 +347,9 @@ load_acl() { [ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS node_remark=$(config_n_get $NODE remarks) - [ -s "${TMP_ACL_PATH}/${sid}/var_node" ] && node=$(cat ${TMP_ACL_PATH}/${sid}/var_node) - [ -s "${TMP_ACL_PATH}/${sid}/var_port" ] && redir_port=$(cat ${TMP_ACL_PATH}/${sid}/var_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}_node") ] && node=$(get_cache_var "ACL_${sid}_node") + [ -n $(get_cache_var "ACL_${sid}_redir_port") ] && redir_port=$(get_cache_var "ACL_${sid}_redir_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} [ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks) @@ -634,109 +634,48 @@ filter_vpsip() { 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() { - local proxy_node=${1} - local stream=$(echo ${2} | tr 'A-Z' 'a-z') - local proxy_port=${3} - - filter_rules() { - local node=${1} - 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 " - 节点配置不正常,略过" + local node=${1} + local stream=${2} + if [ -n "$node" ] && [ "$node" != "nil" ]; then + local address=$(config_n_get $node address) + local port=$(config_n_get $node port) + [ -z "$address" ] && [ -z "$port" ] && { 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) - if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then - 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" + filter_server_port $address $port $stream + filter_server_port $address $port $stream 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() { echolog "开始加载防火墙规则..." gen_nft_tables @@ -922,33 +861,10 @@ add_firewall_rule() { ip -6 rule add fwmark 1 table 100 ip -6 route add local ::/0 dev lo table 100 } - - # 过滤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 - } + + filter_direct_node_list [ "$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 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 \"本机\"" } - for iface in $(ls ${TMP_IFACE_PATH}); do - nft "insert rule $NFTABLE_NAME $nft_output_chain ip protocol tcp oif $iface counter return" - nft "insert rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol tcp oif $iface counter return" - done + [ -d "${TMP_IFACE_PATH}" ] && { + for iface in $(ls ${TMP_IFACE_PATH}); do + nft "insert rule $NFTABLE_NAME $nft_output_chain ip protocol tcp oif $iface counter return" + nft "insert rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol tcp oif $iface counter return" + done + } fi # 加载路由器自身代理 UDP @@ -1049,10 +967,12 @@ add_firewall_rule() { nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo counter return comment \"本机\"" fi - for iface in $(ls ${TMP_IFACE_PATH}); do - nft "insert rule $NFTABLE_NAME $nft_output_chain ip protocol udp oif $iface counter return" - nft "insert rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol udp oif $iface counter return" - done + [ -d "${TMP_IFACE_PATH}" ] && { + for iface in $(ls ${TMP_IFACE_PATH}); do + nft "insert rule $NFTABLE_NAME $nft_output_chain ip protocol udp oif $iface counter return" + nft "insert rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol udp oif $iface counter return" + done + } fi nft "add rule $NFTABLE_NAME mangle_output oif lo counter return comment \"PSW2_OUTPUT_MANGLE\"" @@ -1065,16 +985,6 @@ add_firewall_rule() { # 加载ACLS 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 "防火墙规则加载完成!" } @@ -1208,6 +1118,9 @@ get_wan_ip) get_wan6_ip) get_wan6_ip ;; +filter_direct_node_list) + filter_direct_node_list + ;; stop) stop ;; diff --git a/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh b/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh index 563bf57ea..ee4e88d8a 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh @@ -78,9 +78,8 @@ test_auto_switch() { local b_nodes=$1 local now_node=$2 [ -z "$now_node" ] && { - local f="/tmp/etc/$CONFIG/id/socks_${id}" - if [ -f "${f}" ]; then - now_node=$(cat ${f}) + if [ -n $(/usr/share/${CONFIG}/app.sh get_cache_var "socks_${id}") ]; then + now_node=$(/usr/share/${CONFIG}/app.sh get_cache_var "socks_${id}") else #echolog "自动切换检测:未知错误" return 1 diff --git a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index 29e46ecc6..a52f7ba81 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -312,6 +312,23 @@ do } end 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 if currentNode and currentNode.to_node then