luci-app-ssr-plus: sync upstream

last commit: 2bea2ad79e
This commit is contained in:
gitea-action 2025-01-18 16:00:17 +08:00
parent 9e84c75322
commit ba17044aed
10 changed files with 243 additions and 33 deletions

View File

@ -165,12 +165,12 @@ for key, server_type in pairs(type_table) do
end end
-- Socks User -- Socks User
o = s:option(Value, "socks5_user", translate("Socks5 User"), translate("Only when auth is password valid, Mandatory.")) o = s:option(Value, "socks5_user", translate("Socks5 User"), translate("Only when Socks5 Auth Mode is password valid, Mandatory."))
o.rmempty = true o.rmempty = true
o:depends("socks5_auth", "password") o:depends("socks5_auth", "password")
-- Socks Password -- Socks Password
o = s:option(Value, "socks5_pass", translate("Socks5 Password"), translate("Only when auth is password valid, Not mandatory.")) o = s:option(Value, "socks5_pass", translate("Socks5 Password"), translate("Only when Socks5 Auth Mode is password valid, Not mandatory."))
o.password = true o.password = true
o.rmempty = true o.rmempty = true
o:depends("socks5_auth", "password") o:depends("socks5_auth", "password")
@ -224,7 +224,7 @@ o.default = 0
s = m:section(TypedSection, "xray_noise_packets", translate("Xray Noise Packets")) s = m:section(TypedSection, "xray_noise_packets", translate("Xray Noise Packets"))
s.description = translate( s.description = translate(
"<font style='color:red'>" .. translate("To send noise packets, select \"Noise\" in Xray Settings.") .. "</font>" .. "<font style='color:red'>" .. translate("To send noise packets, select \"Noise\" in Xray Settings.") .. "</font>" ..
"<br/><font><b>" .. translate("For specific usage, see: ") .. "</b></font>" .. "<br/><font><b>" .. translate("For specific usage, see:") .. "</b></font>" ..
"<a href='https://xtls.github.io/config/outbounds/freedom.html' target='_blank'>" .. "<a href='https://xtls.github.io/config/outbounds/freedom.html' target='_blank'>" ..
"<font style='color:green'><b>" .. translate("Click to the page") .. "</b></font></a>") "<font style='color:green'><b>" .. translate("Click to the page") .. "</b></font></a>")
s.template = "cbi/tblsection" s.template = "cbi/tblsection"

View File

