From a69a645fe015b772eeee1f0d6bb78d131ba1992f Mon Sep 17 00:00:00 2001 From: zxlhhyccc Date: Sun, 22 Dec 2024 20:57:47 +0800 Subject: [PATCH] luci-app-ssr-plus: ssrurl.htm: Fix Xray's and Trojan's `trojan` protocol configuration import and subscribe issue. --- .../model/cbi/shadowsocksr/client-config.lua | 2 +- .../luasrc/view/shadowsocksr/ssrurl.htm | 69 +++++++++++++++-- .../root/usr/share/shadowsocksr/subscribe.lua | 77 +++++++++++++++++-- 3 files changed, 135 insertions(+), 13 deletions(-) diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua index ee288c80654..79109786b26 100644 --- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua +++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua @@ -937,7 +937,7 @@ if is_finded("xray") then -- [[ uTLS ]]-- o = s:option(ListValue, "fingerprint", translate("Finger Print")) - o.default = "chrome" + o.default = "" o:value("chrome", translate("chrome")) o:value("firefox", translate("firefox")) o:value("safari", translate("safari")) diff --git a/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm b/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm index f3d9f15ae72..6c11562bc93 100644 --- a/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm +++ b/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm @@ -217,8 +217,9 @@ case "trojan": try { var url = new URL("http://" + ssu[1]); + var params = url.searchParams; } catch(e) { - alert(e) + alert(e); return false; } @@ -232,7 +233,65 @@ document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = decodeURIComponent(url.username); document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true; document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event); - document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = url.searchParams.get("sni"); + document.getElementsByName('cbid.shadowsocksr.' + sid + '.fingerprint')[0].value = params.get("fp") || ""; + document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = params.get("sni"); + if (params.get("allowInsecure") === "1") { + document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].checked = true; // 设置 insecure 为 true + document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].dispatchEvent(event); // 触发事件 + } + document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].value = + params.get("type") == "http" ? "h2" : + (["tcp", "raw"].includes(params.get("type")) ? "raw" : + (params.get("type") || "tcp")); + document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].dispatchEvent(event); + switch (params.get("type")) { + case "ws": + if (params.get("security") !== "tls") { + setElementValue('cbid.shadowsocksr.' + sid + '.ws_host', params.get("host") ? decodeURIComponent(params.get("host")) : ""); + } + setElementValue('cbid.shadowsocksr.' + sid + '.ws_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/"); + break; + case "httpupgrade": + if (params.get("security") !== "tls") { + document.getElementsByName('cbid.shadowsocksr.' + sid + '.httpupgrade_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : ""; + } + document.getElementsByName('cbid.shadowsocksr.' + sid + '.httpupgrade_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/"; + break; + case "splithttp": + if (params.get("security") !== "tls") { + document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : ""; + } + document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/"; + break; + case "kcp": + document.getElementsByName('cbid.shadowsocksr.' + sid + '.kcp_guise')[0].value = params.get("headerType") || "none"; + document.getElementsByName('cbid.shadowsocksr.' + sid + '.seed')[0].value = params.get("seed") || ""; + break; + case "http": + /* this is non-standard, bullshit */ + case "h2": + document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : ""; + document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : ""; + break; + case "quic": + document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_guise')[0].value = params.get("headerType") || "none"; + document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_security')[0].value = params.get("quicSecurity") || "none"; + document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_key')[0].value = params.get("key") || ""; + break; + case "grpc": + document.getElementsByName('cbid.shadowsocksr.' + sid + '.serviceName')[0].value = params.get("serviceName") || ""; + document.getElementsByName('cbid.shadowsocksr.' + sid + '.grpc_mode')[0].value = params.get("mode") || "gun"; + break; + case "raw": + case "tcp": + document.getElementsByName('cbid.shadowsocksr.' + sid + '.tcp_guise')[0].value = params.get("headerType") || "none"; + document.getElementsByName('cbid.shadowsocksr.' + sid + '.tcp_guise')[0].dispatchEvent(event); + if (params.get("headerType") === "http") { + document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : ""; + document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : ""; + } + break; + } s.innerHTML = "<%:Import configuration information successfully.%>"; return false; @@ -306,7 +365,7 @@ var url = new URL("http://" + ssu[1]); var params = url.searchParams; } catch(e) { - alert(e) + alert(e); return false; } // Check if the elements exist before trying to modify them @@ -336,7 +395,7 @@ setElementValue('cbid.shadowsocksr.' + sid + '.vmess_id', url.username); setElementValue('cbid.shadowsocksr.' + sid + '.transport', params.get("type") === "http" ? "h2" : - (["tcp", "raw"].includes(params.get("type")) ? "raw" : + (["tcp", "raw"].includes(params.get("type")) ? "raw" : (params.get("type") || "tcp")) ); dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.transport', event); @@ -415,4 +474,4 @@ -<%+cbi/valuefooter%> +<%+cbi/valuefooter%> \ No newline at end of file diff --git a/luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua b/luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua index 0404be540b9..213a9426a62 100755 --- a/luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua +++ b/luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua @@ -319,6 +319,7 @@ local function processData(szType, content) result.server = nil end elseif szType == "trojan" then + local params = {} local idx_sp = 0 local alias = "" if content:find("#") then @@ -327,20 +328,30 @@ local function processData(szType, content) end local info = content:sub(1, idx_sp - 1) local hostInfo = split(info, "@") - local host = split(hostInfo[2], ":") local userinfo = hostInfo[1] local password = userinfo + + -- 分离服务器地址和端口 + local host = split(hostInfo[2], ":") + local server = host[1] + local port = host[2] + result.alias = UrlDecode(alias) result.type = v2_tj result.v2ray_protocol = "trojan" - result.server = host[1] + result.server = server + result.password = password + -- 按照官方的建议 默认验证ssl证书 result.insecure = "0" result.tls = "1" - if host[2]:find("?") then - local query = split(host[2], "?") + + -- trojan 不使用 kcp_param + result.kcp_param = nil + + if port:find("?") then + local query = split(port, "?") result.server_port = query[1] - local params = {} for _, v in pairs(split(query[2], '&')) do local t = split(v, '=') params[t[1]] = t[2] @@ -349,10 +360,62 @@ local function processData(szType, content) -- 未指定peer(sni)默认使用remote addr result.tls_host = params.sni end + + if params.allowInsecure then + -- 处理 insecure 参数 + result.insecure = params.allowInsecure + end else - result.server_port = host[2] + result.server_port = port + end + + if v2_tj ~= "trojan" then + if params.fp then + -- 处理 fingerprint 参数 + result.fingerprint = params.fp + end + -- 处理传输协议 + result.transport = params.type or "tcp" -- 默认传输协议为 tcp + if result.transport == "tcp" then + result.transport = "raw" + end + if result.transport == "ws" then + result.ws_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil + result.ws_path = params.path and UrlDecode(params.path) or "/" + elseif result.transport == "httpupgrade" then + result.httpupgrade_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil + result.httpupgrade_path = params.path and UrlDecode(params.path) or "/" + elseif result.transport == "splithttp" then + result.splithttp_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil + result.splithttp_path = params.path and UrlDecode(params.path) or "/" + elseif result.transport == "http" or result.transport == "h2" then + result.transport = "h2" + result.h2_host = params.host and UrlDecode(params.host) or nil + result.h2_path = params.path and UrlDecode(params.path) or nil + elseif result.transport == "kcp" then + result.kcp_guise = params.headerType or "none" + result.seed = params.seed + result.mtu = 1350 + result.tti = 50 + result.uplink_capacity = 5 + result.downlink_capacity = 20 + result.read_buffer_size = 2 + result.write_buffer_size = 2 + elseif result.transport == "quic" then + result.quic_guise = params.headerType or "none" + result.quic_security = params.quicSecurity or "none" + result.quic_key = params.key + elseif result.transport == "grpc" then + result.serviceName = params.serviceName + result.grpc_mode = params.mode or "gun" + elseif result.transport == "tcp" or result.transport == "raw" then + result.tcp_guise = params.headerType and params.headerType ~= "" and params.headerType or "none" + if result.tcp_guise == "http" then + result.tcp_host = params.host and UrlDecode(params.host) or nil + result.tcp_path = params.path and UrlDecode(params.path) or nil + end + end end - result.password = password elseif szType == "vless" then local url = URL.parse("http://" .. content) local params = url.query