luci-app-passwall2: sync upstream

last commit: e22af704a2
This commit is contained in:
gitea-action 2025-04-12 00:00:21 +08:00
parent b3c9205cc1
commit 1d794d2efc
12 changed files with 114 additions and 60 deletions

View File

@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2 PKG_NAME:=luci-app-passwall2
PKG_VERSION:=25.4.1 PKG_VERSION:=25.4.11
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_CONFIG_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \

View File

@ -26,7 +26,8 @@ o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
o = s:option(Value, _n("port"), translate("Port")) o = s:option(Value, _n("port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, _n("hop"), translate("Additional ports for hysteria hop")) o = s:option(Value, _n("hop"), translate("Port hopping range"))
o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, _n("obfs"), translate("Obfs Password")) o = s:option(Value, _n("obfs"), translate("Obfs Password"))

View File

@ -31,6 +31,9 @@ local xray_version = api.get_app_version("xray")
-- [[ Xray ]] -- [[ Xray ]]
s.fields["type"]:value(type_name, "Xray") s.fields["type"]:value(type_name, "Xray")
if not s.fields["type"].default then
s.fields["type"].default = type_name
end
o = s:option(ListValue, _n("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("vmess", translate("Vmess")) o:value("vmess", translate("Vmess"))
@ -631,6 +634,7 @@ o = s:option(Flag, _n("xmux"), "XUDP Mux")
o.default = 1 o.default = 1
o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "xtls-rprx-vision" }) o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "xtls-rprx-vision" })
o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "xtls-rprx-vision-udp443" }) o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "xtls-rprx-vision-udp443" })
o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(Value, _n("xudp_concurrency"), translate("XUDP Mux concurrency")) o = s:option(Value, _n("xudp_concurrency"), translate("XUDP Mux concurrency"))
o.default = 8 o.default = 8

View File