@ -4,6 +4,7 @@
require "nixio.fs" require "nixio.fs"
require "luci.sys" require "luci.sys"
require "luci.http" require "luci.http"
require "luci.jsonc"
require "luci.model.ipkg" require "luci.model.ipkg"
local m, s, o local m, s, o
@ -504,7 +505,6 @@ o.rmempty = true
o.default = "" o.default = ""
o:depends("type", "tuic") o:depends("type", "tuic")
o = s:option(ListValue, "udp_relay_mode", translate("UDP relay mode")) o = s:option(ListValue, "udp_relay_mode", translate("UDP relay mode"))
o:depends("type", "tuic") o:depends("type", "tuic")
o:value("native", translate("native UDP characteristics")) o:value("native", translate("native UDP characteristics"))
@ -623,6 +623,7 @@ o:value("kcp", "mKCP")
o:value("ws", "WebSocket") o:value("ws", "WebSocket")
o:value("httpupgrade", "HTTPUpgrade") o:value("httpupgrade", "HTTPUpgrade")
o:value("splithttp", "SplitHTTP") o:value("splithttp", "SplitHTTP")
o:value("xhttp", "XHTTP")
o:value("h2", "HTTP/2") o:value("h2", "HTTP/2")
o:value("quic", "QUIC") o:value("quic", "QUIC")
o:value("grpc", "gRPC") o:value("grpc", "gRPC")
@ -703,6 +704,78 @@ o = s:option(Value, "splithttp_path", translate("Splithttp Path"))
o:depends("transport", "splithttp") o:depends("transport", "splithttp")
o.rmempty = true o.rmempty = true
-- [[ XHTTP部分 ]]--
o = s:option(ListValue, "xhttp_alpn", translate("XHTTP Alpn"))
o.default = ""
o:value("", translate("Default"))
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("transport", "xhttp")
o = s:option(ListValue, "xhttp_mode", translate("XHTTP Mode"))
o:depends("transport", "xhttp")
o.default = "auto"
o:value("auto")
o:value("packet-up")
o:value("stream-up")
o:value("stream-one")
o = s:option(Value, "xhttp_host", translate("XHTTP Host"))
o:depends({transport = "xhttp", tls = false})
o.rmempty = true
o = s:option(Value, "xhttp_path", translate("XHTTP Path"))
o.placeholder = "/"
o:depends("transport", "xhttp")
o.rmempty = true
o = s:option(Flag, "enable_xhttp_extra", translate("XHTTP Extra"))
o.description = translate("Enable this option to configure XHTTP Extra (JSON format).")
o.default = "0"
o.rmempty = false
o:depends("transport", "xhttp")
o = s:option(TextValue, "xhttp_extra", " ")
o.description = translate(
"<font><b>" .. translate("Configure XHTTP Extra Settings (JSON format), see:") .. "</b></font>" ..
" <a href='https://xtls.github.io/config/transports/splithttp.html#extra' target='_blank'>" ..
"<font style='color:green'><b>" .. translate("Click to the page") .. "</b></font></a>")
o:depends("enable_xhttp_extra", true)
o.rmempty = true
o.rows = 10
o.wrap = "off"
o.custom_write = function(self, section, value)
m:set(section, "xhttp_extra", value)
local success, data = pcall(luci.jsonc.parse, value)
if success and data then
local address = (data.extra and data.extra.downloadSettings and data.extra.downloadSettings.address)
or (data.downloadSettings and data.downloadSettings.address)
if address and address ~= "" then
m:set(section, "download_address", address)
else
m:del(section, "download_address")
end
else
m:del(section, "download_address")
end
end
o.validate = function(self, value)
value = value:gsub("\r\n", "\n"):gsub("^[ \t]*\n", ""):gsub("\n[ \t]*$", ""):gsub("\n[ \t]*\n", "\n")
if value:sub(-1) == "\n" then
value = value:sub(1, -2)
end
local success, data = pcall(luci.jsonc.parse, value)
if not success or not data then
return nil, translate("Invalid JSON format")
end
return value
end
-- [[ H2部分 ]]-- -- [[ H2部分 ]]--
-- H2域名 -- H2域名

View File

