update 2022-07-07 20:18:42

This commit is contained in:
github-actions[bot] 2022-07-07 20:18:42 +08:00
parent 395f5b23ac
commit da8965e832
16 changed files with 1401 additions and 1783 deletions

View File

@ -14,13 +14,13 @@ PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan-Go \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Socks5_Proxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Socks_Server
LUCI_TITLE:=SS/SSR/Xray/Trojan/Trojan-Go/NaiveProxy/Socks5/Tun LuCI interface
LUCI_TITLE:=SS/SSR/Xray/Trojan/NaiveProxy/Socks5/Tun LuCI interface
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+ipset +kmod-ipt-nat +ip-full +iptables-mod-tproxy +dnsmasq-full +smartdns +coreutils +coreutils-base64 +curl +tcping +chinadns-ng +lua +luci-compat +unzip +lua-maxminddb \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server:shadowsocks-libev-ss-server \
@ -33,9 +33,9 @@ LUCI_DEPENDS:=+ipset +kmod-ipt-nat +ip-full +iptables-mod-tproxy +dnsmasq-full +
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin:v2ray-plugin \
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray-core \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan-plus \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan-Go:trojan-go \
+PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy:naiveproxy \
+PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun:kcptun-client \
+PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria:hysteria \
+PACKAGE_$(PKG_NAME)_INCLUDE_Socks5_Proxy:redsocks2 \
+PACKAGE_$(PKG_NAME)_INCLUDE_Socks_Server:microsocks
@ -43,7 +43,7 @@ define Package/$(PKG_NAME)/config
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client
bool "Include Shadowsocks Libev Client"
default y
default y if i386||x86_64||arm
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server
bool "Include Shadowsocks Libev Server"
@ -59,7 +59,7 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server
config PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs
bool "Include Shadowsocks Simple Obfs Plugin"
default y
default y if i386||x86_64||arm
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin
bool "Include Shadowsocks V2ray Plugin"
@ -71,10 +71,6 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Xray
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan
bool "Include Trojan"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan-Go
bool "Include Trojan Go"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy
@ -86,9 +82,13 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun
bool "Include Kcptun"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria
bool "Include Hysteria"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Socks5_Proxy
bool "Include Socks5 Transparent Proxy"
default y
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Socks_Server
bool "Include Socks Sever"

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ uci:foreach(bypass,"servers",function(s)
server_count=server_count+1
end)
m=Map(bypass,translate("Servers subscription and manage"),translate("Support SS/SSR/XRAY/TROJAN/TROJAN-GO/NAIVEPROXY/SOCKS5/TUN etc."))
m=Map(bypass,translate("Servers subscription and manage"),translate("Support SS/SSR/XRAY/TROJAN/NAIVEPROXY/SOCKS5/TUN etc."))
s=m:section(TypedSection,"server_subscribe")
s.anonymous=true

View File

