mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-11-14 04:07:56 +08:00
update 2026-11-11 05:36:55
This commit is contained in:
1 parent
ff55a8f71a
commit
30afd5f00d
25 files changed
+794
-241
No files matched your search
+3
-3
@@ -6,12 +6,12 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=dae
|
||||
PKG_VERSION:=2026.11.09
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE:=dae-src-2026.11.09-45df6d7de7ee.tar.gz
|
||||
PKG_SOURCE:=dae-src-2026.11.09-8b744ffb65ee.tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||
PKG_HASH:=45df6d7de7ee262cb8b22a377037dc9c1498ffa282b6be4364bee3fbecdbcc55
|
||||
PKG_HASH:=8b744ffb65eedf46e9f3cf035e757bda30547d2dafed522eb3154bd4e509e146
|
||||
|
||||
PKG_LICENSE:=AGPL-3.0-only
|
||||
PKG_LICENSE_FILE:=LICENSE
|
||||
|
||||
+3
-3
@@ -6,12 +6,12 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=daed
|
||||
PKG_VERSION:=2026.11.09
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE:=daed-src-2026.11.09-82f4f6af67da.tar.gz
|
||||
PKG_SOURCE:=daed-src-2026.11.09-a25f8d76d474.tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||
PKG_HASH:=82f4f6af67da0069958810d484e2957a4d8ab48b078d71e27e62d96c5dcd4faa
|
||||
PKG_HASH:=a25f8d76d4745a114f52f7b80d0636aad7e4a9be06488db8e2753dc119547dd0
|
||||
|
||||
PKG_LICENSE:=AGPL-3.0-only MIT
|
||||
PKG_LICENSE_FILES:=LICENSE wing/LICENSE
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.11.3
|
||||
PKG_VERSION:=26.11.11
|
||||
PKG_RELEASE:=1
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ local trojan_type = {}
|
||||
local vmess_type = {}
|
||||
local vless_type = {}
|
||||
local hysteria2_type = {}
|
||||
local other_type = {}
|
||||
local xray_version = api.get_app_version("xray")
|
||||
if has_ss_rust then
|
||||
local s = "shadowsocks-rust"
|
||||
@@ -22,6 +23,7 @@ if has_singbox then
|
||||
table.insert(vmess_type, s)
|
||||
table.insert(vless_type, s)
|
||||
table.insert(hysteria2_type, s)
|
||||
table.insert(other_type, s)
|
||||
end
|
||||
if has_xray then
|
||||
local s = "xray"
|
||||
@@ -29,6 +31,7 @@ if has_xray then
|
||||
table.insert(ss_type, s)
|
||||
table.insert(vmess_type, s)
|
||||
table.insert(vless_type, s)
|
||||
table.insert(other_type, s)
|
||||
if api.compare_versions(xray_version, ">=", "26.1.13") then
|
||||
table.insert(hysteria2_type, s)
|
||||
end
|
||||
@@ -100,7 +103,15 @@ if #hysteria2_type > 0 then
|
||||
end
|
||||
end
|
||||
|
||||
if #ss_type > 0 or #trojan_type > 0 or #vmess_type > 0 or #vless_type > 0 or #hysteria2_type > 0 then
|
||||
if #other_type > 0 then
|
||||
o = s:option(ListValue, "other_type", translatef("%s Node Use Type", translate("Other")))
|
||||
o:value("", translate("Auto"))
|
||||
for key, value in pairs(other_type) do
|
||||
o:value(value)
|
||||
end
|
||||
end
|
||||
|
||||
if #ss_type > 0 or #trojan_type > 0 or #vmess_type > 0 or #vless_type > 0 or #hysteria2_type > 0 or #other_type > 0 then
|
||||
o.description = string.format("<font color='red'>%s</font>",
|
||||
translate("The configured type also applies to the core specified when manually importing nodes."))
|
||||
end
|
||||
|
||||
@@ -23,6 +23,7 @@ local trojan_type = {}
|
||||
local vmess_type = {}
|
||||
local vless_type = {}
|
||||
local hysteria2_type = {}
|
||||
local other_type = {}
|
||||
local xray_version = api.get_app_version("xray")
|
||||
if has_ss_rust then
|
||||
local s = "shadowsocks-rust"
|
||||
@@ -35,6 +36,7 @@ if has_singbox then
|
||||
table.insert(vmess_type, s)
|
||||
table.insert(vless_type, s)
|
||||
table.insert(hysteria2_type, s)
|
||||
table.insert(other_type, s)
|
||||
end
|
||||
if has_xray then
|
||||
local s = "xray"
|
||||
@@ -42,6 +44,7 @@ if has_xray then
|
||||
table.insert(ss_type, s)
|
||||
table.insert(vmess_type, s)
|
||||
table.insert(vless_type, s)
|
||||
table.insert(other_type, s)
|
||||
if api.compare_versions(xray_version, ">=", "26.1.13") then
|
||||
table.insert(hysteria2_type, s)
|
||||
end
|
||||
@@ -222,7 +225,18 @@ if #hysteria2_type > 0 then
|
||||
for key, value in pairs(hysteria2_type) do
|
||||
o:value(value)
|
||||
end
|
||||
end
|
||||
|
||||
if #other_type > 0 then
|
||||
o = s:option(ListValue, "other_type", translatef("%s Node Use Type", translate("Other")))
|
||||
o.default = "global"
|
||||
o:value("global", translate("Use global config"))
|
||||
for key, value in pairs(other_type) do
|
||||
o:value(value)
|
||||
end
|
||||
end
|
||||
|
||||
if #hysteria2_type > 0 then
|
||||
o = s:option(Value, "hysteria_up_mbps", "Hy/Hy2 " .. translate("Max upload Mbps"))
|
||||
o.datatype = "uinteger"
|
||||
|
||||
|
||||
@@ -706,6 +706,10 @@ if singbox_tags:find("with_wireguard") then
|
||||
|
||||
o = s:option(Value, "wireguard_reserved", translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
|
||||
o:depends({ protocol = "wireguard" })
|
||||
|
||||
o = s:option(Value, "wireguard_keepAlive", translate("Keep Alive"))
|
||||
o.default = "0"
|
||||
o:depends({ protocol = "wireguard" })
|
||||
end
|
||||
|
||||
-- [[ TCP部分(模拟) ]]--
|
||||
|
||||
@@ -507,6 +507,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
pre_shared_key = node.wireguard_preSharedKey,
|
||||
reserved = node.wireguard_reserved,
|
||||
mtu = tonumber(node.wireguard_mtu),
|
||||
persistent_keepalive_interval = tonumber(node.wireguard_keepAlive),
|
||||
}
|
||||
end
|
||||
|
||||
@@ -2438,7 +2439,8 @@ function gen_config(var)
|
||||
port = value.server_port,
|
||||
public_key = value.peer_public_key,
|
||||
pre_shared_key = value.pre_shared_key,
|
||||
allowed_ips = {"0.0.0.0/0"},
|
||||
allowed_ips = {"0.0.0.0/0", "::/0"},
|
||||
persistent_keepalive_interval = value.persistent_keepalive_interval,
|
||||
reserved = value.reserved
|
||||
}
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ local GLOBAL = {
|
||||
|
||||
local xray_version = api.get_app_version("xray")
|
||||
|
||||
local xray_min_version = "26.7.11"
|
||||
local xray_min_version = "26.9.9"
|
||||
|
||||
local function get_domain_excluded()
|
||||
local path = string.format("/etc/%s/rules/domains_excluded", api.c_config)
|
||||
@@ -355,6 +355,30 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
}
|
||||
}
|
||||
udp[#udp+1] = r
|
||||
elseif node.hysteria2_hop and node.hysteria2_hop ~= "" then
|
||||
udp[#udp+1] = {
|
||||
type = "udphop",
|
||||
settings = {
|
||||
mode = "intervallocal,intervalremote",
|
||||
remotePorts = string.gsub(node.hysteria2_hop, ":", "-"),
|
||||
interval = (function(v)
|
||||
if not v then return 30 end
|
||||
if v:find("-", 1, true) then
|
||||
local min, max = v:match("^(%d+)%-(%d+)$")
|
||||
min = tonumber(min)
|
||||
max = tonumber(max)
|
||||
if min and max then
|
||||
min = (min >= 5) and min or 5
|
||||
max = (max >= min) and max or min
|
||||
return min .. "-" .. max
|
||||
end
|
||||
return 30
|
||||
end
|
||||
v = tonumber((v or "30"):match("^%d+"))
|
||||
return (v and v >= 5) and v or 30
|
||||
end)(node.hysteria2_hop_interval)
|
||||
}
|
||||
}
|
||||
end
|
||||
finalmask.udp = udp
|
||||
local up = tonumber(node.hysteria2_up_mbps) or 0
|
||||
@@ -363,25 +387,6 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
congestion = (up <= 0 and down <= 0) and "bbr" or "brutal",
|
||||
brutalUp = up > 0 and (up .. "mbps") or nil,
|
||||
brutalDown = down > 0 and (down .. "mbps") or nil,
|
||||
udpHop = (node.hysteria2_hop) and {
|
||||
ports = string.gsub(node.hysteria2_hop, ":", "-"),
|
||||
interval = (function(v)
|
||||
if not v then return 30 end
|
||||
if v:find("-", 1, true) then
|
||||
local min, max = v:match("^(%d+)%-(%d+)$")
|
||||
min = tonumber(min)
|
||||
max = tonumber(max)
|
||||
if min and max then
|
||||
min = (min >= 5) and min or 5
|
||||
max = (max >= min) and max or min
|
||||
return min .. "-" .. max
|
||||
end
|
||||
return 30
|
||||
end
|
||||
v = tonumber((v or "30"):match("^%d+"))
|
||||
return (v and v >= 5) and v or 30
|
||||
end)(node.hysteria2_hop_interval)
|
||||
} or nil,
|
||||
maxIdleTimeout = (function(t)
|
||||
t = tonumber(tostring(t or "30"):match("^%d+"))
|
||||
return (t and t >= 4 and t <= 120) and t or 30
|
||||
@@ -431,7 +436,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
peers = (node.protocol == "wireguard") and {
|
||||
{
|
||||
publicKey = node.wireguard_public_key,
|
||||
endpoint = node.address .. ":" .. node.port,
|
||||
endpoint = (api.is_ipv6(node.address) and ("[" .. node.address .. "]") or node.address) .. ":" .. node.port,
|
||||
preSharedKey = node.wireguard_preSharedKey,
|
||||
keepAlive = node.wireguard_keepAlive and tonumber(node.wireguard_keepAlive) or nil
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ local trojan_type = api.get_core("trojan_type", {{has_singbox,"sing-box"},{has_x
|
||||
local vmess_type = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local vless_type = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local hysteria2_type = api.get_core("hysteria2_type", {{has_hysteria2,"hysteria2"},{has_singbox,"sing-box"}, {has_xray,"xray"}})
|
||||
local other_type = api.get_core("other_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
|
||||
local current_node = map:get(section)
|
||||
-%>
|
||||
@@ -27,6 +28,7 @@ local current_node = map:get(section)
|
||||
let vmess_type = "<%=vmess_type%>"
|
||||
let vless_type = "<%=vless_type%>"
|
||||
let hysteria2_type = "<%=hysteria2_type%>"
|
||||
let other_type = "<%=other_type%>"
|
||||
|
||||
function padright(str, cnt, pad) {
|
||||
return str + Array(cnt + 1).join(pad);
|
||||
@@ -191,6 +193,8 @@ local current_node = map:get(section)
|
||||
dom_prefix = "xray_"
|
||||
} else if (v_type === "sing-box") {
|
||||
dom_prefix = "singbox_"
|
||||
} else if (v_type === "Socks") {
|
||||
dom_prefix = "socks_"
|
||||
}
|
||||
var _address = ""
|
||||
if (dom_prefix && dom_prefix != null) {
|
||||
@@ -741,6 +745,74 @@ local current_node = map:get(section)
|
||||
params = params.substring(1);
|
||||
}
|
||||
url += params;
|
||||
} else if ((v_type === "Xray" || v_type === "sing-box") && opt.get(dom_prefix + "protocol").value === "wireguard") {
|
||||
protocol = "wireguard";
|
||||
var v_password = opt.get(dom_prefix + "wireguard_secret_key");
|
||||
var v_port = opt.get(dom_prefix + "port");
|
||||
url = encodeURIComponent(v_password.value) +
|
||||
"@" + _address +
|
||||
":" + v_port.value + "?";
|
||||
|
||||
var params = "";
|
||||
params += opt.query("publickey", dom_prefix + "wireguard_public_key");
|
||||
params += opt.query("presharedkey", dom_prefix + "wireguard_preSharedKey");
|
||||
var addresses = opt.getlist(dom_prefix + "wireguard_local_address").map(value => value.trim()).filter(Boolean);
|
||||
params += "&address=" + encodeURIComponent(addresses.join(","));
|
||||
params += opt.query("reserved", dom_prefix + "wireguard_reserved");
|
||||
params += opt.query("mtu", dom_prefix + "wireguard_mtu");
|
||||
params += opt.query("persistent-keepalive", dom_prefix + "wireguard_keepAlive");
|
||||
if (v_type === "Xray" && opt.get(dom_prefix + "use_finalmask")?.checked) {
|
||||
params += opt.query("fm", dom_prefix + "finalmask");
|
||||
}
|
||||
params += "#" + encodeURIComponent(v_alias.value);
|
||||
if (params[0] == "&") {
|
||||
params = params.substring(1);
|
||||
}
|
||||
url += params;
|
||||
} else if (v_type === "Socks" || ((v_type === "sing-box" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "socks")) {
|
||||
protocol = "socks";
|
||||
var v_username = opt.get(dom_prefix + "username");
|
||||
var v_password = opt.get(dom_prefix + "password");
|
||||
var v_port = opt.get(dom_prefix + "port");
|
||||
url = _address + ":" + v_port.value;
|
||||
if (v_username.value || v_password.value) {
|
||||
url = b64encutf8safe(v_username.value + ":" + v_password.value) + "@" + url;
|
||||
}
|
||||
var params = "";
|
||||
params += opt.query("uot", dom_prefix + "uot");
|
||||
params += opt.query("tfo", dom_prefix + "tcp_fast_open");
|
||||
if (params) {
|
||||
url += "?" + params.substring(1);
|
||||
}
|
||||
url += "#" + encodeURIComponent(v_alias.value);
|
||||
} else if ((v_type === "sing-box" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "http") {
|
||||
protocol = opt.get(dom_prefix + "tls").checked ? "https" : "http";
|
||||
var v_username = opt.get(dom_prefix + "username");
|
||||
var v_password = opt.get(dom_prefix + "password");
|
||||
var v_port = opt.get(dom_prefix + "port");
|
||||
url = _address + ":" + v_port.value;
|
||||
if (v_username.value || v_password.value) {
|
||||
url = encodeURIComponent(v_username.value) + ":" + encodeURIComponent(v_password.value) + "@" + url;
|
||||
}
|
||||
var params = "";
|
||||
if (protocol === "https") {
|
||||
params += opt.query("sni", dom_prefix + "tls_serverName");
|
||||
params += opt.query("alpn", dom_prefix + "alpn");
|
||||
params += opt.query("insecure", dom_prefix + "tls_allowInsecure");
|
||||
params += opt.query("pcs", dom_prefix + "tls_pinSHA256");
|
||||
params += opt.query("vcn", dom_prefix + "tls_CertByName");
|
||||
if (opt.get(dom_prefix + "utls")?.checked) {
|
||||
params += opt.query("fp", dom_prefix + "fingerprint");
|
||||
}
|
||||
if (opt.get(dom_prefix + "ech")?.checked) {
|
||||
params += opt.query("ech", dom_prefix + "ech_config");
|
||||
}
|
||||
}
|
||||
params += opt.query("tfo", dom_prefix + "tcp_fast_open");
|
||||
if (params) {
|
||||
url += "?" + params.substring(1);
|
||||
}
|
||||
url += "#" + encodeURIComponent(v_alias.value);
|
||||
}
|
||||
|
||||
if (url) {
|
||||
@@ -1828,6 +1900,126 @@ local current_node = map:get(section)
|
||||
}
|
||||
}
|
||||
|
||||
if (link_type === "wireguard") {
|
||||
if (other_type == "sing-box" && has_singbox) {
|
||||
dom_prefix = "singbox_";
|
||||
opt.set('type', "sing-box");
|
||||
} else if (other_type == "xray" && has_xray) {
|
||||
dom_prefix = "xray_";
|
||||
opt.set('type', "Xray");
|
||||
}
|
||||
opt.set(dom_prefix + 'protocol', "wireguard");
|
||||
var info = link_split[1].split('@');
|
||||
var m = parseNodeUrl("wireguard://" + info[1]);
|
||||
var host_port = info[1].split(/[/?#]/)[0];
|
||||
opt.set(dom_prefix + 'address', unbracketIP(m.hostname));
|
||||
opt.set(dom_prefix + 'port', host_port.match(/:(\d+)$/)?.[1] || '51820');
|
||||
opt.set(dom_prefix + 'wireguard_secret_key', decodeURIComponent(info[0]));
|
||||
var queryParam = {};
|
||||
if (m.search.length > 1) {
|
||||
var queryArray = m.search.substr(1).split('&');
|
||||
for (var i = 0; i < queryArray.length; i++) {
|
||||
var index = queryArray[i].indexOf('=');
|
||||
if (index > 0) {
|
||||
queryParam[decodeURIComponent(queryArray[i].substr(0, index)).toLowerCase()] = decodeURIComponent(queryArray[i].substr(index + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
opt.set(dom_prefix + 'wireguard_public_key', queryParam.publickey);
|
||||
opt.set(dom_prefix + 'wireguard_preSharedKey', queryParam.presharedkey || '');
|
||||
var addresses = ((queryParam.address || queryParam.ip || '') + ',' + (queryParam.ipv6 || '')).split(/[,\s]+/).filter(Boolean);
|
||||
var fullName = opt.base + '.' + dom_prefix + 'wireguard_local_address';
|
||||
var lists = document.querySelectorAll('.cbi-dynlist');
|
||||
for (var i = 0; i < lists.length; i++) {
|
||||
var label = lists[i].closest('.cbi-value')?.querySelector('label.cbi-value-title');
|
||||
if (label?.getAttribute('for') === fullName) {
|
||||
L.dom.callClassMethod(lists[i], 'setValue', addresses);
|
||||
lists[i].dispatchEvent(new Event('change', { bubbles: true }));
|
||||
break;
|
||||
}
|
||||
}
|
||||
opt.set(dom_prefix + 'wireguard_reserved', queryParam.reserved || '');
|
||||
opt.set(dom_prefix + 'wireguard_mtu', queryParam.mtu || '1420');
|
||||
opt.set(dom_prefix + 'wireguard_keepAlive', queryParam['persistent-keepalive'] || queryParam.keepalive || '0');
|
||||
if (dom_prefix === "xray_") {
|
||||
opt.set(dom_prefix + 'use_finalmask', !!queryParam.fm);
|
||||
opt.set(dom_prefix + 'finalmask', queryParam.fm || '');
|
||||
}
|
||||
if (m.hash) {
|
||||
opt.set('remarks', decodeURIComponent(m.hash.substr(1)));
|
||||
}
|
||||
}
|
||||
|
||||
if (link_type === "socks" || link_type === "socks5" || link_type === "socks5h" || link_type === "http" || link_type === "https") {
|
||||
if (other_type == "sing-box" && has_singbox) {
|
||||
dom_prefix = "singbox_";
|
||||
opt.set('type', "sing-box");
|
||||
} else if (other_type == "xray" && has_xray) {
|
||||
dom_prefix = "xray_";
|
||||
opt.set('type', "Xray");
|
||||
}
|
||||
var protocol = (link_type === "http" || link_type === "https") ? "http" : "socks";
|
||||
opt.set(dom_prefix + 'protocol', protocol);
|
||||
var content = link_split[1];
|
||||
var index = content.search(/[?#]/);
|
||||
var suffix = index >= 0 ? content.substr(index) : '';
|
||||
content = index >= 0 ? content.substr(0, index) : content;
|
||||
var base64_auth = false;
|
||||
if (protocol === "socks" && content.indexOf('@') === -1 && content.indexOf(':') === -1) {
|
||||
content = b64decutf8safe(decodeURIComponent(content));
|
||||
base64_auth = true;
|
||||
}
|
||||
var auth = '';
|
||||
var index = content.lastIndexOf('@');
|
||||
if (index >= 0) {
|
||||
auth = content.substr(0, index);
|
||||
content = content.substr(index + 1);
|
||||
}
|
||||
if (protocol === "socks" && auth.indexOf(':') === -1) {
|
||||
auth = b64decutf8safe(decodeURIComponent(auth));
|
||||
base64_auth = true;
|
||||
}
|
||||
var index = auth.indexOf(':');
|
||||
var username = index >= 0 ? auth.substr(0, index) : auth;
|
||||
var password = index >= 0 ? auth.substr(index + 1) : '';
|
||||
if (!base64_auth) {
|
||||
username = decodeURIComponent(username);
|
||||
password = decodeURIComponent(password);
|
||||
}
|
||||
var m = new URL(link_type + "://" + content + suffix);
|
||||
opt.set(dom_prefix + 'address', unbracketIP(m.hostname));
|
||||
opt.set(dom_prefix + 'port', m.port || (protocol === "socks" ? "1080" : (link_type === "https" ? "443" : "80")));
|
||||
opt.set(dom_prefix + 'username', username);
|
||||
opt.set(dom_prefix + 'password', password);
|
||||
opt.set(dom_prefix + 'transport', dom_prefix === "xray_" ? "raw" : "tcp");
|
||||
var queryParam = {};
|
||||
if (m.search.length > 1) {
|
||||
var queryArray = m.search.substr(1).split('&');
|
||||
for (var i = 0; i < queryArray.length; i++) {
|
||||
var index = queryArray[i].indexOf('=');
|
||||
if (index > 0) {
|
||||
queryParam[decodeURIComponent(queryArray[i].substr(0, index)).toLowerCase()] = decodeURIComponent(queryArray[i].substr(index + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
opt.set(dom_prefix + 'uot', queryParam.uot === '1');
|
||||
opt.set(dom_prefix + 'tcp_fast_open', queryParam.tfo === '1');
|
||||
opt.set(dom_prefix + 'tls', link_type === "https");
|
||||
opt.set(dom_prefix + 'reality', false);
|
||||
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
|
||||
opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default');
|
||||
opt.set(dom_prefix + 'tls_allowInsecure', (queryParam.allowinsecure || queryParam.insecure || queryParam.allow_insecure || '0') === '1');
|
||||
opt.set(dom_prefix + 'tls_pinSHA256', queryParam.pcs || '');
|
||||
opt.set(dom_prefix + 'tls_CertByName', queryParam.vcn || '');
|
||||
opt.set(dom_prefix + 'utls', !!queryParam.fp);
|
||||
opt.set(dom_prefix + 'fingerprint', queryParam.fp || 'chrome');
|
||||
opt.set(dom_prefix + 'ech', !!queryParam.ech);
|
||||
opt.set(dom_prefix + 'ech_config', queryParam.ech || '');
|
||||
if (m.hash) {
|
||||
opt.set('remarks', decodeURIComponent(m.hash.substr(1)));
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_type) {
|
||||
sessionStorage.setItem("fromUrl", JSON.stringify({
|
||||
timestamp: Date.now(),
|
||||
|
||||
@@ -1313,12 +1313,18 @@ msgstr "是否允许不安全连接。当勾选时,将跳过证书验证。"
|
||||
msgid "%s Node Use Type"
|
||||
msgstr "%s 节点使用类型"
|
||||
|
||||
msgid "Other"
|
||||
msgstr "其他"
|
||||
|
||||
msgid "UDP relay mode"
|
||||
msgstr "UDP 中继模式"
|
||||
|
||||
msgid "Congestion control algorithm"
|
||||
msgstr "拥塞控制算法"
|
||||
|
||||
msgid "Keep Alive"
|
||||
msgstr "保活间隔"
|
||||
|
||||
msgid "Heartbeat interval(second)"
|
||||
msgstr "保活心跳包发送间隔(单位:秒)"
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ local DEFAULT_TROJAN_TYPE = api.get_core("trojan_type", {{has_singbox,"sing-box
|
||||
local DEFAULT_VMESS_TYPE = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local DEFAULT_VLESS_TYPE = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local DEFAULT_HYSTERIA2_TYPE = api.get_core("hysteria2_type", {{has_hysteria2,"hysteria2"},{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
local DEFAULT_OTHER_TYPE = api.get_core("other_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
local core_has = {
|
||||
["xray"] = has_xray,
|
||||
["sing-box"] = has_singbox,
|
||||
@@ -569,6 +570,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
local sub_vmess_type = DEFAULT_VMESS_TYPE
|
||||
local sub_vless_type = DEFAULT_VLESS_TYPE
|
||||
local sub_hysteria2_type = DEFAULT_HYSTERIA2_TYPE
|
||||
local sub_other_type = DEFAULT_OTHER_TYPE
|
||||
local sub_hy_up_mbps, sub_hy_down_mbps = 1000, 1000
|
||||
if sub_cfg then
|
||||
if sub_cfg.allowInsecure and sub_cfg.allowInsecure ~= "1" then
|
||||
@@ -594,6 +596,10 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
if hysteria2_type ~= "global" and core_has[hysteria2_type] then
|
||||
sub_hysteria2_type = hysteria2_type
|
||||
end
|
||||
local other_type = sub_cfg.other_type or "global"
|
||||
if other_type ~= "global" and core_has[other_type] then
|
||||
sub_other_type = other_type
|
||||
end
|
||||
sub_hy_up_mbps = sub_cfg.hysteria_up_mbps
|
||||
sub_hy_down_mbps = sub_cfg.hysteria_down_mbps
|
||||
end
|
||||
@@ -1664,6 +1670,115 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
result.snell_mode = params.mode or "default"
|
||||
end
|
||||
result.snell_reuse = (params.reuse == "1") and "1" or "0"
|
||||
elseif szType == "wireguard" then
|
||||
if sub_other_type == "sing-box" and has_singbox then
|
||||
result.type = "sing-box"
|
||||
elseif sub_other_type == "xray" and has_xray then
|
||||
result.type = "Xray"
|
||||
else
|
||||
log("跳过 WireGuard 节点,因未安装 WireGuard 核心程序 Xray 或 Sing-box。")
|
||||
return nil
|
||||
end
|
||||
result.protocol = "wireguard"
|
||||
|
||||
local alias = ""
|
||||
if content:find("#") then
|
||||
local idx_sp = content:find("#")
|
||||
alias = content:sub(idx_sp + 1, -1)
|
||||
content = content:sub(0, idx_sp - 1)
|
||||
end
|
||||
result.remarks = UrlDecode(alias)
|
||||
local contents = split(content, "@")
|
||||
result.wireguard_secret_key = UrlDecode(contents[1]:gsub("%+", "%%2B"))
|
||||
local query = split(contents[2], "%?")
|
||||
local host_port = query[1]
|
||||
local params = {}
|
||||
for _, v in pairs(split(query[2], '&')) do
|
||||
local s = v:find("=", 1, true)
|
||||
if s and s > 1 then
|
||||
params[UrlDecode(v:sub(1, s - 1)):lower()] = UrlDecode(v:sub(s + 1):gsub("%+", "%%2B"))
|
||||
end
|
||||
end
|
||||
result.address, result.port = parse_host_port(host_port, "51820")
|
||||
result.wireguard_public_key = params.publickey
|
||||
result.wireguard_preSharedKey = params.presharedkey
|
||||
result.wireguard_local_address = {}
|
||||
for value in ((params.address or params.ip or "") .. "," .. (params.ipv6 or "")):gmatch("[^,%s]+") do
|
||||
result.wireguard_local_address[#result.wireguard_local_address + 1] = value
|
||||
end
|
||||
result.wireguard_reserved = params.reserved
|
||||
result.wireguard_mtu = params.mtu or "1420"
|
||||
result.wireguard_keepAlive = params["persistent-keepalive"] or params.keepalive or "0"
|
||||
result.use_finalmask = (params.fm and params.fm ~= "") and "1" or nil
|
||||
result.finalmask = (params.fm and params.fm ~= "") and api.base64Encode(params.fm) or nil
|
||||
elseif szType == "socks" or szType == "socks5" or szType == "socks5h" or szType == "http" or szType == "https" then
|
||||
if sub_other_type == "sing-box" and has_singbox then
|
||||
result.type = "sing-box"
|
||||
elseif sub_other_type == "xray" and has_xray then
|
||||
result.type = "Xray"
|
||||
else
|
||||
log("跳过 " .. szType .. " 节点,因未安装 " .. szType .. " 核心程序 Xray 或 Sing-box。")
|
||||
return nil
|
||||
end
|
||||
result.protocol = (szType == "http" or szType == "https") and "http" or "socks"
|
||||
|
||||
local alias = ""
|
||||
if content:find("#") then
|
||||
local idx_sp = content:find("#")
|
||||
alias = content:sub(idx_sp + 1, -1)
|
||||
content = content:sub(0, idx_sp - 1)
|
||||
end
|
||||
result.remarks = UrlDecode(alias)
|
||||
local query = split(content, "%?")
|
||||
local Info = query[1]
|
||||
local base64_auth = false
|
||||
if result.protocol == "socks" and not Info:find("@", 1, true) and not Info:find(":", 1, true) then
|
||||
Info = base64Decode(UrlDecode(Info:gsub("%+", "%%2B")))
|
||||
base64_auth = true
|
||||
end
|
||||
local auth, host_port = Info:match("^(.*)@(.*)$")
|
||||
host_port = host_port or Info
|
||||
auth = auth or ""
|
||||
if result.protocol == "socks" and not auth:find(":", 1, true) then
|
||||
auth = base64Decode(UrlDecode(auth:gsub("%+", "%%2B")))
|
||||
base64_auth = true
|
||||
end
|
||||
local idx = auth:find(":", 1, true)
|
||||
result.username = idx and auth:sub(1, idx - 1) or auth
|
||||
result.password = idx and auth:sub(idx + 1) or ""
|
||||
if not base64_auth then
|
||||
result.username = UrlDecode(result.username:gsub("%+", "%%2B"))
|
||||
result.password = UrlDecode(result.password:gsub("%+", "%%2B"))
|
||||
end
|
||||
local params = {}
|
||||
for _, v in pairs(split(query[2], '&')) do
|
||||
local s = v:find("=", 1, true)
|
||||
if s and s > 1 then
|
||||
params[UrlDecode(v:sub(1, s - 1)):lower()] = UrlDecode(v:sub(s + 1):gsub("%+", "%%2B"))
|
||||
end
|
||||
end
|
||||
local port = result.protocol == "socks" and "1080" or (szType == "https" and "443" or "80")
|
||||
result.address, result.port = parse_host_port(host_port, port)
|
||||
result.transport = result.type == "Xray" and "raw" or "tcp"
|
||||
result.uot = params.uot
|
||||
result.tcp_fast_open = params.tfo
|
||||
result.tls = szType == "https" and "1" or "0"
|
||||
if result.tls == "1" then
|
||||
result.tls_serverName = params.sni
|
||||
result.alpn = params.alpn
|
||||
local insecure = params.allowinsecure or params.insecure or params.allow_insecure
|
||||
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0")
|
||||
result.tls_pinSHA256 = params.pcs
|
||||
result.tls_CertByName = params.vcn
|
||||
if params.fp and params.fp ~= "" then
|
||||
result.utls = "1"
|
||||
result.fingerprint = params.fp
|
||||
end
|
||||
if params.ech and params.ech ~= "" then
|
||||
result.ech = "1"
|
||||
result.ech_config = params.ech
|
||||
end
|
||||
end
|
||||
else
|
||||
log("暂时不支持 " .. szType .. " 类型的节点订阅,跳过此节点。")
|
||||
return nil
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall2
|
||||
PKG_VERSION:=26.11.3
|
||||
PKG_VERSION:=26.11.11
|
||||
PKG_RELEASE:=1
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ local trojan_type = {}
|
||||
local vmess_type = {}
|
||||
local vless_type = {}
|
||||
local hysteria2_type = {}
|
||||
local other_type = {}
|
||||
local xray_version = api.get_app_version("xray")
|
||||
if has_ss_rust then
|
||||
local s = "shadowsocks-rust"
|
||||
@@ -21,6 +22,7 @@ if has_singbox then
|
||||
table.insert(vmess_type, s)
|
||||
table.insert(vless_type, s)
|
||||
table.insert(hysteria2_type, s)
|
||||
table.insert(other_type, s)
|
||||
end
|
||||
if has_xray then
|
||||
local s = "xray"
|
||||
@@ -28,6 +30,7 @@ if has_xray then
|
||||
table.insert(ss_type, s)
|
||||
table.insert(vmess_type, s)
|
||||
table.insert(vless_type, s)
|
||||
table.insert(other_type, s)
|
||||
if api.compare_versions(xray_version, ">=", "26.1.13") then
|
||||
table.insert(hysteria2_type, s)
|
||||
end
|
||||
@@ -95,7 +98,15 @@ if #hysteria2_type > 0 then
|
||||
end
|
||||
end
|
||||
|
||||
if #ss_type > 0 or #trojan_type > 0 or #vmess_type > 0 or #vless_type > 0 or #hysteria2_type > 0 then
|
||||
if #other_type > 0 then
|
||||
o = s:option(ListValue, "other_type", translatef("%s Node Use Type", translate("Other")))
|
||||
o:value("", translate("Auto"))
|
||||
for key, value in pairs(other_type) do
|
||||
o:value(value)
|
||||
end
|
||||
end
|
||||
|
||||
if #ss_type > 0 or #trojan_type > 0 or #vmess_type > 0 or #vless_type > 0 or #hysteria2_type > 0 or #other_type > 0 then
|
||||
o.description = string.format("<font color='red'>%s</font>",
|
||||
translate("The configured type also applies to the core specified when manually importing nodes."))
|
||||
end
|
||||
|
||||
@@ -22,6 +22,7 @@ local trojan_type = {}
|
||||
local vmess_type = {}
|
||||
local vless_type = {}
|
||||
local hysteria2_type = {}
|
||||
local other_type = {}
|
||||
local xray_version = api.get_app_version("xray")
|
||||
if has_ss_rust then
|
||||
local s = "shadowsocks-rust"
|
||||
@@ -34,6 +35,7 @@ if has_singbox then
|
||||
table.insert(vmess_type, s)
|
||||
table.insert(vless_type, s)
|
||||
table.insert(hysteria2_type, s)
|
||||
table.insert(other_type, s)
|
||||
end
|
||||
if has_xray then
|
||||
local s = "xray"
|
||||
@@ -41,6 +43,7 @@ if has_xray then
|
||||
table.insert(ss_type, s)
|
||||
table.insert(vmess_type, s)
|
||||
table.insert(vless_type, s)
|
||||
table.insert(other_type, s)
|
||||
if api.compare_versions(xray_version, ">=", "26.1.13") then
|
||||
table.insert(hysteria2_type, s)
|
||||
end
|
||||
@@ -215,7 +218,18 @@ if #hysteria2_type > 0 then
|
||||
for key, value in pairs(hysteria2_type) do
|
||||
o:value(value)
|
||||
end
|
||||
end
|
||||
|
||||
if #other_type > 0 then
|
||||
o = s:option(ListValue, "other_type", translatef("%s Node Use Type", translate("Other")))
|
||||
o.default = "global"
|
||||
o:value("global", translate("Use global config"))
|
||||
for key, value in pairs(other_type) do
|
||||
o:value(value)
|
||||
end
|
||||
end
|
||||
|
||||
if #hysteria2_type > 0 then
|
||||
o = s:option(Value, "hysteria_up_mbps", "Hy/Hy2 " .. translate("Max upload Mbps"))
|
||||
o.datatype = "uinteger"
|
||||
|
||||
|
||||
@@ -768,6 +768,10 @@ if singbox_tags:find("with_wireguard") then
|
||||
|
||||
o = s:option(Value, "wireguard_reserved", translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
|
||||
o:depends({ protocol = "wireguard" })
|
||||
|
||||
o = s:option(Value, "wireguard_keepAlive", translate("Keep Alive"))
|
||||
o.default = "0"
|
||||
o:depends({ protocol = "wireguard" })
|
||||
end
|
||||
|
||||
-- [[ TCP ]]--
|
||||
@@ -810,16 +814,6 @@ o = s:option(Value, "ws_path", translate("WebSocket Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ transport = "ws" })
|
||||
|
||||
o = s:option(Flag, "ws_enableEarlyData", translate("Enable early data"))
|
||||
o:depends({ transport = "ws" })
|
||||
|
||||
o = s:option(Value, "ws_maxEarlyData", translate("Early data length"))
|
||||
o.default = "1024"
|
||||
o:depends({ ws_enableEarlyData = true })
|
||||
|
||||
o = s:option(Value, "ws_earlyDataHeaderName", translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol"))
|
||||
o:depends({ ws_enableEarlyData = true })
|
||||
|
||||
-- [[ HTTPUpgrade ]]--
|
||||
o = s:option(Value, "httpupgrade_host", translate("HTTPUpgrade Host"))
|
||||
o:depends({ transport = "httpupgrade" })
|
||||
|
||||
@@ -459,6 +459,10 @@ o:depends({ transport = "ws" })
|
||||
o = s:option(Value, "ws_path", translate("WebSocket Path"))
|
||||
o:depends({ transport = "ws" })
|
||||
|
||||
o = s:option(Value, "ws_earlyDataHeaderName", translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol"))
|
||||
o.placeholder = "Sec-WebSocket-Protocol"
|
||||
o:depends({ transport = "ws" })
|
||||
|
||||
-- [[ HTTPUpgrade ]]--
|
||||
|
||||
o = s:option(Value, "httpupgrade_host", translate("HTTPUpgrade Host"))
|
||||
|
||||
@@ -366,9 +366,26 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
Host = node.ws_host,
|
||||
["User-Agent"] = node.user_agent
|
||||
} or nil,
|
||||
max_early_data = tonumber(node.ws_maxEarlyData) or nil,
|
||||
early_data_header_name = (node.ws_earlyDataHeaderName) and node.ws_earlyDataHeaderName or nil -- For compatibility with Xray-core, set it to Sec-WebSocket-Protocol. It needs to be consistent with the server.
|
||||
}
|
||||
local path, query = (node.ws_path or "/"):match("^(.-)%?(.*)$")
|
||||
local params, query_params = {}, {}
|
||||
for v in (query or ""):gmatch("[^&]+") do
|
||||
local t = api.split(api.UrlDecode(v), '=')
|
||||
params[t[1]] = t[2]
|
||||
if t[1] ~= "ed" and t[1] ~= "eh" then
|
||||
table.insert(query_params, v)
|
||||
end
|
||||
end
|
||||
local ed = tonumber(params.ed)
|
||||
if ed then
|
||||
-- Consume early-data options while preserving the remaining query.
|
||||
v2ray_transport.path = path
|
||||
if #query_params > 0 then
|
||||
v2ray_transport.path = path .. "?" .. table.concat(query_params, "&")
|
||||
end
|
||||
v2ray_transport.max_early_data = ed
|
||||
end
|
||||
v2ray_transport.early_data_header_name = params.eh or "Sec-WebSocket-Protocol"
|
||||
end
|
||||
|
||||
if node.transport == "httpupgrade" then
|
||||
@@ -506,6 +523,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
pre_shared_key = node.wireguard_preSharedKey,
|
||||
reserved = node.wireguard_reserved,
|
||||
mtu = tonumber(node.wireguard_mtu),
|
||||
persistent_keepalive_interval = tonumber(node.wireguard_keepAlive),
|
||||
}
|
||||
end
|
||||
|
||||
@@ -822,7 +840,7 @@ function gen_config_server(node)
|
||||
type = "ws",
|
||||
path = node.ws_path or "/",
|
||||
headers = (node.ws_host ~= nil) and { Host = node.ws_host } or nil,
|
||||
early_data_header_name = (node.ws_earlyDataHeaderName) and node.ws_earlyDataHeaderName or nil -- For compatibility with Xray-core, set it to Sec-WebSocket-Protocol. It needs to be consistent with the server.
|
||||
early_data_header_name = (node.ws_earlyDataHeaderName) and node.ws_earlyDataHeaderName or "Sec-WebSocket-Protocol"
|
||||
}
|
||||
end
|
||||
|
||||
@@ -2382,7 +2400,8 @@ function gen_config(var)
|
||||
port = value.server_port,
|
||||
public_key = value.peer_public_key,
|
||||
pre_shared_key = value.pre_shared_key,
|
||||
allowed_ips = {"0.0.0.0/0"},
|
||||
allowed_ips = {"0.0.0.0/0", "::/0"},
|
||||
persistent_keepalive_interval = value.persistent_keepalive_interval,
|
||||
reserved = value.reserved
|
||||
}
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ local GLOBAL = {
|
||||
|
||||
local xray_version = api.get_app_version("xray")
|
||||
|
||||
local xray_min_version = "26.7.11"
|
||||
local xray_min_version = "26.9.9"
|
||||
|
||||
local function get_domain_excluded()
|
||||
local path = "/usr/share/passwall2/domains_excluded"
|
||||
@@ -364,6 +364,30 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
}
|
||||
}
|
||||
udp[#udp+1] = r
|
||||
elseif node.hysteria2_hop and node.hysteria2_hop ~= "" then
|
||||
udp[#udp+1] = {
|
||||
type = "udphop",
|
||||
settings = {
|
||||
mode = "intervallocal,intervalremote",
|
||||
remotePorts = string.gsub(node.hysteria2_hop, ":", "-"),
|
||||
interval = (function(v)
|
||||
if not v then return 30 end
|
||||
if v:find("-", 1, true) then
|
||||
local min, max = v:match("^(%d+)%-(%d+)$")
|
||||
min = tonumber(min)
|
||||
max = tonumber(max)
|
||||
if min and max then
|
||||
min = (min >= 5) and min or 5
|
||||
max = (max >= min) and max or min
|
||||
return min .. "-" .. max
|
||||
end
|
||||
return 30
|
||||
end
|
||||
v = tonumber((v or "30"):match("^%d+"))
|
||||
return (v and v >= 5) and v or 30
|
||||
end)(node.hysteria2_hop_interval)
|
||||
}
|
||||
}
|
||||
end
|
||||
finalmask.udp = udp
|
||||
local up = tonumber(node.hysteria2_up_mbps) or 0
|
||||
@@ -372,25 +396,6 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
congestion = (up <= 0 and down <= 0) and "bbr" or "brutal",
|
||||
brutalUp = up > 0 and (up .. "mbps") or nil,
|
||||
brutalDown = down > 0 and (down .. "mbps") or nil,
|
||||
udpHop = (node.hysteria2_hop) and {
|
||||
ports = string.gsub(node.hysteria2_hop, ":", "-"),
|
||||
interval = (function(v)
|
||||
if not v then return 30 end
|
||||
if v:find("-", 1, true) then
|
||||
local min, max = v:match("^(%d+)%-(%d+)$")
|
||||
min = tonumber(min)
|
||||
max = tonumber(max)
|
||||
if min and max then
|
||||
min = (min >= 5) and min or 5
|
||||
max = (max >= min) and max or min
|
||||
return min .. "-" .. max
|
||||
end
|
||||
return 30
|
||||
end
|
||||
v = tonumber((v or "30"):match("^%d+"))
|
||||
return (v and v >= 5) and v or 30
|
||||
end)(node.hysteria2_hop_interval)
|
||||
} or nil,
|
||||
maxIdleTimeout = (function(t)
|
||||
t = tonumber(tostring(t or "30"):match("^%d+"))
|
||||
return (t and t >= 4 and t <= 120) and t or 30
|
||||
@@ -440,7 +445,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
peers = (node.protocol == "wireguard") and {
|
||||
{
|
||||
publicKey = node.wireguard_public_key,
|
||||
endpoint = node.address .. ":" .. node.port,
|
||||
endpoint = (api.is_ipv6(node.address) and ("[" .. node.address .. "]") or node.address) .. ":" .. node.port,
|
||||
preSharedKey = node.wireguard_preSharedKey,
|
||||
keepAlive = node.wireguard_keepAlive and tonumber(node.wireguard_keepAlive) or nil
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ local trojan_type = api.get_core("trojan_type", {{has_singbox,"sing-box"},{has_x
|
||||
local vmess_type = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local vless_type = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local hysteria2_type = api.get_core("hysteria2_type", {{has_singbox,"sing-box"}, {has_xray,"xray"}})
|
||||
local other_type = api.get_core("other_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
|
||||
local current_node = map:get(section)
|
||||
-%>
|
||||
@@ -25,6 +26,7 @@ local current_node = map:get(section)
|
||||
let vmess_type = "<%=vmess_type%>"
|
||||
let vless_type = "<%=vless_type%>"
|
||||
let hysteria2_type = "<%=hysteria2_type%>"
|
||||
let other_type = "<%=other_type%>"
|
||||
|
||||
function padright(str, cnt, pad) {
|
||||
return str + Array(cnt + 1).join(pad);
|
||||
@@ -254,10 +256,6 @@ local current_node = map:get(section)
|
||||
if (v_transport === "ws") {
|
||||
params += opt.query("host", dom_prefix + "ws_host");
|
||||
params += opt.query("path", dom_prefix + "ws_path");
|
||||
if (v_type == "sing-box" && opt.get(dom_prefix + "ws_enableEarlyData").checked) {
|
||||
var ws_maxEarlyData = opt.get(dom_prefix + "ws_maxEarlyData").value;
|
||||
params += "?ed=" + ws_maxEarlyData;
|
||||
}
|
||||
} else if (v_transport === "http") {
|
||||
params += opt.query("host", dom_prefix + "http_host");
|
||||
params += opt.query("path", dom_prefix + "http_path");
|
||||
@@ -376,10 +374,6 @@ local current_node = map:get(section)
|
||||
if (v_transport === "ws") {
|
||||
info.host = opt.get(dom_prefix + "ws_host").value;
|
||||
info.path = opt.get(dom_prefix + "ws_path").value;
|
||||
if (v_type == "sing-box" && opt.get(dom_prefix + "ws_enableEarlyData").checked) {
|
||||
var ws_maxEarlyData = opt.get(dom_prefix + "ws_maxEarlyData").value;
|
||||
info.path = info.path + "?ed=" + ws_maxEarlyData;
|
||||
}
|
||||
} else if (v_transport === "http") {
|
||||
info.host = opt.get(dom_prefix + "http_host").value;
|
||||
info.path = opt.get(dom_prefix + "http_path").value;
|
||||
@@ -436,10 +430,6 @@ local current_node = map:get(section)
|
||||
if (v_transport === "ws") {
|
||||
params += opt.query("host", dom_prefix + "ws_host");
|
||||
params += opt.query("path", dom_prefix + "ws_path");
|
||||
if (v_type == "sing-box" && opt.get(dom_prefix + "ws_enableEarlyData").checked) {
|
||||
var ws_maxEarlyData = opt.get(dom_prefix + "ws_maxEarlyData").value;
|
||||
params += encodeURIComponent("?ed=" + ws_maxEarlyData);
|
||||
}
|
||||
} else if (v_transport === "http") {
|
||||
params += opt.query("host", dom_prefix + "http_host");
|
||||
params += opt.query("path", dom_prefix + "http_path");
|
||||
@@ -528,10 +518,6 @@ local current_node = map:get(section)
|
||||
if (v_transport === "ws") {
|
||||
params += opt.query("host", dom_prefix + "ws_host");
|
||||
params += opt.query("path", dom_prefix + "ws_path");
|
||||
if (v_type == "sing-box" && opt.get(dom_prefix + "ws_enableEarlyData").checked) {
|
||||
var ws_maxEarlyData = opt.get(dom_prefix + "ws_maxEarlyData").value;
|
||||
params += "?ed=" + ws_maxEarlyData;
|
||||
}
|
||||
} else if (v_transport === "http") {
|
||||
params += opt.query("host", dom_prefix + "http_host");
|
||||
params += opt.query("path", dom_prefix + "http_path");
|
||||
@@ -729,6 +715,74 @@ local current_node = map:get(section)
|
||||
params = params.substring(1);
|
||||
}
|
||||
url += params;
|
||||
} else if ((v_type === "Xray" || v_type === "sing-box") && opt.get(dom_prefix + "protocol").value === "wireguard") {
|
||||
protocol = "wireguard";
|
||||
var v_password = opt.get(dom_prefix + "wireguard_secret_key");
|
||||
var v_port = opt.get(dom_prefix + "port");
|
||||
url = encodeURIComponent(v_password.value) +
|
||||
"@" + _address +
|
||||
":" + v_port.value + "?";
|
||||
|
||||
var params = "";
|
||||
params += opt.query("publickey", dom_prefix + "wireguard_public_key");
|
||||
params += opt.query("presharedkey", dom_prefix + "wireguard_preSharedKey");
|
||||
var addresses = opt.getlist(dom_prefix + "wireguard_local_address").map(value => value.trim()).filter(Boolean);
|
||||
params += "&address=" + encodeURIComponent(addresses.join(","));
|
||||
params += opt.query("reserved", dom_prefix + "wireguard_reserved");
|
||||
params += opt.query("mtu", dom_prefix + "wireguard_mtu");
|
||||
params += opt.query("persistent-keepalive", dom_prefix + "wireguard_keepAlive");
|
||||
if (v_type === "Xray" && opt.get(dom_prefix + "use_finalmask")?.checked) {
|
||||
params += opt.query("fm", dom_prefix + "finalmask");
|
||||
}
|
||||
params += "#" + encodeURIComponent(v_alias.value);
|
||||
if (params[0] == "&") {
|
||||
params = params.substring(1);
|
||||
}
|
||||
url += params;
|
||||
} else if ((v_type === "sing-box" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "socks") {
|
||||
protocol = "socks";
|
||||
var v_username = opt.get(dom_prefix + "username");
|
||||
var v_password = opt.get(dom_prefix + "password");
|
||||
var v_port = opt.get(dom_prefix + "port");
|
||||
url = _address + ":" + v_port.value;
|
||||
if (v_username.value || v_password.value) {
|
||||
url = b64encutf8safe(v_username.value + ":" + v_password.value) + "@" + url;
|
||||
}
|
||||
var params = "";
|
||||
params += opt.query("uot", dom_prefix + "uot");
|
||||
params += opt.query("tfo", dom_prefix + "tcp_fast_open");
|
||||
if (params) {
|
||||
url += "?" + params.substring(1);
|
||||
}
|
||||
url += "#" + encodeURIComponent(v_alias.value);
|
||||
} else if ((v_type === "sing-box" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "http") {
|
||||
protocol = opt.get(dom_prefix + "tls").checked ? "https" : "http";
|
||||
var v_username = opt.get(dom_prefix + "username");
|
||||
var v_password = opt.get(dom_prefix + "password");
|
||||
var v_port = opt.get(dom_prefix + "port");
|
||||
url = _address + ":" + v_port.value;
|
||||
if (v_username.value || v_password.value) {
|
||||
url = encodeURIComponent(v_username.value) + ":" + encodeURIComponent(v_password.value) + "@" + url;
|
||||
}
|
||||
var params = "";
|
||||
if (protocol === "https") {
|
||||
params += opt.query("sni", dom_prefix + "tls_serverName");
|
||||
params += opt.query("alpn", dom_prefix + "alpn");
|
||||
params += opt.query("insecure", dom_prefix + "tls_allowInsecure");
|
||||
params += opt.query("pcs", dom_prefix + "tls_pinSHA256");
|
||||
params += opt.query("vcn", dom_prefix + "tls_CertByName");
|
||||
if (opt.get(dom_prefix + "utls")?.checked) {
|
||||
params += opt.query("fp", dom_prefix + "fingerprint");
|
||||
}
|
||||
if (opt.get(dom_prefix + "ech")?.checked) {
|
||||
params += opt.query("ech", dom_prefix + "ech_config");
|
||||
}
|
||||
}
|
||||
params += opt.query("tfo", dom_prefix + "tcp_fast_open");
|
||||
if (params) {
|
||||
url += "?" + params.substring(1);
|
||||
}
|
||||
url += "#" + encodeURIComponent(v_alias.value);
|
||||
}
|
||||
|
||||
if (url) {
|
||||
@@ -1111,24 +1165,6 @@ local current_node = map:get(section)
|
||||
} else if (queryParam.type === "ws") {
|
||||
opt.set(dom_prefix + 'ws_host', queryParam.host || "");
|
||||
opt.set(dom_prefix + 'ws_path', queryParam.path || "");
|
||||
if (dom_prefix == "singbox_" && queryParam.path && queryParam.path.length > 1) {
|
||||
var ws_path_params = {};
|
||||
var ws_path_dat = queryParam.path.split('?');
|
||||
var ws_path = ws_path_dat[0];
|
||||
var ws_path_params = {};
|
||||
var ws_path_params_array = (ws_path_dat[1] || '').split('&');
|
||||
for (i = 0; i < ws_path_params_array.length; i++) {
|
||||
var kv = ws_path_params_array[i].split('=');
|
||||
ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || '');
|
||||
}
|
||||
|
||||
if (ws_path_params.ed) {
|
||||
opt.set(dom_prefix + 'ws_path', ws_path);
|
||||
opt.set(dom_prefix + 'ws_enableEarlyData', true);
|
||||
opt.set(dom_prefix + 'ws_maxEarlyData', ws_path_params.ed);
|
||||
opt.set(dom_prefix + 'ws_earlyDataHeaderName', 'Sec-WebSocket-Protocol');
|
||||
}
|
||||
}
|
||||
} else if (queryParam.type === "http") {
|
||||
if (dom_prefix == "xray_") {
|
||||
opt.set(dom_prefix + 'xhttp_mode', "stream-one");
|
||||
@@ -1259,24 +1295,6 @@ local current_node = map:get(section)
|
||||
} else if (queryParam.type === "ws") {
|
||||
opt.set(dom_prefix + 'ws_host', queryParam.host || "");
|
||||
opt.set(dom_prefix + 'ws_path', queryParam.path || "");
|
||||
if (dom_prefix == "singbox_" && queryParam.path && queryParam.path.length > 1) {
|
||||
var ws_path_params = {};
|
||||
var ws_path_dat = queryParam.path.split('?');
|
||||
var ws_path = ws_path_dat[0];
|
||||
var ws_path_params = {};
|
||||
var ws_path_params_array = (ws_path_dat[1] || '').split('&');
|
||||
for (i = 0; i < ws_path_params_array.length; i++) {
|
||||
var kv = ws_path_params_array[i].split('=');
|
||||
ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || '');
|
||||
}
|
||||
|
||||
if (ws_path_params.ed) {
|
||||
opt.set(dom_prefix + 'ws_path', ws_path);
|
||||
opt.set(dom_prefix + 'ws_enableEarlyData', true);
|
||||
opt.set(dom_prefix + 'ws_maxEarlyData', ws_path_params.ed);
|
||||
opt.set(dom_prefix + 'ws_earlyDataHeaderName', 'Sec-WebSocket-Protocol');
|
||||
}
|
||||
}
|
||||
} else if (queryParam.type === "h2" || queryParam.type === "http") {
|
||||
if (dom_prefix == "xray_") {
|
||||
opt.set(dom_prefix + 'xhttp_mode', "stream-one");
|
||||
@@ -1446,24 +1464,6 @@ local current_node = map:get(section)
|
||||
} else if (ssm.net === "ws") {
|
||||
opt.set(dom_prefix + 'ws_host', ssm.host);
|
||||
opt.set(dom_prefix + 'ws_path', ssm.path);
|
||||
if (dom_prefix == "singbox_" && ssm.path && ssm.path.length > 1) {
|
||||
var ws_path_params = {};
|
||||
var ws_path_dat = ssm.path.split('?');
|
||||
var ws_path = ws_path_dat[0];
|
||||
var ws_path_params = {};
|
||||
var ws_path_params_array = (ws_path_dat[1] || '').split('&');
|
||||
for (i = 0; i < ws_path_params_array.length; i++) {
|
||||
var kv = ws_path_params_array[i].split('=');
|
||||
ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || '');
|
||||
}
|
||||
|
||||
if (ws_path_params.ed) {
|
||||
opt.set(dom_prefix + 'ws_path', ws_path);
|
||||
opt.set(dom_prefix + 'ws_enableEarlyData', true);
|
||||
opt.set(dom_prefix + 'ws_maxEarlyData', ws_path_params.ed);
|
||||
opt.set(dom_prefix + 'ws_earlyDataHeaderName', 'Sec-WebSocket-Protocol');
|
||||
}
|
||||
}
|
||||
} else if (ssm.net === "http") {
|
||||
if (dom_prefix == "xray_") {
|
||||
opt.set(dom_prefix + 'xhttp_mode', "stream-one");
|
||||
@@ -1589,24 +1589,6 @@ local current_node = map:get(section)
|
||||
} else if (queryParam.type === "ws") {
|
||||
opt.set(dom_prefix + 'ws_host', queryParam.host || "");
|
||||
opt.set(dom_prefix + 'ws_path', queryParam.path || "");
|
||||
if (dom_prefix == "singbox_" && queryParam.path && queryParam.path.length > 1) {
|
||||
var ws_path_params = {};
|
||||
var ws_path_dat = queryParam.path.split('?');
|
||||
var ws_path = ws_path_dat[0];
|
||||
var ws_path_params = {};
|
||||
var ws_path_params_array = (ws_path_dat[1] || '').split('&');
|
||||
for (i = 0; i < ws_path_params_array.length; i++) {
|
||||
var kv = ws_path_params_array[i].split('=');
|
||||
ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || '');
|
||||
}
|
||||
|
||||
if (ws_path_params.ed) {
|
||||
opt.set(dom_prefix + 'ws_path', ws_path);
|
||||
opt.set(dom_prefix + 'ws_enableEarlyData', true);
|
||||
opt.set(dom_prefix + 'ws_maxEarlyData', ws_path_params.ed);
|
||||
opt.set(dom_prefix + 'ws_earlyDataHeaderName', 'Sec-WebSocket-Protocol');
|
||||
}
|
||||
}
|
||||
} else if (queryParam.type === "h2" || queryParam.type === "http") {
|
||||
if (dom_prefix == "xray_") {
|
||||
opt.set(dom_prefix + 'xhttp_mode', "stream-one");
|
||||
@@ -1874,6 +1856,126 @@ local current_node = map:get(section)
|
||||
}
|
||||
}
|
||||
|
||||
if (link_type === "wireguard") {
|
||||
if (other_type == "sing-box" && has_singbox) {
|
||||
dom_prefix = "singbox_";
|
||||
opt.set('type', "sing-box");
|
||||
} else if (other_type == "xray" && has_xray) {
|
||||
dom_prefix = "xray_";
|
||||
opt.set('type', "Xray");
|
||||
}
|
||||
opt.set(dom_prefix + 'protocol', "wireguard");
|
||||
var info = link_split[1].split('@');
|
||||
var m = parseNodeUrl("wireguard://" + info[1]);
|
||||
var host_port = info[1].split(/[/?#]/)[0];
|
||||
opt.set(dom_prefix + 'address', unbracketIP(m.hostname));
|
||||
opt.set(dom_prefix + 'port', host_port.match(/:(\d+)$/)?.[1] || '51820');
|
||||
opt.set(dom_prefix + 'wireguard_secret_key', decodeURIComponent(info[0]));
|
||||
var queryParam = {};
|
||||
if (m.search.length > 1) {
|
||||
var queryArray = m.search.substr(1).split('&');
|
||||
for (var i = 0; i < queryArray.length; i++) {
|
||||
var index = queryArray[i].indexOf('=');
|
||||
if (index > 0) {
|
||||
queryParam[decodeURIComponent(queryArray[i].substr(0, index)).toLowerCase()] = decodeURIComponent(queryArray[i].substr(index + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
opt.set(dom_prefix + 'wireguard_public_key', queryParam.publickey);
|
||||
opt.set(dom_prefix + 'wireguard_preSharedKey', queryParam.presharedkey || '');
|
||||
var addresses = ((queryParam.address || queryParam.ip || '') + ',' + (queryParam.ipv6 || '')).split(/[,\s]+/).filter(Boolean);
|
||||
var fullName = opt.base + '.' + dom_prefix + 'wireguard_local_address';
|
||||
var lists = document.querySelectorAll('.cbi-dynlist');
|
||||
for (var i = 0; i < lists.length; i++) {
|
||||
var label = lists[i].closest('.cbi-value')?.querySelector('label.cbi-value-title');
|
||||
if (label?.getAttribute('for') === fullName) {
|
||||
L.dom.callClassMethod(lists[i], 'setValue', addresses);
|
||||
lists[i].dispatchEvent(new Event('change', { bubbles: true }));
|
||||
break;
|
||||
}
|
||||
}
|
||||
opt.set(dom_prefix + 'wireguard_reserved', queryParam.reserved || '');
|
||||
opt.set(dom_prefix + 'wireguard_mtu', queryParam.mtu || '1420');
|
||||
opt.set(dom_prefix + 'wireguard_keepAlive', queryParam['persistent-keepalive'] || queryParam.keepalive || '0');
|
||||
if (dom_prefix === "xray_") {
|
||||
opt.set(dom_prefix + 'use_finalmask', !!queryParam.fm);
|
||||
opt.set(dom_prefix + 'finalmask', queryParam.fm || '');
|
||||
}
|
||||
if (m.hash) {
|
||||
opt.set('remarks', decodeURIComponent(m.hash.substr(1)));
|
||||
}
|
||||
}
|
||||
|
||||
if (link_type === "socks" || link_type === "socks5" || link_type === "socks5h" || link_type === "http" || link_type === "https") {
|
||||
if (other_type == "sing-box" && has_singbox) {
|
||||
dom_prefix = "singbox_";
|
||||
opt.set('type', "sing-box");
|
||||
} else if (other_type == "xray" && has_xray) {
|
||||
dom_prefix = "xray_";
|
||||
opt.set('type', "Xray");
|
||||
}
|
||||
var protocol = (link_type === "http" || link_type === "https") ? "http" : "socks";
|
||||
opt.set(dom_prefix + 'protocol', protocol);
|
||||
var content = link_split[1];
|
||||
var index = content.search(/[?#]/);
|
||||
var suffix = index >= 0 ? content.substr(index) : '';
|
||||
content = index >= 0 ? content.substr(0, index) : content;
|
||||
var base64_auth = false;
|
||||
if (protocol === "socks" && content.indexOf('@') === -1 && content.indexOf(':') === -1) {
|
||||
content = b64decutf8safe(decodeURIComponent(content));
|
||||
base64_auth = true;
|
||||
}
|
||||
var auth = '';
|
||||
var index = content.lastIndexOf('@');
|
||||
if (index >= 0) {
|
||||
auth = content.substr(0, index);
|
||||
content = content.substr(index + 1);
|
||||
}
|
||||
if (protocol === "socks" && auth.indexOf(':') === -1) {
|
||||
auth = b64decutf8safe(decodeURIComponent(auth));
|
||||
base64_auth = true;
|
||||
}
|
||||
var index = auth.indexOf(':');
|
||||
var username = index >= 0 ? auth.substr(0, index) : auth;
|
||||
var password = index >= 0 ? auth.substr(index + 1) : '';
|
||||
if (!base64_auth) {
|
||||
username = decodeURIComponent(username);
|
||||
password = decodeURIComponent(password);
|
||||
}
|
||||
var m = new URL(link_type + "://" + content + suffix);
|
||||
opt.set(dom_prefix + 'address', unbracketIP(m.hostname));
|
||||
opt.set(dom_prefix + 'port', m.port || (protocol === "socks" ? "1080" : (link_type === "https" ? "443" : "80")));
|
||||
opt.set(dom_prefix + 'username', username);
|
||||
opt.set(dom_prefix + 'password', password);
|
||||
opt.set(dom_prefix + 'transport', dom_prefix === "xray_" ? "raw" : "tcp");
|
||||
var queryParam = {};
|
||||
if (m.search.length > 1) {
|
||||
var queryArray = m.search.substr(1).split('&');
|
||||
for (var i = 0; i < queryArray.length; i++) {
|
||||
var index = queryArray[i].indexOf('=');
|
||||
if (index > 0) {
|
||||
queryParam[decodeURIComponent(queryArray[i].substr(0, index)).toLowerCase()] = decodeURIComponent(queryArray[i].substr(index + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
opt.set(dom_prefix + 'uot', queryParam.uot === '1');
|
||||
opt.set(dom_prefix + 'tcp_fast_open', queryParam.tfo === '1');
|
||||
opt.set(dom_prefix + 'tls', link_type === "https");
|
||||
opt.set(dom_prefix + 'reality', false);
|
||||
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
|
||||
opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default');
|
||||
opt.set(dom_prefix + 'tls_allowInsecure', (queryParam.allowinsecure || queryParam.insecure || queryParam.allow_insecure || '0') === '1');
|
||||
opt.set(dom_prefix + 'tls_pinSHA256', queryParam.pcs || '');
|
||||
opt.set(dom_prefix + 'tls_CertByName', queryParam.vcn || '');
|
||||
opt.set(dom_prefix + 'utls', !!queryParam.fp);
|
||||
opt.set(dom_prefix + 'fingerprint', queryParam.fp || 'chrome');
|
||||
opt.set(dom_prefix + 'ech', !!queryParam.ech);
|
||||
opt.set(dom_prefix + 'ech_config', queryParam.ech || '');
|
||||
if (m.hash) {
|
||||
opt.set('remarks', decodeURIComponent(m.hash.substr(1)));
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_type) {
|
||||
sessionStorage.setItem("fromUrl", JSON.stringify({
|
||||
timestamp: Date.now(),
|
||||
|
||||
@@ -604,6 +604,9 @@ msgstr "پنجره دریافت اتصال QUIC"
|
||||
msgid "QUIC concurrent bidirectional streams"
|
||||
msgstr "جریانهای دوطرفه همزمان QUIC"
|
||||
|
||||
msgid "Keep Alive"
|
||||
msgstr "زنده نگه داشتن اتصال"
|
||||
|
||||
msgid "QUIC KeepAlive interval"
|
||||
msgstr "فاصله QUIC KeepAlive"
|
||||
|
||||
@@ -1369,6 +1372,9 @@ msgstr "زمانی استفاده میشود که لینک گره شامل ا
|
||||
msgid "%s Node Use Type"
|
||||
msgstr "نوع استفاده گره %s"
|
||||
|
||||
msgid "Other"
|
||||
msgstr "سایر"
|
||||
|
||||
msgid "UDP relay mode"
|
||||
msgstr "حالت بازپخش UDP"
|
||||
|
||||
@@ -1585,12 +1591,6 @@ msgstr "همزمانی XUDP Mux"
|
||||
msgid "Padding"
|
||||
msgstr "پدینگ (Padding)"
|
||||
|
||||
msgid "Enable early data"
|
||||
msgstr "فعالسازی دادههای اولیه (Early Data)"
|
||||
|
||||
msgid "Early data length"
|
||||
msgstr "طول دادههای اولیه"
|
||||
|
||||
msgid "Early data header name"
|
||||
msgstr "نام هدر دادههای اولیه"
|
||||
|
||||
|
||||
@@ -605,6 +605,9 @@ msgstr "Размер окна приёма соединения QUIC"
|
||||
msgid "QUIC concurrent bidirectional streams"
|
||||
msgstr "Макс. количество одновременных двунаправленных потоков QUIC"
|
||||
|
||||
msgid "Keep Alive"
|
||||
msgstr "Поддержание соединения"
|
||||
|
||||
msgid "QUIC KeepAlive interval"
|
||||
msgstr "Интервал QUIC KeepAlive"
|
||||
|
||||
@@ -1370,6 +1373,9 @@ msgstr "Используется, если в ссылке на узел это
|
||||
msgid "%s Node Use Type"
|
||||
msgstr "Тип использования сервера %s"
|
||||
|
||||
msgid "Other"
|
||||
msgstr "Другие"
|
||||
|
||||
msgid "UDP relay mode"
|
||||
msgstr "Режим ретрансляции UDP"
|
||||
|
||||
@@ -1586,12 +1592,6 @@ msgstr "Макс. параллельных соединений XUDP"
|
||||
msgid "Padding"
|
||||
msgstr "Заполнение"
|
||||
|
||||
msgid "Enable early data"
|
||||
msgstr "Включить 0-RTT данные"
|
||||
|
||||
msgid "Early data length"
|
||||
msgstr "Макс. длина 0-RTT данных"
|
||||
|
||||
msgid "Early data header name"
|
||||
msgstr "Имя HTTP-заголовка для 0-RTT"
|
||||
|
||||
|
||||
@@ -596,6 +596,9 @@ msgstr "QUIC 连接接收窗口"
|
||||
msgid "QUIC concurrent bidirectional streams"
|
||||
msgstr "QUIC 并发双向流的最大数量"
|
||||
|
||||
msgid "Keep Alive"
|
||||
msgstr "保持连接"
|
||||
|
||||
msgid "QUIC KeepAlive interval"
|
||||
msgstr "QUIC KeepAlive 间隔"
|
||||
|
||||
@@ -1361,6 +1364,9 @@ msgstr "当节点链接未包含该参数时,将使用此设置。"
|
||||
msgid "%s Node Use Type"
|
||||
msgstr "%s 节点使用类型"
|
||||
|
||||
msgid "Other"
|
||||
msgstr "其他"
|
||||
|
||||
msgid "UDP relay mode"
|
||||
msgstr "UDP中继模式"
|
||||
|
||||
@@ -1577,12 +1583,6 @@ msgstr "XUDP 最大并发连接数"
|
||||
msgid "Padding"
|
||||
msgstr "填充"
|
||||
|
||||
msgid "Enable early data"
|
||||
msgstr "启用前置数据"
|
||||
|
||||
msgid "Early data length"
|
||||
msgstr "前置数据最大长度"
|
||||
|
||||
msgid "Early data header name"
|
||||
msgstr "前置数据 HTTP 头名"
|
||||
|
||||
|
||||
@@ -596,6 +596,9 @@ msgstr "QUIC 連接接收窗口"
|
||||
msgid "QUIC concurrent bidirectional streams"
|
||||
msgstr "QUIC 並發双向流的最大數量"
|
||||
|
||||
msgid "Keep Alive"
|
||||
msgstr "保持連線"
|
||||
|
||||
msgid "QUIC KeepAlive interval"
|
||||
msgstr "QUIC KeepAlive 間隔"
|
||||
|
||||
@@ -1361,6 +1364,9 @@ msgstr "當節點連結未包含該參數時,將使用此設定。"
|
||||
msgid "%s Node Use Type"
|
||||
msgstr "%s 節點使用類型"
|
||||
|
||||
msgid "Other"
|
||||
msgstr "其他"
|
||||
|
||||
msgid "UDP relay mode"
|
||||
msgstr "UDP中继模式"
|
||||
|
||||
@@ -1577,12 +1583,6 @@ msgstr "XUDP 最大並發連接數"
|
||||
msgid "Padding"
|
||||
msgstr "填充"
|
||||
|
||||
msgid "Enable early data"
|
||||
msgstr "啟用前置數据"
|
||||
|
||||
msgid "Early data length"
|
||||
msgstr "前置數据最大长度"
|
||||
|
||||
msgid "Early data header name"
|
||||
msgstr "前置數据 HTTP 头名"
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ local DEFAULT_TROJAN_TYPE = api.get_core("trojan_type", {{has_singbox,"sing-box"
|
||||
local DEFAULT_VMESS_TYPE = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local DEFAULT_VLESS_TYPE = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local DEFAULT_HYSTERIA2_TYPE = api.get_core("hysteria2_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
local DEFAULT_OTHER_TYPE = api.get_core("other_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
local core_has = {
|
||||
["xray"] = has_xray,
|
||||
["sing-box"] = has_singbox,
|
||||
@@ -536,6 +537,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
local sub_vmess_type = DEFAULT_VMESS_TYPE
|
||||
local sub_vless_type = DEFAULT_VLESS_TYPE
|
||||
local sub_hysteria2_type = DEFAULT_HYSTERIA2_TYPE
|
||||
local sub_other_type = DEFAULT_OTHER_TYPE
|
||||
local sub_hy_up_mbps, sub_hy_down_mbps
|
||||
if sub_cfg then
|
||||
if sub_cfg.allowInsecure and sub_cfg.allowInsecure ~= "1" then
|
||||
@@ -561,6 +563,10 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
if hysteria2_type ~= "global" and core_has[hysteria2_type] then
|
||||
sub_hysteria2_type = hysteria2_type
|
||||
end
|
||||
local other_type = sub_cfg.other_type or "global"
|
||||
if other_type ~= "global" and core_has[other_type] then
|
||||
sub_other_type = other_type
|
||||
end
|
||||
sub_hy_up_mbps = sub_cfg.hysteria_up_mbps
|
||||
sub_hy_down_mbps = sub_cfg.hysteria_down_mbps
|
||||
end
|
||||
@@ -679,21 +685,6 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
if info.net == 'ws' then
|
||||
result.ws_host = info.host
|
||||
result.ws_path = info.path
|
||||
if result.type == "sing-box" and info.path then
|
||||
local ws_path_dat = split(info.path, "?")
|
||||
local ws_path = ws_path_dat[1]
|
||||
local ws_path_params = {}
|
||||
for _, v in pairs(split(ws_path_dat[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
ws_path_params[t[1]] = t[2]
|
||||
end
|
||||
if ws_path_params.ed and tonumber(ws_path_params.ed) then
|
||||
result.ws_path = ws_path
|
||||
result.ws_enableEarlyData = "1"
|
||||
result.ws_maxEarlyData = tonumber(ws_path_params.ed)
|
||||
result.ws_earlyDataHeaderName = "Sec-WebSocket-Protocol"
|
||||
end
|
||||
end
|
||||
end
|
||||
if info.net == "http" then
|
||||
if result.type == "Xray" then
|
||||
@@ -936,21 +927,6 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
if params.type == 'ws' then
|
||||
result.ws_host = params.host
|
||||
result.ws_path = params.path
|
||||
if result.type == "sing-box" and params.path then
|
||||
local ws_path_dat = split(params.path, "%?")
|
||||
local ws_path = ws_path_dat[1]
|
||||
local ws_path_params = {}
|
||||
for _, v in pairs(split(ws_path_dat[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
ws_path_params[t[1]] = t[2]
|
||||
end
|
||||
if ws_path_params.ed and tonumber(ws_path_params.ed) then
|
||||
result.ws_path = ws_path
|
||||
result.ws_enableEarlyData = "1"
|
||||
result.ws_maxEarlyData = tonumber(ws_path_params.ed)
|
||||
result.ws_earlyDataHeaderName = "Sec-WebSocket-Protocol"
|
||||
end
|
||||
end
|
||||
end
|
||||
if params.type == "http" then
|
||||
if result.type == "sing-box" then
|
||||
@@ -1152,21 +1128,6 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
if params.type == 'ws' then
|
||||
result.ws_host = params.host
|
||||
result.ws_path = params.path
|
||||
if result.type == "sing-box" and params.path then
|
||||
local ws_path_dat = split(params.path, "%?")
|
||||
local ws_path = ws_path_dat[1]
|
||||
local ws_path_params = {}
|
||||
for _, v in pairs(split(ws_path_dat[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
ws_path_params[t[1]] = t[2]
|
||||
end
|
||||
if ws_path_params.ed and tonumber(ws_path_params.ed) then
|
||||
result.ws_path = ws_path
|
||||
result.ws_enableEarlyData = "1"
|
||||
result.ws_maxEarlyData = tonumber(ws_path_params.ed)
|
||||
result.ws_earlyDataHeaderName = "Sec-WebSocket-Protocol"
|
||||
end
|
||||
end
|
||||
end
|
||||
if params.type == "http" then
|
||||
if result.type == "sing-box" then
|
||||
@@ -1281,21 +1242,6 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
if params.type == 'ws' then
|
||||
result.ws_host = params.host
|
||||
result.ws_path = params.path
|
||||
if result.type == "sing-box" and params.path then
|
||||
local ws_path_dat = split(params.path, "%?")
|
||||
local ws_path = ws_path_dat[1]
|
||||
local ws_path_params = {}
|
||||
for _, v in pairs(split(ws_path_dat[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
ws_path_params[t[1]] = t[2]
|
||||
end
|
||||
if ws_path_params.ed and tonumber(ws_path_params.ed) then
|
||||
result.ws_path = ws_path
|
||||
result.ws_enableEarlyData = "1"
|
||||
result.ws_maxEarlyData = tonumber(ws_path_params.ed)
|
||||
result.ws_earlyDataHeaderName = "Sec-WebSocket-Protocol"
|
||||
end
|
||||
end
|
||||
end
|
||||
if params.type == "http" then
|
||||
if result.type == "sing-box" then
|
||||
@@ -1682,6 +1628,115 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
result.snell_mode = params.mode or "default"
|
||||
end
|
||||
result.snell_reuse = (params.reuse == "1") and "1" or "0"
|
||||
elseif szType == "wireguard" then
|
||||
if sub_other_type == "sing-box" and has_singbox then
|
||||
result.type = "sing-box"
|
||||
elseif sub_other_type == "xray" and has_xray then
|
||||
result.type = "Xray"
|
||||
else
|
||||
log(2, i18n.translatef("Skipping the %s node is due to incompatibility with the %s core program or incorrect node usage type settings.", "WireGuard", "Xray / sing-box"))
|
||||
return nil
|
||||
end
|
||||
result.protocol = "wireguard"
|
||||
|
||||
local alias = ""
|
||||
if content:find("#") then
|
||||
local idx_sp = content:find("#")
|
||||
alias = content:sub(idx_sp + 1, -1)
|
||||
content = content:sub(0, idx_sp - 1)
|
||||
end
|
||||
result.remarks = UrlDecode(alias)
|
||||
local contents = split(content, "@")
|
||||
result.wireguard_secret_key = UrlDecode(contents[1]:gsub("%+", "%%2B"))
|
||||
local query = split(contents[2], "%?")
|
||||
local host_port = query[1]
|
||||
local params = {}
|
||||
for _, v in pairs(split(query[2], '&')) do
|
||||
local s = v:find("=", 1, true)
|
||||
if s and s > 1 then
|
||||
params[UrlDecode(v:sub(1, s - 1)):lower()] = UrlDecode(v:sub(s + 1):gsub("%+", "%%2B"))
|
||||
end
|
||||
end
|
||||
result.address, result.port = parse_host_port(host_port, "51820")
|
||||
result.wireguard_public_key = params.publickey
|
||||
result.wireguard_preSharedKey = params.presharedkey
|
||||
result.wireguard_local_address = {}
|
||||
for value in ((params.address or params.ip or "") .. "," .. (params.ipv6 or "")):gmatch("[^,%s]+") do
|
||||
result.wireguard_local_address[#result.wireguard_local_address + 1] = value
|
||||
end
|
||||
result.wireguard_reserved = params.reserved
|
||||
result.wireguard_mtu = params.mtu or "1420"
|
||||
result.wireguard_keepAlive = params["persistent-keepalive"] or params.keepalive or "0"
|
||||
result.use_finalmask = (params.fm and params.fm ~= "") and "1" or nil
|
||||
result.finalmask = (params.fm and params.fm ~= "") and api.base64Encode(params.fm) or nil
|
||||
elseif szType == "socks" or szType == "socks5" or szType == "socks5h" or szType == "http" or szType == "https" then
|
||||
if sub_other_type == "sing-box" and has_singbox then
|
||||
result.type = "sing-box"
|
||||
elseif sub_other_type == "xray" and has_xray then
|
||||
result.type = "Xray"
|
||||
else
|
||||
log(2, i18n.translatef("Skipping the %s node is due to incompatibility with the %s core program or incorrect node usage type settings.", szType, "Xray / sing-box"))
|
||||
return nil
|
||||
end
|
||||
result.protocol = (szType == "http" or szType == "https") and "http" or "socks"
|
||||
|
||||
local alias = ""
|
||||
if content:find("#") then
|
||||
local idx_sp = content:find("#")
|
||||
alias = content:sub(idx_sp + 1, -1)
|
||||
content = content:sub(0, idx_sp - 1)
|
||||
end
|
||||
result.remarks = UrlDecode(alias)
|
||||
local query = split(content, "%?")
|
||||
local Info = query[1]
|
||||
local base64_auth = false
|
||||
if result.protocol == "socks" and not Info:find("@", 1, true) and not Info:find(":", 1, true) then
|
||||
Info = base64Decode(UrlDecode(Info:gsub("%+", "%%2B")))
|
||||
base64_auth = true
|
||||
end
|
||||
local auth, host_port = Info:match("^(.*)@(.*)$")
|
||||
host_port = host_port or Info
|
||||
auth = auth or ""
|
||||
if result.protocol == "socks" and not auth:find(":", 1, true) then
|
||||
auth = base64Decode(UrlDecode(auth:gsub("%+", "%%2B")))
|
||||
base64_auth = true
|
||||
end
|
||||
local idx = auth:find(":", 1, true)
|
||||
result.username = idx and auth:sub(1, idx - 1) or auth
|
||||
result.password = idx and auth:sub(idx + 1) or ""
|
||||
if not base64_auth then
|
||||
result.username = UrlDecode(result.username:gsub("%+", "%%2B"))
|
||||
result.password = UrlDecode(result.password:gsub("%+", "%%2B"))
|
||||
end
|
||||
local params = {}
|
||||
for _, v in pairs(split(query[2], '&')) do
|
||||
local s = v:find("=", 1, true)
|
||||
if s and s > 1 then
|
||||
params[UrlDecode(v:sub(1, s - 1)):lower()] = UrlDecode(v:sub(s + 1):gsub("%+", "%%2B"))
|
||||
end
|
||||
end
|
||||
local port = result.protocol == "socks" and "1080" or (szType == "https" and "443" or "80")
|
||||
result.address, result.port = parse_host_port(host_port, port)
|
||||
result.transport = result.type == "Xray" and "raw" or "tcp"
|
||||
result.uot = params.uot
|
||||
result.tcp_fast_open = params.tfo
|
||||
result.tls = szType == "https" and "1" or "0"
|
||||
if result.tls == "1" then
|
||||
result.tls_serverName = params.sni
|
||||
result.alpn = params.alpn
|
||||
local insecure = params.allowinsecure or params.insecure or params.allow_insecure
|
||||
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0")
|
||||
result.tls_pinSHA256 = params.pcs
|
||||
result.tls_CertByName = params.vcn
|
||||
if params.fp and params.fp ~= "" then
|
||||
result.utls = "1"
|
||||
result.fingerprint = params.fp
|
||||
end
|
||||
if params.ech and params.ech ~= "" then
|
||||
result.ech = "1"
|
||||
result.ech_config = params.ech
|
||||
end
|
||||
end
|
||||
else
|
||||
log(2, i18n.translatef("%s type node subscriptions are not currently supported, skip this node.", szType))
|
||||
return nil
|
||||
|
||||
@@ -21,13 +21,13 @@ define Download/geoip
|
||||
HASH:=eedb24b3b9fcba27e06b92c0428dab90d9496083091ae4cf39e11387fd99d0e2
|
||||
endef
|
||||
|
||||
GEOSITE_VER:=20261110004853
|
||||
GEOSITE_VER:=20261110034535
|
||||
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
|
||||
define Download/geosite
|
||||
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
|
||||
URL_FILE:=dlc.dat
|
||||
FILE:=$(GEOSITE_FILE)
|
||||
HASH:=5ce9f05c8968772940e29b7898adf232464a2a2a820252d17c5b33ffaecd1da9
|
||||
HASH:=6cc4decf520dbfd96e1e3750661976eb31d2a5381090b8768cb2ab1528201fcf
|
||||
endef
|
||||
|
||||
GEOSITE_IRAN_VER:=202610230802
|
||||
|
||||
Reference in new issue
Block a user