@ -26,8 +26,8 @@ s = fb:section(SimpleSection, translate("Backup and Restore"), translate("Backup
"<br><font style='color:red'><b>" .. "<br><font style='color:red'><b>" ..
translate("Note: Restoring configurations across different versions may cause compatibility issues.") .. translate("Note: Restoring configurations across different versions may cause compatibility issues.") ..
"</b></font>") "</b></font>")
o = s:option(DummyValue, '', nil) s.anonymous = true
o.template = "shadowsocksr/backup_restore" s:append(Template("shadowsocksr/backup_restore"))
-- 定义备份目标文件和目录 -- 定义备份目标文件和目录
local backup_targets = { local backup_targets = {

View File

@ -1,22 +1,21 @@
<%+cbi/valueheader%>
<div class="cbi-value" id="_backup_div"> <div class="cbi-value" id="_backup_div">
<label class="cbi-value-title"><%:Create Backup File%></label> <label class="cbi-value-title"><%:Create Backup File%></label>
<div class="cbi-value-field"> <div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-input-apply" onclick="dl_backup()" value="<%:DL Backup%>" /> <input class="btn cbi-button cbi-button-save" type="button" onclick="dl_backup()" value="<%:DL Backup%>" />
</div> </div>
</div> </div>
<div class="cbi-value" id="_upload_div"> <div class="cbi-value" id="_upload_div">
<label class="cbi-value-title"><%:Restore Backup File%></label> <label class="cbi-value-title"><%:Restore Backup File%></label>
<div class="cbi-value-field"> <div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-input-apply" id="upload-btn" value="<%:RST Backup%>" /> <input class="btn cbi-button cbi-button-apply" type="button" id="upload-btn" value="<%:RST Backup%>" />
</div> </div>
</div> </div>
<div class="cbi-value" id="_reset_div"> <div class="cbi-value" id="_reset_div">
<label class="cbi-value-title"><%:Restore to default configuration%></label> <label class="cbi-value-title"><%:Restore to default configuration%></label>
<div class="cbi-value-field"> <div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-remove" onclick="do_reset()" value="<%:Do Reset%>" /> <input class="btn cbi-button cbi-button-remove" type="button" onclick="do_reset()" value="<%:Do Reset%>" />
</div> </div>
</div> </div>
@ -28,8 +27,8 @@
<input class="cbi-input-file" type="file" id="ulfile" name="ulfile" accept=".tar.gz" required /> <input class="cbi-input-file" type="file" id="ulfile" name="ulfile" accept=".tar.gz" required />
<br /> <br />
<div class="up-button-container"> <div class="up-button-container">
<input type="submit" class="btn cbi-button cbi-input-apply" value="<%:UL Restore%>" /> <input class="btn cbi-button cbi-button-apply" type="submit" value="<%:UL Restore%>" />
<button class="btn cbi-button cbi-button-remove" id="upload-close"><%:CLOSE WIN%></button> <input class="btn cbi-button cbi-button-remove" type="button" id="upload-close" value="<%:CLOSE WIN%>" />
</div> </div>
</div> </div>
</div> </div>
@ -151,4 +150,3 @@
} }
} }
</script> </script>
<%+cbi/valuefooter%>

View File

