From 391adf918f23803c4dbd5a5b3c7f0710dbb3bc12 Mon Sep 17 00:00:00 2001 From: actions Date: Mon, 12 Aug 2024 20:30:07 +0800 Subject: [PATCH] luci-app-passwall2: sync upstream last commit: https://github.com/xiaorouji/openwrt-passwall2/commit/dfb1721ee55893f24df772051e027e51343bf678 --- .../model/cbi/passwall2/client/node_list.lua | 11 +++ .../model/cbi/passwall2/client/other.lua | 12 ++- .../model/cbi/passwall2/client/type/ray.lua | 6 +- luci-app-passwall2/luasrc/passwall2/api.lua | 15 ++- .../passwall2/node_list/link_share_man.htm | 70 +++++++++++++- .../root/usr/share/passwall2/nftables.sh | 22 +++-- .../root/usr/share/passwall2/subscribe.lua | 96 +++++++++++++++++-- 7 files changed, 203 insertions(+), 29 deletions(-) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua index 647dd28b8..ab24748de 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua @@ -98,9 +98,20 @@ o.cfgvalue = function(t, n) protocol = "VMess" elseif protocol == "vless" then protocol = "VLESS" + elseif protocol == "shadowsocks" then + protocol = "SS" + elseif protocol == "shadowsocksr" then + protocol = "SSR" + elseif protocol == "wireguard" then + protocol = "WG" + elseif protocol == "hysteria" then + protocol = "HY" + elseif protocol == "hysteria2" then + protocol = "HY2" else protocol = protocol:gsub("^%l",string.upper) end + if type == "sing-box" then type = "Sing-Box" end type = type .. " " .. protocol end local address = m:get(n, "address") or "" diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua index 16545f0dd..a45de6af7 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua @@ -193,8 +193,10 @@ if has_singbox then o.rmempty = false o = s:option(Value, "geoip_url", translate("Custom geoip URL")) - o.default = "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db" - o:value("https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db") + o.default = "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.db" + o:value("https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.db") + o:value("https://github.com/1715173329/sing-geoip/releases/latest/download/geoip.db") + o:value("https://github.com/lyc8503/sing-box-rules/releases/latest/download/geoip.db") o.rmempty = false o = s:option(Value, "geosite_path", translate("Custom geosite Path")) @@ -202,8 +204,10 @@ if has_singbox then o.rmempty = false o = s:option(Value, "geosite_url", translate("Custom geosite URL")) - o.default = "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db" - o:value("https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db") + o.default = "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.db" + o:value("https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.db") + o:value("https://github.com/1715173329/sing-geosite/releases/latest/download/geosite.db") + o:value("https://github.com/lyc8503/sing-box-rules/releases/latest/download/geosite.db") o.rmempty = false o = s:option(Button, "_remove_resource", translate("Remove resource files")) 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 3fcad8cce..bb4aea440 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 @@ -341,12 +341,12 @@ o:depends({ [option_name("tls")] = true, [option_name("transport")] = "grpc" }) o = s:option(ListValue, option_name("alpn"), translate("alpn")) o.default = "default" o:value("default", translate("Default")) -o:value("h3,h2,http/1.1") -o:value("h3,h2") -o:value("h2,http/1.1") o:value("h3") o:value("h2") +o:value("h3,h2") o:value("http/1.1") +o:value("h2,http/1.1") +o:value("h3,h2,http/1.1") o:depends({ [option_name("tls")] = true, [option_name("reality")] = false }) -- o = s:option(Value, option_name("minversion"), translate("minversion")) diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua index e50bd5ea0..4aff3e379 100644 --- a/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/luci-app-passwall2/luasrc/passwall2/api.lua @@ -298,7 +298,9 @@ function get_valid_nodes() e.id = e[".name"] if e.type and e.remarks then if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then - e["remark"] = "%s:[%s] " % {e.type .. " " .. i18n.translatef(e.protocol), e.remarks} + local type = e.type + if type == "sing-box" then type = "Sing-Box" end + e["remark"] = "%s:[%s] " % {type .. " " .. i18n.translatef(e.protocol), e.remarks} e["node_type"] = "special" nodes[#nodes + 1] = e end @@ -312,9 +314,20 @@ function get_valid_nodes() protocol = "VMess" elseif protocol == "vless" then protocol = "VLESS" + elseif protocol == "shadowsocks" then + protocol = "SS" + elseif protocol == "shadowsocksr" then + protocol = "SSR" + elseif protocol == "wireguard" then + protocol = "WG" + elseif protocol == "hysteria" then + protocol = "HY" + elseif protocol == "hysteria2" then + protocol = "HY2" else protocol = protocol:gsub("^%l",string.upper) end + if type == "sing-box" then type = "Sing-Box" end type = type .. " " .. protocol end if is_ipv6(address) then address = get_ipv6_full(address) end diff --git a/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm b/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm index 626cf5ceb..56c433595 100644 --- a/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm +++ b/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm @@ -307,6 +307,10 @@ local api = require "luci.passwall2.api" params += opt.query("path", dom_prefix + "grpc_serviceName"); params += opt.query("serviceName", dom_prefix + "grpc_serviceName"); params += opt.query("mode", dom_prefix + "grpc_mode"); + } else if (v_transport === "splithttp") { + v_transport = "splithttp"; + params += opt.query("host", dom_prefix + "splithttp_host"); + params += opt.query("path", dom_prefix + "splithttp_path"); } params += "&type=" + v_transport; @@ -329,6 +333,7 @@ local api = require "luci.passwall2.api" params += "&flow=" + v_flow; } params += "&security=" + v_security; + params += opt.query("alpn", dom_prefix + "alpn"); params += opt.query("sni", dom_prefix + "tls_serverName"); } @@ -347,9 +352,37 @@ local api = require "luci.passwall2.api" var params = ""; if (opt.get(dom_prefix + "tls").checked) { params += opt.query("sni", dom_prefix + "tls_serverName"); - params += "&tls=1" + params += "&security=tls" params += opt.query("allowinsecure", dom_prefix + "tls_allowInsecure"); } + // 获取transport参数并设置type + var transport = opt.get(dom_prefix + "transport").value || ""; + switch (transport.toLowerCase()) { + case 'tcp': + params += "&type=tcp"; + break; + case 'ws': + params += "&type=ws"; + break; + case 'kcp': + params += "&type=kcp"; + break; + case 'mkcp': + params += "&type=kcp"; + break; + case 'http': + params += "&type=http"; + break; + case 'h2': + params += "&type=h2"; + break; + case 'grpc': + params += "&type=grpc"; + break; + default: + // 默认不添加type参数 + break; + } params += "#" + encodeURI(v_alias.value); if (params[0] == "&") { params = params.substring(1); @@ -655,7 +688,7 @@ local api = require "luci.passwall2.api" var queryParams = query[1]; var queryArray = queryParams.split('&'); var params; - for (i = 0; i < queryArray.length; i++) { + for (var i = 0; i < queryArray.length; i++) { params = queryArray[i].split('='); queryParam[decodeURIComponent(params[0]).toLowerCase()] = decodeURIComponent(params[1] || ''); } @@ -671,10 +704,37 @@ local api = require "luci.passwall2.api" opt.set(dom_prefix + 'address', m.hostname); opt.set(dom_prefix + 'port', m.port || "443"); opt.set(dom_prefix + 'password', decodeURIComponent(password)); - opt.set(dom_prefix + 'tls', queryParam.tls === "1"); + opt.set(dom_prefix + 'tls', queryParam.security === "tls" ? "1" : "0"); opt.set(dom_prefix + 'tls_serverName', queryParam.peer || queryParam.sni || ''); opt.set(dom_prefix + 'tls_allowInsecure', queryParam.allowinsecure === '1'); opt.set(dom_prefix + 'mux', queryParam.mux === '1'); + // 根据type参数设置transport + var transportType = queryParam.type || ""; + switch (transportType.toLowerCase()) { + case 'tcp': + opt.set(dom_prefix + 'transport', 'tcp'); + break; + case 'ws': + opt.set(dom_prefix + 'transport', 'ws'); + break; + case 'kcp': + opt.set(dom_prefix + 'transport', 'mkcp'); + break; + case 'mkcp': + opt.set(dom_prefix + 'transport', 'mkcp'); + break; + case 'http': + opt.set(dom_prefix + 'transport', 'http'); + break; + case 'h2': + opt.set(dom_prefix + 'transport', 'h2'); + break; + case 'grpc': + opt.set(dom_prefix + 'transport', 'grpc'); + break; + default: + opt.set(dom_prefix + 'transport', ''); // 默认清空transport + } if (m.hash) { opt.set('remarks', decodeURI(m.hash.substr(1))); } @@ -789,6 +849,7 @@ local api = require "luci.passwall2.api" opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'reality', false) opt.set(dom_prefix + 'flow', queryParam.flow || ''); + opt.set(dom_prefix + 'alpn', queryParam.alpn || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_allowInsecure', true); if (queryParam.allowinsecure === '0') { @@ -859,6 +920,9 @@ local api = require "luci.passwall2.api" } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + } else if (queryParam.type === "splithttp") { + opt.set(dom_prefix + 'splithttp_host', queryParam.host || ""); + opt.set(dom_prefix + 'splithttp_path', queryParam.path || ""); } if (m.hash) { diff --git a/luci-app-passwall2/root/usr/share/passwall2/nftables.sh b/luci-app-passwall2/root/usr/share/passwall2/nftables.sh index 18e518938..98736c402 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/nftables.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/nftables.sh @@ -685,7 +685,8 @@ add_firewall_rule() { nft "add rule inet fw4 PSW2_OUTPUT_MANGLE meta mark 0xff counter return" # jump chains - nft "add rule inet fw4 mangle_prerouting meta nfproto {ipv4} counter jump PSW2_MANGLE" + nft "add rule inet fw4 mangle_prerouting ip protocol udp counter jump PSW2_MANGLE" + [ -n "${is_tproxy}" ] && nft "add rule inet fw4 mangle_prerouting ip protocol tcp counter jump PSW2_MANGLE" insert_rule_before "inet fw4" "mangle_prerouting" "PSW2_MANGLE" "counter jump PSW2_DIVERT" #ipv4 tcp redirect mode @@ -943,10 +944,11 @@ flush_include() { } gen_include() { + flush_include local nft_chain_file=$TMP_PATH/PSW2_RULE.nft local nft_set_file=$TMP_PATH/PSW2_SETS.nft - echo "#!/usr/sbin/nft -f" > $nft_chain_file - echo "#!/usr/sbin/nft -f" > $nft_set_file + echo '#!/usr/sbin/nft -f' > $nft_chain_file + echo '#!/usr/sbin/nft -f' > $nft_set_file for chain in $(nft -a list chains | grep -E "chain PSW2_" | awk -F ' ' '{print$2}'); do nft list chain inet fw4 ${chain} >> $nft_chain_file done @@ -978,14 +980,16 @@ gen_include() { nft "add rule inet fw4 dstnat ip protocol tcp counter jump PSW2_NAT" nft "add rule inet fw4 nat_output ip protocol tcp counter jump PSW2_OUTPUT_NAT" } + + PR_INDEX=\$(sh ${MY_PATH} RULE_LAST_INDEX "inet fw4" PSW2_MANGLE WAN_IP_RETURN -1) + if [ \$PR_INDEX -ge 0 ]; then + WAN_IP=\$(sh ${MY_PATH} get_wan_ip) + [ ! -z "\${WAN_IP}" ] && nft "replace rule inet fw4 PSW2_MANGLE handle \$PR_INDEX ip daddr "\${WAN_IP}" counter return comment \"WAN_IP_RETURN\"" + fi + nft "add rule inet fw4 mangle_prerouting ip protocol udp counter jump PSW2_MANGLE" [ -n "${is_tproxy}" ] && { - PR_INDEX=\$(sh ${MY_PATH} RULE_LAST_INDEX "inet fw4" PSW2_MANGLE WAN_IP_RETURN -1) - if [ \$PR_INDEX -ge 0 ]; then - WAN_IP=\$(sh ${MY_PATH} get_wan_ip) - [ ! -z "\${WAN_IP}" ] && nft "replace rule inet fw4 PSW2_MANGLE handle \$PR_INDEX ip daddr "\${WAN_IP}" counter return comment \"WAN_IP_RETURN\"" - fi - nft "add rule inet fw4 mangle_prerouting meta nfproto {ipv4} counter jump PSW2_MANGLE" + nft "add rule inet fw4 mangle_prerouting ip protocol tcp counter jump PSW2_MANGLE" nft "add rule inet fw4 mangle_output ip protocol tcp counter jump PSW2_OUTPUT_MANGLE comment \"PSW2_OUTPUT_MANGLE\"" } \$(sh ${MY_PATH} insert_rule_before "inet fw4" "mangle_prerouting" "PSW2_MANGLE" "counter jump PSW2_DIVERT") diff --git a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index 1fd64fa08..0391c6f90 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -610,6 +610,12 @@ local function processData(szType, content, add_mode, add_from) end end elseif szType == "trojan" then + if trojan_type_default == "sing-box" and has_singbox then + result.type = 'sing-box' + elseif trojan_type_default == "xray" and has_xray then + result.type = 'Xray' + end + result.protocol = 'trojan' local alias = "" if content:find("#") then local idx_sp = content:find("#") @@ -655,8 +661,10 @@ local function processData(szType, content, add_mode, add_from) if sni == "" and params.wshost then sni = params.wshost end end result.port = port + result.tls = '1' result.tls_serverName = peer and peer or sni + if params.allowinsecure then if params.allowinsecure == "1" or params.allowinsecure == "0" then result.tls_allowInsecure = params.allowinsecure @@ -668,12 +676,71 @@ local function processData(szType, content, add_mode, add_from) result.tls_allowInsecure = allowInsecure_default and "1" or "0" end - if trojan_type_default == "sing-box" and has_singbox then - result.type = 'sing-box' - elseif trojan_type_default == "xray" and has_xray then - result.type = 'Xray' + if not params.type then + params.type = "tcp" end - result.protocol = 'trojan' + params.type = string.lower(params.type) + result.transport = params.type + if params.type == 'ws' then + result.ws_host = params.host + result.ws_path = params.path + if result.type == "sing-box" and params.path then + local ws_path_dat = split(params.path, "?") + local ws_path = ws_path_dat[1] + local ws_path_params = {} + for _, v in pairs(split(ws_path_dat[2], '&')) do + local t = split(v, '=') + ws_path_params[t[1]] = t[2] + end + if ws_path_params.ed and tonumber(ws_path_params.ed) then + result.ws_path = ws_path + result.ws_enableEarlyData = "1" + result.ws_maxEarlyData = tonumber(ws_path_params.ed) + result.ws_earlyDataHeaderName = "Sec-WebSocket-Protocol" + end + end + end + if params.type == 'h2' or params.type == 'http' then + if result.type == "sing-box" then + result.transport = "http" + result.http_host = params.host + result.http_path = params.path + elseif result.type == "xray" then + result.transport = "h2" + result.h2_host = params.host + result.h2_path = params.path + end + end + if params.type == 'tcp' then + result.tcp_guise = params.headerType or "none" + result.tcp_guise_http_host = params.host + result.tcp_guise_http_path = params.path + end + if params.type == 'kcp' or params.type == 'mkcp' then + result.transport = "mkcp" + result.mkcp_guise = params.headerType or "none" + result.mkcp_mtu = 1350 + result.mkcp_tti = 50 + result.mkcp_uplinkCapacity = 5 + result.mkcp_downlinkCapacity = 20 + result.mkcp_readBufferSize = 2 + result.mkcp_writeBufferSize = 2 + result.mkcp_seed = params.seed + end + if params.type == 'quic' then + result.quic_guise = params.headerType or "none" + result.quic_key = params.key + result.quic_security = params.quicSecurity or "none" + end + if params.type == 'grpc' then + if params.path then result.grpc_serviceName = params.path end + if params.serviceName then result.grpc_serviceName = params.serviceName end + result.grpc_mode = params.mode + end + + result.encryption = params.encryption or "none" + + result.flow = params.flow or nil end elseif szType == "ssd" then result.type = "SS" @@ -757,9 +824,15 @@ local function processData(szType, content, add_mode, add_from) end end if params.type == 'h2' or params.type == 'http' then - params.type = "h2" - result.h2_host = params.host - result.h2_path = params.path + if result.type == "sing-box" then + result.transport = "http" + result.http_host = params.host + result.http_path = params.path + elseif result.type == "xray" then + result.transport = "h2" + result.h2_host = params.host + result.h2_path = params.path + end end if params.type == 'tcp' then result.tcp_guise = params.headerType or "none" @@ -767,7 +840,7 @@ local function processData(szType, content, add_mode, add_from) result.tcp_guise_http_path = params.path end if params.type == 'kcp' or params.type == 'mkcp' then - params.type = "mkcp" + result.transport = "mkcp" result.mkcp_guise = params.headerType or "none" result.mkcp_mtu = 1350 result.mkcp_tti = 50 @@ -786,6 +859,10 @@ local function processData(szType, content, add_mode, add_from) if params.serviceName then result.grpc_serviceName = params.serviceName end result.grpc_mode = params.mode end + if params.type == 'splithttp' then + result.splithttp_host = params.host + result.splithttp_path = params.path + end result.encryption = params.encryption or "none" @@ -795,6 +872,7 @@ local function processData(szType, content, add_mode, add_from) if params.security == "tls" or params.security == "reality" then result.tls = "1" result.tls_serverName = (params.sni and params.sni ~= "") and params.sni or params.host + result.alpn = params.alpn result.fingerprint = (params.fp and params.fp ~= "") and params.fp or "chrome" if params.security == "reality" then result.reality = "1"