@ -1,179 +0,0 @@
module("luci.model.cbi.bypass.trojan_go", package.seeall)
local fs = require "nixio.fs"
local sys = require "luci.sys"
local util = require "luci.util"
local i18n = require "luci.i18n"
local api = require "luci.model.cbi.bypass.api"
local trojan_go_api = "https://api.github.com/repos/p4gefau1t/trojan-go/releases?per_page=1"
function to_check(arch)
local app_path = api.get_trojan_go_path() or ""
if app_path == "" then
return {
code = 1,
error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Trojan-GO")
}
end
if not arch or arch == "" then arch = api.auto_get_arch() end
local file_tree, sub_version = api.get_file_info(arch)
if file_tree == "" then
return {
code = 1,
error = i18n.translate("Can't determine ARCH, or ARCH not supported.")
}
end
if file_tree == "mips" then file_tree = "mips%-hardfloat" end
if file_tree == "mipsle" then file_tree = "mipsle%-hardfloat" end
if file_tree == "arm64" then
file_tree = "armv8"
else
if sub_version and sub_version:match("^[5-8]$") then file_tree = file_tree .. "v" .. sub_version end
end
local json = api.get_api_json(trojan_go_api)
if #json > 0 then
json = json[1]
end
if json.tag_name == nil then
return {
code = 1,
error = i18n.translate("Get remote version info failed.")
}
end
local now_version = api.get_trojan_go_version()
local remote_version = json.tag_name
local needs_update = api.compare_versions(now_version:match("[^v]+"), "<", remote_version:match("[^v]+"))
local html_url, download_url
if needs_update then
html_url = json.html_url
for _, v in ipairs(json.assets) do
if v.name and v.name:match("linux%-" .. file_tree .. "%.zip") then
download_url = v.browser_download_url
break
end
end
end
if needs_update and not download_url then
return {
code = 1,
now_version = now_version,
version = remote_version,
html_url = html_url,
error = i18n.translate("New version found, but failed to get new version download url.") .. " [linux-" .. file_tree .. ".zip]"
}
end
return {
code = 0,
update = needs_update,
now_version = now_version,
version = remote_version,
url = {html = html_url, download = download_url}
}
end
function to_download(url)
local app_path = api.get_trojan_go_path() or ""
if app_path == "" then
return {
code = 1,
error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Trojan-GO")
}
end
if not url or url == "" then
return {code = 1, error = i18n.translate("Download url is required.")}
end
sys.call("/bin/rm -f /tmp/trojan-go_download.*")
local tmp_file = util.trim(util.exec("mktemp -u -t trojan-go_download.XXXXXX"))
local result = api.exec(api.curl, {api._unpack(api.curl_args), "-o", tmp_file, url}, nil, api.command_timeout) == 0
if not result then
api.exec("/bin/rm", {"-f", tmp_file})
return {
code = 1,
error = i18n.translatef("File download failed or timed out: %s", url)
}
end
return {code = 0, file = tmp_file}
end
function to_extract(file, subfix)
local app_path = api.get_trojan_go_path() or ""
if app_path == "" then
return {
code = 1,
error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Trojan-GO")
}
end
if sys.exec("echo -n $(opkg list-installed | grep -c unzip)") ~= "1" then
api.exec("/bin/rm", {"-f", file})
return {
code = 1,
error = i18n.translate("Not installed unzip, Can't unzip!")
}
end
if not file or file == "" or not fs.access(file) then
return {code = 1, error = i18n.translate("File path required.")}
end
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
local tmp_dir = util.trim(util.exec("mktemp -d -t trojan-go_extract.XXXXXX"))
local output = {}
api.exec("/usr/bin/unzip", {"-o", file, "-d", tmp_dir},
function(chunk) output[#output + 1] = chunk end)
local files = util.split(table.concat(output))
api.exec("/bin/rm", {"-f", file})
return {code = 0, file = tmp_dir}
end
function to_move(file)
local app_path = api.get_trojan_go_path() or ""
if app_path == "" then
return {
code = 1,
error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Trojan-GO")
}
end
if not file or file == "" then
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
return {code = 1, error = i18n.translate("Client file is required.")}
end
local app_path_bak
if fs.access(app_path) then
app_path_bak = app_path .. ".bak"
api.exec("/bin/mv", {"-f", app_path, app_path_bak})
end
local result = api.exec("/bin/mv", { "-f", file .. "/trojan-go", app_path }, nil, api.command_timeout) == 0
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
if not result or not fs.access(app_path) then
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s", app_path)
}
end
api.exec("/bin/chmod", {"-R", "755", app_path})
return {code = 0}
end

View File

@ -1,831 +0,0 @@
<%+cbi/valueheader%>
<%
local api = require "luci.model.cbi.bypass.api"
-%>
<script type="text/javascript">//<![CDATA[
function padright(str, cnt, pad) {
return str + Array(cnt + 1).join(pad);
}
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
function b64encutf8safe(str) {
return b64EncodeUnicode(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '');
}
function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
function b64decutf8safe(str) {
var l;
str = str.replace(/-/g, "+").replace(/_/g, "/");
l = str.length;
l = (4 - l % 4) % 4;
if (l)
str = padright(str, l, "=");
return b64DecodeUnicode(str);
}
function b64encsafe(str) {
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '')
}
function b64decsafe(str) {
var l;
str = str.replace(/-/g, "+").replace(/_/g, "/");
l = str.length;
l = (4 - l % 4) % 4;
if (l)
str = padright(str, l, "=");
return atob(str);
}
function dictvalue(d, key) {
var v = d[key];
if (typeof(v) === 'undefined' || v === '')
return '';
return b64decsafe(v);
}
function parseNodeUrl(url) {
var m = url.match(/^(([^:\/?#]+:)?(?:\/\/((?:([^\/?#:]*)([^\/?#:]*)@)?([^\/?#:]*)(?::([^\/?#:]*))?)))?([^?#]*)(\?[^#]*)?(#.*)?$/),
r = {
hash: m[10] || "", // #asd
host: m[3] || "", // localhost:257
hostname: m[6] || "", // localhost
href: m[0] || "", // http://username:password@localhost:257/deploy/?asd=asd#asd
origin: m[1] || "", // http://username:password@localhost:257
pathname: m[8] || (m[1] ? "/" : ""), // /deploy/
port: m[7] || "", // 257
protocol: m[2] || "", // http:
search: m[9] || "", // ?asd=asd
passwd: m[4] || "", // username
removed: m[5] || "" // password
};
if (r.protocol.length === 2) {
r.protocol = "file:///" + r.protocol.toUpperCase();
r.origin = r.protocol + "//" + r.host;
}
r.href = r.origin + r.pathname + r.search + r.hash;
return m && r;
}
function buildUrl(btn, urlname, sid) {
var opt = {
base: "cbid.bypass",
client : true,
get: function(opt) {
var id = this.base + "." + opt;
var obj = document.getElementsByName(id)[0] || document.getElementsByClassName(id)[0] || document.getElementById(id)
if (obj) {
return obj;
} else {
return null;
}
},
getlist: function(opt) {
var id = this.base + "." + opt;
var objs = document.getElementsByName(id) || document.getElementsByClassName(id);
var ret = [];
if (objs) {
for (var i = 0; i < objs.length; i++) {
ret[i] = objs[i].value;
}
} else {
alert("<%:Faltal on get option, please help in debug: %>" + opt);
}
return ret;
},
query: function(param, src, tval = "1", fval = "0") {
var ret = "&" + param + "=";
var obj = this.get(src);
if (obj) {
if (obj.type === "checkbox") {
return ret + (obj.checked === true ? tval : fval);
} else {
return ret + encodeURIComponent(obj.value);
}
}
return ""
}
}
var s = document.getElementById(urlname + "-status");
if (!s) {
alert("Never");
return false;
}
opt.base = 'cbid.bypass.' + sid;
opt.client = urlname.indexOf("server") === -1;
var v_type = opt.get("type").value;
var v_alias = opt.get("alias");
var url = null;
if (v_type === "ss") {
var v_server = opt.get("server");
var v_port = opt.get("server_port");
var v_method = opt.get("encrypt_method_ss");
var v_password = opt.get("password");
url = b64encsafe(v_method.value + ":" + v_password.value) + "@" +
v_server.value + ":" +
v_port.value + "/?";
var params = "";
var v_plugin = opt.get("plugin").value;
if (v_plugin && v_plugin != "none") {
if (v_plugin == "simple-obfs" || v_plugin == "obfs-local") {
v_plugin = "obfs-local";
}
var v_plugin_opts = opt.get("plugin_opts").value;
if (v_plugin_opts && v_plugin_opts != "") {
v_plugin += encodeURI(";" + v_plugin_opts);
}
params += "&plugin=" + encodeURI(v_plugin);
}
params += "&group="
params += "#" + encodeURI(v_alias.value);
if (params[0] == "&") {
params = params.substring(1);
}
url += params;
} else if (v_type === "ssr") {
var v_server = opt.get("server");
var v_port = opt.get("server_port");
var v_protocol = opt.get("protocol");
var v_method = opt.get("encrypt_method");
var v_obfs = opt.get("obfs");
var v_password = opt.get("password");
var v_obfs_param = opt.get("obfs_param");
var v_protocol_param = opt.get("protocol_param");
var ssr_str = v_server.value + ":" +
v_port.value + ":" +
v_protocol.value + ":" +
v_method.value + ":" +
v_obfs.value + ":" +
b64encsafe(v_password.value) +
"/?obfsparam=" + b64encsafe(v_obfs_param.value) +
"&protoparam=" + b64encsafe(v_protocol_param.value) +
"&remarks=" + b64encutf8safe(v_alias.value);
url = b64encsafe(ssr_str);
} else if (v_type === "vmess") {
v_type = "vmess";
var info = {};
info.v = "2";
info.ps = v_alias.value;
info.add = opt.get("server").value;
info.port = opt.get("server_port").value;
info.id = opt.get("uuid").value;
info.aid = opt.get("alter_id").value;
var v_transport = opt.get("transport").value;
if (v_transport === "ws") {
info.host = opt.get("ws_host").value;
info.path = opt.get("ws_path").value;
} else if (v_transport === "h2") {
info.host = opt.get("h2_host").value;
info.path = opt.get("h2_path").value;
} else if (v_transport === "tcp") {
info.type = opt.get("tcp_guise").value;
info.host = opt.get("http_host").value;
info.path = opt.get("http_path").value;
} else if (v_transport === "mkcp") {
v_transport = "kcp";
info.type = opt.get("kcp_guise").value;
} else if (v_transport === "quic") {
info.type = opt.get("quic_guise").value;
info.key = opt.get("quic_key").value;
info.securty = opt.get("quic_security").value;
} else if (v_transport === "grpc") {
info.path = opt.get("grpc_serviceName").value;
}
if (info.path && info.path != "") {
info.path = encodeURI(info.path);
}
info.net = v_transport;
info.security = opt.get("security").value || "auto";
if (opt.get("tls").checked) {
var v_security = "tls";
info.tls = "tls";
info.sni = opt.get("tls_host").value;
}
url = b64EncodeUnicode(JSON.stringify(info));
} else if (v_type === "vless") {
v_type = "vless";
var v_password = opt.get("uuid");
var v_server = opt.get("server");
var v_port = opt.get("server_port");
url = encodeURIComponent(v_password.value) +
"@" + v_server.value +
":" + v_port.value + "?";
var params = "";
var v_transport = opt.get("transport").value;
if (v_transport === "ws") {
params += opt.query("host", "ws_host");
params += opt.query("path", "ws_path");
} else if (v_transport === "h2") {
params += opt.query("host", "h2_host");
params += opt.query("path", "h2_path");
} else if (v_transport === "tcp") {
params += opt.query("headerType", "tcp_guise");
params += opt.query("host", "http_host");
params += opt.query("path", "http_path");
} else if (v_transport === "mkcp") {
v_transport = "kcp";
params += opt.query("headerType", "kcp_guise");
} else if (v_transport === "quic") {
params += opt.query("headerType", "quic_guise");
params += opt.query("key", "quic_key");
params += opt.query("quicSecurity", "quic_security");
} else if (v_transport === "grpc") {
//不知道是用path还是serviceName这里先这样吧
params += opt.query("path", "grpc_serviceName");
params += opt.query("serviceName", "grpc_serviceName");
}
params += "&type=" + v_transport;
params += opt.query("encryption", "encryption");
if (opt.get("tls")) {
if (opt.get("tls").checked) {
var v_security = "tls";
params += "&security=" + v_security;
params += opt.query("sni", "tls_host");
}
}
if (opt.get("xtls")) {
if (opt.get("xtls").checked) {
v_security = "xtls";
var v_flow = "xtls-rprx-direct";
if (opt.get("vless_flow").value) {
v_flow = opt.get("vless_flow").value;
}
params += "&flow=" + v_flow;
params += "&security=" + v_security;
params += opt.query("sni", "tls_host");
}
}
params += "#" + encodeURI(v_alias.value);
if (params[0] == "&") {
params = params.substring(1);
}
url += params;
} else if ((v_type === "xray" && opt.get("protocol").value === "trojan") || v_type === "trojan" || v_type === "trojan" || v_type === "trojan-go") {
if (v_type === "xray" && opt.get("protocol").value === "trojan") {
v_type = "trojan";
}
var v_password = opt.get(!opt.client && v_type === "trojan-go" ? "passwords" : "password");
var v_server = opt.get("server");
var v_port = opt.get("server_port");
url = encodeURIComponent(v_password.value) +
"@" + v_server.value +
":" + v_port.value + "/?";
var params = "";
if (opt.get("tls").checked) {
params += opt.query("sni", "tls_host");
if (v_type !== "trojan-go") {
params += "&tls=1"
params += opt.query("allowinsecure", "insecure");
}
}
if (v_type === "trojan-go") {
if (!opt.get("tls").checked && opt.get("trojan_transport").value === "original") {
var plugin = {};
plugin.type = opt.get("plugin_type").value;
if (plugin.type !== "plaintext") {
plugin.command = opt.get("plugin_cmd").value;
plugin.option = opt.get("plugin_option").value;
plugin.arg = opt.getlist("plugin_arg");
}
params += "&plugin=" + encodeURIComponent(JSON.stringify(plugin));
}
params += opt.query("type", "trojan_transport");
var ws = (opt.get("trojan_transport").value.indexOf("ws") !== -1);
var h2 = (opt.get("trojan_transport").value.indexOf("h2") !== -1);
if (ws) {
params += opt.query("host", "ws_host");
params += opt.query("path", "ws_path");
} else if (h2) {
params += opt.query("host", "h2_host");
params += opt.query("path", "h2_path");
}
var enc = "none";
if (opt.get("ss_aead").checked === true) {
enc = "ss;" +
opt.get("ss_aead_method").value +
":" + opt.get("ss_aead_pwd").value;
}
params += "&encryption=" + encodeURIComponent(enc);
}
params += "#" + encodeURI(v_alias.value);
if (params[0] == "&") {
params = params.substring(1);
}
url += params;
}
if (url) {
url = v_type.toLowerCase() + "://" + url;
var textarea = document.createElement("textarea");
textarea.textContent = url;
textarea.style.position = "fixed";
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand("copy"); // Security exception may be thrown by some browsers.
s.innerHTML = "<font color='green'><%:Share URL to clipboard successfully.%></font>";
} catch (ex) {
s.innerHTML = "<font color='red'><%:Share URL to clipboard unable.%></font>";
} finally {
document.body.removeChild(textarea);
}
//alert(url);
} else {
alert("<%:Not a supported scheme:%> " + v_type);
}
return false;
}
function fromUrl(btn, urlname, sid) {
var opt = {
base: 'cbid.bypass',
client : true,
get: function(opt) {
var obj;
var id = this.base + '.' + opt;
obj = document.getElementsByName(id)[0] || document.getElementById(id);
if (obj) {
return obj;
} else {
return null;
}
},
set: function(opt, val) {
var obj;
obj = this.get(opt)
if (obj) {
if (obj.type === 'checkbox') {
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
obj.checked = val;
obj.dispatchEvent(event);
} else {
obj.value = val;
}
} else {
//alert('<%:Faltal on set option, please help in debug: %>' + opt + ' = ' + val);
}
},
setlist: function(opt, vlist) {
var id = this.base + "." + opt;
var objs = document.getElementsByName(id) || document.getElementsByClassName(id);
if (objs) {
var values = "";
for (var i = 0; i < vlist.length; i++) {
values += vlist[i] + ", ";
}
alert("Manually input the option:\n" + opt + "s:\n[" + values + "]");
} else {
//alert("<%:Faltal on set option, please help in debug: %>" + opt);
}
}
}
var s = document.getElementById(urlname + '-status');
if (!s) {
alert("Never");
return false;
}
opt.base = 'cbid.bypass.' + sid;
opt.client = urlname.indexOf("server") === -1;
var ssrurl = prompt('<%:Paste Share URL Here%>', '');
if (ssrurl === null || ssrurl === "") {
return false;
}
s.innerHTML = "";
var ssu = ssrurl.split('://');
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
if (ssu[0] === "ssr") {
//var b64c = ssu[1].match(/([A-Za-z0-9_-]+)/);
var sstr = b64decsafe(ssu[1]);
var ploc = sstr.indexOf("/?");
var url0 = "", param = "";
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
} else {
var url0 = sstr;
}
console.log(param);
var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
if (!ssm || ssm.length < 7) {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>";
return false;
}
var pdict = {};
if (param.length > 2) {
var a = param.split('&');
for (var i = 0; i < a.length; i++) {
var b = a[i].split('=');
pdict[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
}
}
opt.set('type', "ssr");
opt.get('type').dispatchEvent(event);
opt.set('server', ssm[1]);
opt.set('server_port', ssm[2]);
opt.set('protocol', ssm[3]);
opt.set('encrypt_method', ssm[4]);
opt.set('obfs', ssm[5]);
opt.set('password', b64decsafe(ssm[6]));
opt.set('obfs_param', dictvalue(pdict, 'obfsparam'));
opt.set('protocol_param', dictvalue(pdict, 'protoparam'));
var rem = pdict['remarks'];
if (typeof(rem) !== 'undefined' && rem !== '' && rem.length > 0)
opt.set('alias', b64decutf8safe(rem));
} else if (ssu[0] === "ss") {
var url0 = "", param = "";
var sipIndex = ssu[1].indexOf("@");
var ploc = ssu[1].indexOf("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = ssu[1].substr(ploc + 1);
} else {
url0 = ssu[1];
}
if (sipIndex !== -1) {
// SIP002
var userInfo = b64decsafe(url0.substr(0, sipIndex));
var temp = url0.substr(sipIndex + 1).split("/?");
var serverInfo = temp[0].split(":");
var server = serverInfo[0];
var port = serverInfo[1];
var method, password, plugin, pluginOpts;
if (temp[1]) {
var pluginInfo = decodeURIComponent(temp[1]);
var pluginIndex = pluginInfo.indexOf(";");
var pluginNameInfo = pluginInfo.substr(0, pluginIndex);
plugin = pluginNameInfo.substr(pluginNameInfo.indexOf("=") + 1)
pluginOpts = pluginInfo.substr(pluginIndex + 1);
}
var userInfoSplitIndex = userInfo.indexOf(":");
if (userInfoSplitIndex !== -1) {
method = userInfo.substr(0, userInfoSplitIndex);
password = userInfo.substr(userInfoSplitIndex + 1);
}
opt.set('type', "ss");
opt.get('type').dispatchEvent(event);
opt.set('server', server);
opt.set('server_port', port);
opt.set('password', password || "");
opt.set('encrypt_method_ss', method || "");
opt.set('plugin', plugin || "none");
if (plugin && plugin != "none") {
opt.get('plugin').dispatchEvent(event);
opt.set('plugin_opts', pluginOpts || "");
opt.get('plugin_opts').dispatchEvent(event);
}
if (param !== undefined) {
opt.set('alias', decodeURI(param));
}
} else {
var sstr = b64decsafe(url0);
var team = sstr.split('@');
opt.set('type', "ss");
opt.get('type').dispatchEvent(event);
var part1 = team[0].split(':');
var part2 = team[1].split(':');
opt.set('server', part2[0]);
opt.set('server_port', part2[1]);
opt.set('password', part1[1]);
opt.set('encrypt_method_ss', part1[0]);
opt.set('plugin', "none");
opt.get('plugin').dispatchEvent(event);
//opt.set('ss_plugin_opts', "");
if (param !== undefined) {
opt.set('alias', decodeURI(param));
}
}
} else if (ssu[0] === "trojan") {
var stype = "trojan";
var m = parseNodeUrl(ssrurl);
console.log(m.search);
var password = m.passwd;
if (password === "") {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>";
return false;
}
var queryParam = {};
if (m.search.length > 1) {
var query = m.search.split('?');
var queryParams = query[1];
var queryArray = queryParams.split('&');
var params;
for (i = 0; i < queryArray.length; i++) {
params = queryArray[i].split('=');
queryParam[decodeURIComponent(params[0]).toLowerCase()] = decodeURIComponent(params[1] || '');
}
}
if (queryParam.mux || queryParam.ws || queryParam.h2 || queryParam.ss || queryParam.plugin) {
stype = "trojan-go";
}
opt.set('type', stype);
opt.get('type').dispatchEvent(event);
opt.set('server', m.hostname);
opt.set('server_port', m.port || "443");
opt.set(!opt.client && stype === "trojan-go" ? 'passwords' : 'password', decodeURIComponent(password));
var tls = true;
if (stype === "trojan-go") {
tls = queryParam.plugin === undefined;
}
if (tls === false) { alert("TODO: plugin params for trojan-go."); }
opt.set('tls', tls);
opt.get('tls').dispatchEvent(event);
if (tls) {
opt.set('tls_host', queryParam.peer || queryParam.sni || '');
opt.set('insecure', queryParam.allowinsecure === '1');
}
var tran = 'original';
var ws = queryParam.type.indexOf('ws') !== -1;
var h2 = queryParam.type.indexOf('h2') !== -1;
if (ws && h2) {
tran = 'h2+ws'
} else {
if (ws) tran = 'ws';
if (h2) tran = 'h2';
}
opt.set('trojan_transport', 'tran');
opt.get('trojan_transport').dispatchEvent(event);
if (ws) {
opt.set('ws_host', queryParam.wshost || '');
opt.set('ws_path', queryParam.wspath || '/');
}
if (h2) {
opt.set('h2_host', queryParam.h2host || '');
opt.set('h2_path', queryParam.h2path || '/');
}
var ss = queryParam.ss === '1';
opt.set('ss_aead', ss);
if (ss) {
opt.set('ss_aead_method', queryParam.ssmethod.toLowerCase() || '');
opt.set('ss_aead_pwd', queryParam.sspasswd || '');
}
opt.set('mux', queryParam.mux === '1');
if (m.hash) {
opt.set('alias', decodeURI(m.hash.substr(1)));
}
} else if (ssu[0] === "trojan-go") {
var m = parseNodeUrl(ssrurl);
console.log(m.search);
var password = m.passwd;
if (password === "") {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>";
return false;
}
var queryParam = {};
if (m.search.length > 1) {
var query = m.search.split('?');
var queryParams = query[1];
var queryArray = queryParams.split('&');
for (i = 0; i < queryArray.length; i++) {
var params = queryArray[i].split('=');
queryParam[decodeURIComponent(params[0]).toLowerCase()] = decodeURIComponent(params[1] || '');
}
}
opt.set('type', 'trojan-go');
opt.get('type').dispatchEvent(event);
opt.set('server', m.hostname);
opt.set('server_port', m.port || "443");
opt.set(opt.client ? 'password' : 'passwords', decodeURIComponent(password));
opt.set('tls', '1');
opt.get('tls').dispatchEvent(event);
opt.set('insecure', '0');
opt.set('tls_host', queryParam.peer || queryParam.sni || '');
var plugin = queryParam.plugin !== undefined;
if (plugin) {
opt.set('trojan_transport', 'original');
opt.get('trojan_transport').dispatchEvent(event);
var plugin = JSON.parse(queryParam.plugin);
if (plugin) {
opt.set('plugin_type', plugin.type);
opt.get('plugin_type').dispatchEvent(event);
if (plugin.type !== "plaintext") {
opt.set('plugin_cmd', plugin.command);
opt.set('plugin_option', plugin.option);
opt.setlist('plugin_arg', plugin.arg);
}
} else
alert(queryParam.plugin);
}
var tran = 'original';
var or = queryParam.type === undefined || queryParam.type === 'original';
var ws = queryParam.type.indexOf('ws') !== -1;
var h2 = queryParam.type.indexOf('h2') !== -1;
if (ws && h2) {
tran = 'h2+ws'
} else {
if (ws) tran = 'ws';
if (h2) tran = 'h2';
}
opt.set('trojan_transport', tran);
opt.get('trojan_transport').dispatchEvent(event);
if (ws) {
opt.set('ws_host', queryParam.host || '');
opt.set('ws_path', queryParam.path || '/');
}
if (h2){
opt.set('h2_host', queryParam.host || '');
opt.set('h2_path', queryParam.path || '/');
}
var enc = {};
var ss = false;
if (queryParam.encryption) {
var r = queryParam.encryption.match(/^(ss);([^;:]*)[;:](.*)$/),
enc = {type: r[1], method: r[2], password: r[3]};
}
ss = enc.type === 'ss';
opt.set('ss_aead', ss);
if (ss) {
opt.set('ss_aead_method', enc.method.toLowerCase() || '');
opt.set('ss_aead_pwd', enc.password || '');
}
opt.set('mux', '1');
if (m.hash) {
opt.set('alias', decodeURI(m.hash.substr(1)));
}
} else if (ssu[0] === "vmess") {
var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?");
opt.set('type', "vmess");
opt.get('type').dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
}
var ssm = JSON.parse(sstr);
console.log(ssm);
opt.set('alias', ssm.ps);
opt.set('server', ssm.add);
opt.set('server_port', ssm.port);
opt.set('alter_id', ssm.aid);
opt.set('uuid', ssm.id);
opt.set('tls', ssm.tls === "tls");
opt.get('tls').dispatchEvent(event);
if (ssm.tls === "tls") {
var tls_host = ssm.host;
if (ssm.sni) {
tls_host = ssm.sni
}
opt.set('tls_host', tls_host);
}
ssm.net = ssm.net.toLowerCase();
if (ssm.net === "kcp" || ssm.net === "mkcp")
ssm.net = "mkcp"
opt.set('transport', ssm.net);
opt.get('transport').dispatchEvent(event);
if (ssm.net === "tcp") {
opt.set('tcp_guise', (ssm.host && ssm.path) ? "http" : "none");
opt.get('tcp_guise').dispatchEvent(event);
if (ssm.host && ssm.path) {
opt.set('http_host', ssm.host);
opt.set('http_path', ssm.path);
}
} else if (ssm.net === "ws") {
opt.set('ws_host', ssm.host);
opt.set('ws_path', ssm.path);
} else if (ssm.net === "h2") {
opt.set('h2_host', ssm.host);
opt.set('h2_path', ssm.path);
} else if (ssm.net === "quic") {
opt.set('quic_security', ssm.securty);
opt.set('quic_key', ssm.key);
} else if (ssm.net === "kcp" || ssm.net === "mkcp") {
opt.set('kcp_guise', ssm.type);
opt.get('kcp_guise').dispatchEvent(event);
} else if (ssm.net === "grpc") {
opt.set('grpc_serviceName', ssm.path);
}
} else if (ssu[0] === "vless") {
opt.set('type', "vless");
opt.get('type').dispatchEvent(event);
var m = parseNodeUrl(ssrurl);
console.log(m.search);
var password = m.passwd;
if (password === "") {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>";
return false;
}
opt.set('uuid', password);
opt.set('server', m.hostname);
opt.set('server_port', m.port || "443");
var queryParam = {};
if (m.search.length > 1) {
var query = m.search.split('?');
var queryParams = query[1];
var queryArray = queryParams.split('&');
var params;
for (i = 0; i < queryArray.length; i++) {
params = queryArray[i].split('=');
queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || '');
}
}
opt.set('encryption', queryParam.encryption);
if (queryParam.security) {
if (queryParam.security == "tls" || queryParam.security == "xtls") {
if (queryParam.security == "tls") {
opt.set('tls', true);
opt.get('tls').dispatchEvent(event);
}
if (queryParam.security == "xtls") {
opt.set('xtls', true);
opt.get('xtls').dispatchEvent(event);
opt.set('vless_flow', queryParam.flow || "xtls-rprx-direct");
}
opt.set('tls_host', queryParam.sni || '');
opt.set('insecure', true);
if (queryParam.allowinsecure === '0') {
opt.set('insecure', false);
}
opt.get('insecure').dispatchEvent(event);
}
}
queryParam.type = queryParam.type.toLowerCase();
if (queryParam.type === "kcp" || queryParam.type === "mkcp")
queryParam.type = "mkcp"
opt.set('transport', queryParam.type);
opt.get('transport').dispatchEvent(event);
if (queryParam.type === "tcp") {
opt.set('tcp_guise', queryParam.headerType || "none");
opt.get('tcp_guise').dispatchEvent(event);
if (queryParam.headerType && queryParam.headerType != "none") {
opt.set('http_host', queryParam.host || "");
opt.set('http_path', queryParam.path || "");
}
} else if (queryParam.type === "ws") {
opt.set('ws_host', queryParam.host || "");
opt.set('ws_path', queryParam.path || "");
} else if (queryParam.type === "h2") {
opt.set('h2_host', queryParam.host || "");
opt.set('h2_path', queryParam.path || "");
} else if (queryParam.type === "quic") {
opt.set('quic_guise', queryParam.headerType || "none");
opt.get('quic_guise').dispatchEvent(event);
opt.set('quic_security', queryParam.quicSecurity);
opt.set('quic_key', queryParam.key);
} else if (queryParam.type === "kcp" || queryParam.type === "mkcp") {
opt.set('kcp_guise', queryParam.headerType || "none");
opt.get('kcp_guise').dispatchEvent(event);
} else if (queryParam.type === "grpc") {
opt.set('grpc_serviceName', (queryParam.serviceName || queryParam.path) || "");
}
if (m.hash) {
opt.set('alias', decodeURI(m.hash.substr(1)));
}
} else {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>: " + ssu[0];
return false;
}
s.innerHTML = "<font color='green'><%:Import Finished %></font>";
return false;
}
//]]></script>
<input type="button" class="btn cbi-button cbi-button-apply" value='<%:From Share URL%>' onclick="return fromUrl(this, '<%=self.option%>', '<%=self.value%>')" />
<input type="button" class="btn cbi-button cbi-button-apply" value='<%:Build Share URL%>' onclick="return buildUrl(this, '<%=self.option%>', '<%=self.value%>')" />
<span id="<%=self.option%>-status"></span>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,366 @@
<%+cbi/valueheader%>
<script type="text/javascript">
//<![CDATA[
function padright(str, cnt, pad) {
return str + Array(cnt + 1).join(pad);
}
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
function b64encutf8safe(str) {
return b64EncodeUnicode(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '');
}
function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
function b64decutf8safe(str) {
var l;
str = str.replace(/-/g, "+").replace(/_/g, "/");
l = str.length;
l = (4 - l % 4) % 4;
if (l) str = padright(str, l, "=");
return b64DecodeUnicode(str);
}
function b64encsafe(str) {
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '')
}
function b64decsafe(str) {
var l;
str = str.replace(/-/g, "+").replace(/_/g, "/");
l = str.length;
l = (4 - l % 4) % 4;
if (l) str = padright(str, l, "=");
return atob(str);
}
function dictvalue(d, key) {
var v = d[key];
if (typeof (v) == 'undefined' || v == '') return '';
return b64decsafe(v);
}
function export_ssr_url(btn, urlname, sid) {
var s = document.getElementById(urlname + '-status');
if (!s) return false;
var v_server = document.getElementsByName('cbid.bypass.' + sid + '.server')[0];
var v_port = document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0];
var v_protocol = document.getElementsByName('cbid.bypass.' + sid + '.protocol')[0];
var v_method = document.getElementsByName('cbid.bypass.' + sid + '.encrypt_method')[0];
var v_obfs = document.getElementsByName('cbid.bypass.' + sid + '.obfs')[0];
var v_password = document.getElementsByName('cbid.bypass.' + sid + '.password')[0];
var v_obfs_param = document.getElementsByName('cbid.bypass.' + sid + '.obfs_param')[0];
var v_protocol_param = document.getElementsByName('cbid.bypass.' + sid + '.protocol_param')[0];
var v_alias = document.getElementsByName('cbid.bypass.' + sid + '.alias')[0];
var ssr_str = v_server.value + ":" + v_port.value + ":" + v_protocol.value + ":" + v_method.value + ":" + v_obfs.value + ":" + b64encsafe(v_password.value) + "/?obfsparam=" + b64encsafe(v_obfs_param.value) + "&protoparam=" + b64encsafe(v_protocol_param.value) + "&remarks=" + b64encutf8safe(v_alias.value);
var textarea = document.createElement("textarea");
textarea.textContent = "ssr://" + b64encsafe(ssr_str);
textarea.style.position = "fixed";
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand("copy"); // Security exception may be thrown by some browsers.
s.innerHTML = "<font color='green'><%:Copy SSR to clipboard successfully.%></font>";
} catch (ex) {
s.innerHTML = "<font color='red'><%:Unable to copy SSR to clipboard.%></font>";
} finally {
document.body.removeChild(textarea);
}
return false;
}
function import_ssr_url(btn, urlname, sid) {
var s = document.getElementById(urlname + '-status');
if (!s) return false;
var ssrurl = prompt("<%:Paste sharing link here%>", "");
if (ssrurl == null || ssrurl == "") {
s.innerHTML = "<font color='red'><%:User cancelled.%></font>";
return false;
}
s.innerHTML = "";
//var ssu = ssrurl.match(/ssr:\/\/([A-Za-z0-9_-]+)/i);
var ssu = ssrurl.split('://');
//console.log(ssu.length);
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
switch (ssu[0]) {
case "ss":
var url0, param = "";
var sipIndex = ssu[1].indexOf("@");
var ploc = ssu[1].indexOf("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = ssu[1].substr(ploc + 1);
} else {
url0 = ssu[1];
}
if (sipIndex != -1) {
// SIP002
var userInfo = b64decsafe(url0.substr(0, sipIndex));
var temp = url0.substr(sipIndex + 1).split("/?");
var serverInfo = temp[0].split(":");
var server = serverInfo[0];
var port = serverInfo[1].replace("/","");
var method, password, plugin, pluginOpts;
if (temp[1]) {
var pluginInfo = decodeURIComponent(temp[1]);
var pluginIndex = pluginInfo.indexOf(";");
var pluginNameInfo = pluginInfo.substr(0, pluginIndex);
plugin = pluginNameInfo.substr(pluginNameInfo.indexOf("=") + 1);
pluginOpts = pluginInfo.substr(pluginIndex + 1);
}
var userInfoSplitIndex = userInfo.indexOf(":");
if (userInfoSplitIndex != -1) {
method = userInfo.substr(0, userInfoSplitIndex);
password = userInfo.substr(userInfoSplitIndex + 1);
}
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].value = ssu[0];
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.server')[0].value = server;
document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0].value = port;
document.getElementsByName('cbid.bypass.' + sid + '.password')[0].value = password || "";
document.getElementsByName('cbid.bypass.' + sid + '.encrypt_method_ss')[0].value = method || "";
document.getElementsByName('cbid.bypass.' + sid + '.plugin')[0].value = plugin || "none";
document.getElementsByName('cbid.bypass.' + sid + '.plugin')[0].dispatchEvent(event);
if (plugin != undefined) {
document.getElementsByName('cbid.bypass.' + sid + '.plugin_opts')[0].value = pluginOpts || "";
}
if (param != undefined) {
document.getElementsByName('cbid.bypass.' + sid + '.alias')[0].value = decodeURI(param);
}
s.innerHTML = "<font color='green'><%:Import configuration information successfully.%></font>";
} else {
var sstr = b64decsafe(url0);
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].value = ssu[0];
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].dispatchEvent(event);
var team = sstr.split('@');
var part1 = team[0].split(':');
var part2 = team[1].split(':');
document.getElementsByName('cbid.bypass.' + sid + '.server')[0].value = part2[0];
document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0].value = part2[1];
document.getElementsByName('cbid.bypass.' + sid + '.password')[0].value = part1[1];
document.getElementsByName('cbid.bypass.' + sid + '.encrypt_method_ss')[0].value = part1[0];
if (param != undefined) {
document.getElementsByName('cbid.bypass.' + sid + '.alias')[0].value = decodeURI(param);
}
s.innerHTML = "<font color='green'><%:Import configuration information successfully.%></font>";
}
return false;
case "ssr":
var sstr = b64decsafe(ssu[1]);
var ploc = sstr.indexOf("/?");
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].value = ssu[0];
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
}
var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
if (!ssm || ssm.length < 7) return false;
var pdict = {};
if (param.length > 2) {
var a = param.split('&');
for (var i = 0; i < a.length; i++) {
var b = a[i].split('=');
pdict[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
}
}
document.getElementsByName('cbid.bypass.' + sid + '.server')[0].value = ssm[1];
document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0].value = ssm[2];
document.getElementsByName('cbid.bypass.' + sid + '.protocol')[0].value = ssm[3];
document.getElementsByName('cbid.bypass.' + sid + '.encrypt_method')[0].value = ssm[4];
document.getElementsByName('cbid.bypass.' + sid + '.obfs')[0].value = ssm[5];
document.getElementsByName('cbid.bypass.' + sid + '.password')[0].value = b64decsafe(ssm[6]);
document.getElementsByName('cbid.bypass.' + sid + '.obfs_param')[0].value = dictvalue(pdict, 'obfsparam');
document.getElementsByName('cbid.bypass.' + sid + '.protocol_param')[0].value = dictvalue(pdict, 'protoparam');
var rem = pdict['remarks'];
if (typeof (rem) != 'undefined' && rem != '' && rem.length > 0) document.getElementsByName('cbid.bypass.' + sid + '.alias')[0].value = b64decutf8safe(rem);
s.innerHTML = "<font color='green'><%:Import configuration information successfully.%></font>";
return false;
case "trojan":
var url0, param = "";
var ploc = ssu[1].indexOf("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = ssu[1].substr(ploc + 1);
} else {
url0 = ssu[1]
}
var sstr = url0;
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].value = "v2ray";
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.v2ray_protocol')[0].value = "trojan";
document.getElementsByName('cbid.bypass.' + sid + '.v2ray_protocol')[0].dispatchEvent(event);
var team = sstr.split('@');
var password = team[0]
var serverPart = team[1].split(':');
var others = serverPart[1].split('?');
var port = parseInt(others[0]);
var queryParam = {}
if (others.length > 1) {
var queryParams = others[1]
var queryArray = queryParams.split('&');
for (i = 0; i < queryArray.length; i++) {
var params = queryArray[i].split('=');
queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || '');
}
}
document.getElementsByName('cbid.bypass.' + sid + '.server')[0].value = serverPart[0];
document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0].value = port || '443';
document.getElementsByName('cbid.bypass.' + sid + '.password')[0].value = password;
document.getElementsByName('cbid.bypass.' + sid + '.tls')[0].checked = true;
document.getElementsByName('cbid.bypass.' + sid + '.tls')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.tls_host')[0].value = queryParam.sni || '';
if (param != undefined) {
document.getElementsByName('cbid.bypass.' + sid + '.alias')[0].value = decodeURI(param);
}
s.innerHTML = "<font color='green'><%:Import configuration information successfully.%></font>";
return false;
case "vmess":
var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?");
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].value = "v2ray";
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.v2ray_protocol')[0].value = "vmess";
document.getElementsByName('cbid.bypass.' + sid + '.v2ray_protocol')[0].dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
}
var ssm = JSON.parse(sstr);
document.getElementsByName('cbid.bypass.' + sid + '.alias')[0].value = ssm.ps;
document.getElementsByName('cbid.bypass.' + sid + '.server')[0].value = ssm.add;
document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0].value = ssm.port;
document.getElementsByName('cbid.bypass.' + sid + '.vmess_id')[0].value = ssm.id;
document.getElementsByName('cbid.bypass.' + sid + '.transport')[0].value = ssm.net;
document.getElementsByName('cbid.bypass.' + sid + '.transport')[0].dispatchEvent(event);
if (ssm.net == "tcp") {
if (ssm.type && ssm.type != "http") {
ssm.type = "none"
}
document.getElementsByName('cbid.bypass.' + sid + '.tcp_guise')[0].value = ssm.type;
document.getElementsByName('cbid.bypass.' + sid + '.tcp_guise')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.http_host')[0].value = ssm.host;
document.getElementsByName('cbid.bypass.' + sid + '.http_path')[0].value = ssm.path;
}
if (ssm.net == "ws") {
document.getElementsByName('cbid.bypass.' + sid + '.ws_host')[0].value = ssm.host;
document.getElementsByName('cbid.bypass.' + sid + '.ws_path')[0].value = ssm.path;
}
if (ssm.net == "h2") {
document.getElementsByName('cbid.bypass.' + sid + '.h2_host')[0].value = ssm.host;
document.getElementsByName('cbid.bypass.' + sid + '.h2_path')[0].value = ssm.path;
}
if (ssm.net == "quic") {
document.getElementsByName('cbid.bypass.' + sid + '.quic_security')[0].value = ssm.securty;
document.getElementsByName('cbid.bypass.' + sid + '.quic_key')[0].value = ssm.key;
}
if (ssm.net == "kcp") {
document.getElementsByName('cbid.bypass.' + sid + '.kcp_guise')[0].value = ssm.type;
}
if (ssm.tls == "tls") {
document.getElementsByName('cbid.bypass.' + sid + '.tls')[0].checked = true;
document.getElementsByName('cbid.bypass.' + sid + '.tls')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.tls_host')[0].value = ssm.host;
}
document.getElementsByName('cbid.bypass.' + sid + '.mux')[0].checked = true;
document.getElementsByName('cbid.bypass.' + sid + '.mux')[0].dispatchEvent(event);
s.innerHTML = "<font color='green'><%:Import configuration information successfully.%></font>";
return false;
case "vless":
var url0, param = "";
var ploc = ssu[1].indexOf("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = decodeURIComponent(ssu[1].substr(ploc + 1));
} else {
url0 = ssu[1]
}
var sstr = url0;
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].value = "v2ray";
document.getElementsByName('cbid.bypass.' + sid + '.type')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.v2ray_protocol')[0].value = "vless";
document.getElementsByName('cbid.bypass.' + sid + '.v2ray_protocol')[0].dispatchEvent(event);
var team = sstr.split('@');
var uuid = team[0]
var serverPart = team[1].split(':');
var others = serverPart[1].split('?');
var port = others[0]
var queryParam = {}
if (others.length > 1) {
var queryParams = others[1]
var queryArray = queryParams.split('&');
for (i = 0; i < queryArray.length; i++) {
var params = queryArray[i].split('=');
queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || '');
}
}
document.getElementsByName('cbid.bypass.' + sid + '.server')[0].value = serverPart[0];
document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0].value = port;
document.getElementsByName('cbid.bypass.' + sid + '.vmess_id')[0].value = uuid;
document.getElementsByName('cbid.bypass.' + sid + '.transport')[0].value = queryParam.type ? (queryParam.type == "http" ? "h2" : queryParam.type) : "tcp";
document.getElementsByName('cbid.bypass.' + sid + '.transport')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.vless_encryption')[0].value = queryParam.encryption || "none";
if (queryParam.security == "tls") {
document.getElementsByName('cbid.bypass.' + sid + '.tls')[0].checked = true;
document.getElementsByName('cbid.bypass.' + sid + '.tls')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.tls_host')[0].value = queryParam.sni || serverPart[0];
}
switch (queryParam.type) {
case "ws":
//document.getElementsByName('cbid.bypass.' + sid + '.ws_host')[0].value = queryParam.host;
document.getElementsByName('cbid.bypass.' + sid + '.ws_path')[0].value = queryParam.path || "/";
break;
case "kcp":
document.getElementsByName('cbid.bypass.' + sid + '.kcp_guise')[0].value = queryParam.headerType || "none";
document.getElementsByName('cbid.bypass.' + sid + '.kcp_guise')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.seed')[0].value = queryParam.seed;
break;
case "http":
document.getElementsByName('cbid.bypass.' + sid + '.h2_host')[0].value = queryParam.host || serverPart[0];
document.getElementsByName('cbid.bypass.' + sid + '.h2_path')[0].value = queryParam.path || "/";
break;
case "quic":
document.getElementsByName('cbid.bypass.' + sid + '.quic_guise')[0].value = queryParam.headerType || "none";
document.getElementsByName('cbid.bypass.' + sid + '.quic_guise')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.quic_security')[0].value = queryParam.quicSecurity || "none";
document.getElementsByName('cbid.bypass.' + sid + '.quic_key')[0].value = queryParam.key;
break;
case "grpc":
document.getElementsByName('cbid.bypass.' + sid + '.serviceName')[0].value = queryParam.serviceName;
break;
default:
if (queryParam.security == "xtls") {
document.getElementsByName('cbid.bypass.' + sid + '.xtls')[0].checked = true;
document.getElementsByName('cbid.bypass.' + sid + '.xtls')[0].dispatchEvent(event);
document.getElementsByName('cbid.bypass.' + sid + '.vless_flow')[0].value = queryParam.flow || "xtls-rprx-splice";
document.getElementsByName('cbid.bypass.' + sid + '.tls_host')[0].value = queryParam.sni || serverPart[0];
}
break;
}
if (param != undefined) {
document.getElementsByName('cbid.bypass.' + sid + '.alias')[0].value = decodeURI(param);
}
s.innerHTML = "<font color='green'><%:Import configuration information successfully.%></font>";
return false;
default:
s.innerHTML = "<font color='red'><%:Invalid format.%></font>";
return false;
}
}
//]]>
</script>
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:Import%>" onclick="return import_ssr_url(this, '<%=self.option%>', '<%=self.value%>')" />
<span id="<%=self.option%>-status"></span>
<%+cbi/valuefooter%>

