Преглед изворни кода

luci-app-ssr-plus: ssrurl.htm: Fix Xray's and Trojan's trojan protocol configuration import and subscribe issue.

*** 修改 `fingerprint` 为默认禁用,有效解决节点的 `fingerprint` 在保存后自动改为 `chrome` ,此时如再次保存节点,将改变节点实际的 `fingerprint` 值的问题,此修改在保存后仍默认节点的 `fingerprint` 值。
*** 此PR为: https://github.com/fw876/helloworld/pull/1637  重开。
zxlhhyccc пре 10 месеци
родитељ
комит
d2a276cc2e

+ 2 - 2
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"))
@@ -1016,7 +1016,7 @@ o:depends("mux", true)
 
 
 -- [[ MPTCP ]]--
-o = s:option(Flag, "mptcp", translate("MPTCP"))
+o = s:option(Flag, "mptcp", translate("MPTCP"), translate("Enabling MPTCP Requires Server Support."))
 o.rmempty = false
 o.default = false
 o:depends({type = "v2ray", v2ray_protocol = "vless"})

+ 63 - 4
luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm

@@ -217,8 +217,9 @@ function import_ssr_url(btn, urlname, sid) {
 		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 @@ function import_ssr_url(btn, urlname, sid) {
 			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") || "raw"));
+			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 = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
 			return false;
@@ -306,7 +365,7 @@ function import_ssr_url(btn, urlname, sid) {
 				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 @@ function import_ssr_url(btn, urlname, sid) {
 			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);

+ 2 - 0
luci-app-ssr-plus/po/zh_Hans/ssr-plus.po

@@ -91,6 +91,8 @@ msgstr "TLS 主机名"
 msgid "allowInsecure"
 msgstr "允许不安全连接"
 
+msgid "Enabling MPTCP Requires Server Support."
+msgstr "启用 MPTCP 需服务端支持。"
 
 msgid "concurrency"
 msgstr "TCP 最大并发连接数"

+ 7 - 4
luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua

@@ -283,8 +283,9 @@ end
 					initial_windows_size = tonumber(server.initial_windows_size) or nil
 				} or nil,
 				sockopt = {
-					tcpMptcp = (server.mptcp == "1") and true or false, -- MPTCP
-					tcpNoDelay = (server.mptcp == "1") and true or false, -- MPTCP
+					mark = 250,
+					tcpMptcp = (server.mptcp == "1") and true or nil, -- MPTCP
+					tcpNoDelay = (server.mptcp == "1") and true or nil, -- MPTCP
 					tcpcongestion = server.custom_tcpcongestion, -- 连接服务器节点的 TCP 拥塞控制算法
 					dialerProxy = (xray_fragment.fragment == "1" or xray_fragment.noise == "1") and "dialerproxy" or nil
 				}
@@ -321,8 +322,10 @@ if xray_fragment.fragment ~= "0" or (xray_fragment.noise ~= "0" and xray_noise.e
 		},
 		streamSettings = {
 			sockopt = {
-			tcpMptcp = (server.mptcp == "1") and true or false, -- MPTCP
-			tcpNoDelay = (server.mptcp == "1") and true or false -- MPTCP
+			mark = 250,
+			tcpMptcp = (server.mptcp == "1") and true or nil, -- MPTCP
+			tcpNoDelay = (server.mptcp == "1") and true or nil, -- MPTCP
+			tcpcongestion = server.custom_tcpcongestion -- 连接服务器节点的 TCP 拥塞控制算法
 			}
 		}
 	})

+ 67 - 7
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,27 @@ 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], "?")
+
+		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 +357,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