parent
b3c9205cc1
commit
1d794d2efc
@ -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:= \
|
||||||
|
@ -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"))
|
||||||
|
@ -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
|
||||||
|
@ -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"))
|
||||||
|
@ -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")
|
||||||
|
@ -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")
|
||||||
|
@ -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 = {
|
||||||
|
@ -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
|
||||||
|
@ -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 class="cbi-value">
|
<div id="add_link_modal_container">
|
||||||
<label class="cbi-value-title"><%:Share Link%></label>
|
<h3><%:Add the node via the link%></h3>
|
||||||
<div class="cbi-value-field">
|
<div class="cbi-value">
|
||||||
<p><textarea id="nodes_link" rows="5" cols="50"></textarea></p>
|
<textarea id="nodes_link" rows="10"></textarea>
|
||||||
<font color="red"><%:Not a subscription link!!!%></font>
|
<p id="nodes_link_text"><%:Enter share links, one per line. Subscription links are not supported!%></p>
|
||||||
</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>
|
||||||
|
@ -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");
|
||||||
params += opt.query("obfs-password", dom_prefix + "hysteria2_obfs_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("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);
|
||||||
}
|
}
|
||||||
|
@ -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 多组时用逗号(,)隔开。"
|
||||||
|
@ -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")
|
parse_link(raw, "1", "导入")
|
||||||
for _, raw in ipairs(nodes) do
|
|
||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user