View File

@ -1,172 +0,0 @@
<%
local trojan_go_version = require "luci.model.cbi.bypass.api".get_trojan_go_version()
-%>
<script type="text/javascript">
//<![CDATA[
var trojanInfo;
var tokenStr = '<%=token%>';
var manuallyUpdateText = '<%:Check update%>';
var noUpdateText = '<%:It is the latest version%>';
var updateSuccessText = '<%:Update successful%>';
var clickToUpdateText = '<%:Click to update%>';
var inProgressText = '<%:Updating...%>';
var unexpectedErrorText = '<%:Unexpected error%>';
var updateInProgressNotice = '<%:Updating, are you sure to close?%>';
var downloadingText = '<%:Downloading...%>';
var decompressioningText = '<%:Unpacking...%>';
var movingText = '<%:Moving...%>';
window.onload = function() {
var trojanCheckBtn = document.getElementById('_trojan-check_btn');
var trojanDetailElm = document.getElementById('_trojan-check_btn-detail');
};
function addPageNotice_trojan() {
window.onbeforeunload = function(e) {
e.returnValue = updateInProgressNotice;
return updateInProgressNotice;
};
}
function removePageNotice_trojan() {
window.onbeforeunload = undefined;
}
function onUpdateSuccess_trojan(btn) {
alert(updateSuccessText);
if(btn) {
btn.value = updateSuccessText;
btn.placeholder = updateSuccessText;
btn.disabled = true;
}
window.setTimeout(function() {
window.location.reload();
}, 1000);
}
function onRequestError_trojan(btn, errorMessage) {
btn.disabled = false;
btn.value = manuallyUpdateText;
if(errorMessage) {
alert(errorMessage);
}
}
function onBtnClick_trojan(btn) {
if(trojanInfo === undefined) {
checkUpdate_trojan(btn);
} else {
doUpdate_trojan(btn);
}
}
function checkUpdate_trojan(btn) {
btn.disabled = true;
btn.value = inProgressText;
addPageNotice_trojan();
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=url([[admin]], [[services]], [[bypass]], [[trojan_go_check]])%>', {
token: tokenStr,
arch: ''
}, function(x,json) {
removePageNotice_trojan();
if(json.code) {
trojanInfo = undefined;
onRequestError_trojan(btn, json.error);
} else {
if(json.update) {
trojanInfo = json;
btn.disabled = false;
btn.value = clickToUpdateText;
btn.placeholder = clickToUpdateText;
if(ckeckDetailElm) {
var urlNode = '';
if(json.version) {
urlNode = '<em style="color:red;">最新版本号:' + json.version + '</em>';
if(json.url && json.url.html) {
urlNode = '<a href="' + json.url.html + '" target="_blank">' + urlNode + '</a>';
}
}
ckeckDetailElm.innerHTML = urlNode;
}
} else {
btn.disabled = true;
btn.value = noUpdateText;
}
}
},300);
}
function doUpdate_trojan(btn) {
btn.disabled = true;
btn.value = downloadingText;
addPageNotice_trojan();
var trojanUpdateUrl = '<%=url([[admin]], [[services]], [[bypass]], [[trojan_go_update]])%>';
// Download file
XHR.get(trojanUpdateUrl, {
token: tokenStr,
url: trojanInfo ? trojanInfo.url.download : ''
}, function(x,json) {
if(json.code) {
removePageNotice_trojan();
onRequestError_trojan(btn, json.error);
} else {
btn.value = decompressioningText;
// Extract file
XHR.get(trojanUpdateUrl, {
token: tokenStr,
task: 'extract',
file: json.file,
subfix: trojanInfo ? trojanInfo.type : ''
}, function(x,json) {
if(json.code) {
removePageNotice_trojan();
onRequestError_trojan(btn, json.error);
} else {
btn.value = movingText;
// Move file to target dir
XHR.get(trojanUpdateUrl, {
token: tokenStr,
task: 'move',
file: json.file
}, function(x,json) {
removePageNotice_trojan();
if(json.code) {
onRequestError_trojan(btn, json.error);
} else {
onUpdateSuccess_trojan(btn);
}
},300)
}
},300)
}
},300)
}
//]]>
</script>
<div class="cbi-value">
<label class="cbi-value-title">Trojan-Go
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<span><%=trojan_go_version%> 】</span>
<input class="cbi-button cbi-input-apply" type="button" id="_trojan-check_btn" onclick="onBtnClick_trojan(this);" value="<%:Check update%>" />
<span id="_trojan-check_btn-detail"></span>
</div>
</div>
</div>

