Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 113 additions & 13 deletions luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,10 @@ o:depends({ [option_name("protocol")] = "shadowsocks" })

o = s:option(Flag, option_name("reality"), translate("REALITY"))
o.default = 0
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "tcp" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "raw" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "h2" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "grpc" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "xhttp" })

o = s:option(ListValue, option_name("alpn"), translate("alpn"))
o.default = "default"
Expand Down Expand Up @@ -392,15 +393,15 @@ o:depends({ [option_name("tls")] = true, [option_name("utls")] = true })
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })

o = s:option(ListValue, option_name("transport"), translate("Transport"))
o:value("tcp", "TCP")
o:value("raw", "RAW")
o:value("mkcp", "mKCP")
o:value("ws", "WebSocket")
o:value("h2", "HTTP/2")
o:value("ds", "DomainSocket")
o:value("quic", "QUIC")
o:value("grpc", "gRPC")
o:value("httpupgrade", "HttpUpgrade")
o:value("splithttp", "SplitHTTP")
o:value("xhttp", "XHTTP")
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "socks" })
Expand Down Expand Up @@ -432,13 +433,13 @@ o = s:option(Value, option_name("wireguard_keepAlive"), translate("Keep Alive"))
o.default = "0"
o:depends({ [option_name("protocol")] = "wireguard" })

-- [[ TCP部分 ]]--
-- [[ RAW部分 ]]--

-- TCP伪装
o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type"))
o:value("none", "none")
o:value("http", "http")
o:depends({ [option_name("transport")] = "tcp" })
o:depends({ [option_name("transport")] = "raw" })

-- HTTP域名
o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host"))
Expand Down Expand Up @@ -566,16 +567,115 @@ o = s:option(Value, option_name("httpupgrade_path"), translate("HttpUpgrade Path
o.placeholder = "/"
o:depends({ [option_name("transport")] = "httpupgrade" })

-- [[ SplitHTTP部分 ]]--
o = s:option(Value, option_name("splithttp_host"), translate("SplitHTTP Host"))
o:depends({ [option_name("transport")] = "splithttp" })
-- [[ XHTTP部分 ]]--
o = s:option(Value, option_name("xhttp_host"), translate("XHTTP Host"))
o:depends({ [option_name("transport")] = "xhttp" })

o = s:option(Value, option_name("splithttp_path"), translate("SplitHTTP Path"))
o = s:option(Value, option_name("xhttp_path"), translate("XHTTP Path"))
o.placeholder = "/"
o:depends({ [option_name("transport")] = "splithttp" })
o:depends({ [option_name("transport")] = "xhttp" })

-- [[ Mux ]]--
o = s:option(Flag, option_name("mux"), translate("Mux"))
-- XHTTP XMUX
o = s:option(Flag, option_name("xhttp_xmux"), "XMUX", translate("Enable XHTTP XMUX. It's not recommended to enable Mux.Cool at the same time."))
o:depends({ [option_name("transport")] = "xhttp" })

o = s:option(Value, option_name("maxConcurrency"), translate("XMUX Max Concurrency"))
o:depends({ [option_name("xhttp_xmux")] = true })

o = s:option(Value, option_name("maxConnections"), translate("XMUX Max Connections"))
o:depends({ [option_name("xhttp_xmux")] = true })

o = s:option(Value, option_name("cMaxReuseTimes"), translate("XMUX Connection Max Reuse Times"))
o:depends({ [option_name("xhttp_xmux")] = true })

o = s:option(Value, option_name("cMaxLifetimeMs"), translate("XMUX Connection Max Lifetime (ms)"))
o:depends({ [option_name("xhttp_xmux")] = true })

-- XHTTP 下行
o = s:option(Flag, option_name("xhttp_download"), string.format('<a style="color:red">%s</a>', translate("XHTTP download splitting")))
o:depends({ [option_name("transport")] = "xhttp" })

o = s:option(Value, option_name("xhttp_download_address"), string.format('<a style="color:red">%s</a>', translate("Address")))
o:depends({ [option_name("xhttp_download")] = true })

o = s:option(Value, option_name("xhttp_download_port"), string.format('<a style="color:red">%s</a>', translate("Port")))
o:depends({ [option_name("xhttp_download")] = true })

o = s:option(Value, option_name("xhttp_download_host"), string.format('<a style="color:red">%s</a>', "XHTTP Host"))
o:depends({ [option_name("xhttp_download")] = true })

o = s:option(Value, option_name("xhttp_download_path"), string.format('<a style="color:red">%s</a>', "XHTTP Path"), translate("Must be the same as upload path."))
o.placeholder = "/"
o:depends({ [option_name("xhttp_download")] = true })

o = s:option(Flag, option_name("xhttp_download_tls"), string.format('<a style="color:red">%s</a>', "TLS"))
o:depends({ [option_name("xhttp_download")] = true })
o.default = 0

o = s:option(Flag, option_name("xhttp_download_reality"), string.format('<a style="color:red">%s</a>', "REALITY"))
o.default = 0
o:depends({ [option_name("xhttp_download_tls")] = true })

o = s:option(ListValue, option_name("xhttp_download_alpn"), string.format('<a style="color:red">%s</a>', "alpn"))
o.default = "default"
o:value("default", 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({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = false })

o = s:option(Value, option_name("xhttp_download_tls_serverName"), string.format('<a style="color:red">%s</a>', translate("Domain")))
o:depends({ [option_name("xhttp_download_tls")] = true })

o = s:option(Value, option_name("xhttp_download_reality_publicKey"), string.format('<a style="color:red">%s</a>', translate("Public Key")))
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = true })

o = s:option(Value, option_name("xhttp_download_reality_shortId"), string.format('<a style="color:red">%s</a>', translate("Short Id")))
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = true })