@ -33,6 +33,9 @@ local security_list = { "none", "auto", "aes-128-gcm", "chacha20-poly1305", "zer
-- [[ sing-box ]] -- [[ sing-box ]]
s.fields["type"]:value(type_name, translate("Sing-Box")) s.fields["type"]:value(type_name, translate("Sing-Box"))
if not s.fields["type"].default then
s.fields["type"].default = type_name
end
o = s:option(ListValue, _n("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("socks", "Socks") o:value("socks", "Socks")
@ -401,8 +404,8 @@ if singbox_tags:find("with_quic") then
end end
if singbox_tags:find("with_quic") then if singbox_tags:find("with_quic") then
o = s:option(Value, _n("hysteria2_ports"), translate("Port hopping range")) o = s:option(Value, _n("hysteria2_hop"), translate("Port hopping range"))
o.description = translate("Format as 1000:2000 Multiple groups are separated by commas (,).") o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
o:depends({ [_n("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))

View File

@ -25,6 +25,9 @@ local header_type_list = {
-- [[ Xray ]] -- [[ Xray ]]
s.fields["type"]:value(type_name, "Xray") s.fields["type"]:value(type_name, "Xray")
if not s.fields["type"].default then
s.fields["type"].default = type_name
end
o = s:option(ListValue, _n("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("vmess", "Vmess") o:value("vmess", "Vmess")

View File

@ -26,6 +26,9 @@ local ss_method_list = {
-- [[ Sing-Box ]] -- [[ Sing-Box ]]
s.fields["type"]:value(type_name, "Sing-Box") s.fields["type"]:value(type_name, "Sing-Box")
if not s.fields["type"].default then
s.fields["type"].default = type_name
end
o = s:option(ListValue, _n("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("mixed", "Mixed") o:value("mixed", "Mixed")

View File

@ -54,7 +54,7 @@ function gen_config(var)
local server = server_host .. ":" .. server_port local server = server_host .. ":" .. server_port
if (node.hysteria2_hop) then if (node.hysteria2_hop) then
server = server .. "," .. node.hysteria2_hop server = server .. "," .. string.gsub(node.hysteria2_hop, ":", "-")
end end
local config = { local config = {

View File

@ -350,8 +350,9 @@ function gen_outbound(flag, node, tag, proxy_table)
if node.protocol == "hysteria2" then if node.protocol == "hysteria2" then
local server_ports = {} local server_ports = {}
if node.hysteria2_ports then if node.hysteria2_hop then
for range in node.hysteria2_ports:gmatch("([^,]+)") do node.hysteria2_hop = string.gsub(node.hysteria2_hop, "-", ":")
for range in node.hysteria2_hop:gmatch("([^,]+)") do
if range:match("^%d+:%d+$") then if range:match("^%d+:%d+$") then
table.insert(server_ports, range) table.insert(server_ports, range)
end end

View File

@ -2,22 +2,6 @@
local api = require "luci.passwall2.api" local api = require "luci.passwall2.api"
-%> -%>
<style>
#add_link_div{
display: none;
width: auto;
position: absolute;
left:50%;
top:50%;
transform: translate(-50%, -50%);
z-index: 99;
text-align: center;
background: white;
box-shadow: darkgrey 10px 10px 30px 5px;
padding: 30px 15px;
}
</style>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
function ajax_add_node(link) { function ajax_add_node(link) {
@ -47,7 +31,8 @@ local api = require "luci.passwall2.api"
function add_node() { function add_node() {
var nodes_link = document.getElementById("nodes_link").value; var nodes_link = document.getElementById("nodes_link").value;
if (nodes_link.trim() != "") { nodes_link = nodes_link.replace(/\t/g, "").replace(/\r\n|\r/g, "\n").trim();
if (nodes_link != "") {
var s = nodes_link.split('://'); var s = nodes_link.split('://');
if (s.length > 1) { if (s.length > 1) {
ajax_add_node(nodes_link); ajax_add_node(nodes_link);
@ -79,15 +64,13 @@ local api = require "luci.passwall2.api"
</script> </script>
<div id="add_link_div"> <div id="add_link_div">
<div id="add_link_modal_container">
<h3><%:Add the node via the link%></h3>
<div class="cbi-value"> <div class="cbi-value">
<label class="cbi-value-title"><%:Share Link%></label> <textarea id="nodes_link" rows="10"></textarea>
<div class="cbi-value-field"> <p id="nodes_link_text"><%:Enter share links, one per line. Subscription links are not supported!%></p>
<p><textarea id="nodes_link" rows="5" cols="50"></textarea></p>
<font color="red"><%:Not a subscription link!!!%></font>
</div> </div>
</div> <div id="add_link_button_container">
<div class="cbi-value">
<div class="cbi-value-field" style="display: unset">
<input class="btn cbi-button cbi-button-add" type="button" onclick="add_node()" value="<%:Add%>" /> <input class="btn cbi-button cbi-button-add" type="button" onclick="add_node()" value="<%:Add%>" />
<input class="btn cbi-button cbi-button-remove" type="button" onclick="close_add_link_div()" value="<%:Close%>" /> <input class="btn cbi-button cbi-button-remove" type="button" onclick="close_add_link_div()" value="<%:Close%>" />
</div> </div>
@ -108,3 +91,55 @@ local api = require "luci.passwall2.api"
<div id="div_node_count"></div> <div id="div_node_count"></div>
</div> </div>
</div> </div>
<style>
#add_link_div {
display: none;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
border: 2px solid #ccc;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
z-index: 1000;
width: 90%;
max-width: 500px;
}
#add_link_modal_container {
width: 100%;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 20px;
}
#nodes_link {
width: 100%;
height: 180px;
resize: vertical;
font-family: monospace;
padding: 5px;
border: 1px solid #ccc;
border-radius: 5px;
}
#nodes_link_text {
color: red;
font-size: 14px;
margin-top: 5px;
text-align: center;
width: 100%;
}
#add_link_button_container {
display: flex;
justify-content: space-between;
width: 100%;
max-width: 300px;
margin-top: 10px;
}
</style>

View File

@ -487,22 +487,33 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
} }
url += params; url += params;
} else if ((v_type === "Hysteria2") || (v_type === "sing-box" && opt.get(dom_prefix + "protocol").value === "hysteria2")) { } else if ((v_type === "Hysteria2") || (v_type === "sing-box" && opt.get(dom_prefix + "protocol").value === "hysteria2")) {
protocol = "hysteria2"; protocol = "hysteria2"
var v_port = opt.get(dom_prefix + "port"); var v_port = opt.get(dom_prefix + "port");
var params = ""; var params = "";
params += opt.query("sni", dom_prefix + "tls_serverName"); params += opt.query("sni", dom_prefix + "tls_serverName");
params += opt.query("insecure", dom_prefix + "tls_allowInsecure"); params += opt.query("insecure", dom_prefix + "tls_allowInsecure");
var v_password = null; var v_password = null;
params += opt.query("obfs", "salamander");
if (v_type === "Hysteria2") { if (v_type === "Hysteria2") {
v_password = opt.get("hysteria2_auth_password"); v_password = opt.get("hysteria2_auth_password");
params += opt.query("obfs-password", "hysteria2_obfs");
params += opt.query("pinSHA256", "hysteria2_tls_pinSHA256"); params += opt.query("pinSHA256", "hysteria2_tls_pinSHA256");
var dom_obfs = opt.get("hysteria2_obfs");
if (dom_obfs && dom_obfs.value != "") {
params += "&obfs=" + "salamander";
params += opt.query("obfs-password", "hysteria2_obfs");
}
params += opt.query("mport", "hysteria2_hop");
} else { } else {
v_password = opt.get(dom_prefix + "hysteria2_auth_password"); v_password = opt.get(dom_prefix + "hysteria2_auth_password");
var dom_obfs_type = opt.get(dom_prefix + "hysteria2_obfs_type");
if (dom_obfs_type && dom_obfs_type.value != "") {
params += opt.query("obfs", dom_prefix + "hysteria2_obfs_type");
params += opt.query("obfs-password", dom_prefix + "hysteria2_obfs_password"); params += opt.query("obfs-password", dom_prefix + "hysteria2_obfs_password");
} }
params += opt.query("mport", dom_prefix + "hysteria2_hop");
}
params = params.replace(/^&/, "");
url = url =
_address + ":" + _address + ":" +
v_port.value + "?" + v_port.value + "?" +
@ -1289,6 +1300,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
opt.set(dom_prefix + 'hysteria2_obfs_type', "salamander"); opt.set(dom_prefix + 'hysteria2_obfs_type', "salamander");
opt.set(dom_prefix + 'hysteria2_obfs_password', queryParam["obfs-password"]); opt.set(dom_prefix + 'hysteria2_obfs_password', queryParam["obfs-password"]);
} }
opt.set(dom_prefix + 'hysteria2_hop', queryParam.mport || "");
} else if (has_hysteria2) { } else if (has_hysteria2) {
opt.set('type', "Hysteria2"); opt.set('type', "Hysteria2");
dom_prefix = "hysteria2_" dom_prefix = "hysteria2_"
@ -1299,12 +1311,13 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
if (queryParam.pinSHA256) { if (queryParam.pinSHA256) {
opt.set(dom_prefix + 'tls_pinSHA256', queryParam.pinSHA256); opt.set(dom_prefix + 'tls_pinSHA256', queryParam.pinSHA256);
} }
opt.set(dom_prefix + 'hop', queryParam.mport || "");
} }
opt.set(dom_prefix + 'address', m.hostname); opt.set(dom_prefix + 'address', m.hostname);
opt.set(dom_prefix + 'port', m.port || "443"); opt.set(dom_prefix + 'port', m.port || "443");
opt.set(dom_prefix + 'tls_serverName', queryParam.sni); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || "");
if (queryParam.insecure && queryParam.insecure == "1") { if (queryParam.insecure && queryParam.insecure == "1") {
opt.set(dom_prefix + 'tls_allowInsecure', true); opt.set(dom_prefix + 'tls_allowInsecure', true);
} }

View File

@ -265,11 +265,8 @@ msgstr "添加节点"
msgid "Add the node via the link" msgid "Add the node via the link"
msgstr "通过链接添加节点" msgstr "通过链接添加节点"
msgid "Share Link" msgid "Enter share links, one per line. Subscription links are not supported!"
msgstr "分享链接" msgstr "输入分享链接,支持多个节点,每行一个。请勿输入订阅链接!"
msgid "Not a subscription link!!!"
msgstr "不是订阅链接!!!"
msgid "Please enter the correct link." msgid "Please enter the correct link."
msgstr "请输入正确的链接。" msgstr "请输入正确的链接。"
@ -1492,9 +1489,6 @@ msgstr "空闲超时 "
msgid "Hop Interval" msgid "Hop Interval"
msgstr "端口跳跃时间 " msgstr "端口跳跃时间 "
msgid "Additional ports for hysteria hop"
msgstr "端口跳跃额外端口"
msgid "HeartbeatPeriod(second)" msgid "HeartbeatPeriod(second)"
msgstr "心跳周期(单位:秒)" msgstr "心跳周期(单位:秒)"
@ -1690,5 +1684,5 @@ msgstr "当选择的出站发生变化时中断现有连接。"
msgid "Port hopping range" msgid "Port hopping range"
msgstr "端口跳跃范围" msgstr "端口跳跃范围"
msgid "Format as 1000:2000 Multiple groups are separated by commas (,)." msgid "Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,)."
msgstr "格式为1000:2000 多组时用逗号(,)隔开。" msgstr "格式为1000:2000 或 1000-2000 多组时用逗号(,)隔开。"

View File

@ -1222,13 +1222,8 @@ local function processData(szType, content, add_mode, add_from)
result.tls_allowInsecure = allowInsecure_default and "1" or "0" result.tls_allowInsecure = allowInsecure_default and "1" or "0"
end end
result.hysteria2_tls_pinSHA256 = params.pinSHA256 result.hysteria2_tls_pinSHA256 = params.pinSHA256
result.hysteria2_hop = params.mport
if has_hysteria2 then
result.type = "Hysteria2"
if params["obfs-password"] then
result.hysteria2_obfs = params["obfs-password"]
end
end
if hysteria2_type_default == "sing-box" and has_singbox then if hysteria2_type_default == "sing-box" and has_singbox then
result.type = 'sing-box' result.type = 'sing-box'
result.protocol = "hysteria2" result.protocol = "hysteria2"
@ -1236,6 +1231,11 @@ local function processData(szType, content, add_mode, add_from)
result.hysteria2_obfs_type = "salamander" result.hysteria2_obfs_type = "salamander"
result.hysteria2_obfs_password = params["obfs-password"] result.hysteria2_obfs_password = params["obfs-password"]
end end
elseif has_hysteria2 then
result.type = "Hysteria2"
if params["obfs-password"] then
result.hysteria2_obfs = params["obfs-password"]
end
end end
elseif szType == 'tuic' then elseif szType == 'tuic' then
local alias = "" local alias = ""
@ -1593,7 +1593,7 @@ local function parse_link(raw, add_mode, add_from, cfgid)
end end
for _, v in ipairs(nodes) do for _, v in ipairs(nodes) do
if v then if v and not string.match(v, "^%s*$") then
xpcall(function () xpcall(function ()
local result local result
if szType == 'ssd' then if szType == 'ssd' then
@ -1771,12 +1771,9 @@ if arg[1] then
log('订阅完毕...') log('订阅完毕...')
elseif arg[1] == "add" then elseif arg[1] == "add" then
local f = assert(io.open("/tmp/links.conf", 'r')) local f = assert(io.open("/tmp/links.conf", 'r'))
local content = f:read('*all') local raw = f:read('*all')
f:close() f:close()
local nodes = split(content:gsub(" ", "\n"), "\n")
for _, raw in ipairs(nodes) do
parse_link(raw, "1", "导入") parse_link(raw, "1", "导入")
end
update_node(1) update_node(1)
luci.sys.call("rm -f /tmp/links.conf") luci.sys.call("rm -f /tmp/links.conf")
elseif arg[1] == "truncate" then elseif arg[1] == "truncate" then