View File

@ -4,8 +4,8 @@ msgstr "基本设置"
msgid "Bypass Settings"
msgstr "Bypass 设置"
msgid "Support SS/SSR/XRAY/TROJAN/TROJAN-GO/NAIVEPROXY/SOCKS5/TUN etc."
msgstr "支持 SS/SSR/Xray/Trojan/Trojan-Go/NavieProxy/Socks5/TUN 等协议"
msgid "Support SS/SSR/XRAY/TROJAN/NAIVEPROXY/SOCKS5/TUN etc."
msgstr "支持 SS/SSR/Xray/Trojan/NavieProxy/Socks5/TUN 等协议"
msgid "Bypass RUNNING"
msgstr "Bypass 客户端运行中"
@ -304,13 +304,28 @@ msgstr "插件参数"
msgid "Protocol"
msgstr "传输协议"
msgid "Protocol param(optional)"
msgid "Protocol param (optional)"
msgstr "传输协议参数(可选)"
msgid "Authentication type"
msgstr "验证类型"
msgid "Authentication payload"
msgstr "验证载荷"
msgid "QUIC connection receive window"
msgstr "QUIC 连接接收窗口"
msgid "QUIC stream receive window"
msgstr "QUIC 流接收窗口"
msgid "Disable Path MTU discovery"
msgstr "禁用 MTU 探测"
msgid "Obfs"
msgstr "混淆插件"
msgid "Obfs param(optional)"
msgid "Obfs param (optional)"
msgstr "混淆参数(可选)"
msgid "VLESS Encryption"
@ -722,4 +737,5 @@ msgid "Used with AdGuardHome"
msgstr "与AdGuardHome搭配使用"
msgid "Luci-app-adguardhome require"
msgstr "请确保luci-app-adguardhome能正常启用,本插件会联动开启并配置ADG,ADG无需任何设置"
msgstr "请确保luci-app-adguardhome能正常启用,本插件会联动开启并配置ADG,ADG无需任何设置"