o = s:option(Value, option_name("xhttp_download_reality_spiderX"), string.format('<a style="color:red">%s</a>', "Spider X"))
o.placeholder = "/"
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = true })

o = s:option(Flag, option_name("xhttp_download_utls"), string.format('<a style="color:red">%s</a>', "uTLS"))
o.default = "0"
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = false })

o = s:option(ListValue, option_name("xhttp_download_fingerprint"), string.format('<a style="color:red">%s</a>', translate("Finger Print")))
o:value("chrome")
o:value("firefox")
o:value("edge")
o:value("safari")
o:value("360")
o:value("qq")
o:value("ios")
o:value("android")
o:value("random")
o:value("randomized")
o.default = "chrome"
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_utls")] = true })
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = true })

o = s:option(Flag, option_name("xhttp_download_xmux"), string.format('<a style="color:red">%s</a>', "XMUX"), translate("Enable XHTTP XMUX. It's not recommended to enable Mux.Cool at the same time."))
o:depends({ [option_name("xhttp_download")] = true })

o = s:option(Value, option_name("download_maxConcurrency"), string.format('<a style="color:red">%s</a>', translate("XMUX Max Concurrency")))
o:depends({ [option_name("xhttp_download_xmux")] = true })

o = s:option(Value, option_name("download_maxConnections"), string.format('<a style="color:red">%s</a>', translate("XMUX Max Connections")))
o:depends({ [option_name("xhttp_download_xmux")] = true })

o = s:option(Value, option_name("download_cMaxReuseTimes"), string.format('<a style="color:red">%s</a>', translate("XMUX Connection Max Reuse Times")))
o:depends({ [option_name("xhttp_download_xmux")] = true })

o = s:option(Value, option_name("download_cMaxLifetimeMs"), string.format('<a style="color:red">%s</a>', translate("XMUX Connection Max Lifetime (ms)")))
o:depends({ [option_name("xhttp_download_xmux")] = true })

-- [[ Mux.Cool ]]--
o = s:option(Flag, option_name("mux"), "Mux", translate("Enable Mux.Cool"))
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" })
o:depends({ [option_name("protocol")] = "http" })
Expand All @@ -588,7 +688,7 @@ o.default = 8
o:depends({ [option_name("mux")] = true })

-- [[ XUDP Mux ]]--
o = s:option(Flag, option_name("xmux"), translate("xMux"))
o = s:option(Flag, option_name("xmux"), "XUDP Mux")
o.default = 1
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "xtls-rprx-vision" })
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "xtls-rprx-vision-udp443" })
Expand Down
80 changes: 75 additions & 5 deletions luci-app-passwall2/luasrc/passwall2/util_xray.lua
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ function gen_outbound(flag, node, tag, proxy_table)
end
end