@ -263,6 +263,18 @@ function import_ssr_url(btn, urlname, sid) {
} }
document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/"; document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
break; break;
case "xhttp":
if (params.get("security") !== "tls") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
}
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_mode')[0].value = params.get("mode") || "auto";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
if (params.get("extra") && params.get("extra").trim() !== "") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].checked = true; // 设置 enable_xhttp_extra 为 true
document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].dispatchEvent(event); // 触发事件
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_extra')[0].value = params.get("extra") || "";
}
break;
case "kcp": case "kcp":
document.getElementsByName('cbid.shadowsocksr.' + sid + '.kcp_guise')[0].value = params.get("headerType") || "none"; document.getElementsByName('cbid.shadowsocksr.' + sid + '.kcp_guise')[0].value = params.get("headerType") || "none";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.seed')[0].value = params.get("seed") || ""; document.getElementsByName('cbid.shadowsocksr.' + sid + '.seed')[0].value = params.get("seed") || "";
@ -338,6 +350,16 @@ function import_ssr_url(btn, urlname, sid) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_host')[0].value = ssm.host; document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_host')[0].value = ssm.host;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_path')[0].value = ssm.path; document.getElementsByName('cbid.shadowsocksr.' + sid + '.splithttp_path')[0].value = ssm.path;
} }
if (ssm.net == "xhttp") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_mode')[0].value = ssm.mode;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_host')[0].value = ssm.host;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_path')[0].value = ssm.path;
if (params.get("extra") && params.get("extra").trim() !== "") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].checked = true; // 设置 enable_xhttp_extra 为 true
document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra')[0].dispatchEvent(event); // 触发事件
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_extra')[0].value = ssm.extra;
}
}
if (ssm.net == "h2") { if (ssm.net == "h2") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_host')[0].value = ssm.host; document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_host')[0].value = ssm.host;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_path')[0].value = ssm.path; document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_path')[0].value = ssm.path;
@ -352,6 +374,7 @@ function import_ssr_url(btn, urlname, sid) {
if (ssm.tls == "tls") { if (ssm.tls == "tls") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true; document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event); document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.xhttp_alpn')[0].value = ssm.alpn;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = ssm.sni || ssm.host; document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = ssm.sni || ssm.host;
} }
if (ssm.mux !== undefined) { if (ssm.mux !== undefined) {
@ -412,6 +435,7 @@ function import_ssr_url(btn, urlname, sid) {
setElementValue('cbid.shadowsocksr.' + sid + '.tls_flow', params.get("flow") || "none"); setElementValue('cbid.shadowsocksr.' + sid + '.tls_flow', params.get("flow") || "none");
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.tls_flow', event); dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.tls_flow', event);
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_alpn', params.get("alpn") || "");
setElementValue('cbid.shadowsocksr.' + sid + '.fingerprint', params.get("fp") || ""); setElementValue('cbid.shadowsocksr.' + sid + '.fingerprint', params.get("fp") || "");
setElementValue('cbid.shadowsocksr.' + sid + '.tls_host', params.get("sni") || ""); setElementValue('cbid.shadowsocksr.' + sid + '.tls_host', params.get("sni") || "");
} }
@ -434,6 +458,18 @@ function import_ssr_url(btn, urlname, sid) {
} }
setElementValue('cbid.shadowsocksr.' + sid + '.splithttp_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/"); setElementValue('cbid.shadowsocksr.' + sid + '.splithttp_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
break; break;
case "xhttp":
if (params.get("security") !== "tls") {
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
}
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_mode', params.get("mode") || "auto");
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
if (params.get("extra") && params.get("extra").trim() !== "") {
setElementValue('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra', true); // 设置 enable_xhttp_extra 为 true
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra', event); // 触发事件
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_extra', params.get("extra") || "");
}
break;
case "kcp": case "kcp":
setElementValue('cbid.shadowsocksr.' + sid + '.kcp_guise', params.get("headerType") || "none"); setElementValue('cbid.shadowsocksr.' + sid + '.kcp_guise', params.get("headerType") || "none");
setElementValue('cbid.shadowsocksr.' + sid + '.seed', params.get("seed") || ""); setElementValue('cbid.shadowsocksr.' + sid + '.seed', params.get("seed") || "");

View File

@ -880,14 +880,14 @@ msgstr "Socks 协议的认证方式默认值noauth。"
msgid "Socks5 User" msgid "Socks5 User"
msgstr "Socks5 用户名" msgstr "Socks5 用户名"
msgid "Only when auth is password valid, Mandatory." msgid "Only when Socks5 Auth Mode is password valid, Mandatory."
msgstr "仅当 auth 为 password 时有效,必填。" msgstr "仅当 Socks5 认证方式为 Password 时有效,必填。"
msgid "Socks5 Password" msgid "Socks5 Password"
msgstr "Socks5 密码" msgstr "Socks5 密码"
msgid "Only when auth is password valid, Not mandatory." msgid "Only when Socks5 Auth Mode is password valid, Not mandatory."
msgstr "仅当 auth 为 password 时有效,非必填。" msgstr "仅当 Socks5 认证方式为 Password 时有效,非必填。"
msgid "Enabled Mixed" msgid "Enabled Mixed"
msgstr "启用 Mixed" msgstr "启用 Mixed"
@ -931,8 +931,8 @@ msgstr "UDP 噪声,在某些情况下可以绕过一些针对 UDP 协议的限
msgid "To send noise packets, select \"Noise\" in Xray Settings." msgid "To send noise packets, select \"Noise\" in Xray Settings."
msgstr "在 Xray 设置中勾选 “噪声” 以发送噪声包。" msgstr "在 Xray 设置中勾选 “噪声” 以发送噪声包。"
msgid "For specific usage, see: " msgid "For specific usage, see:"
msgstr "具体使用方法参见:" msgstr "具体使用方法,请参见:"
msgid "Click to the page" msgid "Click to the page"
msgstr "点击前往" msgstr "点击前往"
@ -997,6 +997,27 @@ msgstr "SplitHTTP 主机名"
msgid "Splithttp Path" msgid "Splithttp Path"
msgstr "SplitHTTP 路径" msgstr "SplitHTTP 路径"
msgid "XHTTP Mode"
msgstr "XHTTP 模式"
msgid "XHTTP Host"
msgstr "XHTTP 主机名"
msgid "XHTTP Path"
msgstr "XHTTP 路径"
msgid "XHTTP Extra"
msgstr "XHTTP 附加项"
msgid "Enable this option to configure XHTTP Extra (JSON format)."
msgstr "启用此选项配置 XHTTP 附加项JSON 格式)。"
msgid "Configure XHTTP Extra Settings (JSON format), see:"
msgstr "配置 XHTTP 额外设置JSON 格式),请参见:"
msgid "Invalid JSON format"
msgstr "无效的 JSON 格式"
msgid "HTTP/2 Host" msgid "HTTP/2 Host"
msgstr "HTTP/2 主机名" msgstr "HTTP/2 主机名"

View File

@ -2,9 +2,15 @@
"luci-app-ssr-plus": { "luci-app-ssr-plus": {
"description": "Grant UCI access for luci-app-ssr-plus", "description": "Grant UCI access for luci-app-ssr-plus",
"read": { "read": {
"file": {
"/etc/ssrplus/*": [ "read" ]
},
"uci": ["shadowsocksr"] "uci": ["shadowsocksr"]
}, },
"write": { "write": {
"file": {
"/etc/ssrplus/*": [ "write" ]
},
"uci": ["shadowsocksr"] "uci": ["shadowsocksr"]
} }
} }

View File

@ -4,7 +4,7 @@ local ucursor = require "luci.model.uci".cursor()
local json = require "luci.jsonc" local json = require "luci.jsonc"
local server_section = arg[1] local server_section = arg[1]
local proto = arg[2] local proto = arg[2] or "tcp"
local local_port = arg[3] or "0" local local_port = arg[3] or "0"
local socks_port = arg[4] or "0" local socks_port = arg[4] or "0"
@ -179,12 +179,12 @@ end
-- 开启 socks 代理 -- 开启 socks 代理
-- 检查是否启用 socks 代理 -- 检查是否启用 socks 代理
if proto:find("tcp") and socks_port ~= "0" then if proto and proto:find("tcp") and socks_port ~= "0" then
table.insert(Xray.inbounds, { table.insert(Xray.inbounds, {
-- socks -- socks
protocol = "socks", protocol = "socks",
port = tonumber(socks_port), port = tonumber(socks_port),
settings = { settings = (socks_server.server ~= "same") and {
auth = socks_server.socks5_auth, auth = socks_server.socks5_auth,
udp = true, udp = true,
mixed = (socks_server.socks5_mixed == '1') and true or false, mixed = (socks_server.socks5_mixed == '1') and true or false,
@ -194,7 +194,7 @@ if proto:find("tcp") and socks_port ~= "0" then
pass = socks_server.socks5_pass pass = socks_server.socks5_pass
} }
} or nil } or nil
} } or nil
}) })
end end
@ -209,7 +209,7 @@ end
security = (server.xtls == '1') and "xtls" or (server.tls == '1') and "tls" or (server.reality == '1') and "reality" or nil, security = (server.xtls == '1') and "xtls" or (server.tls == '1') and "tls" or (server.reality == '1') and "reality" or nil,
tlsSettings = (server.tls == '1') and { tlsSettings = (server.tls == '1') and {
-- tls -- tls
alpn = server.tls_alpn, alpn = (server.transport == "xhttp" and server.xhttp_alpn ~= "") and server.xhttp_alpn or server.tls_alpn,
fingerprint = server.fingerprint, fingerprint = server.fingerprint,
allowInsecure = (server.insecure == "1"), allowInsecure = (server.insecure == "1"),
serverName = server.tls_host, serverName = server.tls_host,
@ -225,6 +225,7 @@ end
minVersion = "1.3" minVersion = "1.3"
} or nil, } or nil,
realitySettings = (server.reality == '1') and { realitySettings = (server.reality == '1') and {
alpn = (server.transport == "xhttp" and server.xhttp_alpn ~= "") and server.xhttp_alpn or nil,
publicKey = server.reality_publickey, publicKey = server.reality_publickey,
shortId = server.reality_shortid, shortId = server.reality_shortid,
spiderX = server.reality_spiderx, spiderX = server.reality_spiderx,
@ -271,6 +272,20 @@ end
host = (server.splithttp_host or server.tls_host) or nil, host = (server.splithttp_host or server.tls_host) or nil,
path = server.splithttp_path or "/" path = server.splithttp_path or "/"
} or nil, } or nil,
xhttpSettings = (server.transport == "xhttp") and {
-- xhttp
mode = server.xhttp_mode or "auto",
host = (server.xhttp_host or server.tls_host) or nil,
path = server.xhttp_path or "/",
extra = (server.enable_xhttp_extra == "1" and server.xhttp_extra) and (function()
local success, parsed = pcall(json.parse, server.xhttp_extra)
if success then
return parsed.extra or parsed
else
return nil
end
end)() or nil
} or nil,
httpSettings = (server.transport == "h2") and { httpSettings = (server.transport == "h2") and {
-- h2 -- h2
path = server.h2_path or "", path = server.h2_path or "",
@ -387,7 +402,7 @@ local ss = {
server_port = tonumber(server.server_port), server_port = tonumber(server.server_port),
local_address = "0.0.0.0", local_address = "0.0.0.0",
local_port = tonumber(local_port), local_port = tonumber(local_port),
mode = (proto == "tcp,udp") and "tcp_and_udp" or proto .. "_only", mode = (proto == "tcp,udp") and "tcp_and_udp" or (proto .. "_only"),
password = server.password, password = server.password,
method = server.encrypt_method_ss, method = server.encrypt_method_ss,
timeout = tonumber(server.timeout), timeout = tonumber(server.timeout),
@ -395,7 +410,7 @@ local ss = {
reuse_port = true reuse_port = true
} }
local hysteria = { local hysteria = {
server = (server.server_port and (server.port_range and (server.server .. ":" .. server.server_port .. "," .. server.port_range) or server.server .. ":" .. server.server_port) or (server.port_range and server.server .. ":" .. server.port_range or server.server .. ":443")), server = (server.server_port and (server.port_range and (server.server .. ":" .. server.server_port .. "," .. server.port_range) or (server.server .. ":" .. server.server_port) or (server.port_range and server.server .. ":" .. server.port_range or server.server .. ":443"))),
bandwidth = (server.uplink_capacity or server.downlink_capacity) and { bandwidth = (server.uplink_capacity or server.downlink_capacity) and {
up = tonumber(server.uplink_capacity) and tonumber(server.uplink_capacity) .. " mbps" or nil, up = tonumber(server.uplink_capacity) and tonumber(server.uplink_capacity) .. " mbps" or nil,
down = tonumber(server.downlink_capacity) and tonumber(server.downlink_capacity) .. " mbps" or nil down = tonumber(server.downlink_capacity) and tonumber(server.downlink_capacity) .. " mbps" or nil

View File

@ -193,6 +193,24 @@ local function processData(szType, content)
result.splithttp_host = info.host result.splithttp_host = info.host
result.splithttp_path = info.path result.splithttp_path = info.path
end end
if info.net == 'xhttp' then
result.xhttp_mode = info.mode
result.xhttp_host = info.host
result.xhttp_path = info.path
-- 检查 extra 参数是否存在且非空
result.enable_xhttp_extra = (info.extra and info.extra ~= "") and "1" or nil
result.xhttp_extra = (info.extra and info.extra ~= "") and info.extra or nil
-- 尝试解析 JSON 数据
local success, Data = pcall(jsonParse, info.extra)
if success and Data then
local address = (Data.extra and Data.extra.downloadSettings and Data.extra.downloadSettings.address)
or (Data.downloadSettings and Data.downloadSettings.address)
result.download_address = address and address ~= "" and address or nil
else
-- 如果解析失败,清空下载地址
result.download_address = nil
end
end
if info.net == 'h2' then if info.net == 'h2' then
result.h2_host = info.host result.h2_host = info.host
result.h2_path = info.path result.h2_path = info.path
@ -231,6 +249,9 @@ local function processData(szType, content)
end end
if info.tls == "tls" or info.tls == "1" then if info.tls == "tls" or info.tls == "1" then
result.tls = "1" result.tls = "1"
if info.alpn and info.alpn ~= "" then
result.xhttp_alpn = info.alpn
end
if info.sni and info.sni ~= "" then if info.sni and info.sni ~= "" then
result.tls_host = info.sni result.tls_host = info.sni
elseif info.host then elseif info.host then
@ -353,6 +374,11 @@ local function processData(szType, content)
local t = split(v, '=') local t = split(v, '=')
params[t[1]] = t[2] params[t[1]] = t[2]
end end
if params.alpn then
-- 处理 alpn 参数
result.xhttp_alpn = params.alpn
end
if params.sni then if params.sni then
-- 未指定peersni默认使用remote addr -- 未指定peersni默认使用remote addr
result.tls_host = params.sni result.tls_host = params.sni
@ -385,6 +411,23 @@ local function processData(szType, content)
elseif result.transport == "splithttp" then elseif result.transport == "splithttp" then
result.splithttp_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil 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 "/" result.splithttp_path = params.path and UrlDecode(params.path) or "/"
elseif result.transport == "xhttp" then
result.xhttp_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.xhttp_mode = params.mode or "auto"
result.xhttp_path = params.path and UrlDecode(params.path) or "/"
-- 检查 extra 参数是否存在且非空
result.enable_xhttp_extra = (params.extra and params.extra ~= "") and "1" or nil
result.xhttp_extra = (params.extra and params.extra ~= "") and params.extra or nil
-- 尝试解析 JSON 数据
local success, Data = pcall(jsonParse, params.extra)
if success and Data then
local address = (Data.extra and Data.extra.downloadSettings and Data.extra.downloadSettings.address)
or (Data.downloadSettings and Data.downloadSettings.address)
result.download_address = address and address ~= "" and address or nil
else
-- 如果解析失败,清空下载地址
result.download_address = nil
end
elseif result.transport == "http" or result.transport == "h2" then elseif result.transport == "http" or result.transport == "h2" then
result.transport = "h2" result.transport = "h2"
result.h2_host = params.host and UrlDecode(params.host) or nil result.h2_host = params.host and UrlDecode(params.host) or nil
@ -426,6 +469,7 @@ local function processData(szType, content)
result.vless_encryption = params.encryption or "none" result.vless_encryption = params.encryption or "none"
result.transport = params.type or "tcp" result.transport = params.type or "tcp"
result.tls = (params.security == "tls" or params.security == "xtls") and "1" or "0" result.tls = (params.security == "tls" or params.security == "xtls") and "1" or "0"
result.xhttp_alpn = params.alpn or ""
result.tls_host = params.sni result.tls_host = params.sni
result.tls_flow = (params.security == "tls" or params.security == "reality") and params.flow or nil result.tls_flow = (params.security == "tls" or params.security == "reality") and params.flow or nil
result.fingerprint = params.fp result.fingerprint = params.fp
@ -442,6 +486,23 @@ local function processData(szType, content)
elseif result.transport == "splithttp" then elseif result.transport == "splithttp" then
result.splithttp_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil 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 "/" result.splithttp_path = params.path and UrlDecode(params.path) or "/"
elseif result.transport == "xhttp" then
result.xhttp_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.xhttp_mode = params.mode or "auto"
result.xhttp_path = params.path and UrlDecode(params.path) or "/"
-- 检查 extra 参数是否存在且非空
result.enable_xhttp_extra = (params.extra and params.extra ~= "") and "1" or nil
result.xhttp_extra = (params.extra and params.extra ~= "") and params.extra or nil
-- 尝试解析 JSON 数据
local success, Data = pcall(jsonParse, params.extra)
if success and Data then
local address = (Data.extra and Data.extra.downloadSettings and Data.extra.downloadSettings.address)
or (Data.downloadSettings and Data.downloadSettings.address)
result.download_address = address and address ~= "" and address or nil
else
-- 如果解析失败,清空下载地址
result.download_address = nil
end
-- make it compatible with bullshit, "h2" transport is non-existent at all -- make it compatible with bullshit, "h2" transport is non-existent at all
elseif result.transport == "http" or result.transport == "h2" then elseif result.transport == "http" or result.transport == "h2" then
result.transport = "h2" result.transport = "h2"

View File

@ -134,7 +134,7 @@ index 31989b0..75e141f 100644
page.acl_depends = { "luci-app-ssr-plus" } page.acl_depends = { "luci-app-ssr-plus" }
entry({"admin", "services", "shadowsocksr", "client"}, cbi("shadowsocksr/client"), _("SSR Client"), 10).leaf = true entry({"admin", "services", "shadowsocksr", "client"}, cbi("shadowsocksr/client"), _("SSR Client"), 10).leaf = true
diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua
index 88351ff..e5f1593 100644 index 6bd7aaa..3c96aad 100644
--- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua --- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua
+++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua +++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua
@@ -75,45 +75,6 @@ o.default = "https://fastly.jsdelivr.net/gh/QiuSimons/Netflix_IP/NF_only.txt" @@ -75,45 +75,6 @@ o.default = "https://fastly.jsdelivr.net/gh/QiuSimons/Netflix_IP/NF_only.txt"
@ -338,7 +338,7 @@ index d0b77f1..259cb7f 100644
res(); res();
}); });
diff --git a/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm b/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm diff --git a/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm b/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm
index 2607fb7..62e1b1c 100644 index d8dfbdd..255beaa 100644
--- a/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm --- a/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm
+++ b/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm +++ b/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm
@@ -69,9 +69,9 @@ function export_ssr_url(btn, urlname, sid) { @@ -69,9 +69,9 @@ function export_ssr_url(btn, urlname, sid) {
@ -398,7 +398,7 @@ index 2607fb7..62e1b1c 100644
return false; return false;
case "trojan": case "trojan":
try { try {
@@ -293,7 +293,7 @@ function import_ssr_url(btn, urlname, sid) { @@ -305,7 +305,7 @@ function import_ssr_url(btn, urlname, sid) {
break; break;
} }
@ -407,7 +407,7 @@ index 2607fb7..62e1b1c 100644
return false; return false;
case "vmess": case "vmess":
var sstr = b64DecodeUnicode(ssu[1]); var sstr = b64DecodeUnicode(ssu[1]);
@@ -358,7 +358,7 @@ function import_ssr_url(btn, urlname, sid) { @@ -381,7 +381,7 @@ function import_ssr_url(btn, urlname, sid) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].checked = true; document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].dispatchEvent(event); document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].dispatchEvent(event);
} }
@ -416,7 +416,7 @@ index 2607fb7..62e1b1c 100644
return false; return false;
case "vless": case "vless":
try { try {
@@ -463,10 +463,10 @@ function import_ssr_url(btn, urlname, sid) { @@ -499,10 +499,10 @@ function import_ssr_url(btn, urlname, sid) {
} }
break; break;
} }
@ -430,7 +430,7 @@ index 2607fb7..62e1b1c 100644
} }
} }
diff --git a/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po b/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po diff --git a/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po b/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po
index 9992e81..6d547ca 100644 index 03541f4..3faa805 100644
--- a/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po --- a/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po
+++ b/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po +++ b/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po
@@ -577,27 +577,6 @@ msgstr "使用 DNS2TCP 查询" @@ -577,27 +577,6 @@ msgstr "使用 DNS2TCP 查询"