View File

@ -72,9 +72,9 @@ f_bin(){
ssr) ret=$(which ssr-redir);;
ssr-local) ret=$(which ssr-local);;
ssr-server) ret=$(which ssr-server);;
vmess|vless) ret=$(which xray);;
v2ray) ret=$(which xray);;
hysteria) ret=$(which hysteria);;
trojan) ret=$(which trojan-plus);;
trojan-go) ret=$(which trojan-go);;
naiveproxy) ret=$(which naive);;
socks5|tun) ret=$(which redsocks2);;
esac
@ -150,13 +150,13 @@ gen_config_file(){
}
EOF
;;
vmess|vless)
v2ray|hysteria)
[ $rtype = udp ] && smode=udp || smode=tcp
[ $rtype = socks ] && lport=0
lua $BIN_DIR/genv2config $1 $smode $lport $ssport $serv_ip >$config_file
lua $BIN_DIR/gen_config $1 $smode $lport $ssport $serv_ip >$config_file
sed -i 's/\\//g' $config_file
;;
trojan|trojan-go)
trojan)
case $rtype in
tcp|udp|nf) smode=nat;;
socks) smode=client;;
@ -397,7 +397,7 @@ start_retcp(){
[ $ttype = ss ] && name=Shadowsocks || name=ShadowsocksR
log "Main Node: $name $threads Threads Started!"
;;
vmess|vless)
v2ray|hysteria)
if [ $SO_SERVER = $GLOBAL_SERVER ];then
port=$(uci_get_by_type socks5_proxy local_port 1080)
socks5_start=1
@ -412,20 +412,14 @@ start_retcp(){
log "Socks5 Node: $($cmd -version | head -1 | awk '{print$1,$2}') Started!"
fi
;;
trojan|trojan-go)
trojan)
gen_config_file $GLOBAL_SERVER $rtype "" $server
if [ $type = trojan ];then
redir_tcp=$threads
for i in $(seq 1 $threads);do
$cmd --config $config_file >$log_file 2>&1 &
done
name=Trojan-Plus
ver="$($cmd --version 2>&1 | head -1 | awk '{print$3}')"
else
redir_tcp=$threads
for i in $(seq 1 $threads);do
$cmd --config $config_file >$log_file 2>&1 &
name=Trojan-Go
ver="$($cmd --version 2>&1 | head -1 | awk '{print$2}')"
fi
done
name=Trojan-Plus
ver="$($cmd --version 2>&1 | head -1 | awk '{print$3}')"
log "Main Node: $name (Ver $ver) $threads Threads Started!"
;;
naiveproxy)
@ -468,21 +462,16 @@ start_reudp(){
[ $utype = ss ] && name=Shadowsocks || name=ShadowsocksR
log "UDP Relay: $name Started!"
;;
vmess|vless)
v2ray|hysteria)
gen_config_file $UDP_RELAY_SERVER $rtype 0 $udp_server
$cmd -c $config_file >$log_file 2>&1 &
log "UDP Relay: $($cmd -version | head -1 | awk '{print$1,$2}') Started!"
;;
trojan|trojan-go)
trojan)
gen_config_file $UDP_RELAY_SERVER $rtype "" $udp_server
$cmd --config $config_file >$log_file 2>&1 &
[ $utype = trojan ] && {
name=Trojan-Plus
ver="$($cmd --version 2>&1 | head -1 | awk '{print$3}')"
} || {
name=Trojan-Go
ver="$($cmd --version 2>&1 | head -1 | awk '{print$2}')"
}
name=Trojan-Plus
ver="$($cmd --version 2>&1 | head -1 | awk '{print$3}')"
log "UDP Relay: $name (Ver $ver) Started!"
;;
naiveproxy)
@ -518,20 +507,17 @@ start_renf(){
[ $ntype = ss ] && name=Shadowsocks || name=ShadowsocksR
log "NF Shunt : $name Started!"
;;
vmess|vless)
v2ray|hysteria)
gen_config_file $NF_SERVER $rtype 0 $nf_ip
$cmd -c $config_file >$log_file 2>&1 &
log "NF Shunt : $($cmd -version | head -1 | awk '{print$1,$2}') Started!"
;;
trojan|trojan-go)
trojan)
gen_config_file $NF_SERVER $rtype "" $nf_ip
$cmd --config $config_file >$log_file 2>&1 &
[ $ntype = trojan ] && {
name=Trojan-Plus
ver="$($cmd --version 2>&1 | head -1 | awk '{print$3}')"
} || {
name=Trojan-Go
ver="$($cmd --version 2>&1 | head -1 | awk '{print$2}')"
}
log "NF Shunt : $name (Ver $ver) Started!"
;;
@ -572,20 +558,17 @@ start_local(){
[ $type = ss ] && name=Shadowsocks || name=ShadowsocksR
log "Socks5 Node: $name Started!"
;;
vmess|vless)
v2ray|hysteria)
gen_config_file $SO_SERVER $rtype $socks5_port $socks5_ip
$cmd -c $config_file >$log_file 2>&1 &
log "Socks5 Node: $($cmd -version | head -1 | awk '{print$1,$2}') Started!"
;;
trojan|trojan-go)
trojan)
gen_config_file $SO_SERVER $rtype "" $socks5_ip
$cmd --config $config_file >$log_file 2>&1 &
[ $type = trojan ] && {
name=Trojan-Plus
ver="$($cmd --version 2>&1 | head -1 | awk '{print$3}')"
} || {
name=Trojan-Go
ver="$($cmd --version 2>&1 | head -1 | awk '{print$2}')"
}
log "Socks5 Node: $name (Ver $ver) Started!"
;;