if node.type == "Xray" and node.transport == "xhttp" then
if node.xhttp_download_tls and node.xhttp_download_tls == "1" then
node.xhttp_download_stream_security = "tls"
if node.xhttp_download_reality and node.xhttp_download_reality == "1" then
node.xhttp_download_stream_security = "reality"
end
end
end

if node.protocol == "wireguard" and node.wireguard_reserved then
local bytes = {}
if not node.wireguard_reserved:match("[^%d,]+") then
Expand Down Expand Up @@ -164,7 +173,7 @@ function gen_outbound(flag, node, tag, proxy_table)
spiderX = node.reality_spiderX or "/",
fingerprint = (node.type == "Xray" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or "chrome"
} or nil,
tcpSettings = (node.transport == "tcp" and node.protocol ~= "socks") and {
rawSettings = ((node.transport == "raw" or node.transport == "tcp") and node.protocol ~= "socks") and {
header = {
type = node.tcp_guise or "none",
request = (node.tcp_guise == "http") and {
Expand Down Expand Up @@ -218,9 +227,35 @@ function gen_outbound(flag, node, tag, proxy_table)
path = node.httpupgrade_path or "/",
host = node.httpupgrade_host
} or nil,
splithttpSettings = (node.transport == "splithttp") and {
path = node.splithttp_path or "/",
host = node.splithttp_host
xhttpSettings = (node.transport == "xhttp" or node.transport == "splithttp") and {
path = node.xhttp_path or node.splithttp_path or "/",
host = node.xhttp_host or node.splithttp_host,
downloadSettings = (node.xhttp_download == "1") and {
address = node.xhttp_download_address,
port = tonumber(node.xhttp_download_port),
network = "xhttp",
xhttpSettings = {
path = node.xhttp_download_path,
host = node.xhttp_download_host,
},
security = node.xhttp_download_stream_security,
tlsSettings = (node.xhttp_download_stream_security == "tls") and {
serverName = node.xhttp_download_tls_serverName,
allowInsecure = false,
fingerprint = (node.xhttp_download_utls == "1" and
node.xhttp_download_fingerprint and
node.xhttp_download_fingerprint ~= "") and node.xhttp_download_fingerprint or nil
} or nil,
realitySettings = (node.xhttp_download_stream_security == "reality") and {
serverName = node.xhttp_download_tls_serverName,
publicKey = node.xhttp_download_reality_publicKey,
shortId = node.xhttp_download_reality_shortId or "",
spiderX = node.xhttp_download_reality_spiderX or "/",
fingerprint = (
node.xhttp_download_fingerprint and
node.xhttp_download_fingerprint ~= "") and node.xhttp_download_fingerprint or nil
} or nil,
} or nil
} or nil,
} or nil,
settings = {
Expand Down Expand Up @@ -285,6 +320,41 @@ function gen_outbound(flag, node, tag, proxy_table)
result.streamSettings.tlsSettings.alpn = alpn
end
end

local alpn_download = {}
if node.xhttp_download_alpn and node.xhttp_download_alpn ~= "default" then
string.gsub(node.xhttp_download_alpn, '[^' .. "," .. ']+', function(w)
table.insert(alpn_download, w)
end)
end
if alpn_download and #alpn_download > 0 then
if result.streamSettings.xhttpSettings.downloadSettings.tlsSettings then
result.streamSettings.xhttpSettings.downloadSettings.tlsSettings.alpn = alpn_download
end
end

local xmux = {}
if (node.xhttp_xmux == "1") then
xmux.maxConcurrency = node.maxConcurrency and (string.find(node.maxConcurrency, "-") and node.maxConcurrency or tonumber(node.maxConcurrency)) or 0
xmux.maxConnections = node.maxConnections and (string.find(node.maxConnections, "-") and node.maxConnections or tonumber(node.maxConnections)) or 0
xmux.cMaxReuseTimes = node.cMaxReuseTimes and (string.find(node.cMaxReuseTimes, "-") and node.cMaxReuseTimes or tonumber(node.cMaxReuseTimes)) or 0
xmux.cMaxLifetimeMs = node.cMaxLifetimeMs and (string.find(node.cMaxLifetimeMs, "-") and node.cMaxLifetimeMs or tonumber(node.cMaxLifetimeMs)) or 0
if result.streamSettings.xhttpSettings then
result.streamSettings.xhttpSettings.xmux = xmux
end
end

local xmux_download = {}
if (node.xhttp_download_xmux == "1") then
xmux_download.maxConcurrency = node.download_maxConcurrency and (string.find(node.download_maxConcurrency, "-") and node.download_maxConcurrency or tonumber(node.download_maxConcurrency)) or 0
xmux_download.maxConnections = node.download_maxConnections and (string.find(node.download_maxConnections, "-") and node.download_maxConnections or tonumber(node.download_maxConnections)) or 0
xmux_download.cMaxReuseTimes = node.download_cMaxReuseTimes and (string.find(node.download_cMaxReuseTimes, "-") and node.download_cMaxReuseTimes or tonumber(node.download_cMaxReuseTimes)) or 0
xmux_download.cMaxLifetimeMs = node.download_cMaxLifetimeMs and (string.find(node.download_cMaxLifetimeMs, "-") and node.download_cMaxLifetimeMs or tonumber(node.download_cMaxLifetimeMs)) or 0
if result.streamSettings.xhttpSettings.downloadSettings.xhttpSettings then
result.streamSettings.xhttpSettings.downloadSettings.xhttpSettings.xmux = xmux_download
end
end

end
return result
end
Expand Down Expand Up @@ -453,7 +523,7 @@ function gen_config_server(node)
}
}
} or nil,
tcpSettings = (node.transport == "tcp") and {
rawSettings = (node.transport == "raw" or node.transport == "tcp") and {
header = {
type = node.tcp_guise,
request = (node.tcp_guise == "http") and {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,10 @@
v_transport = "splithttp";
params += opt.query("host", dom_prefix + "splithttp_host");
params += opt.query("path", dom_prefix + "splithttp_path");
} else if (v_transport === "xhttp") {
v_transport = "xhttp";
params += opt.query("host", dom_prefix + "xhttp_host");
params += opt.query("path", dom_prefix + "xhttp_path");
}
params += "&type=" + v_transport;

Expand Down Expand Up @@ -1135,6 +1139,9 @@
} else if (queryParam.type === "splithttp") {
opt.set(dom_prefix + 'splithttp_host', queryParam.host || "");
opt.set(dom_prefix + 'splithttp_path', queryParam.path || "");
} else if (queryParam.type === "xhttp") {
opt.set(dom_prefix + 'xhttp_host', queryParam.host || "");
opt.set(dom_prefix + 'xhttp_path', queryParam.path || "");
}

if (m.hash) {
Expand Down
24 changes: 24 additions & 0 deletions luci-app-passwall2/po/zh-cn/passwall2.po
Original file line number Diff line number Diff line change
Expand Up @@ -1378,6 +1378,30 @@ msgstr "客户端文件不适合当前设备。"
msgid "Can't move new file to path: %s"
msgstr "无法移动新文件到:%s"

msgid "XHTTP download splitting"
msgstr "XHTTP 下行分离"

msgid "Must be the same as upload path."
msgstr "必须与上行 path 相同。"

msgid "Enable XHTTP XMUX. It's not recommended to enable Mux.Cool at the same time."
msgstr "启用 XHTTP XMUX。不建议与 Mux.Cool 同时启用。"

msgid "XMUX Max Concurrency"
msgstr "XMUX 连接最大复用流数"

msgid "XMUX Max Connections"
msgstr "XMUX 最大连接数"

msgid "XMUX Connection Max Reuse Times"
msgstr "XMUX 连接最多复用次数"

msgid "XMUX Connection Max Lifetime (ms)"
msgstr "XMUX 连接最大存活时间(ms)"

msgid "Enable Mux.Cool"
msgstr "启用 Mux.Cool"

msgid "Mux concurrency"
msgstr "最大并发连接数"

Expand Down