View File

@ -12,5 +12,16 @@ uci batch <<EOF
chmod +x /etc/init.d/bypass /usr/share/bypass/* >/dev/null 2>&1
rm -rf /tmp/luci-modulecache/
killall -HUP rpcd 2>/dev/null
exit 0
EOF
if [[ "$(grep "option type 'vless'" /etc/config/bypass)" || "$(grep "option type 'vmess'" /etc/config/bypass)" ]]; then
sed -i "s/option uuid/option vmess_id/" /etc/config/bypass
for i in {1..100}
do
uci -q set bypass.@servers[$i].type='v2ray'
[ "$(uci -q get bypass.@servers[$i].type)" == 'vless' ] && uci -q set bypass.@servers[$i].v2ray_protocol='vless' || uci -q set bypass.@servers[$i].v2ray_protocol='vmess'
done
uci commit bypass
fi
exit 0

View File

@ -33,9 +33,8 @@ f_bin(){
case $1 in
ss)w=$(which ss-local);;
ssr)w=$(which ssr-local);;
vmess|vless)w=$(which xray);;
v2ray)w=$(which xray);;
trojan)w=$(which trojan-plus);;
trojan-go)w=$(which trojan-go);;
naiveproxy)w=$(which naive);;
esac
echo ${w:=0}
@ -123,11 +122,11 @@ curl_check(){
case $type in
ss|ssr)
$cmd -c $J >/dev/null 2>&1 &;;
vmess|vless)
v2ray)
$S/genv2config $1 tcp 0 $lport $ip > $J
sed -i 's/\\//g' $J
$cmd -c $J >/dev/null 2>&1 &;;
trojan|trojan-go)
trojan)
$S/gentrojanconfig $1 client $lport $ip > $J
sed -i 's/\\//g' $J
$cmd --config $J >/dev/null 2>&1 &;;

View File

@ -0,0 +1,369 @@
#!/usr/bin/lua
local ucursor = require "luci.model.uci".cursor()
local json = require "luci.jsonc"
local server_section = arg[1]
local proto = arg[2]
local local_port = arg[3] or "0"
local socks_port = arg[4] or "0"
local ip_addr = arg[5]
local server = ucursor:get_all("bypass", server_section)
local outbound_settings = nil
local tls_host = (server.tls_host) and server.tls_host or server.server
function vmess_vless()
outbound_settings = {
vnext = {
{
address = ip_addr,
port = tonumber(server.server_port),
users = {
{
id = server.vmess_id,
security = (server.v2ray_protocol == "vmess" or not server.v2ray_protocol) and server.security or nil,
encryption = (server.v2ray_protocol == "vless") and server.vless_encryption or nil,
flow = (server.xtls == '1') and (server.vless_flow and server.vless_flow or "xtls-rprx-splice") or nil
}
}
}
},
packetEncoding = server.packet_encoding or nil
}
end
function trojan_shadowsocks()
outbound_settings = {
plugin = ((server.v2ray_protocol == "shadowsocks") and server.plugin ~= "none" and server.plugin) or (server.v2ray_protocol == "shadowsocksr" and "shadowsocksr") or nil,
pluginOpts = (server.v2ray_protocol == "shadowsocks") and server.plugin_opts or nil,
pluginArgs = (server.v2ray_protocol == "shadowsocksr") and {
"--protocol=" .. server.protocol,
"--protocol-param=" .. (server.protocol_param or ""),
"--obfs=" .. server.obfs,
"--obfs-param=" .. (server.obfs_param or "")
} or nil,
servers = {
{
address = ip_addr,
port = tonumber(server.server_port),
password = server.password,
method = ((server.v2ray_protocol == "shadowsocks") and server.encrypt_method_ss) or ((server.v2ray_protocol == "shadowsocksr") and server.encrypt_method) or nil,
uot = (server.v2ray_protocol == "shadowsocks") and (server.uot == '1') or nil,
ivCheck = (server.v2ray_protocol == "shadowsocks") and (server.ivCheck == '1') or nil,
flow = (server.v2ray_protocol == "trojan") and (server.xtls == '1') and (server.vless_flow and server.vless_flow or "xtls-rprx-splice") or nil
}
}
}
if server.v2ray_protocol == "shadowsocksr" then
server.v2ray_protocol = "shadowsocks"
--[[ elseif (server.v2ray_protocol == "shadowsocks") and (server.mux ~= "1") and (not (outbound_settings.plugin or server.transport ~= "tcp" or server.tls or server.xtls)) then
server.v2ray_protocol = "shadowsocks_sing"
outbound_settings = outbound_settings.servers[1]
elseif (server.v2ray_protocol == "trojan") and (server.tls and server.mux ~= "1") and (not (server.transport ~= "tcp" or server.xtls)) then
server.v2ray_protocol = "trojan_sing"
outbound_settings = outbound_settings.servers[1]
outbound_settings.serverName = tls_host
outbound_settings.insecure = (server.insecure == "1") and true or false
]]
end
end
function socks_http()
outbound_settings = {
version = server.socks_ver or nil,
servers = {
{
address = ip_addr,
port = tonumber(server.server_port),
users = (server.auth_enable == "1") and {
{
user = server.username,
pass = server.password
}
} or nil
}
}
}
end
function wireguard()
outbound_settings = {
address = ip_addr,
port = tonumber(server.server_port),
localAddresses = server.local_addresses,
privateKey = server.private_key,
peerPublicKey = server.peer_pubkey,
preSharedKey = server.preshared_key or nil,
mtu = tonumber(server.mtu) or 1500
}
end
local outbound = {}
function outbound:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function outbound:handleIndex(index)
local switch = {
vmess = function()
vmess_vless()
end,
vless = function()
vmess_vless()
end,
trojan = function()
trojan_shadowsocks()
end,
shadowsocks = function()
trojan_shadowsocks()
end,
shadowsocksr = function()
trojan_shadowsocks()
end,
socks = function()
socks_http()
end,
http = function()
socks_http()
end,
wireguard = function()
wireguard()
end
}
if switch[index] then
switch[index]()
end
end
local settings = outbound:new()
settings:handleIndex(server.v2ray_protocol)
local Xray = {
log = {
-- error = "/var/ssrplus.log",
loglevel = "warning"
},
-- 传入连接
inbound = (local_port ~= "0") and {
-- listening
port = tonumber(local_port),
protocol = "dokodemo-door",
settings = {network = proto, followRedirect = true},
sniffing = {enabled = true, destOverride = {"http", "tls"}}
} or nil,
-- 开启 socks 代理
inboundDetour = (proto:find("tcp") and socks_port ~= "0") and {
{
-- socks
protocol = "socks",
port = tonumber(socks_port),
settings = {auth = "noauth", udp = true}
}
} or nil,
-- 传出连接
outbound = {
protocol = server.v2ray_protocol,
settings = outbound_settings,
-- 底层传输配置
streamSettings = (server.v2ray_protocol and server.v2ray_protocol:sub(-#"_sing") ~= "_sing") and {
network = server.transport or "tcp",
security = (server.xtls == '1') and "xtls" or (server.tls == '1') and "tls" or nil,
tlsSettings = (server.tls == '1' and (server.insecure == "1" or tls_host or server.fingerprint)) and {
-- tls
fingerprint = server.fingerprint,
allowInsecure = (server.insecure == "1") and true or nil,
serverName = tls_host
} or nil,
xtlsSettings = (server.xtls == '1' and (server.insecure == "1" or tls_host)) and {
-- xtls
allowInsecure = (server.insecure == "1") and true or nil,
serverName = tls_host
} or nil,
tcpSettings = (server.transport == "tcp" and server.tcp_guise == "http") and {
-- tcp
header = {
type = server.tcp_guise,
request = {
-- request
path = {server.http_path} or {"/"},
headers = {Host = {server.http_host} or {}}
}
}
} or nil,
kcpSettings = (server.transport == "kcp") and {
mtu = tonumber(server.mtu),
tti = tonumber(server.tti),
uplinkCapacity = tonumber(server.uplink_capacity),
downlinkCapacity = tonumber(server.downlink_capacity),
congestion = (server.congestion == "1") and true or false,
readBufferSize = tonumber(server.read_buffer_size),
writeBufferSize = tonumber(server.write_buffer_size),
header = {type = server.kcp_guise},
seed = server.seed or nil
} or nil,
wsSettings = (server.transport == "ws") and (server.ws_path or server.ws_host or tls_host) and {
-- ws
headers = (server.ws_host or tls_host) and {
-- headers
Host = server.ws_host or tls_host
} or nil,
path = server.ws_path,
maxEarlyData = tonumber(server.ws_ed) or nil,
earlyDataHeaderName = server.ws_ed_header or nil
} or nil,
httpSettings = (server.transport == "h2") and {
-- h2
path = server.h2_path or "",
host = {server.h2_host} or nil,
read_idle_timeout = tonumber(server.read_idle_timeout) or nil,
health_check_timeout = tonumber(server.health_check_timeout) or nil
} or nil,
quicSettings = (server.transport == "quic") and {
-- quic
security = server.quic_security,
key = server.quic_key,
header = {type = server.quic_guise}
} or nil,
grpcSettings = (server.transport == "grpc") and {
-- grpc
serviceName = server.serviceName or "",
mode = (server.grpc_mode ~= "gun") and server.grpc_mode or nil,
multiMode = (server.grpc_mode == "multi") and true or false,
idle_timeout = tonumber(server.idle_timeout) or nil,
health_check_timeout = tonumber(server.health_check_timeout) or nil,
permit_without_stream = (server.permit_without_stream == "1") and true or nil,
initial_windows_size = tonumber(server.initial_windows_size) or nil
} or nil
} or nil,
mux = (server.mux == "1" and server.xtls ~= "1" and server.transport ~= "grpc") and {
-- mux
enabled = true,
concurrency = tonumber(server.concurrency),
packetEncoding = (server.v2ray_protocol == "vmess" or server.v2ray_protocol == "vless") and server.packet_encoding or nil
} or nil
} or nil
}
local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA"
local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"
local trojan = {
log_level = 3,
run_type = (proto == "nat" or proto == "tcp") and "nat" or "client",
local_addr = "0.0.0.0",
local_port = tonumber(local_port),
remote_addr = ip_addr,
remote_port = tonumber(server.server_port),
udp_timeout = 60,
-- 传入连接
password = {server.password},
-- 传出连接
ssl = {
verify = (server.insecure == "0") and true or false,
verify_hostname = (server.tls == "1") and true or false,
cert = (server.certificate) and server.certpath or nil,
cipher = cipher,
cipher_tls13 = cipher13,
sni = tls_host,
alpn = {"h2", "http/1.1"},
curve = "",
reuse_session = true,
session_ticket = (server.tls_sessionTicket == "1") and true or false
},
udp_timeout = 60,
tcp = {
-- tcp
no_delay = true,
keep_alive = true,
reuse_port = true,
fast_open = (server.fast_open == "1") and true or false,
fast_open_qlen = 20
}
}
local naiveproxy = {
proxy = (server.username and server.password and server.server and server.server_port) and "https://" .. server.username .. ":" .. server.password .. "@" .. ip_addr .. ":" .. server.server_port,
listen = (proto == "redir") and "redir" .. "://0.0.0.0:" .. tonumber(local_port) or "socks" .. "://0.0.0.0:" .. tonumber(local_port),
["insecure-concurrency"] = tonumber(server.concurrency) or 1
}
local ss = {
server = (server.kcp_enable == "1") and "127.0.0.1" or ip_addr,
server_port = tonumber(server.server_port),
local_address = "0.0.0.0",
local_port = tonumber(local_port),
mode = (proto == "tcp,udp") and "tcp_and_udp" or proto .. "_only",
password = server.password,
method = server.encrypt_method_ss,
timeout = tonumber(server.timeout),
fast_open = (server.fast_open == "1") and true or false,
reuse_port = true
}
local hysteria = {
server = ip_addr .. ":" .. server.server_port,
protocol = server.hysteria_protocol,
up_mbps = tonumber(server.uplink_capacity),
down_mbps = tonumber(server.downlink_capacity),
socks5 = (proto:find("tcp") and tonumber(socks_port) and tonumber(socks_port) ~= "0") and {
listen = "0.0.0.0:" .. tonumber(socks_port),
timeout = 300,
disable_udp = false
} or nil,
redirect_tcp = (proto:find("tcp") and local_port ~= "0") and {
listen = "0.0.0.0:" .. tonumber(local_port),
timeout = 300
} or nil,
tproxy_udp = (proto:find("udp") and local_port ~= "0") and {
listen = "0.0.0.0:" .. tonumber(local_port),
timeout = 60
} or nil,
obfs = server.seed,
auth = (server.auth_type == "1") and server.auth_payload or nil,
auth_str = (server.auth_type == "2") and server.auth_payload or nil,
alpn = server.quic_tls_alpn,
server_name = tls_host,
insecure = (server.insecure == "1") and true or false,
ca = (server.certificate) and server.certpath or nil,
recv_window_conn = tonumber(server.recv_window_conn),
recv_window = tonumber(server.recv_window),
disable_mtu_discovery = (server.disable_mtu_discovery == "1") and true or false
}
local config = {}
function config:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function config:handleIndex(index)
local switch = {
ss = function()
ss.protocol = socks_port
if server.plugin and server.plugin ~= "none" then
ss.plugin = server.plugin
ss.plugin_opts = server.plugin_opts or nil
end
print(json.stringify(ss, 1))
end,
ssr = function()
ss.protocol = server.protocol
ss.protocol_param = server.protocol_param
ss.method = server.encrypt_method
ss.obfs = server.obfs
ss.obfs_param = server.obfs_param
print(json.stringify(ss, 1))
end,
v2ray = function()
print(json.stringify(Xray, 1))
end,
trojan = function()
print(json.stringify(trojan, 1))
end,
naiveproxy = function()
print(json.stringify(naiveproxy, 1))
end,
hysteria = function()
print(json.stringify(hysteria, 1))
end
}
if switch[index] then
switch[index]()
end
end
local f = config:new()
f:handleIndex(server.type)

View File

@ -1,73 +0,0 @@
#!/usr/bin/lua
local ucursor = require "luci.model.uci".cursor()
local json = require "luci.jsonc"
local node_section = arg[1]
local run_type = arg[2]
local local_port = arg[3]
local ip_addr=arg[4]
local threads = tonumber(arg[5]) or 2
local node = ucursor:get_all("bypass", node_section)
local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA"
local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"
local trojan = {
run_type = run_type,
local_addr = "0.0.0.0",
local_port = tonumber(local_port),
remote_addr = ip_addr,
remote_port = tonumber(node.server_port),
password = {node.password},
log_level = 3,
ssl = {
verify = (node.insecure ~= "1") and true or false,
verify_hostname = true,
cert = "",
cipher = cipher,
cipher_tls13 = cipher13,
sni = node.tls_host or node.server,
alpn = {"h2", "http/1.1"},
reuse_session = true,
session_ticket = (node.tls_sessionTicket and node.tls_sessionTicket == "1") and true or false,
curves = ""
},
udp_timeout = 60,
mux = (node.mux == "1") and {
enabled = true,
concurrency = tonumber(node.concurrency),
idle_timeout = 60,
} or nil,
tcp = {
no_delay = true,
keep_alive = true,
reuse_port = (threads > 1) and true or false,
fast_open = (node.fast_open == "1") and true or false,
fast_open_qlen = 20
}
}
if node.type == "trojan-go" then
trojan.ssl.cipher = node.fingerprint == nil and cipher or (node.fingerprint == "disable" and cipher13 .. ":" .. cipher or "")
trojan.ssl.cipher_tls13 = node.fingerprint == nil and cipher13 or nil
trojan.ssl.fingerprint = (node.fingerprint ~= nil and node.fingerprint ~= "disable" ) and node.fingerprint or ""
trojan.ssl.alpn = node.trojan_transport == 'ws' and {} or {"h2", "http/1.1"}
if node.tls ~= "1" and node.trojan_transport == "original" then trojan.ssl = nil end
trojan.transport_plugin = node.tls ~= "1" and node.trojan_transport == "original" and {
enabled = node.plugin_type ~= nil,
type = node.plugin_type or "plaintext",
command = node.plugin_type ~= "plaintext" and node.plugin_cmd or nil,
option = node.plugin_type ~= "plaintext" and node.plugin_option or nil,
arg = node.plugin_type ~= "plaintext" and { node.plugin_arg } or nil,
env = {}
} or nil
trojan.websocket = node.trojan_transport and node.trojan_transport:find('ws') and {
enabled = true,
path = node.ws_path or "/",
host = node.ws_host or (node.tls_serverName or node.address)
} or nil
trojan.shadowsocks = (node.ss_aead == "1") and {
enabled = true,
method = node.ss_aead_method or "aead_aes_128_gcm",
password = node.ss_aead_pwd or ""
} or nil
end
print(json.stringify(trojan, 1))

View File

@ -1,123 +0,0 @@
#!/usr/bin/lua
local ucursor = require "luci.model.uci".cursor()
local json = require "luci.jsonc"
local server_section = arg[1]
local proto = arg[2]
local local_port = arg[3] or "0"
local socks_port = arg[4] or "0"
local ip_addr = arg[5]
local server = ucursor:get_all("bypass", server_section)
local Xray = {
log = {
-- error = "/var/bypass.log",
loglevel = "warning"
},
-- 传入连接
inbound = (local_port ~= "0") and {
port = tonumber(local_port),
protocol = "dokodemo-door",
settings = {
network = proto,
followRedirect = true
},
sniffing = {
enabled = true,
destOverride = { "http", "tls" }
}
} or nil,
-- 开启 socks 代理
inboundDetour = (proto == "tcp" and socks_port ~= "0") and {
{
protocol = "socks",
port = socks_port,
settings = {
auth = "noauth",
udp = true
}
}
} or nil,
-- 传出连接
outbound = {
protocol = server.type,
settings = {
vnext = {
{
address = ip_addr,
port = tonumber(server.server_port),
users = {
{
id = server.uuid,
alterId = (server.type == "vmess") and tonumber(server.alter_id) or nil,
security = (server.type == "vmess") and server.security or nil,
encryption = (server.type == "vless") and server.vless_encryption or nil,
flow = (server.xtls == '1') and (server.vless_flow and server.vless_flow or "xtls-rprx-splice") or nil,
}
}
}
}
},
-- 底层传输配置
streamSettings = {
network = server.transport,
security = (server.xtls == '1') and "xtls" or (server.tls == '1') and "tls" or "none",
tlsSettings = (server.tls == '1') and {
allowInsecure = (server.insecure == "1") and true or nil,
serverName = (server.tls_host) and server.tls_host or server.server
} or nil,
xtlsSettings = (server.xtls == '1') and {
allowInsecure = (server.insecure == "1") and true or nil,
serverName = (server.tls_host) and server.tls_host or server.server
} or nil,
tcpSettings = (server.transport == "tcp" and server.tcp_guise == "http") and {
header = {
type = server.tcp_guise,
request = {
path = {server.http_path} or {"/"},
headers = {
Host = {server.http_host} or {}
}
}
}
} or nil,
kcpSettings = (server.transport == "kcp") and {
mtu = tonumber(server.mtu),
tti = tonumber(server.tti),
uplinkCapacity = tonumber(server.uplink_capacity),
downlinkCapacity = tonumber(server.downlink_capacity),
congestion = (server.congestion == "1") and true or false,
readBufferSize = tonumber(server.read_buffer_size),
writeBufferSize = tonumber(server.write_buffer_size),
header = {
type = server.kcp_guise
},
seed = server.seed or nil
} or nil,
wsSettings = (server.transport == "ws") and (server.ws_path or server.ws_host or server.tls_host) and {
path = server.ws_path,
headers = (server.ws_host or server.tls_host) and {
Host = server.ws_host or server.tls_host
} or nil,
} or nil,
httpSettings = (server.transport == "h2") and {
path = server.h2_path or "",
host = {server.h2_host} or nil
} or nil,
quicSettings = (server.transport == "quic") and {
security = server.quic_security,
key = server.quic_key,
header = {
type = server.quic_guise
}
} or nil,
grpcSettings = (server.transport == "grpc") and {
serviceName = server.grpc_serviceName,
MultiMode = (server.gRPC_MultiMode == "1") and true or nil
} or nil
},
mux = (server.mux == "1" and server.xtls ~= "1") and {
enabled = true,
concurrency = tonumber(server.concurrency)
} or nil
} or nil
}
print(json.stringify(Xray,1))

View File

@ -9,6 +9,7 @@ require "nixio"
require "luci.util"
require "luci.sys"
require "luci.jsonc"
require "luci.model.ipkg"
-- these global functions are accessed all the time by the event handler
-- so caching them is worth the effort
local tinsert = table.insert
@ -16,31 +17,41 @@ local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string.
local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify
local b64decode = nixio.bin.b64decode
local cache = {}
local nodeResult = setmetatable({}, { __index = cache }) -- update result
local nodeResult = setmetatable({}, {__index = cache}) -- update result
local name = 'bypass'
local uciType = 'servers'
local ucic = luci.model.uci.cursor()
local proxy = ucic:get_first(name, 'server_subscribe', 'proxy', '0')
local switch = ucic:get_first(name, 'server_subscribe', 'switch', '1')
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url', {})
local filter_mode = ucic:get_first(name, 'server_subscribe', 'filter_mode', '0')
local filter_words = ucic:get_first(name, 'server_subscribe', 'filter_words', '过期时间/剩余流量')
local save_words = ucic:get_first(name, 'server_subscribe', 'save_words', '')
local packet_encoding = luci.model.ipkg.installed("sagernet-core") and ucic:get_first(name, 'global', 'default_packet_encoding', 'xudp') or nil
local v2_ss = luci.sys.exec('type -t -p ss-redir sslocal') ~= "" and "ss" or "v2ray"
local v2_tj = luci.sys.exec('type -t -p trojan-plus') ~= "" and "trojan" or "v2ray"
local v2_ssr = luci.sys.exec('type -t -p ssr-redir') ~= "" and "ssr" or "v2ray"
local v2_tj = luci.sys.exec('type -t -p trojan') ~= "" and "trojan" or "v2ray"
local log = function(...)
local file = io.open("/var/log/bypass.log", "a")
io.output(file)
io.write(os.date("%Y-%m-%d %H:%M:%S ") .. "Subscribe : " .. table.concat({ ... }, " ") .. "\n")
io.close(file)
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({...}, " "))
end
local encrypt_methods_ss = {
-- plain
"none",
"plain",
-- aead
"aes-128-gcm",
"aes-192-gcm",
"aes-256-gcm",
"chacha20-ietf-poly1305",
"xchacha20-ietf-poly1305",
--stream
-- aead 2022
"2022-blake3-aes-128-gcm",
"2022-blake3-aes-256-gcm",
"2022-blake3-chacha20-poly1305"
--[[ stream
"table",
"rc4",
"rc4-md5",
@ -56,7 +67,7 @@ local encrypt_methods_ss = {
"camellia-256-cfb",
"salsa20",
"chacha20",
"chacha20-ietf"
"chacha20-ietf" ]]
}
-- 分割字符串
local function split(full, sep)
@ -135,7 +146,7 @@ end
-- https://www.04007.cn/article/135.html
local function checkTabValue(tab)
local revtab = {}
for k, v in pairs(tab) do
for k,v in pairs(tab) do
revtab[v] = true
end
return revtab
@ -143,10 +154,12 @@ end
-- 处理数据
local function processData(szType, content)
local result = { type = szType, local_port = 1234, kcp_param = '--nocomp' }
local result = {type = szType, local_port = 1234, kcp_param = '--nocomp'}
if szType == 'ssr' then
local dat = split(content, "/%?")
local hostInfo = split(dat[1], ':')
result.type = v2_ssr
result.v2ray_protocol = (v2_ssr == "v2ray") and "shadowsocksr" or nil
result.server = hostInfo[1]
result.server_port = hostInfo[2]
result.protocol = hostInfo[3]
@ -167,14 +180,15 @@ local function processData(szType, content)
result.alias = result.alias .. base64Decode(params.remarks)
elseif szType == 'vmess' then
local info = jsonParse(content)
result.type = 'vmess'
result.type = 'v2ray'
result.v2ray_protocol = 'vmess'
result.server = info.add
result.server_port = info.port
result.transport = info.net
result.alter_id = info.aid
result.uuid = info.id
result.vmess_id = info.id
result.alias = info.ps
result.packet_encoding = packet_encoding
-- result.mux = 1
-- result.concurrency = 8
if info.net == 'ws' then
@ -202,24 +216,39 @@ local function processData(szType, content)
result.read_buffer_size = 2
result.write_buffer_size = 2
end
if info.net == 'grpc' then
if info.path then
result.serviceName = info.path
elseif info.serviceName then
result.serviceName = info.serviceName
end
end
if info.net == 'quic' then
result.quic_guise = info.type
result.quic_key = info.key
result.quic_security = info.securty
end
if info.net == 'grpc' then
result.grpc_serviceName = info.path
end
if info.security then
result.security = info.security
end
if info.tls == "tls" or info.tls == "1" then
result.tls = "1"
result.tls_host = info.host
if info.host then
result.tls_host = info.host
elseif info.sni then
result.tls_host = info.sni
end
result.insecure = 1
else
result.tls = "0"
end
-- https://www.v2fly.org/config/protocols/vmess.html#vmess-md5-认证信息-淘汰机制
if info.aid and (tonumber(info.aid) > 0) then
result.server = nil
end
elseif szType == "ss" then
local idx_sp = 0
local alias = ""
@ -235,7 +264,9 @@ local function processData(szType, content)
local password = userinfo:sub(userinfo:find(":") + 1, #userinfo)
result.alias = UrlDecode(alias)
result.type = v2_ss
result.v2ray_protocol = "shadowsocks"
result.v2ray_protocol = (v2_ss == "v2ray") and "shadowsocks" or nil
result.encrypt_method_ss = method
result.password = password
result.server = host[1]
if host[2]:find("/%?") then
local query = split(host[2], "/%?")
@ -260,18 +291,18 @@ local function processData(szType, content)
end
end
else
result.server_port = host[2]
result.server_port = host[2]:gsub("/","")
end
if checkTabValue(encrypt_methods_ss)[method] then
result.encrypt_method_ss = method
result.password = password
else
if not checkTabValue(encrypt_methods_ss)[method] then
-- 1202 年了还不支持 SS AEAD 的屑机场
result.server = nil
end
elseif szType == "sip008" then
result.type = v2_ss
result.v2ray_protocol = "shadowsocks"
result.v2ray_protocol = (v2_ss == "v2ray") and "shadowsocks" or nil
result.server = content.server
result.server_port = content.server_port
result.password = content.password
@ -284,18 +315,23 @@ local function processData(szType, content)
end
elseif szType == "ssd" then
result.type = v2_ss
result.v2ray_protocol = "shadowsocks"
result.v2ray_protocol = (v2_ss == "v2ray") and "shadowsocks" or nil
result.server = content.server
result.server_port = content.port
result.password = content.password
result.encrypt_method_ss = content.encryption
result.plugin = content.plugin
result.encrypt_method_ss = content.method
result.plugin_opts = content.plugin_options
result.alias = "[" .. content.airport .. "] " .. content.remarks
if checkTabValue(encrypt_methods_ss)[result.encrypt_method_ss] then
result.server = nil
elseif result.plugin == "simple-obfs" then
if content.plugin == "simple-obfs" then
result.plugin = "obfs-local"
else
result.plugin = content.plugin
end
if not checkTabValue(encrypt_methods_ss)[content.encryption] then
result.server = nil
end
elseif szType == "trojan" then
local idx_sp = 0
@ -351,13 +387,14 @@ local function processData(szType, content)
params[t[1]] = t[2]
end
result.alias = UrlDecode(alias)
result.type = 'vless'
result.type = 'v2ray'
result.v2ray_protocol = 'vless'
result.server = host[1]
result.server_port = query[1]
result.uuid = uuid
result.vmess_id = uuid
result.vless_encryption = params.encryption or "none"
result.transport = params.type and (params.type == 'http' and 'h2' or params.type) or "tcp"
result.packet_encoding = packet_encoding
if not params.type or params.type == "tcp" then
if params.security == "xtls" then
result.xtls = "1"
@ -391,8 +428,8 @@ local function processData(szType, content)
result.quic_security = params.quicSecurity or "none"
end
if params.type == 'grpc' then
if params.path then result.grpc_serviceName = params.path end
if params.serviceName then result.grpc_serviceName = params.serviceName end
result.serviceName = params.serviceName
end
if params.security == "tls" then
result.tls = "1"
@ -421,22 +458,54 @@ local function processData(szType, content)
result.switch_enable = switch_enable
return result
end
-- curl
local function curl(url)
local stdout = luci.sys.exec('curl --retry 3 -m 10 -LfskA "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" "' .. url .. '"')
-- wget
local function wget(url)
local stdout = luci.sys.exec('wget -q --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36" --no-check-certificate -O- "' .. url .. '"')
return trim(stdout)
end
local function check_filer(result)
local filter_word = split(filter_words, "/")
for i, v in pairs(filter_word) do
if result.alias:find(v) then
-- log('命中关键词:“'..v..'” pwd')
return filter_mode == '0'
do
-- 过滤的关键词列表
local filter_word = split(filter_words, "/")
-- 保留的关键词列表
local check_save = false
if save_words ~= nil and save_words ~= "" and save_words ~= "NULL" then
check_save = true
end
local save_word = split(save_words, "/")
-- 检查结果
local filter_result = false
local save_result = true
-- 检查是否存在过滤关键词
for i, v in pairs(filter_word) do
if tostring(result.alias):find(v, nil, true) then
filter_result = true
end
end
-- 检查是否打开了保留关键词检查,并且进行过滤
if check_save == true then
for i, v in pairs(save_word) do
if tostring(result.alias):find(v, nil, true) then
save_result = false
end
end
else
save_result = false
end
-- 不等时返回
if filter_result == true or save_result == true then
return true
else
return false
end
end
return filter_mode == '1'
end
local execute = function()
@ -447,7 +516,7 @@ local execute = function()
luci.sys.init.stop(name)
end
for k, url in ipairs(subscribe_url) do
local raw = curl(url)
local raw = wget(url)
if #raw > 0 then
local nodes, szType
local groupHash = md5(url)
@ -460,16 +529,16 @@ local execute = function()
local nEnd = select(2, raw:find('ssd://'))
nodes = base64Decode(raw:sub(nEnd + 1, #raw))
nodes = jsonParse(nodes)
local extra = { airport = nodes.airport, port = nodes.port, encryption = nodes.encryption, password = nodes.password }
local extra = {airport = nodes.airport, port = nodes.port, encryption = nodes.encryption, password = nodes.password}
local servers = {}
-- SS里面包着 干脆直接这样
for _, server in ipairs(nodes.servers) do
tinsert(servers, setmetatable(server, { __index = extra }))
tinsert(servers, setmetatable(server, {__index = extra}))
end
nodes = servers
-- SS SIP008 直接使用 Json 格式
-- SS SIP008 直接使用 Json 格式
elseif jsonParse(raw) then
nodes = jsonParse(raw)
nodes = jsonParse(raw).servers or jsonParse(raw)
if nodes[1].server and nodes[1].method then
szType = 'sip008'
end
@ -539,7 +608,7 @@ local execute = function()
local dat = nodeResult[old.grouphashkey][old.hashkey]
ucic:tset(name, old['.name'], dat)
-- 标记一下
setmetatable(nodeResult[old.grouphashkey][old.hashkey], { __index = { _ignore = true } })
setmetatable(nodeResult[old.grouphashkey][old.hashkey], {__index = {_ignore = true}})
end
else
if not old.alias then

View File

@ -5,12 +5,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=naiveproxy
PKG_VERSION:=103.0.5060.53-2
PKG_VERSION:=103.0.5060.53-3
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/klzgrad/naiveproxy/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=68830ad9d363e24bf1006fe6781c22c00fe6fdafe6c6faf98fb6cbdb80810499
PKG_HASH:=29ffeb8ee5354739f5445f82665d03fbc78aa34c967d4a5a1d106ae7fa23a918
PKG_LICENSE:=BSD 3-Clause
PKG_LICENSE_FILES:=LICENSE