update 2025-01-12 10:41:08
This commit is contained in:
parent
2bcb9533d8
commit
41714631db
42
luci-app-bypass/README.md
Normal file
42
luci-app-bypass/README.md
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
## 说明
|
||||
|
||||
# 本源码来源于sirpdboy固件源码,目前使用上基本没问题, 也许不完美、也许有BUG,请勿喷,留点口德,真有这个闲工,来一起修复问题才是解决问题之道.
|
||||
|
||||
## 特色
|
||||
|
||||
Smartdns 支持
|
||||
|
||||
MOSDNS 支持
|
||||
|
||||
DNS over Https(DoH) 支持
|
||||
|
||||
基于ChinaDNS-NG的国外智能DNS解析, 可与AdGuardHome搭配使用 (AdGuardHome->DNSMASQ->ChinaDNS-NG->SmartDNS)
|
||||
|
||||
走代理网站屏蔽IPV6,不影响其他正常网站使用IPV6
|
||||
|
||||
国内DNS方案集成
|
||||
|
||||
故障转移支持中转节点
|
||||
|
||||
功能与视觉体验增强
|
||||
|
||||
其他大量修复与优化
|
||||
|
||||
TG交流与反馈 :https://t.me/+RV6mxIxZJVDByibQ
|
||||
|
||||
默认集成本插件的固件推荐: https://github.com/sirpdboy/OpenWrt
|
||||
|
||||
|
||||
## 感谢
|
||||
https://github.com/fw876/helloworld
|
||||
|
||||
https://github.com/small-5
|
||||
|
||||
https://github.com/xiaorouji/openwrt-passwall/tree/main/luci-app-passwall
|
||||
|
||||
https://github.com/jerrykuku/luci-app-vssr
|
||||
|
||||
https://github.com/kiddin9
|
||||
|
||||
https://github.com/sirpdboy
|
103
luci-app-bypass/luci-app-bypass/Makefile
Normal file
103
luci-app-bypass/luci-app-bypass/Makefile
Normal file
@ -0,0 +1,103 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-bypass
|
||||
PKG_VERSION:=1.8.1
|
||||
PKG_RELEASE:=23
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Simple_obfs \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Simple_obfs_server \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray_plugin \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Socks5_Proxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Socks_Server
|
||||
|
||||
LUCI_TITLE:=LuCI support for bypass
|
||||
LUCI_PKGARCH:=all
|
||||
LUCI_DEPENDS:=+ipset +kmod-ipt-nat +ip-full +iptables-mod-tproxy +lua-neturl +dnsmasq-full +smartdns +coreutils \
|
||||
+coreutils-base64 +curl +tcping +resolveip +chinadns-ng +lua +luci-compat +luci-base +unzip \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server:shadowsocks-libev-ss-server \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client:shadowsocks-libev-ss-local \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client:shadowsocks-libev-ss-redir \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-local \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-redir \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server:shadowsocksr-libev-ssr-server \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Simple_obfs:simple-obfs \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray_plugin:xray-plugin \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray-core \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan-plus \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy:naiveproxy \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria:hysteria \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Socks5_Proxy:redsocks2 \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Socks_Server:microsocks
|
||||
|
||||
define Package/$(PKG_NAME)/config
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client
|
||||
bool "Include Shadowsocks Libev Client"
|
||||
default y if i386||x86_64||arm||aarch64
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server
|
||||
bool "Include Shadowsocks Libev Server"
|
||||
default y if i386||x86_64||arm||aarch64
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client
|
||||
bool "Include ShadowsocksR Libev Client"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server
|
||||
bool "Include ShadowsocksR Libev Server"
|
||||
default y if i386||x86_64||aarch64
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs
|
||||
bool "Include Shadowsocks Simple Obfs Plugin"
|
||||
default y
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Xray_plugin
|
||||
bool "Include Shadowsocks Xray Plugin"
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Xray
|
||||
bool "Include Xray"
|
||||
default y
|
||||
|
||||
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan
|
||||
bool "Include Trojan"
|
||||
default y if i386||x86_64||arm||aarch64
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy
|
||||
bool "Include NaiveProxy"
|
||||
depends on !(arc||armeb||mips||mips64||powerpc)
|
||||
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 n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Socks_Server
|
||||
bool "Include Socks Sever"
|
||||
default y
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/conffiles
|
||||
/etc/config/bypass
|
||||
/etc/bypass/
|
||||
endef
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
177
luci-app-bypass/luci-app-bypass/luasrc/controller/bypass.lua
Normal file
177
luci-app-bypass/luci-app-bypass/luasrc/controller/bypass.lua
Normal file
@ -0,0 +1,177 @@
|
||||
module("luci.controller.bypass",package.seeall)
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/bypass") then
|
||||
call("act_reset")
|
||||
end
|
||||
local e=entry({"admin","services","bypass"},firstchild(),_("Bypass"),1)
|
||||
e.dependent=false
|
||||
e.acl_depends={ "luci-app-bypass" }
|
||||
entry({"admin","services","bypass","base"},cbi("bypass/base"),_("Base Setting"),10).leaf=true
|
||||
entry({"admin","services","bypass","servers"},arcombine(cbi("bypass/servers",{autoapply=true}),cbi("bypass/client-config")),_("Servers Nodes"),20).leaf=true
|
||||
entry({'admin', 'services','bypass','servers-subscribe'}, cbi('bypass/servers-subscribe', {hideapplybtn = true, hidesavebtn = true, hideresetbtn = true}), _('Subscribe'), 30).leaf = true
|
||||
entry({"admin","services","bypass","control"},cbi("bypass/control"),_("Access Control"),40).leaf=true
|
||||
entry({"admin","services","bypass","advanced"},cbi("bypass/advanced"),_("Advanced Settings"),60).leaf=true
|
||||
if luci.sys.call("which ssr-server >/dev/null")==0 or luci.sys.call("which ss-server >/dev/null")==0 or luci.sys.call("which microsocks >/dev/null")==0 then
|
||||
entry({"admin","services","bypass","server"},arcombine(cbi("bypass/server"),cbi("bypass/server-config")),_("Server"),70).leaf=true
|
||||
end
|
||||
entry({"admin","services","bypass","log"},form("bypass/log"),_("Log"),80).leaf=true
|
||||
entry({"admin","services","bypass","run"},call("act_status"))
|
||||
entry({"admin", "services", "bypass", "checknet"}, call("check_net"))
|
||||
entry({"admin","services","bypass","subscribe"},call("subscribe"))
|
||||
entry({"admin","services","bypass","checkport"},call("check_port"))
|
||||
entry({"admin","services","bypass","ping"},call("act_ping"))
|
||||
|
||||
entry({"admin","services","bypass","check"},call("check_status"))
|
||||
entry({"admin","services","bypass","getlog"},call("getlog")).leaf = true
|
||||
entry({"admin", "services", "bypass", "connect_status"}, call("connect_status")).leaf = true
|
||||
entry({"admin", "services", "bypass", "reset"}, call("act_reset"))
|
||||
entry({"admin", "services", "bypass", "restart"}, call("act_restart"))
|
||||
entry({"admin","services","bypass","dellog"},call("dellog")).leaf = true
|
||||
--[[Backup]]
|
||||
entry({"admin", "services", "bypass", "backup"}, call("create_backup")).leaf = true
|
||||
end
|
||||
|
||||
function subscribe()
|
||||
luci.sys.call("/usr/bin/lua /usr/share/bypass/subscribe")
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ret=1})
|
||||
end
|
||||
|
||||
function act_status()
|
||||
local e = {}
|
||||
e.tcp = luci.sys.call('busybox ps -w | grep by-retcp | grep -v grep >/dev/null ') == 0
|
||||
e.udp = luci.sys.call('busybox ps -w | grep by-reudp | grep -v grep >/dev/null ') == 0
|
||||
e.nf = luci.sys.call('busybox ps -w | grep by-nf | grep -v grep >/dev/null ') == 0
|
||||
e.sdns = luci.sys.call("busybox ps -w | grep 'smartdns_by' | grep -v grep >/dev/null ")==0
|
||||
e.mdns = luci.sys.call("busybox ps -w | grep 'mosdns_by' | grep -v grep >/dev/null ")==0
|
||||
e.chinadns=luci.sys.call("busybox ps -w | grep 'chinadns-ng -l 5337' | grep -v grep >/dev/null")==0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
function check_net()
|
||||
local r=0
|
||||
local u=luci.http.formvalue("url")
|
||||
local p
|
||||
|
||||
if luci.sys.call("nslookup www."..u..".com >/dev/null 2>&1")==0 then
|
||||
if u=="google" then p="/generate_204" else p="" end
|
||||
local use_time = luci.sys.exec("curl --connect-timeout 3 -silent -o /dev/null -I -skL -w %{time_starttransfer} https://www."..u..".com"..p)
|
||||
if use_time~="0" then
|
||||
r=string.format("%.1f", use_time * 1000/2)
|
||||
if r=="0" then r="0.1" end
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ret=r})
|
||||
end
|
||||
|
||||
|
||||
|
||||
function act_ping()
|
||||
local e={}
|
||||
local domain=luci.http.formvalue("domain")
|
||||
local port=luci.http.formvalue("port")
|
||||
local dp=luci.sys.exec("netstat -unl | grep 5336 >/dev/null && echo -n 5336 || echo -n 53")
|
||||
local ip=luci.sys.exec("echo "..domain.." | grep -E ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ || nslookup "..domain.." 2>/dev/null | grep Address | awk -F' ' '{print$NF}' | grep -E ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ | sed -n 1p")
|
||||
ip=luci.sys.exec("echo -n "..ip)
|
||||
local iret=luci.sys.call("ipset add ss_spec_wan_ac "..ip.." 2>/dev/null")
|
||||
e.ping = luci.sys.exec(string.format("tcping -q -c 1 -i 1 -t 2 -p %s %s 2>&1 | awk -F 'time=' '{print $2}' | awk -F ' ' '{print $1}'",port,ip))
|
||||
|
||||
if (iret==0) then
|
||||
luci.sys.call(" ipset del ss_spec_wan_ac " .. ip)
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
function check_status()
|
||||
sret=luci.sys.call("curl -so /dev/null -m 3 www."..luci.http.formvalue("set")..".com")
|
||||
if sret==0 then
|
||||
retstring="0"
|
||||
else
|
||||
retstring="1"
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ret=retstring})
|
||||
end
|
||||
|
||||
function check_port()
|
||||
local retstring="<br/>"
|
||||
local s
|
||||
local server_name
|
||||
local iret=1
|
||||
luci.model.uci.cursor():foreach("bypass","servers",function(s)
|
||||
if s.alias then
|
||||
server_name=s.alias
|
||||
elseif s.server and s.server_port then
|
||||
server_name="%s:%s"%{s.server,s.server_port}
|
||||
end
|
||||
luci.sys.exec(s.server..">>/a")
|
||||
local dp=luci.sys.exec("netstat -unl | grep 5336 >/dev/null && echo -n 5336 || echo -n 53")
|
||||
local ip=luci.sys.exec("echo "..s.server.." | grep -E \"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$\" || \\\
|
||||
nslookup "..s.server.." 127.0.0.1:"..dp.." 2>/dev/null | grep Address | awk -F' ' '{print$NF}' | grep -E \"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$\" | sed -n 1p")
|
||||
ip=luci.sys.exec("echo -n "..ip)
|
||||
iret=luci.sys.call("ipset add ss_spec_wan_ac "..ip.." 2>/dev/null")
|
||||
socket=nixio.socket("inet","stream")
|
||||
socket:setopt("socket","rcvtimeo",3)
|
||||
socket:setopt("socket","sndtimeo",3)
|
||||
ret=socket:connect(ip,s.server_port)
|
||||
socket:close()
|
||||
if tostring(ret)=="true" then
|
||||
retstring = retstring .. "<font><b style='color:green'>[" .. server_name .. "] OK.</b></font><br />"
|
||||
else
|
||||
retstring = retstring .. "<font><b style='color:red'>[" .. server_name .. "] Error.</b></font><br />"
|
||||
end
|
||||
if iret==0 then
|
||||
luci.sys.call("ipset del ss_spec_wan_ac "..ip)
|
||||
end
|
||||
end)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ret=retstring})
|
||||
end
|
||||
|
||||
local function http_write_json(content)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(content or {code = 1})
|
||||
end
|
||||
|
||||
|
||||
function act_reset()
|
||||
luci.sys.call("/etc/init.d/bypass reset >/dev/null 2>&1")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "bypass"))
|
||||
end
|
||||
|
||||
|
||||
function act_restart()
|
||||
luci.sys.call("/etc/init.d/bypass restart &")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "bypass"))
|
||||
end
|
||||
|
||||
function getlog()
|
||||
luci.http.write(luci.sys.exec("[ -f '/var/log/bypass.log' ] && cat /var/log/bypass.log"))
|
||||
|
||||
end
|
||||
|
||||
function dellog()
|
||||
|
||||
luci.sys.call("echo '' > /var/log/bypass.log")
|
||||
end
|
||||
function create_backup()
|
||||
local backup_files = {
|
||||
"/etc/config/bypass",
|
||||
"/etc/bypass/*"
|
||||
}
|
||||
local date = os.date("%Y%m%d")
|
||||
local tar_file = "/tmp/bypass-" .. date .. "-backup.tar.gz"
|
||||
nixio.fs.remove(tar_file)
|
||||
local cmd = "tar -czf " .. tar_file .. " " .. table.concat(backup_files, " ")
|
||||
luci.sys.call(cmd)
|
||||
luci.http.header("Content-Disposition", "attachment; filename=bypass-" .. date .. "-backup.tar.gz")
|
||||
luci.http.header("X-Backup-Filename", "bypass-" .. date .. "-backup.tar.gz")
|
||||
luci.http.prepare_content("application/octet-stream")
|
||||
luci.http.write(nixio.fs.readfile(tar_file))
|
||||
nixio.fs.remove(tar_file)
|
||||
end
|
@ -0,0 +1,141 @@
|
||||
local m,s,o
|
||||
local bypass="bypass"
|
||||
local uci=luci.model.uci.cursor()
|
||||
local server_count=0
|
||||
local SYS=require"luci.sys"
|
||||
|
||||
function url(...)
|
||||
local url = string.format("admin/services/%s", bypass)
|
||||
local args = { ... }
|
||||
for i, v in pairs(args) do
|
||||
if v ~= "" then
|
||||
url = url .. "/" .. v
|
||||
end
|
||||
end
|
||||
return require "luci.dispatcher".build_url(url)
|
||||
end
|
||||
local server_table={}
|
||||
luci.model.uci.cursor():foreach("bypass","servers",function(s)
|
||||
if (s.type=="ss" and not nixio.fs.access("/usr/bin/ss-local")) or (s.type=="ssr" and not nixio.fs.access("/usr/bin/ssr-local")) or s.type=="socks5" or s.type=="tun" then
|
||||
return
|
||||
end
|
||||
if s.alias then
|
||||
server_table[s[".name"]]="[%s]:%s"%{string.upper(s.type),s.alias}
|
||||
elseif s.server and s.server_port then
|
||||
server_table[s[".name"]]="[%s]:%s:%s"%{string.upper(s.type),s.server,s.server_port}
|
||||
end
|
||||
end)
|
||||
|
||||
local key_table={}
|
||||
for key,_ in pairs(server_table) do
|
||||
table.insert(key_table,key)
|
||||
end
|
||||
|
||||
table.sort(key_table)
|
||||
|
||||
m=Map("bypass")
|
||||
|
||||
s=m:section(TypedSection,"global",translate("Server failsafe auto swith settings"))
|
||||
s.anonymous=true
|
||||
|
||||
o=s:option(Flag,"ad_list",translate("Enable DNS anti-AD"))
|
||||
o.default=0
|
||||
|
||||
o=s:option(Flag,"monitor_enable",translate("Enable Process Deamon"))
|
||||
o.default=1
|
||||
|
||||
o=s:option(Flag,"enable_switch",translate("Enable Auto Switch"))
|
||||
o.default=1
|
||||
|
||||
o=s:option(Value,"start_delay",translate("Start Run Delay(second)"))
|
||||
o.datatype="uinteger"
|
||||
o.default=30
|
||||
|
||||
o=s:option(Value,"switch_time",translate("Switch check cycly(second)"))
|
||||
o.datatype="uinteger"
|
||||
o.default=120
|
||||
o:depends("enable_switch",1)
|
||||
|
||||
o=s:option(Value,"switch_timeout",translate("Check timout(second)"))
|
||||
o.datatype="uinteger"
|
||||
o.default=5
|
||||
o:depends("enable_switch",1)
|
||||
|
||||
o=s:option(Value,"switch_try_count",translate("Check Try Count"))
|
||||
o.datatype="uinteger"
|
||||
o.default=3
|
||||
o:depends("enable_switch",1)
|
||||
|
||||
o = s:option(Button, "Reset", translate("Reset to defaults"))
|
||||
o.inputstyle = "reload"
|
||||
o.write = function()
|
||||
luci.sys.call("/etc/init.d/bypass reset")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "bypass", "servers"))
|
||||
end
|
||||
|
||||
-- [[ Rule Settings ]]--
|
||||
s = m:section(TypedSection, "global_rules", translate("Rule status"))
|
||||
s.anonymous = true
|
||||
|
||||
----ad_list URL
|
||||
o = s:option(Value, "ad_url", translate("anti-AD Update URL"))
|
||||
o:value("https://raw.githubusercontent.com/privacy-protection-tools/anti-AD/master/anti-ad-domains.txt", translate("privacy-protection-tools/anti-ad-github"))
|
||||
o:value("https://anti-ad.net/domains.txt", translate("privacy-protection-tools/anti-AD"))
|
||||
o:value("https://github.com/sirpdboy/iplist/releases/latest/download/ad_list.txt", translate("sirpdboy/ad_list"))
|
||||
o.default = "https://github.com/sirpdboy/iplist/releases/latest/download/ad_list.txt"
|
||||
|
||||
---- gfwlist URL
|
||||
o = s:option(Value, "gfwlist_url", translate("GFW domains Update URL"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/YW5vbnltb3Vz/domain-list-community@release/gfwlist.txt", translate("v2fly/domain-list-community"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/Loukky/gfwlist-by-loukky/gfwlist.txt", translate("Loukky/gfwlist-by-loukky"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt", translate("gfwlist/gfwlist"))
|
||||
o:value("https://github.com/sirpdboy/iplist/releases/latest/download/gfwlist.txt", translate("sirpdboy/gfwlist"))
|
||||
o:value("https://openwrt.ai/bypass/gfwlist.txt", translate("supes/gfwlist"))
|
||||
o.default = "https://github.com/sirpdboy/iplist/releases/latest/download/gfwlist.txt"
|
||||
|
||||
|
||||
----chnroute URL
|
||||
o = s:option(Value, "chnroute_url", translate("China IPv4 Update URL"))
|
||||
o:value("https://ispip.clang.cn/all_cn.txt", translate("Clang.CN"))
|
||||
o:value("https://ispip.clang.cn/all_cn_cidr.txt", translate("Clang.CN.CIDR"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/Loyalsoldier/geoip@release/text/cn.txt", translate("Loyalsoldier/geoip-CN"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/gaoyifan/china-operator-ip@ip-lists/china.txt", translate("gaoyifan/china-cn"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/soffchen/GeoIP2-CN@release/CN-ip-cidr.txt", translate("soffchen/GeoIP2-CN"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/Hackl0us/GeoIP2-CN@release/CN-ip-cidr.txt", translate("Hackl0us/GeoIP2-CN"))
|
||||
o:value("https://github.com/sirpdboy/iplist/releases/latest/download/all_cn.txt", translate("sirpdboy/all_cn"))
|
||||
o:value("https://openwrt.ai/bypass/all_cn.txt", translate("supes/all_cn"))
|
||||
o.default = "https://github.com/sirpdboy/iplist/releases/latest/download/all_cn.txt"
|
||||
|
||||
----chnroute6 URL
|
||||
o = s:option(Value, "chnroute6_url", translate("China IPv6 Update URL"))
|
||||
o:value("https://ispip.clang.cn/all_cn_ipv6.txt", translate("Clang.CN.IPv6"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/gaoyifan/china-operator-ip@ip-lists/china6.txt", translate("gaoyifan/china-ipv6"))
|
||||
o:value("https://github.com/sirpdboy/iplist/releases/latest/download/all_cn_ipv6.txt", translate("sirpdboy/all_cn_ipv6"))
|
||||
o.default = "https://github.com/sirpdboy/iplist/releases/latest/download/all_cn_ipv6.txt"
|
||||
|
||||
----domains URL
|
||||
o = s:option(Value, "domains_url", translate("China Domains Update URL"))
|
||||
o:value("https://fastly.jsdelivr.net/gh/yubanmeiqin9048/domain@release/accelerated-domains.china.txt", translate("yubanmeiqin9048/domains.china"))
|
||||
o:value("https://github.com/sirpdboy/iplist/releases/latest/download/domains_cn.txt", translate("sirpdboy/domains_cn"))
|
||||
o.default = "https://github.com/sirpdboy/iplist/releases/latest/download/domains_cn.txt"
|
||||
|
||||
o = s:option(Button, "UpdateRule", translate("Update All Rule List"))
|
||||
o.inputstyle = "apply"
|
||||
function o.write(t, n)
|
||||
luci.sys.call("/usr/share/bypass/update")
|
||||
luci.http.redirect(url("log"))
|
||||
end
|
||||
|
||||
s=m:section(TypedSection,"socks5_proxy",translate("Global SOCKS5 Server"))
|
||||
s.anonymous=true
|
||||
|
||||
o=s:option(ListValue,"server",translate("Server"))
|
||||
o:value("",translate("Disable"))
|
||||
o:value("same",translate("Same as Global Server"))
|
||||
for _,key in pairs(key_table) do o:value(key,server_table[key]) end
|
||||
|
||||
o=s:option(Value,"local_port",translate("Local Port"))
|
||||
o.datatype="port"
|
||||
o.placeholder=1080
|
||||
|
||||
return m
|
173
luci-app-bypass/luci-app-bypass/luasrc/model/cbi/bypass/base.lua
Normal file
173
luci-app-bypass/luci-app-bypass/luasrc/model/cbi/bypass/base.lua
Normal file
@ -0,0 +1,173 @@
|
||||
local m,s,o
|
||||
local bypass="bypass"
|
||||
local function is_bin(e)
|
||||
return luci.sys.exec('type -t -p "%s"' % e) ~= "" and true or false
|
||||
end
|
||||
|
||||
m=Map(bypass)
|
||||
m:section(SimpleSection).template="bypass/status"
|
||||
|
||||
local server_table={}
|
||||
luci.model.uci.cursor():foreach(bypass,"servers",function(s)
|
||||
if s.alias then
|
||||
server_table[s[".name"]]="[%s]:%s"%{string.upper(s.type),s.alias}
|
||||
elseif s.server and s.server_port then
|
||||
server_table[s[".name"]]="[%s]:%s:%s"%{string.upper(s.type),s.server,s.server_port}
|
||||
end
|
||||
end)
|
||||
|
||||
local key_table={}
|
||||
for key in pairs(server_table) do
|
||||
table.insert(key_table,key)
|
||||
end
|
||||
table.sort(key_table)
|
||||
|
||||
s = m:section(TypedSection, 'global')
|
||||
s.anonymous=true
|
||||
|
||||
s:tab("Main", translate("Main"))
|
||||
|
||||
o = s:taboption("Main", Flag, "enabled", translate("Enable Service[Master Switch]"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:taboption("Main",ListValue,"global_server",translate("Main Server"))
|
||||
o:value("", translate("Disable"))
|
||||
for _,key in pairs(key_table) do o:value(key,server_table[key]) end
|
||||
|
||||
o = s:taboption("Main",ListValue,"udp_relay_server",translate("UDP Server"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("same",translate("Same as Global Server"))
|
||||
for _,key in pairs(key_table) do o:value(key,server_table[key]) end
|
||||
|
||||
o = s:taboption("Main",ListValue,"nf_server",translate("Netflix Server"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("same",translate("Same as Global Server"))
|
||||
for _,key in pairs(key_table) do o:value(key,server_table[key]) end
|
||||
o:depends("run_mode","gfw")
|
||||
o:depends("run_mode","router")
|
||||
o:depends("run_mode","all")
|
||||
|
||||
o = s:taboption("Main",DynamicList,"nf_dns",translate("Netflix Query DNS"))
|
||||
o:value("cloudflare_doh","Cloudflare DNS DoH(1.1.1.1)")
|
||||
o:value("cloudflare2_doh","Cloudflare DNS DoH(162.159.36.1)")
|
||||
o:value("google_doh",""..translate("Google").." DNS DoH(8.8.4.4)")
|
||||
o:value("google2_doh",""..translate("Google").." DNS DoH(8.8.8.8)")
|
||||
o:value("quad9_doh","Quad9 DNS DoH(9.9.9.9)")
|
||||
o:value("quad92_doh","Quad9 DNS DoH(149.112.112.112)")
|
||||
o:value("cloudflare_tcp","Cloudflare DNS Tcp(1.1.1.1)")
|
||||
o:value("cloudflare2_tcp","Cloudflare DNS Tcp(1.0.0.1)")
|
||||
o:value("google_tcp",""..translate("Google").." DNS Tcp(8.8.4.4)")
|
||||
o:value("google2_tcp",""..translate("Google").." DNS Tcp(8.8.8.8)")
|
||||
o:value("quad9_tcp","Quad9 DNS Tcp(9.9.9.9)")
|
||||
o:value("quad92_tcp","Quad9 DNS Tcp(149.112.112.112)")
|
||||
o:value("opendns_tcp","OpenDNS DNS Tcp(208.67.222.222)")
|
||||
o:value("opendns2_tcp","OpenDNS DNS Tcp(208.67.220.220)")
|
||||
o.default="cloudflare2_doh"
|
||||
for _,key in pairs(key_table) do o:depends("nf_server",key) end
|
||||
|
||||
o = s:taboption("Main",ListValue,"threads",translate("Multi Threads Option"))
|
||||
o:value("0",translate("Auto Threads"))
|
||||
o:value("1",translate("1 Thread"))
|
||||
o:value("2",translate("2 Threads"))
|
||||
o:value("4",translate("4 Threads"))
|
||||
o:value("8",translate("8 Threads"))
|
||||
o:value("16",translate("16 Threads"))
|
||||
o:value("32",translate("32 Threads"))
|
||||
o:value("64",translate("64 Threads"))
|
||||
o:value("128",translate("128 Threads"))
|
||||
|
||||
o = s:taboption("Main",ListValue,"run_mode",translate("Running Mode"))
|
||||
o:value("router",translate("Smart Mode"))
|
||||
o:value("gfw",translate("GFW List Mode"))
|
||||
o:value("all",translate("Global Mode"))
|
||||
o:value("oversea",translate("Oversea Mode"))
|
||||
|
||||
o = s:taboption("Main",Flag,"gfw_mode",translate("Load GFW List"),
|
||||
translate("If the domestic DNS does not hijack foreign domain name to domestic IP, No need to be enabled"))
|
||||
o:depends("run_mode","router")
|
||||
|
||||
o = s:taboption("Main",Value,"dports",translate("Proxy Ports"),
|
||||
translate("Custom format is 22,53,80,143,443,465,587,853,993,995,9418"))
|
||||
o:value("",translate("All Ports"))
|
||||
o:value("2",translate("Only Common Ports"))
|
||||
|
||||
s:tab("DNS", translate("DNS"))
|
||||
if luci.sys.call("test `grep MemTotal /proc/meminfo | awk '{print $2}'` -gt 233000") == 0 then
|
||||
o = s:taboption("DNS",Flag,"adguardhome",translate("Used with AdGuardHome"),
|
||||
translate("Luci-app-adguardhome require"))
|
||||
if luci.sys.call("test `which AdGuardHome` && test -r /etc/init.d/AdGuardHome") == 0 then
|
||||
o.default=1
|
||||
else
|
||||
o.default=0
|
||||
end
|
||||
end
|
||||
|
||||
o = s:taboption("DNS",ListValue,"dns_mode",translate("DNS Query Method"))
|
||||
o:value(1, translate("Use SmartDNS query"))
|
||||
if is_bin("mosdns") then
|
||||
o:value(2, translate("Use MOSDNS query"))
|
||||
end
|
||||
|
||||
o = s:taboption("DNS",Flag,"proxy_ipv6_mode",translate("IPV6 parsing"), translate("Use DNS to return IPv6 records"))
|
||||
o.default=0
|
||||
|
||||
o = s:taboption("DNS",Flag,"dns_hijack",translate("Take over LAN DNS"),
|
||||
translate("Redirect LAN device DNS to router(Do not disable if you do not understand)"))
|
||||
o.default=1
|
||||
|
||||
o = s:taboption("DNS",Flag,"dns_pollution",translate("Preventing DNS pollution"))
|
||||
o.default=0
|
||||
|
||||
o = s:taboption("DNS",DynamicList,"dns_remote",translate("Remote Query DNS"))
|
||||
o:value("cloudflare_doh","Cloudflare DNS DoH(1.1.1.1)")
|
||||
o:value("cloudflare2_doh","Cloudflare DNS DoH(162.159.36.1)")
|
||||
o:value("cloudflare3_doh","Cloudflare DNS DoH(dns.cloudflare.com)")
|
||||
o:value("google_doh",""..translate("Google").." DNS DoH(8.8.4.4)")
|
||||
o:value("google2_doh",""..translate("Google").." DNS DoH(8.8.8.8)")
|
||||
o:value("google3_doh",""..translate("Google").." DNS DoH(dns.google)")
|
||||
o:value("quad9_doh","Quad9 DNS DoH(9.9.9.9)")
|
||||
o:value("quad92_doh","Quad9 DNS DoH(149.112.112.112)")
|
||||
o:value("cloudflare_tcp","Cloudflare DNS Tcp(1.1.1.1)")
|
||||
o:value("cloudflare2_tcp","Cloudflare DNS Tcp(1.0.0.1)")
|
||||
o:value("google_tcp",""..translate("Google").." DNS Tcp(8.8.4.4)")
|
||||
o:value("google2_tcp",""..translate("Google").." DNS Tcp(8.8.8.8)")
|
||||
o:value("quad9_tcp","Quad9 DNS Tcp(9.9.9.9)")
|
||||
o:value("quad92_tcp","Quad9 DNS Tcp(149.112.112.112)")
|
||||
o:value("opendns_tcp","OpenDNS DNS Tcp(208.67.222.222)")
|
||||
o:value("opendns2_tcp","OpenDNS DNS Tcp(208.67.220.220)")
|
||||
o.default="cloudflare_doh"
|
||||
|
||||
o = s:taboption("DNS",DynamicList,"dns_local",translate("Local Query DNS"))
|
||||
o:value("isp",translate("ISP DNS"))
|
||||
o:value("alidns_doh",""..translate("Ali").." DNS DoH(223.5.5.5)")
|
||||
o:value("alidns2_doh",""..translate("Ali").." DNS DoH(223.6.6.6)")
|
||||
o:value("alidns3_doh",""..translate("Ali").." DNS DoH(dns.alidns.com)")
|
||||
o:value("dnspod_doh",""..translate("Tencent").." DNS DoH(175.24.219.66)")
|
||||
o:value("dnspod2_doh",""..translate("Tencent").." DNS DoH(doh.pub)")
|
||||
o:value("360dns_doh","360 DNS DoH(101.226.4.6)")
|
||||
o:value("360dns2_doh","360 DNS DoH(doh.360.cn)")
|
||||
o:value("alidns_tcp",""..translate("Ali").." DNS Tcp(223.5.5.5)")
|
||||
o:value("alidns2_tcp",""..translate("Ali").." DNS Tcp(223.6.6.6)")
|
||||
o:value("dnspod_tcp",""..translate("Tencent").." DNS Tcp(175.24.219.66)")
|
||||
o:value("360dns_tcp","360 DNS Tcp(101.226.4.6)")
|
||||
o:value("360dns2_tcp","360DNS DNS Tcp(123.6.48.18)")
|
||||
o:value("baidu_tcp",""..translate("BaiDu").."DNS Tcp(180.76.76.76)")
|
||||
o:value("114dns_tcp","114DNS DNS Tcp(114.114.114.114)")
|
||||
o:value("114dns2_tcp","114DNS DNS Tcp(114.114.115.115)")
|
||||
o.default="alidns_doh"
|
||||
|
||||
o = s:taboption("DNS",Value, "bootstrap_dns", translate("Bootstrap DNS servers"), translate("Bootstrap DNS server is used to resolve IP addresses in the upstream DoH/DoT resolution list"))
|
||||
o:value("119.29.29.29", ""..translate("Tencent").." DNS (119.29.29.29)")
|
||||
o:value("119.28.28.28", ""..translate("Tencent").." DNS (119.28.28.28)")
|
||||
o:value("223.5.5.5", ""..translate("Ali").."(223.5.5.5)")
|
||||
o:value("223.6.6.6", ""..translate("Ali").."(223.6.6.6)")
|
||||
o:value("114.114.114.114", translate("114DNS(114.114.114.114)"))
|
||||
o:value("114.114.115.115", translate("114DNS(114.114.115.115)"))
|
||||
o:value("180.76.76.76", ""..translate("BaiDu").." DNS(180.76.76.76)")
|
||||
o:value("8.8.8.8",""..translate("Google").." DNS(8.8.8.8)")
|
||||
o:value("8.8.4.4", ""..translate("Google").." DNS(8.8.4.4)")
|
||||
o:value("1.1.1.1", translate("CloudFlare DNS(1.1.1.1)"))
|
||||
o.default = "114.114.114.114"
|
||||
|
||||
|
||||
return m
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,135 @@
|
||||
local fs = require "nixio.fs"
|
||||
local m,s,o
|
||||
|
||||
m=Map("bypass",translate("IP Access Control"))
|
||||
s=m:section(TypedSection,"access_control")
|
||||
s.anonymous=true
|
||||
|
||||
m.apply_on_parse=true
|
||||
function m.on_apply(self)
|
||||
luci.sys.call("/etc/init.d/bypass reload > /dev/null 2>&1 &")
|
||||
end
|
||||
|
||||
s:tab("wan_ac",translate("WAN IP AC"))
|
||||
|
||||
o=s:taboption("wan_ac",DynamicList,"wan_bp_ips",translate("WAN White List IP"))
|
||||
o.datatype="ip4addr"
|
||||
|
||||
o=s:taboption("wan_ac",DynamicList,"wan_fw_ips",translate("WAN Force Proxy IP"))
|
||||
o.datatype="ip4addr"
|
||||
|
||||
s:tab("lan_ac",translate("LAN IP AC"))
|
||||
|
||||
o=s:taboption("lan_ac",ListValue,"lan_ac_mode",translate("LAN Access Control"))
|
||||
o:value("w",translate("Allow listed only"))
|
||||
o:value("b",translate("Allow all except listed"))
|
||||
o.rmempty=false
|
||||
|
||||
o=s:taboption("lan_ac",DynamicList,"lan_ac_ips",translate("LAN Host List"))
|
||||
o.datatype="ipaddr"
|
||||
luci.ip.neighbors({family=4},function(entry)
|
||||
if entry.reachable then
|
||||
o:value(entry.dest:string())
|
||||
end
|
||||
end)
|
||||
o:depends("lan_ac_mode","w")
|
||||
o:depends("lan_ac_mode","b")
|
||||
|
||||
o=s:taboption("lan_ac",DynamicList,"lan_fp_ips",translate("LAN Force Proxy Host List"))
|
||||
o.datatype="ipaddr"
|
||||
luci.ip.neighbors({family=4},function(entry)
|
||||
if entry.reachable then
|
||||
o:value(entry.dest:string())
|
||||
end
|
||||
end)
|
||||
|
||||
o=s:taboption("lan_ac",DynamicList,"lan_gm_ips",translate("Game Mode Host List"))
|
||||
o.datatype="ipaddr"
|
||||
luci.ip.neighbors({family=4},function(entry)
|
||||
if entry.reachable then
|
||||
o:value(entry.dest:string())
|
||||
end
|
||||
end)
|
||||
|
||||
s:tab("direct_list", translate("Direct Domain List"))
|
||||
s:tab("proxy_list", translate("Proxy Domain List"))
|
||||
s:tab("netflix_list", translate("Netflix Domain List"))
|
||||
s:tab("oversea_list", translate("Oversea Domain List"))
|
||||
|
||||
---- Direct Hosts
|
||||
local direct_host = string.format("/etc/bypass/white.list")
|
||||
o = s:taboption("direct_list", TextValue, "direct_host", "", "<font color='red'>" .. translate("These had been joined websites will not proxy.") .. "</font>")
|
||||
o.rows = 15
|
||||
o.wrap = "off"
|
||||
o.cfgvalue = function(self, section) return fs.readfile(direct_host) or "" end
|
||||
o.write = function(self, section, value) fs.writefile(direct_host, value:gsub("\r\n", "\n")) end
|
||||
o.remove = function(self, section, value) fs.writefile(direct_host, "") end
|
||||
o.validate = function(self, value)
|
||||
local hosts= {}
|
||||
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end)
|
||||
for index, host in ipairs(hosts) do
|
||||
if not datatypes.hostname(host) then
|
||||
return nil, host .. " " .. translate("Not valid domain name, please re-enter!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
---- Proxy Hosts
|
||||
local proxy_host = string.format("/etc/bypass/black.list")
|
||||
o = s:taboption("proxy_list", TextValue, "proxy_host", "", "<font color='red'>" .. translate("These had been joined websites will use proxy.") .. "</font>")
|
||||
o.rows = 15
|
||||
o.wrap = "off"
|
||||
o.cfgvalue = function(self, section) return fs.readfile(proxy_host) or "" end
|
||||
o.write = function(self, section, value) fs.writefile(proxy_host, value:gsub("\r\n", "\n")) end
|
||||
o.remove = function(self, section, value) fs.writefile(proxy_host, "") end
|
||||
o.validate = function(self, value)
|
||||
local hosts= {}
|
||||
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end)
|
||||
for index, host in ipairs(hosts) do
|
||||
if not datatypes.hostname(host) then
|
||||
return nil, host .. " " .. translate("Not valid domain name, please re-enter!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
---- Netflix Hosts
|
||||
local netflix_host = string.format("/etc/bypass/netflix.list")
|
||||
o = s:taboption("netflix_list", TextValue, "netflix_host", "", "<font color='red'>" .. translate("Netflix Domain List") .. "</font>")
|
||||
o.rows = 15
|
||||
o.wrap = "off"
|
||||
o.cfgvalue = function(self, section) return fs.readfile(netflix_host) or "" end
|
||||
o.write = function(self, section, value) fs.writefile(netflix_host, value:gsub("\r\n", "\n")) end
|
||||
o.remove = function(self, section, value) fs.writefile(netflix_host, "") end
|
||||
o.validate = function(self, value)
|
||||
local hosts= {}
|
||||
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end)
|
||||
for index, host in ipairs(hosts) do
|
||||
if not datatypes.hostname(host) then
|
||||
return nil, host .. " " .. translate("Not valid domain name, please re-enter!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
---- Oversea Hosts
|
||||
local oversea_host = string.format("/etc/bypass/oversea.list")
|
||||
o = s:taboption("oversea_list", TextValue, "oversea_host", "", "<font color='red'>" .. translate("Oversea Domain List") .. "</font>")
|
||||
o.rows = 15
|
||||
o.wrap = "off"
|
||||
o.cfgvalue = function(self, section) return fs.readfile(oversea_host) or "" end
|
||||
o.write = function(self, section, value) fs.writefile(oversea_host, value:gsub("\r\n", "\n")) end
|
||||
o.remove = function(self, section, value) fs.writefile(oversea_host, "") end
|
||||
o.validate = function(self, value)
|
||||
local hosts= {}
|
||||
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end)
|
||||
for index, host in ipairs(hosts) do
|
||||
if not datatypes.hostname(host) then
|
||||
return nil, host .. " " .. translate("Not valid domain name, please re-enter!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
return m
|
@ -0,0 +1,12 @@
|
||||
local fs=require"nixio.fs"
|
||||
local f,t
|
||||
f=SimpleForm("logview")
|
||||
f.reset=false
|
||||
f.submit=false
|
||||
t=f:field(TextValue,"conf")
|
||||
t.rmempty=true
|
||||
t.rows=20
|
||||
t.template="bypass/log"
|
||||
t.readonly="readonly"
|
||||
|
||||
return f
|
@ -0,0 +1,154 @@
|
||||
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
require "luci.http"
|
||||
require "luci.dispatcher"
|
||||
require "nixio.fs"
|
||||
|
||||
local m, s, o
|
||||
local sid = arg[1]
|
||||
|
||||
local encrypt_methods = {
|
||||
"rc4-md5",
|
||||
"rc4-md5-6",
|
||||
"rc4",
|
||||
"table",
|
||||
"aes-128-cfb",
|
||||
"aes-192-cfb",
|
||||
"aes-256-cfb",
|
||||
"aes-128-ctr",
|
||||
"aes-192-ctr",
|
||||
"aes-256-ctr",
|
||||
"bf-cfb",
|
||||
"camellia-128-cfb",
|
||||
"camellia-192-cfb",
|
||||
"camellia-256-cfb",
|
||||
"cast5-cfb",
|
||||
"des-cfb",
|
||||
"idea-cfb",
|
||||
"rc2-cfb",
|
||||
"seed-cfb",
|
||||
"salsa20",
|
||||
"chacha20",
|
||||
"chacha20-ietf"
|
||||
}
|
||||
|
||||
local encrypt_methods_ss = {
|
||||
-- aead
|
||||
"aes-128-gcm",
|
||||
"aes-192-gcm",
|
||||
"aes-256-gcm",
|
||||
"chacha20-ietf-poly1305",
|
||||
"xchacha20-ietf-poly1305",
|
||||
-- aead 2022
|
||||
"2022-blake3-aes-128-gcm",
|
||||
"2022-blake3-aes-256-gcm",
|
||||
"2022-blake3-chacha20-poly1305"
|
||||
--[[ stream
|
||||
"table",
|
||||
"rc4",
|
||||
"rc4-md5",
|
||||
"aes-128-cfb",
|
||||
"aes-192-cfb",
|
||||
"aes-256-cfb",
|
||||
"aes-128-ctr",
|
||||
"aes-192-ctr",
|
||||
"aes-256-ctr",
|
||||
"bf-cfb",
|
||||
"camellia-128-cfb",
|
||||
"camellia-192-cfb",
|
||||
"camellia-256-cfb",
|
||||
"salsa20",
|
||||
"chacha20",
|
||||
"chacha20-ietf" ]]
|
||||
}
|
||||
|
||||
local protocol = {"origin"}
|
||||
|
||||
obfs = {"plain", "http_simple", "http_post"}
|
||||
|
||||
m = Map("bypass", translate("Edit Server"))
|
||||
|
||||
m.redirect = luci.dispatcher.build_url("admin/services/bypass/server")
|
||||
if m.uci:get("bypass", sid) ~= "server_config" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
-- [[ Server Setting ]]--
|
||||
s = m:section(NamedSection, sid, "server_config")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(Flag, "enable", translate("Enable"))
|
||||
o.default = 1
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "type", translate("Server Type"))
|
||||
o:value("socks5", translate("Socks5"))
|
||||
if nixio.fs.access("/usr/bin/ssserver") or nixio.fs.access("/usr/bin/ss-server") then
|
||||
o:value("ss", translate("Shadowsocks"))
|
||||
end
|
||||
if nixio.fs.access("/usr/bin/ssr-server") then
|
||||
o:value("ssr", translate("ShadowsocksR"))
|
||||
end
|
||||
o.default = "socks5"
|
||||
|
||||
o = s:option(Value, "server_port", translate("Server Port"))
|
||||
o.datatype = "port"
|
||||
math.randomseed(tostring(os.time()):reverse():sub(1, 7))
|
||||
o.default = math.random(10240, 20480)
|
||||
o.rmempty = false
|
||||
o.description = translate("warning! Please do not reuse the port!")
|
||||
|
||||
o = s:option(Value, "timeout", translate("Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 60
|
||||
o.rmempty = false
|
||||
o:depends("type", "ss")
|
||||
o:depends("type", "ssr")
|
||||
|
||||
o = s:option(Value, "username", translate("Username"))
|
||||
o.rmempty = false
|
||||
o:depends("type", "socks5")
|
||||
|
||||
o = s:option(Value, "password", translate("Password"))
|
||||
o.password = true
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
|
||||
for _, v in ipairs(encrypt_methods) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = false
|
||||
o:depends("type", "ssr")
|
||||
|
||||
o = s:option(ListValue, "encrypt_method_ss", translate("Encrypt Method"))
|
||||
for _, v in ipairs(encrypt_methods_ss) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = false
|
||||
o:depends("type", "ss")
|
||||
|
||||
o = s:option(ListValue, "protocol", translate("Protocol"))
|
||||
for _, v in ipairs(protocol) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = false
|
||||
o:depends("type", "ssr")
|
||||
|
||||
o = s:option(ListValue, "obfs", translate("Obfs"))
|
||||
for _, v in ipairs(obfs) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = false
|
||||
o:depends("type", "ssr")
|
||||
|
||||
o = s:option(Value, "obfs_param", translate("Obfs param(optional)"))
|
||||
o:depends("type", "ssr")
|
||||
|
||||
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
|
||||
o.rmempty = false
|
||||
o:depends("type", "ss")
|
||||
o:depends("type", "ssr")
|
||||
|
||||
return m
|
@ -0,0 +1,71 @@
|
||||
local m,s,o
|
||||
|
||||
m=Map("bypass")
|
||||
s=m:section(TypedSection,"server_global",translate("Global Setting"))
|
||||
s.anonymous=true
|
||||
|
||||
o=s:option(Flag,"enable_server",translate("Enable Server"))
|
||||
|
||||
s=m:section(TypedSection,"server_config",translate("Server Setting"))
|
||||
s.anonymous=true
|
||||
s.addremove=true
|
||||
s.template="cbi/tblsection"
|
||||
s.extedit=luci.dispatcher.build_url("admin/services/bypass/server/%s")
|
||||
function s.create(...)
|
||||
local sid=TypedSection.create(...)
|
||||
if sid then
|
||||
luci.http.redirect(s.extedit%sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
o=s:option(Flag,"enable",translate("Enable"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or translate("0")
|
||||
end
|
||||
o.rmempty=false
|
||||
|
||||
o=s:option(DummyValue,"type",translate("Server Type"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "-"
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"server_port",translate("Server Port"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "-"
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"username",translate("Username"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "-"
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"encrypt_method_ss",translate("Encrypt Method (SS)"))
|
||||
function o.cfgvalue(...)
|
||||
local v=Value.cfgvalue(...)
|
||||
return v and v:upper() or "-"
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"plugin",translate("Plugin (SS)"))
|
||||
function o.cfgvalue(...)
|
||||
local v=Value.cfgvalue(...)
|
||||
return v and v:upper() or "-"
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"encrypt_method",translate("Encrypt Method"))
|
||||
function o.cfgvalue(...)
|
||||
local v=Value.cfgvalue(...)
|
||||
return v and v:upper() or "-"
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"protocol",translate("Protocol"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "-"
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"obfs",translate("Obfs"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "-"
|
||||
end
|
||||
|
||||
return m
|
@ -0,0 +1,83 @@
|
||||
local m,s,o
|
||||
local bypass="bypass"
|
||||
local uci=luci.model.uci.cursor()
|
||||
local server_count=0
|
||||
|
||||
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/NAIVEPROXY/SOCKS5/TUN etc."))
|
||||
s=m:section(TypedSection,"server_subscribe")
|
||||
s.anonymous=true
|
||||
|
||||
o=s:option(Flag,"auto_update",translate("Auto Update"))
|
||||
o.rmempty=false
|
||||
o.description=translate("Auto Update Server subscription,GFW list and CHN route")
|
||||
|
||||
o=s:option(ListValue,"auto_update_time",translate("Update time (every day)"))
|
||||
for t=0,23 do
|
||||
o:value(t,t..":00")
|
||||
end
|
||||
o.default=2
|
||||
o.rmempty=false
|
||||
|
||||
o=s:option(DynamicList,"subscribe_url",translate("Subscribe URL"))
|
||||
o.rmempty=true
|
||||
|
||||
o=s:option(Button,"update_Sub",translate("Save Subscribe Setting"))
|
||||
o.inputstyle="reload"
|
||||
o.description=translate("Update subscribe url or Setting list first")
|
||||
o.write=function()
|
||||
uci:commit(bypass)
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin","services",bypass,"servers-subscribe"))
|
||||
end
|
||||
|
||||
o=s:option(Button,"subscribe",translate("Update All Subscribe Servers"))
|
||||
o.rawhtml=true
|
||||
o.template="bypass/subscribe"
|
||||
|
||||
o=s:option(Button,"delete",translate("Delete All Subscribe Servers"))
|
||||
o.inputstyle="reset"
|
||||
o.description=string.format(translate("Server Count")..": %d",server_count)
|
||||
o.write=function()
|
||||
uci:delete_all(bypass,"servers",function(s)
|
||||
if s.hashkey or s.isSubscribe then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end)
|
||||
uci:commit(bypass)
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin","services",bypass,"servers-subscribe"))
|
||||
end
|
||||
|
||||
o=s:option(ListValue,"filter_mode",translate("Filter Words Mode"))
|
||||
o:value("",translate("Discard Mode"))
|
||||
o:value(1,translate("Keep Mode"))
|
||||
o = s:option(Value, "filter_words", translate("Subscribe Filter Words"))
|
||||
o.rmempty = true
|
||||
o.description = translate("Filter Words splited by /")
|
||||
|
||||
|
||||
o=s:option(Flag,"switch",translate("Subscribe Default Auto-Switch"))
|
||||
o.rmempty=false
|
||||
o.description=translate("Subscribe new add server default Auto-Switch on")
|
||||
o.default=0
|
||||
|
||||
o=s:option(Flag,"insecure",translate("allowInsecure"))
|
||||
o.rmempty=false
|
||||
o.description=translate("If true, allowss insecure connection at TLS client, e.g., TLS server uses unverifiable certificates.")
|
||||
o.default=1
|
||||
|
||||
o=s:option(Flag,"proxy",translate("Through proxy update"))
|
||||
o.rmempty=false
|
||||
o.description=translate("Through proxy update list,Not Recommended")
|
||||
|
||||
|
||||
o = s:option(Value, "user_agent", translate("User-Agent"))
|
||||
o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", translate("Win64"))
|
||||
o:value("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",translate("Linux"))
|
||||
o.default = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
|
||||
|
||||
return m
|
@ -0,0 +1,64 @@
|
||||
local m,s,o
|
||||
local bypass="bypass"
|
||||
local uci=luci.model.uci.cursor()
|
||||
|
||||
m=Map(bypass)
|
||||
-- s=m:section(TypedSection,"server_subscribe")
|
||||
|
||||
-- s.anonymous = true
|
||||
-- s:append(Template("bypass/node_add"))
|
||||
s=m:section(TypedSection,"servers")
|
||||
s.anonymous=true
|
||||
s.addremove=true
|
||||
s.template="cbi/tblsection"
|
||||
-- s.sortable=true
|
||||
s.extedit=luci.dispatcher.build_url("admin","services",bypass,"servers","%s")
|
||||
function s.create(...)
|
||||
local sid=TypedSection.create(...)
|
||||
if sid then
|
||||
uci:set(bypass,sid,'switch_enable',1)
|
||||
luci.http.redirect(s.extedit%sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"type",translate("Type"))
|
||||
function o.cfgvalue(...)
|
||||
return (Value.cfgvalue(...)=="vless") and "VLESS" or Value.cfgvalue(...)
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"alias",translate("Alias"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or translate("None")
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"server_port",translate("Server Port"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "N/A"
|
||||
end
|
||||
|
||||
o=s:option(DummyValue,"server_port",translate("Socket Connected"))
|
||||
o.template="bypass/socket"
|
||||
o.width="10%"
|
||||
|
||||
o=s:option(DummyValue,"server",translate("TCPing Latency"))
|
||||
o.template="bypass/ping"
|
||||
o.width="10%"
|
||||
|
||||
o=s:option(Button,"apply_node",translate("Apply"))
|
||||
o.inputstyle="apply"
|
||||
o.write=function(self,section)
|
||||
uci:set(bypass,'@global[0]','global_server',section)
|
||||
uci:commit(bypass)
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin","services",bypass,"base"))
|
||||
end
|
||||
|
||||
o=s:option(Flag,"switch_enable",translate("Auto Switch"))
|
||||
o.rmempty=false
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or 1
|
||||
end
|
||||
|
||||
m:append(Template("bypass/server_list"))
|
||||
|
||||
return m
|
@ -0,0 +1,4 @@
|
||||
<%+cbi/valueheader%>
|
||||
<input class="cbi-input-file" style="width: 400px" type="file" id="ulfile" name="ulfile"/>
|
||||
<input type="submit" class="cbi-button cbi-input-apply" name="upload" value="<%:Upload%>"/>
|
||||
<%+cbi/valuefooter%>
|
30
luci-app-bypass/luci-app-bypass/luasrc/view/bypass/check.htm
Normal file
30
luci-app-bypass/luci-app-bypass/luasrc/view/bypass/check.htm
Normal file
@ -0,0 +1,30 @@
|
||||
<%+cbi/valueheader%>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function check_connect(btn,urlname)
|
||||
{
|
||||
btn.disabled=true;
|
||||
btn.value='<%:Check...%>';
|
||||
murl=urlname;
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin","services","bypass","check")%>',
|
||||
{set:murl},
|
||||
function(x,rv)
|
||||
{
|
||||
var s=document.getElementById(urlname+'-status');
|
||||
if (s)
|
||||
{
|
||||
if (rv.ret=="0")
|
||||
s.innerHTML="<font style=\'color:green\'>"+"<%:Connect OK%>"+"</font>";
|
||||
else
|
||||
s.innerHTML="<font style=\'color=:red\'>"+"<%:Connect Error%>"+"</font>";
|
||||
}
|
||||
btn.disabled=false;
|
||||
btn.value='<%:Check Connect%>';
|
||||
}
|
||||
);
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Check Connect%>" onclick="return check_connect(this,'<%=self.option%>')"/>
|
||||
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||
|
||||
<%+cbi/valuefooter%>
|
@ -0,0 +1,26 @@
|
||||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function check_port(btn)
|
||||
{
|
||||
btn.disabled=true;
|
||||
btn.value='<%:Check...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin","services","bypass","checkport")%>',
|
||||
null,
|
||||
function(x,rv)
|
||||
{
|
||||
var s=document.getElementById('<%=self.option%>-status');
|
||||
if (s)
|
||||
{
|
||||
s.innerHTML=rv.ret;
|
||||
}
|
||||
btn.disabled=false;
|
||||
btn.value='<%:Check Server%>';
|
||||
}
|
||||
);
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Check Server%>" onclick="return check_port(this)"/>
|
||||
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||
<%+cbi/valuefooter%>
|
54
luci-app-bypass/luci-app-bypass/luasrc/view/bypass/log.htm
Normal file
54
luci-app-bypass/luci-app-bypass/luasrc/view/bypass/log.htm
Normal file
@ -0,0 +1,54 @@
|
||||
<%+cbi/valueheader%>
|
||||
<input type="button" class="btn cbi-button cbi-button-apply" id="apply_update_button" value="<%:Clear Log%>" onclick="apply_del_log()"/>
|
||||
<input type="checkbox" name="NAME" value="reverse" onclick="reverselog()" style="vertical-align:middle;height:auto;"><%:Reverse%></input>
|
||||
<textarea id="cbid.logview.1.conf" class="cbi-input-textarea" style="width: 100%;display:inline" data-update="change" rows="32" cols="60" readonly="readonly" > </textarea>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var islogreverse=false;
|
||||
|
||||
function createAndDownloadFile(fileName,content){
|
||||
var aTag=document.createElement('a');
|
||||
var blob=new Blob([content]);
|
||||
aTag.download=fileName;
|
||||
aTag.href=URL.createObjectURL(blob);
|
||||
aTag.click();
|
||||
URL.revokeObjectURL(blob);
|
||||
}
|
||||
|
||||
function apply_del_log(){
|
||||
XHR.get('<%=url([[admin]],[[services]],[[bypass]],[[dellog]])%>',null,function(x,data){
|
||||
var lv=document.getElementById('cbid.logview.1.conf');
|
||||
lv.innerHTML="";
|
||||
}
|
||||
);
|
||||
return
|
||||
}
|
||||
|
||||
function reverselog(){
|
||||
var lv=document.getElementById('cbid.logview.1.conf');
|
||||
lv.innerHTML=lv.innerHTML.split('\n').reverse().join('\n')
|
||||
if (islogreverse){
|
||||
islogreverse=false;
|
||||
}else{
|
||||
islogreverse=true;
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
XHR.poll(3,'<%=url([[admin]],[[services]],[[bypass]],[[getlog]])%>',null,
|
||||
function(x,data){
|
||||
var lv=document.getElementById('cbid.logview.1.conf');
|
||||
lv.innerHTML=""
|
||||
if (x.responseText && lv){
|
||||
if (islogreverse){
|
||||
lv.innerHTML=x.responseText.split('\n').reverse().join('\n')+lv.innerHTML;
|
||||
}else{
|
||||
lv.innerHTML+=x.responseText;
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
//]]>
|
||||
</script>
|
||||
<%+cbi/valuefooter%>
|
@ -0,0 +1,10 @@
|
||||
<%
|
||||
local dsp=require "luci.dispatcher"
|
||||
local NAME="bypass"
|
||||
-%>
|
||||
<div class="cbi-value">
|
||||
<label class="cbi-value-title"></label>
|
||||
<div class="cbi-value-field">
|
||||
<input class="btn cbi-button cbi-button-add" type="submit" name="cbi.sts.bypass.server_list." value="<%:Add%>" />
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,3 @@
|
||||
<%+cbi/valueheader%>
|
||||
<span class="pingtime" hint="<%=self:cfgvalue(section)%>">-- ms</span>
|
||||
<%+cbi/valuefooter%>
|
@ -0,0 +1,181 @@
|
||||
<%#
|
||||
Copyright 2018-2019 Lienol <lawlienol@gmail.com>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
<%
|
||||
local dsp=require "luci.dispatcher"
|
||||
-%>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
window.addEventListener('load',function(){
|
||||
const doms=document.getElementsByClassName('pingtime');
|
||||
const ports=document.getElementsByClassName("socket-connected")
|
||||
const xhr=(index) =>{
|
||||
return new Promise((res) =>{
|
||||
const dom=doms[index];
|
||||
const port=ports[index];
|
||||
if (!dom) res()
|
||||
port.innerHTML='<font style=\"color:#0072c3\"><%:connecting%></font>';
|
||||
XHR.get('<%=dsp.build_url("admin/services/bypass/ping")%>',{
|
||||
index,
|
||||
domain: dom.getAttribute("hint"),
|
||||
port: port.getAttribute("hint")
|
||||
},
|
||||
(x,result) =>{
|
||||
let col='#ff0000';
|
||||
if (result.ping){
|
||||
if (result.ping < 300) col='#ff3300';
|
||||
if (result.ping < 200) col='#ff7700';
|
||||
if (result.ping < 100) col='#249400';
|
||||
port.innerHTML='<font style=\"color:#249400\"><%:ok%></font>'
|
||||
}else{
|
||||
port.innerHTML='<font style=\"color:#ff0000\"><%:fail%></font>'
|
||||
}
|
||||
dom.innerHTML =`<font style=\"${col}\">${(result.ping?result.ping:"--")+" ms"}</font>`
|
||||
res();
|
||||
});
|
||||
})
|
||||
}
|
||||
let task=-1;
|
||||
const thread=() =>{
|
||||
task=task + 1
|
||||
if (doms[task]){
|
||||
xhr(task).then(thread);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i=0; i < 20; i++){
|
||||
thread()
|
||||
}
|
||||
})
|
||||
|
||||
function cbi_row_drop(fromId,toId,store,isToBottom){
|
||||
var fromNode=document.getElementById(fromId);
|
||||
var toNode=document.getElementById(toId);
|
||||
if (!fromNode || !toNode) return false;
|
||||
|
||||
var table=fromNode.parentNode;
|
||||
while (table && table.nodeName.toLowerCase() != "table")
|
||||
table=table.parentNode;
|
||||
if (!table) return false;
|
||||
|
||||
var ids=[];
|
||||
if (isToBottom){
|
||||
toNode.parentNode.appendChild(fromNode);
|
||||
} else{
|
||||
fromNode.parentNode.insertBefore(fromNode,toNode);
|
||||
}
|
||||
|
||||
for (var idx=2; idx < table.rows.length; idx++){
|
||||
table.rows[idx].className=table.rows[idx].className.replace(
|
||||
/cbi-rowstyle-[12]/,
|
||||
"cbi-rowstyle-" + (1 + (idx % 2))
|
||||
);
|
||||
|
||||
if (table.rows[idx].id && table.rows[idx].id.match(/-([^\-]+)$/))
|
||||
ids.push(RegExp.$1);
|
||||
}
|
||||
|
||||
var input=document.getElementById(store);
|
||||
if (input) input.value=ids.join(" ");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// set tr draggable
|
||||
function enableDragForTable(table_selecter,store){
|
||||
var trs=document.querySelectorAll(table_selecter + " tr");
|
||||
if (!trs || trs.length.length < 3){
|
||||
return;
|
||||
}
|
||||
|
||||
function ondragstart(ev){
|
||||
ev.dataTransfer.setData("Text",ev.target.id);
|
||||
}
|
||||
|
||||
function ondrop(ev){
|
||||
var from=ev.dataTransfer.getData("Text");
|
||||
cbi_row_drop(from,this.id,store);
|
||||
}
|
||||
|
||||
function ondragover(ev){
|
||||
ev.preventDefault();
|
||||
ev.dataTransfer.dropEffect="move";
|
||||
}
|
||||
|
||||
function moveToTop(id){
|
||||
var top=document.querySelectorAll(table_selecter + " tr")[2];
|
||||
cbi_row_drop(id,top.id,store);
|
||||
}
|
||||
|
||||
function moveToBottom(id){
|
||||
console.log('moveToBottom:',id);
|
||||
var trList=document.querySelectorAll(table_selecter + " tr");
|
||||
var bottom=trList[trList.length - 1];
|
||||
cbi_row_drop(id,bottom.id,store,true);
|
||||
}
|
||||
|
||||
for (let index=2; index < trs.length; index++){
|
||||
const el=trs[index];
|
||||
el.setAttribute("draggable",true);
|
||||
el.ondragstart=ondragstart;
|
||||
el.ondrop=ondrop;
|
||||
el.ondragover=ondragover;
|
||||
|
||||
// reset the behaviors of the btns
|
||||
var upBtns=el.querySelectorAll(".cbi-button.cbi-button-up");
|
||||
if (upBtns && upBtns.length > 0){
|
||||
upBtns.forEach(function (_el){
|
||||
_el.onclick=function (){
|
||||
moveToTop(el.id);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
var downBtns=el.querySelectorAll(".cbi-button.cbi-button-down");
|
||||
if (downBtns && downBtns.length > 0){
|
||||
downBtns.forEach(function (_el){
|
||||
_el.onclick=function (){
|
||||
moveToBottom(el.id);
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// enable
|
||||
enableDragForTable(
|
||||
"#cbi-bypass-servers table",
|
||||
"cbi.sts.bypass.servers"
|
||||
);
|
||||
|
||||
function _cbi_row_top(id) {
|
||||
var dom = document.getElementById("cbi-bypass-" + id);
|
||||
if (dom) {
|
||||
var trs = document.getElementById("cbi-bypass-servers").getElementsByClassName("cbi-section-table-row");
|
||||
if (trs && trs.length > 0) {
|
||||
for (var i = 0; i < trs.length; i++) {
|
||||
var up = dom.getElementsByClassName("cbi-button-up");
|
||||
if (up) {
|
||||
cbi_row_swap(up[0], true, 'cbi.sts.bypass.servers');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var edit_btn = document.getElementById("cbi-bypass-servers").getElementsByClassName("cbi-button cbi-button-edit");
|
||||
for (var i = 0; i < edit_btn.length; i++) {
|
||||
try {
|
||||
var onclick_str = edit_btn[i].getAttribute("onclick");
|
||||
var id = onclick_str.substring(onclick_str.lastIndexOf('/') + 1, onclick_str.length - 1);
|
||||
var td = edit_btn[i].parentNode;
|
||||
var new_div = "";
|
||||
new_div += '<input class="cbi-button" type="button" value="<%:To Top%>" onclick="_cbi_row_top(\'' + id + '\')"/> ';
|
||||
td.innerHTML = new_div + td.innerHTML;
|
||||
}
|
||||
catch(err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,3 @@
|
||||
<%+cbi/valueheader%>
|
||||
<span class="socket-connected" hint="<%=self:cfgvalue(section)%>"><%:None%></span>
|
||||
<%+cbi/valuefooter%>
|
706
luci-app-bypass/luci-app-bypass/luasrc/view/bypass/ssrurl.htm
Normal file
706
luci-app-bypass/luci-app-bypass/luasrc/view/bypass/ssrurl.htm
Normal file
@ -0,0 +1,706 @@
|
||||
<%+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 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."+sid,
|
||||
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("<%:Fatal 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) return false;
|
||||
var v_type=opt.get("type").value;
|
||||
var v_alias=opt.get("alias").value;
|
||||
var _address = ""
|
||||
if (v_type) {
|
||||
try {
|
||||
var v_server = opt.get("server");
|
||||
const ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
|
||||
if (ipv6Regex.test(v_server.value)) {
|
||||
_address = "[" + v_server.value + "]"
|
||||
} else {
|
||||
_address = v_server.value
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
var url=null;
|
||||
switch (v_type){
|
||||
case "ss":
|
||||
|
||||
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)+"@"+
|
||||
_address+":"+
|
||||
v_port.value+"/?";
|
||||
var params='';
|
||||
var v_plugin=opt.get("plugin").value;
|
||||
if (v_plugin){
|
||||
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+="#"+encodeURI(v_alias);
|
||||
if (params[0]=="&"){
|
||||
params=params.substring(1);
|
||||
}
|
||||
url+=params;
|
||||
break;
|
||||
case "ssr":
|
||||
|
||||
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=_address+":"+
|
||||
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);
|
||||
url=b64encsafe(ssr_str);
|
||||
break;
|
||||
case "vmess":
|
||||
var info={};
|
||||
info.v="2";
|
||||
info.ps=v_alias;
|
||||
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 || "0";
|
||||
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;
|
||||
if (info.type=='http'){
|
||||
info.host=opt.get("http_host").value;
|
||||
info.path=opt.get("http_path").value;
|
||||
}
|
||||
}else if (v_transport=="kcp"){
|
||||
info.type=opt.get("kcp_guise").value;
|
||||
info.seed=opt.get("seed").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.serviceName=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));
|
||||
break;
|
||||
case "vless":
|
||||
var v_password=opt.get("uuid");
|
||||
var v_port=opt.get("server_port");
|
||||
url=encodeURIComponent(v_password.value)+
|
||||
"@"+_address+
|
||||
":"+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");
|
||||
params+=opt.query("seed","seed");
|
||||
}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"){
|
||||
params+=opt.query("serviceName","grpc_serviceName");
|
||||
}
|
||||
params+="&type="+v_transport;
|
||||
params+=opt.query("encryption","vless_encryption");
|
||||
if (opt.get("tls").checked || opt.get("xtls").checked){
|
||||
if (opt.get("xtls").checked){
|
||||
v_security="xtls";
|
||||
var v_flow=opt.get("vless_flow").value;
|
||||
params+="&flow="+v_flow;
|
||||
}else{
|
||||
var v_security="tls";
|
||||
}
|
||||
params+="&security="+v_security;
|
||||
params+=opt.query("sni","tls_host");
|
||||
}
|
||||
params+="#"+encodeURI(v_alias);
|
||||
if (params[0]=="&"){
|
||||
params=params.substring(1);
|
||||
}
|
||||
url+=params;
|
||||
break;
|
||||
|
||||
case "trojan":
|
||||
var v_password=opt.get("password");
|
||||
|
||||
var v_port=opt.get("server_port");
|
||||
url=encodeURIComponent(v_password.value)+
|
||||
"@"+_address+
|
||||
":"+v_port.value+"/?";
|
||||
var params='';
|
||||
if (opt.get("tls").checked){
|
||||
params+=opt.query("sni","tls_host");
|
||||
params+="&tls=1"
|
||||
params+=opt.query("allowinsecure","insecure");
|
||||
}
|
||||
params+="#"+encodeURI(v_alias);
|
||||
if (params[0]=="&"){
|
||||
params=params.substring(1);
|
||||
}
|
||||
url+=params;
|
||||
|
||||
break;
|
||||
|
||||
case "hysteria2":
|
||||
var v_port=opt.get("server_port");
|
||||
var params = "";
|
||||
params += opt.query("auth", "hy2_auth_password");
|
||||
params += opt.query("sni", "tls_host");
|
||||
params += opt.query("insecure", "insecure");
|
||||
params += opt.query("obfs", "salamander");
|
||||
params += opt.query("obfs-password", "hy2_obfs_password");
|
||||
|
||||
var url =
|
||||
_address + ":" +
|
||||
v_port.value + "?" +
|
||||
params +
|
||||
"#" + encodeURI(v_alias);
|
||||
}
|
||||
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 style=\'color:green\'><%:Share to clipboard successfully%></font>";
|
||||
}catch (ex){
|
||||
s.innerHTML="<font style=\'color:red\'><%:Unable share to clipboard%></font>";
|
||||
}finally{
|
||||
document.body.removeChild(textarea);
|
||||
}
|
||||
//alert(url);
|
||||
}else{
|
||||
s.innerHTML='';
|
||||
alert("<%:Not a supported Format%>: "+v_type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
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 style=\'color:green\'><%:Copy SSR to clipboard successfully.%></font>";
|
||||
} catch (ex) {
|
||||
s.innerHTML = "<font style=\'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 style=\'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]) {
|
||||
|
||||
//alert(url);
|
||||
case "hysteria":
|
||||
try {
|
||||
var url = new URL("http://" + ssu[1]);
|
||||
var params = url.searchParams;
|
||||
} catch(e) {
|
||||
alert(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
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 = url.hostname;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0].value = url.port || "80";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.hysteria_protocol')[0].value = params.get("protocol") || "udp";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.hy_auth_password')[0].value = params.get("auth") ? "2" : "0";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.hy_auth_password')[0].dispatchEvent(event);
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.auth_payload')[0].value = params.get("auth") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.uplink_capacity')[0].value = params.get("upmbps") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.downlink_capacity')[0].value = params.get("downmbps") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.seed')[0].value = params.get("obfsParam") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.tls_host')[0].value = params.get("peer") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.quic_tls_alpn')[0].value = params.get("alpn") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.insecure')[0].checked = params.get("insecure") ? true : false;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.alias')[0].value = url.hash ? decodeURIComponent(url.hash.slice(1)) : "";
|
||||
|
||||
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
|
||||
return false;
|
||||
case "hysteria2":
|
||||
try {
|
||||
var url = new URL("http://" + ssu[1]);
|
||||
var params = url.searchParams;
|
||||
} catch(e) {
|
||||
alert(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
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 = url.hostname;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0].value = url.port || "80";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.transport_protocol')[0].value = params.get("protocol") || "udp";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.hy2_obfs_type')[0].value = params.get("obfs") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.hy2_obfs_password')[0].value = params.get("obfs_password")|| "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.hy2_auth_password')[0].value = params.get("auth") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.tls_host')[0].value = params.get("sni") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.insecure')[0].checked = params.get("insecure") ? true : false;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.alias')[0].value = url.hash ? decodeURIComponent(url.hash.slice(1)) : "";
|
||||
|
||||
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
|
||||
return false;
|
||||
|
||||
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 style=\'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 style=\'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 style=\'color:green\'><%:Import configuration information successfully.%></font>";
|
||||
return false;
|
||||
case "trojan":
|
||||
try {
|
||||
var url = new URL("http://" + ssu[1]);
|
||||
} catch(e) {
|
||||
alert(e)
|
||||
return false;
|
||||
}
|
||||
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.alias')[0].value = url.hash ? decodeURIComponent(url.hash.slice(1)) : "";
|
||||
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);
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.server')[0].value = url.hostname;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0].value = url.port || "80";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.password')[0].value = decodeURIComponent(url.username);
|
||||
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 = url.searchParams.get("sni");
|
||||
|
||||
s.innerHTML = "<font style=\'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 + '.alter_id')[0].value = ssm.aid;
|
||||
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"
|
||||
} else {
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.http_host')[0].value = ssm.host;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.http_path')[0].value = ssm.path;
|
||||
}
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.tcp_guise')[0].value = ssm.type;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.tcp_guise')[0].dispatchEvent(event);
|
||||
}
|
||||
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 == "httpupgrade") {
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.httpupgrade_host')[0].value = ssm.host;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.httpupgrade_path')[0].value = ssm.path;
|
||||
}
|
||||
if (ssm.net == "splithttp") {
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.splithttp_host')[0].value = ssm.host;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.splithttp_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.sni || ssm.host;
|
||||
}
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.mux')[0].checked = true;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.mux')[0].dispatchEvent(event);
|
||||
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
|
||||
return false;
|
||||
|
||||
case "vless":
|
||||
try {
|
||||
var url = new URL("http://" + ssu[1]);
|
||||
var params = url.searchParams;
|
||||
} catch(e) {
|
||||
alert(e)
|
||||
return false;
|
||||
}
|
||||
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.alias')[0].value = url.hash ? decodeURIComponent(url.hash.slice(1)) : "";
|
||||
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);
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.server')[0].value = url.hostname;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.server_port')[0].value = url.port || "80";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.vmess_id')[0].value = url.username;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.transport')[0].value =
|
||||
params.get("type") == "http" ? "h2" :
|
||||
(params.get("type") == "raw" ? "raw" :
|
||||
(params.get("type") || "tcp"));
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.transport')[0].dispatchEvent(event);
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.vless_encryption')[0].value = params.get("encryption") || "none";
|
||||
if ([ "tls", "xtls", "reality" ].includes(params.get("security"))) {
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.' + params.get("security"))[0].checked = true;
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.' + params.get("security"))[0].dispatchEvent(event);
|
||||
|
||||
|
||||
if (params.get("security") === "reality") {
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.reality_publickey')[0].value = params.get("pbk") ? decodeURIComponent(params.get("pbk")) : "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.reality_shortid')[0].value = params.get("sid") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.reality_spiderx')[0].value = params.get("spx") ? decodeURIComponent(params.get("spx")) : "";
|
||||
}
|
||||
if (params.get("security") === "xtls") {
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.tls_flow')[0].value = params.get("flow") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.tls_flow')[0].dispatchEvent(event);
|
||||
}
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.fingerprint')[0].value = params.get("fp") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.tls_host')[0].value = params.get("sni") || "";
|
||||
}
|
||||
switch (params.get("type")) {
|
||||
case "ws":
|
||||
if (params.get("security") !== "tls")
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.ws_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.ws_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
|
||||
break;
|
||||
case "httpupgrade":
|
||||
if (params.get("security") !== "tls")
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.httpupgrade_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.httpupgrade_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
|
||||
break;
|
||||
case "splithttp":
|
||||
if (params.get("security") !== "tls")
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.splithttp_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.splithttp_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "/";
|
||||
break;
|
||||
case "kcp":
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.kcp_guise')[0].value = params.get("headerType") || "none";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.seed')[0].value = params.get("seed") || "";
|
||||
break;
|
||||
case "http":
|
||||
/* this is non-standard, bullshit */
|
||||
case "h2":
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.h2_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.h2_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "";
|
||||
break;
|
||||
case "quic":
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.quic_guise')[0].value = params.get("headerType") || "none";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.quic_security')[0].value = params.get("quicSecurity") || "none";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.quic_key')[0].value = params.get("key") || "";
|
||||
break;
|
||||
case "grpc":
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.serviceName')[0].value = params.get("serviceName") || "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.grpc_mode')[0].value = params.get("mode") || "gun";
|
||||
break;
|
||||
case "tcp":
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.tcp_guise')[0].value = params.get("headerType") || "none";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.tcp_guise')[0].dispatchEvent(event);
|
||||
if (params.get("headerType") === "http") {
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.http_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.http_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "";
|
||||
}
|
||||
case "raw":
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.raw_guise')[0].value = params.get("headerType") || "none";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.raw_guise')[0].dispatchEvent(event);
|
||||
if (params.get("headerType") === "http") {
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.http_host')[0].value = params.get("host") ? decodeURIComponent(params.get("host")) : "";
|
||||
document.getElementsByName('cbid.bypass.' + sid + '.http_path')[0].value = params.get("path") ? decodeURIComponent(params.get("path")) : "";
|
||||
}
|
||||
break;
|
||||
}
|
||||
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
|
||||
return false;
|
||||
default:
|
||||
s.innerHTML = "<font style=\'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%>')" />
|
||||
<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%>
|
557
luci-app-bypass/luci-app-bypass/luasrc/view/bypass/status.htm
Normal file
557
luci-app-bypass/luci-app-bypass/luasrc/view/bypass/status.htm
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,17 @@
|
||||
<%+cbi/valueheader%>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function subscribe(s){
|
||||
s.disabled=true;
|
||||
s.value='<%:Refresh...%>';
|
||||
const S_URL = '<%=luci.dispatcher.build_url("admin", "services", "bypass","log")%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin","services","bypass","subscribe")%>',null,function(x,rv){
|
||||
setTimeout(function(){
|
||||
window.location = S_URL
|
||||
},60);
|
||||
|
||||
});
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:Update All Subscribe Servers%> " onclick="return subscribe(this)"/>
|
||||
<%+cbi/valuefooter%>
|
992
luci-app-bypass/luci-app-bypass/po/zh-cn/bypass.po
Normal file
992
luci-app-bypass/luci-app-bypass/po/zh-cn/bypass.po
Normal file
@ -0,0 +1,992 @@
|
||||
msgid "Base Setting"
|
||||
msgstr "基本设置"
|
||||
|
||||
msgid "Bypass Settings"
|
||||
msgstr "Bypass 设置"
|
||||
|
||||
msgid "Support SS/SSR/XRAY/TROJAN/NAIVEPROXY/SOCKS5/TUN etc."
|
||||
msgstr "支持 SS/SSR/Xray/Trojan/NavieProxy/Socks5/TUN 等协议"
|
||||
|
||||
msgid "Bypass RUNNING"
|
||||
msgstr "Bypass 客户端运行中"
|
||||
|
||||
msgid "Bypass NOT RUNNING"
|
||||
msgstr "Bypass 客户端未运行"
|
||||
|
||||
msgid "Main Server"
|
||||
msgstr "TCP主服务器"
|
||||
|
||||
msgid "Client"
|
||||
msgstr "客户端"
|
||||
|
||||
msgid "Enable"
|
||||
msgstr "启用"
|
||||
|
||||
msgid "Enable Service[Master Switch]"
|
||||
msgstr "启用服务【总开关】"
|
||||
|
||||
msgid "Disable"
|
||||
msgstr "停用"
|
||||
|
||||
msgid "UDP Server"
|
||||
msgstr "游戏模式UDP服务器"
|
||||
|
||||
msgid "Same as Global Server"
|
||||
msgstr "与全局服务器相同"
|
||||
|
||||
msgid "Netflix Server"
|
||||
msgstr "Netflix服务器"
|
||||
|
||||
msgid "Netflix Query DNS"
|
||||
msgstr "Netflix查询DNS"
|
||||
|
||||
msgid "Multi Threads Option"
|
||||
msgstr "多线程并发转发"
|
||||
|
||||
msgid "Auto Threads"
|
||||
msgstr "自动(CPU线程数)"
|
||||
|
||||
msgid "1 Thread"
|
||||
msgstr "单线程"
|
||||
|
||||
msgid "2 Threads"
|
||||
msgstr "2 线程"
|
||||
|
||||
msgid "4 Threads"
|
||||
msgstr "4 线程"
|
||||
|
||||
msgid "8 Threads"
|
||||
msgstr "8 线程"
|
||||
|
||||
msgid "16 Threads"
|
||||
msgstr "16 线程"
|
||||
|
||||
msgid "32 Threads"
|
||||
msgstr "32 线程"
|
||||
|
||||
msgid "64 Threads"
|
||||
msgstr "64 线程"
|
||||
|
||||
msgid "128 Threads"
|
||||
msgstr "128 线程"
|
||||
|
||||
msgid "Running Mode"
|
||||
msgstr "运行模式"
|
||||
|
||||
msgid "GFW List Mode"
|
||||
msgstr "GFW列表模式"
|
||||
|
||||
msgid "Smart Mode"
|
||||
msgstr "智能模式(基于ChinaDNS-NG)"
|
||||
|
||||
msgid "Global Mode"
|
||||
msgstr "全局模式"
|
||||
|
||||
msgid "Oversea Mode"
|
||||
msgstr "海外用户回国模式"
|
||||
|
||||
msgid "Proxy Ports"
|
||||
msgstr "需要代理的端口"
|
||||
|
||||
msgid "Load GFW List"
|
||||
msgstr "加载GFW列表"
|
||||
|
||||
msgid "GFW domains Update URL"
|
||||
msgstr "防火墙域名列表更新链接"
|
||||
|
||||
msgid "China IPv4 Update URL"
|
||||
msgstr "中国IPv4段更新链接"
|
||||
|
||||
msgid "China IPv6 Update URL"
|
||||
msgstr "中国IPv6段更新链接"
|
||||
|
||||
msgid "If the domestic DNS does not hijack foreign domain name to domestic IP, No need to be enabled"
|
||||
msgstr "如果国内DNS未劫持国外域名返回国内的IP,不需要启用"
|
||||
|
||||
msgid "anti-AD Update URL"
|
||||
msgstr "去广告更新链接"
|
||||
|
||||
msgid "Enable DNS anti-AD"
|
||||
msgstr "开启DNS去广告"
|
||||
|
||||
msgid "Take over LAN DNS"
|
||||
msgstr "接管局域网DNS"
|
||||
|
||||
msgid "Redirect LAN device DNS to router(Do not disable if you do not understand)"
|
||||
msgstr "将LAN设备DNS重定向到路由器(如果不理解,请不要禁用)"
|
||||
|
||||
msgid "All Ports"
|
||||
msgstr "所有端口(默认)"
|
||||
|
||||
msgid "Only Common Ports"
|
||||
msgstr "仅常用端口(不走P2P流量到代理)"
|
||||
|
||||
msgid "Custom format is 22,53,80,143,443,465,587,853,993,995,9418"
|
||||
msgstr "自定义端口格式为 22,53,80,143,443,465,587,853,993,995,9418"
|
||||
|
||||
msgid "Remote Query DNS"
|
||||
msgstr "远程查询DNS"
|
||||
|
||||
msgid "DNS Query Method"
|
||||
msgstr "DNS查询方式"
|
||||
|
||||
msgid "Bootstrap DNS servers"
|
||||
msgstr "Bootstrap DNS服务器"
|
||||
|
||||
msgid "Bootstrap DNS server is used to resolve IP addresses in the upstream DoH/DoT resolution list"
|
||||
msgstr "Bootstrap DNS服务器用于解析上游DoH/DoT解析列表中的IP地址"
|
||||
|
||||
msgid "Main"
|
||||
msgstr "主要"
|
||||
|
||||
msgid "Google"
|
||||
msgstr "谷歌"
|
||||
|
||||
msgid "Do not use the same DNS server as the global server"
|
||||
msgstr "不要使用与全局服务器相同的DNS"
|
||||
|
||||
msgid "Local Query DNS"
|
||||
msgstr "本地查询DNS"
|
||||
|
||||
msgid "Use SmartDNS query"
|
||||
msgstr "使用SmartDNS查询"
|
||||
|
||||
msgid "Use MOSDNS query"
|
||||
msgstr "使用MOSDNS查询"
|
||||
|
||||
msgid "Ali"
|
||||
msgstr "阿里"
|
||||
|
||||
msgid "Tencent"
|
||||
msgstr "腾讯"
|
||||
|
||||
msgid "BaiDu"
|
||||
msgstr "百度"
|
||||
|
||||
msgid "ISP DNS"
|
||||
msgstr "运营商DNS"
|
||||
|
||||
msgid "ISP"
|
||||
msgstr "运营商"
|
||||
|
||||
msgid "Taiwan"
|
||||
msgstr "台湾"
|
||||
|
||||
msgid "Singapore"
|
||||
msgstr "新加坡"
|
||||
|
||||
msgid "Japan"
|
||||
msgstr "日本"
|
||||
|
||||
msgid "India"
|
||||
msgstr "印度"
|
||||
|
||||
msgid "New York"
|
||||
msgstr "纽约"
|
||||
|
||||
msgid "Germany"
|
||||
msgstr "德国"
|
||||
|
||||
msgid "IPV6 parsing"
|
||||
msgstr "IPV6解析"
|
||||
|
||||
msgid "Use DNS to return IPv6 records"
|
||||
msgstr "使DNS返回IPv6记录"
|
||||
|
||||
msgid "Servers Nodes"
|
||||
msgstr "节点列表"
|
||||
|
||||
msgid "Subscribe"
|
||||
msgstr "节点订阅"
|
||||
|
||||
msgid "User-Agent"
|
||||
msgstr "用户代理(User-Agent)"
|
||||
|
||||
msgid "Servers subscription and manage"
|
||||
msgstr "服务器节点订阅与管理"
|
||||
|
||||
msgid "Auto Update"
|
||||
msgstr "自动更新"
|
||||
|
||||
msgid "Start Run Delay(second)"
|
||||
msgstr "开机时延时启动(秒)"
|
||||
|
||||
msgid "Auto Update Server subscription,GFW list and CHN route"
|
||||
msgstr "自动更新服务器订阅、GFW列表和 CHN路由表"
|
||||
|
||||
msgid "Update time (every day)"
|
||||
msgstr "更新时间 (每天)"
|
||||
|
||||
msgid "Subscribe URL"
|
||||
msgstr "SS/SSR/V2/TROJAN订阅URL"
|
||||
|
||||
msgid "Subscribe Filter Words"
|
||||
msgstr "订阅节点关键字过滤"
|
||||
|
||||
msgid "Filter Words splited by /"
|
||||
msgstr "命中关键字的节点将被丢弃或保留。多个关键字用 / 分隔"
|
||||
|
||||
msgid "Filter Words Mode"
|
||||
msgstr "节点关键字过滤模式"
|
||||
|
||||
msgid "Discard Mode"
|
||||
msgstr "丢弃命中关键词的节点"
|
||||
|
||||
msgid "Keep Mode"
|
||||
msgstr "保留命中关键词的节点"
|
||||
|
||||
msgid "Save Subscribe Setting"
|
||||
msgstr "保存订阅列表及设置"
|
||||
|
||||
msgid "Update Subscribe List"
|
||||
msgstr "更新订阅URL列表"
|
||||
|
||||
msgid "UpdateRule"
|
||||
msgstr "更新规则"
|
||||
|
||||
msgid "Update All Rule List"
|
||||
msgstr "手动更新规则列表"
|
||||
|
||||
msgid "Update subscribe url or Setting list first"
|
||||
msgstr "修改订阅URL和节点关键字后,点击保存才生效"
|
||||
|
||||
msgid "Subscribe Default Auto-Switch"
|
||||
msgstr "订阅新节点故障转移设置"
|
||||
|
||||
msgid "Subscribe new add server default Auto-Switch on"
|
||||
msgstr "订阅加入的新节点默认开启故障转移"
|
||||
|
||||
msgid "Through proxy update"
|
||||
msgstr "通过代理更新"
|
||||
|
||||
msgid "Through proxy update list,Not Recommended"
|
||||
msgstr "通过路由器自身代理更新订阅"
|
||||
|
||||
msgid "Update All Subscribe Servers"
|
||||
msgstr "更新所有订阅服务器节点"
|
||||
|
||||
msgid "Delete All Subscribe Servers"
|
||||
msgstr "删除所有订阅服务器节点"
|
||||
|
||||
msgid "Server Count"
|
||||
msgstr "服务器节点数量"
|
||||
|
||||
msgid "Type"
|
||||
msgstr "类型"
|
||||
|
||||
msgid "Alias"
|
||||
msgstr "别名"
|
||||
|
||||
msgid "None"
|
||||
msgstr "无"
|
||||
|
||||
msgid "Server Port"
|
||||
msgstr "端口"
|
||||
|
||||
msgid "Socket Connected"
|
||||
msgstr "连接测试"
|
||||
|
||||
msgid "TCPing Latency"
|
||||
msgstr "TCPing延迟"
|
||||
|
||||
msgid "connecting"
|
||||
msgstr "连接中"
|
||||
|
||||
msgid "ok"
|
||||
msgstr "成功"
|
||||
|
||||
msgid "fail"
|
||||
msgstr "失败"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "使用"
|
||||
|
||||
msgid "Auto Switch"
|
||||
msgstr "故障转移"
|
||||
|
||||
msgid "Edit Server"
|
||||
msgstr "编辑服务器配置"
|
||||
|
||||
msgid "Paste ssr url here"
|
||||
msgstr "在此处粘贴ssr://网址"
|
||||
|
||||
msgid "Unable to copy SSR to clipboard."
|
||||
msgstr "无法复制SSR网址到剪贴板。"
|
||||
|
||||
msgid "Copy SSR to clipboard successfully."
|
||||
msgstr "成功复制SSR网址到剪贴板。"
|
||||
|
||||
msgid "Server Node Type"
|
||||
msgstr "服务器节点类型"
|
||||
|
||||
msgid "Using incorrect encryption mothod may causes service fail to start"
|
||||
msgstr "输入不正确的参数组合可能会导致服务无法启动"
|
||||
|
||||
msgid "Alias(optional)"
|
||||
msgstr "别名(可选)"
|
||||
|
||||
msgid "Network interface to use"
|
||||
msgstr "选择使用的网络接口"
|
||||
|
||||
msgid "Redirect traffic to this network interface"
|
||||
msgstr "分流到这个网络接口"
|
||||
|
||||
msgid "Server Address"
|
||||
msgstr "服务器地址"
|
||||
|
||||
msgid "Enable Authentication"
|
||||
msgstr "启用用户名/密码认证"
|
||||
|
||||
msgid "Username"
|
||||
msgstr "用户名"
|
||||
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
|
||||
msgid "Encrypt Method"
|
||||
msgstr "加密方式"
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "插件"
|
||||
|
||||
msgid "Plugin Opts"
|
||||
msgstr "插件参数"
|
||||
|
||||
msgid "Protocol"
|
||||
msgstr "传输协议"
|
||||
|
||||
msgid "Protocol param (optional)"
|
||||
msgstr "传输协议参数(可选)"
|
||||
|
||||
msgid "Authentication type"
|
||||
msgstr "验证类型"
|
||||
|
||||
msgid "Authentication payload"
|
||||
msgstr "验证载荷"
|
||||
|
||||
msgid "Auth Password"
|
||||
msgstr "Auth密码"
|
||||
|
||||
msgid "Obfs Password"
|
||||
msgstr "Obfs密码"
|
||||
|
||||
msgid "NOTE: If the server uses the userpass authentication, the format must be username:password."
|
||||
msgstr "注意: 如果服务器使用 userpass 验证,格式必须是 username:password。"
|
||||
|
||||
msgid "Enable Port Hopping"
|
||||
msgstr "启用端口跃迁"
|
||||
|
||||
|
||||
msgid "Port Hopping Interval(Unit:Second)"
|
||||
msgstr "端口跃迁间隔(单位:秒)"
|
||||
|
||||
msgid "Enable Lazy Mode"
|
||||
msgstr "启用懒狗模式"
|
||||
|
||||
msgid "Enable Obfuscation"
|
||||
msgstr "启用混淆功能"
|
||||
|
||||
msgid "Obfuscation Type"
|
||||
msgstr "混淆类型"
|
||||
|
||||
msgid "Obfuscation Password"
|
||||
msgstr "混淆密码"
|
||||
|
||||
msgid "TUIC User UUID"
|
||||
msgstr "TUIC用户uuid"
|
||||
|
||||
msgid "TUIC Server IP Address"
|
||||
msgstr "TUIC 服务器IP地址"
|
||||
|
||||
msgid "TUIC User Password"
|
||||
msgstr "TUIC用户密钥"
|
||||
|
||||
msgid "native UDP characteristics"
|
||||
msgstr "原生UDP特性"
|
||||
|
||||
msgid "lossless UDP relay using QUIC streams"
|
||||
msgstr "使用 QUIC 流的无损 UDP 中继"
|
||||
|
||||
msgid "native UDP characteristics"
|
||||
msgstr "原生UDP特性"
|
||||
|
||||
msgid "lossless UDP relay using QUIC streams"
|
||||
msgstr "使用 QUIC 流的无损 UDP 中继"
|
||||
|
||||
msgid "Congestion control algorithm"
|
||||
msgstr "拥塞控制算法"
|
||||
|
||||
msgid "Heartbeat interval(second)"
|
||||
msgstr "保活心跳包发送间隔(单位:秒)"
|
||||
|
||||
msgid "Timeout for establishing a connection to server(second)"
|
||||
msgstr "连接超时时间(单位:秒)"
|
||||
|
||||
msgid "Garbage collection interval(second)"
|
||||
msgstr "UDP数据包片残片清理间隔(单位:秒)"
|
||||
|
||||
msgid "Garbage collection lifetime(second)"
|
||||
msgstr "UDP数据包残片在服务器的保留时间(单位:秒)"
|
||||
|
||||
msgid "Disable SNI"
|
||||
msgstr "关闭SNI服务器名称指示"
|
||||
|
||||
msgid "Enable 0-RTT QUIC handshake"
|
||||
msgstr "客户端启用 0-RTT QUIC 连接握手"
|
||||
|
||||
msgid "TUIC send window"
|
||||
msgstr "发送窗口(无需确认即可发送的最大字节数:默认8Mb*2)"
|
||||
|
||||
msgid "TUIC receive window"
|
||||
msgstr "接收窗口(无需确认即可接收的最大字节数:默认8Mb)"
|
||||
|
||||
msgid "Hysterir QUIC parameters"
|
||||
msgstr "QUIC参数"
|
||||
|
||||
msgid "QUIC initStreamReceiveWindow"
|
||||
msgstr "QUIC初始流接收窗口大小。"
|
||||
|
||||
msgid "QUIC maxStreamReceiveWindow"
|
||||
msgstr "QUIC最大的流接收窗口大小"
|
||||
|
||||
msgid "QUIC initConnReceiveWindow"
|
||||
msgstr "QUIC初始的连接接收窗口大小"
|
||||
|
||||
msgid "QUIC maxConnReceiveWindow"
|
||||
msgstr "QUIC最大的连接接收窗口大小"
|
||||
|
||||
msgid "QUIC maxIdleTimeout(Unit:second)"
|
||||
msgstr "QUIC最长空闲超时时间(单位:秒)"
|
||||
|
||||
msgid "The keep-alive period.(Unit:second)"
|
||||
msgstr "心跳包发送间隔(单位:秒)"
|
||||
|
||||
|
||||
msgid "Certificate fingerprint"
|
||||
msgstr "证书指纹"
|
||||
|
||||
msgid "shadowTLS protocol Version"
|
||||
msgstr "ShadowTLS协议版本"
|
||||
|
||||
msgid "TLS 1.3 Strict mode"
|
||||
msgstr "TLS 1.3 限定模式"
|
||||
|
||||
msgid "Disable TCP No_delay"
|
||||
msgstr "禁用TCP无延迟"
|
||||
|
||||
msgid "shadow-TLS SNI"
|
||||
msgstr "服务器名称指示"
|
||||
|
||||
msgid "Shadow-TLS ChainPoxy type"
|
||||
msgstr "代理链类型"
|
||||
|
||||
msgid "Shadowsocks-rust Version"
|
||||
msgstr "shadowsocks rust版本"
|
||||
|
||||
msgid "Vmess Protocol"
|
||||
msgstr "VMESS协议"
|
||||
|
||||
msgid "Shadowsocks password"
|
||||
msgstr "shadowsocks密码"
|
||||
|
||||
msgid "Uplink Capacity(Default:Mbps)"
|
||||
msgstr "上行链路容量(默认:Mbps)"
|
||||
|
||||
msgid "Downlink Capacity(Default:Mbps)"
|
||||
msgstr "下行链路容量(默认:Mbps)"
|
||||
|
||||
msgid "Dual-stack Listening Socket"
|
||||
msgstr "双栈Socket监听"
|
||||
|
||||
|
||||
msgid "DNS Query Mode For Shunt Mode"
|
||||
msgstr "分流模式下的 DNS 查询模式"
|
||||
|
||||
msgid "Anti-pollution DNS Server For Shunt Mode"
|
||||
msgstr "分流模式下的访问国外域名 DNS 服务器"
|
||||
|
||||
msgid "Disable IPv6 In MOSDNS Query Mode (Shunt Mode)"
|
||||
msgstr "禁止 MOSDNS 返回 IPv6 记录 (分流模式)"
|
||||
|
||||
|
||||
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)"
|
||||
msgstr "混淆参数(可选)"
|
||||
|
||||
msgid "VLESS Encryption"
|
||||
msgstr "VLESS 加密"
|
||||
|
||||
msgid "Transport"
|
||||
msgstr "传输协议"
|
||||
|
||||
msgid "allowInsecure"
|
||||
msgstr "允许不安全连接"
|
||||
|
||||
msgid "concurrency"
|
||||
msgstr "TCP 最大并发连接数"
|
||||
|
||||
msgid "xudpConcurrency"
|
||||
msgstr "UDP 最大并发连接数"
|
||||
|
||||
msgid "xudpProxyUDP443"
|
||||
msgstr "对被代理的 UDP/443 流量处理方式"
|
||||
|
||||
msgid "custom_tcpcongestion"
|
||||
msgstr "连接服务器节点的 TCP 拥塞控制算法"
|
||||
|
||||
msgid "comment_tcpcongestion_disable"
|
||||
msgstr "系统默认值"
|
||||
|
||||
msgid "If true, allowss insecure connection at TLS client, e.g., TLS server uses unverifiable certificates."
|
||||
msgstr "是否允许不安全连接。当选择时,将不会检查远端主机所提供的 TLS 证书的有效性。"
|
||||
|
||||
msgid "Flow"
|
||||
msgstr "流控 (Flow)"
|
||||
|
||||
msgid "Concurrency"
|
||||
msgstr "最大并发连接数"
|
||||
|
||||
msgid "Self-signed Certificate"
|
||||
msgstr "自签证书"
|
||||
|
||||
msgid "If you have a self-signed certificate,please check the box"
|
||||
msgstr "如果你使用自签证书,请选择"
|
||||
|
||||
msgid "upload"
|
||||
msgstr "上传证书"
|
||||
|
||||
msgid "Upload"
|
||||
msgstr "上传"
|
||||
|
||||
msgid "Create upload file error"
|
||||
msgstr "创建证书文件失败"
|
||||
|
||||
msgid "No specify upload file"
|
||||
msgstr "没有上传证书"
|
||||
|
||||
msgid "Current Certificate Path"
|
||||
msgstr "当前证书路径"
|
||||
|
||||
msgid "Please confirm the current certificate path"
|
||||
msgstr "请选择确认所传证书,证书不正确将无法运行"
|
||||
|
||||
msgid "TCP Fast Open"
|
||||
msgstr "TCP快速打开"
|
||||
|
||||
msgid "Enable Auto Switch"
|
||||
msgstr "启用故障转移"
|
||||
|
||||
msgid "Local Port"
|
||||
msgstr "本地端口"
|
||||
|
||||
msgid "KcpTun Enable"
|
||||
msgstr "KcpTun 启用"
|
||||
|
||||
msgid "KcpTun Port"
|
||||
msgstr "KcpTun 端口"
|
||||
|
||||
msgid "KcpTun Password"
|
||||
msgstr "KcpTun 密码"
|
||||
|
||||
msgid "KcpTun Param"
|
||||
msgstr "KcpTun 参数"
|
||||
|
||||
msgid "Access Control"
|
||||
msgstr "访问控制"
|
||||
|
||||
msgid "IP Access Control"
|
||||
msgstr "IP访问控制"
|
||||
|
||||
msgid "WAN IP AC"
|
||||
msgstr "WAN IP访问控制"
|
||||
|
||||
msgid "WAN White List IP"
|
||||
msgstr "不走代理的WAN IP"
|
||||
|
||||
msgid "WAN Force Proxy IP"
|
||||
msgstr "强制走代理的WAN IP"
|
||||
|
||||
msgid "LAN IP AC"
|
||||
msgstr "LAN IP访问控制"
|
||||
|
||||
msgid "LAN Access Control"
|
||||
msgstr "内网客户端分流代理控制"
|
||||
|
||||
msgid "Allow listed only"
|
||||
msgstr "仅允许列表内主机"
|
||||
|
||||
msgid "Allow all except listed"
|
||||
msgstr "除列表外主机皆允许"
|
||||
|
||||
msgid "LAN Host List"
|
||||
msgstr "内网主机列表"
|
||||
|
||||
msgid "LAN Force Proxy Host List"
|
||||
msgstr "全局代理的LAN IP"
|
||||
|
||||
msgid "Game Mode Host List"
|
||||
msgstr "增强游戏模式客户端LAN IP"
|
||||
|
||||
msgid "Domain List"
|
||||
msgstr "域名列表"
|
||||
|
||||
msgid "Direct Domain List"
|
||||
msgstr "不走代理的域名"
|
||||
|
||||
msgid "Proxy Domain List"
|
||||
msgstr "强制走代理的域名"
|
||||
|
||||
msgid "These had been joined websites will not proxy."
|
||||
msgstr "加入的域名将不走代理。"
|
||||
|
||||
msgid "These had been joined websites will use proxy."
|
||||
msgstr "加入的域名将走代理。"
|
||||
|
||||
msgid "Not valid domain name, please re-enter!"
|
||||
msgstr "不是有效域名,请重新输入!"
|
||||
|
||||
msgid "Netflix Domain List"
|
||||
msgstr "Netflix分流域名"
|
||||
|
||||
msgid "Oversea Domain List"
|
||||
msgstr "回国模式域名"
|
||||
|
||||
msgid "Preload domain(GFW Only)"
|
||||
msgstr "预加载域名(仅GFW模式)"
|
||||
|
||||
msgid "Advanced Settings"
|
||||
msgstr "高级设置"
|
||||
|
||||
msgid "Server failsafe auto swith settings"
|
||||
msgstr "服务器节点故障故障转移设置"
|
||||
|
||||
msgid "Global SOCKS5 Server"
|
||||
msgstr "SOCKS5服务端(全局)"
|
||||
|
||||
msgid "Enable Process Deamon"
|
||||
msgstr "启用进程自动守护"
|
||||
|
||||
msgid "Switch check cycly(second)"
|
||||
msgstr "故障转移检查周期(秒)"
|
||||
|
||||
msgid "Check timout(second)"
|
||||
msgstr "切换检查超时时间(秒)"
|
||||
|
||||
msgid "Check Try Count"
|
||||
msgstr "切换检查重试次数"
|
||||
|
||||
msgid "Reverse"
|
||||
msgstr "逆序"
|
||||
|
||||
msgid "Taobao Delay"
|
||||
msgstr "淘宝延时"
|
||||
|
||||
msgid "Baidu Delay"
|
||||
msgstr "百度延时"
|
||||
|
||||
msgid "Rule status"
|
||||
msgstr "规则版本"
|
||||
|
||||
msgid "Google Delay"
|
||||
msgstr "谷歌延时"
|
||||
|
||||
msgid "Global SOCKS5 Proxy Server"
|
||||
msgstr "SOCKS5 代理服务端(全局)"
|
||||
|
||||
msgid "Github Delay"
|
||||
msgstr "Github延时"
|
||||
|
||||
msgid "Youtube Delay"
|
||||
msgstr "Youtube延时"
|
||||
|
||||
msgid "Server"
|
||||
msgstr "服务器"
|
||||
|
||||
msgid "SSR Server"
|
||||
msgstr "服务端"
|
||||
|
||||
msgid "Global Setting"
|
||||
msgstr "全局设置"
|
||||
|
||||
msgid "Enable Server"
|
||||
msgstr "启动服务端"
|
||||
|
||||
msgid "Server Setting"
|
||||
msgstr "服务端配置"
|
||||
|
||||
msgid "Server Type"
|
||||
msgstr "服务端类型"
|
||||
|
||||
msgid "Encrypt Method (SS)"
|
||||
msgstr "加密方式 (SS)"
|
||||
|
||||
msgid "Plugin (SS)"
|
||||
msgstr "插件 (SS)"
|
||||
|
||||
msgid "Warning! Please do not reuse the port!"
|
||||
msgstr "警告!请不要重复使用端口!"
|
||||
|
||||
msgid "Enable Once Auth Mode"
|
||||
msgstr "启用一次性认证"
|
||||
|
||||
msgid "Enable Once Auth,the client IP that passed the authentication will be added to the whitelist address, this IP no longer needs to be verified"
|
||||
msgstr "启用一次性认证后会将通过认证的客户端IP地址加入白名单,之后的连接不再进行认证"
|
||||
|
||||
msgid "Connection Timeout"
|
||||
msgstr "连接超时"
|
||||
|
||||
msgid "Unknown"
|
||||
msgstr "未知"
|
||||
|
||||
msgid "Not exist"
|
||||
msgstr "未安装可执行文件"
|
||||
|
||||
msgid "Status"
|
||||
msgstr "状态"
|
||||
|
||||
msgid "Global Client"
|
||||
msgstr "TCP透明代理"
|
||||
|
||||
msgid "Running"
|
||||
msgstr "运行中"
|
||||
|
||||
msgid "Not Running"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "Game Mode UDP Relay"
|
||||
msgstr "游戏模式UDP中继"
|
||||
|
||||
msgid "Local Servers"
|
||||
msgstr "本机服务端"
|
||||
|
||||
msgid "KcpTun Version"
|
||||
msgstr "KcpTun 版本号"
|
||||
|
||||
|
||||
msgid "No Check"
|
||||
msgstr "未检查"
|
||||
|
||||
msgid "Check..."
|
||||
msgstr "正在检查.."
|
||||
|
||||
msgid "Connect OK"
|
||||
msgstr "连接正常"
|
||||
|
||||
msgid "Connect Error"
|
||||
msgstr "连接错误"
|
||||
|
||||
msgid "Check Connect"
|
||||
msgstr "检查连通性"
|
||||
|
||||
msgid "GFW List"
|
||||
msgstr "GFW列表"
|
||||
|
||||
msgid "Refresh Data"
|
||||
msgstr "更新数据"
|
||||
|
||||
msgid "Records"
|
||||
msgstr "条"
|
||||
|
||||
msgid "Refresh..."
|
||||
msgstr "正在更新,请稍候.."
|
||||
|
||||
msgid "Refresh OK!"
|
||||
msgstr "已更新"
|
||||
|
||||
msgid "Refresh Error!"
|
||||
msgstr "更新失败!"
|
||||
|
||||
msgid "No New data!"
|
||||
msgstr "已经最新!"
|
||||
|
||||
msgid "Total Record:"
|
||||
msgstr "总数:"
|
||||
|
||||
msgid "China IPv4 List"
|
||||
msgstr "国内IPv4列表"
|
||||
|
||||
msgid "China IPv6 List"
|
||||
msgstr "国内IPv6列表"
|
||||
|
||||
msgid "Preventing DNS pollution"
|
||||
msgstr "防止DNS污染(测试功能)"
|
||||
|
||||
msgid "China Domains Update URL"
|
||||
msgstr "国内域名列表"
|
||||
|
||||
msgid "Configure block domain list."
|
||||
msgstr "配置屏蔽域名列表(禁止联网)"
|
||||
|
||||
msgid "Domain DNS Block Setting"
|
||||
msgstr "域名屏蔽设置"
|
||||
|
||||
msgid "IP Blacklist Setting"
|
||||
msgstr "IP黑名单屏蔽设置"
|
||||
|
||||
msgid "Set Specific ip blacklist."
|
||||
msgstr "设置指定的IP黑名单屏蔽列表(禁止联网)。"
|
||||
|
||||
msgid "Check Server Port"
|
||||
msgstr "【服务器端口】检查"
|
||||
|
||||
msgid "Check Server"
|
||||
msgstr "检查服务器"
|
||||
|
||||
msgid "Log"
|
||||
msgstr "日志"
|
||||
|
||||
msgid "Finger Print"
|
||||
msgstr "指纹伪造"
|
||||
|
||||
msgid "Shadowsocks2"
|
||||
msgstr "二次加密"
|
||||
|
||||
msgid "From Share URL"
|
||||
msgstr "导入配置信息"
|
||||
|
||||
msgid "Build Share URL"
|
||||
msgstr "导出配置信息"
|
||||
|
||||
msgid "Import Finished"
|
||||
msgstr "导入完成"
|
||||
|
||||
msgid "Not a supported Format"
|
||||
msgstr "不支持此格式"
|
||||
|
||||
msgid "Invalid Share URL Format"
|
||||
msgstr "无效的配置链接"
|
||||
|
||||
msgid "User cancelled"
|
||||
msgstr "用户已取消"
|
||||
|
||||
msgid "Paste Share URL Here"
|
||||
msgstr "在此处粘贴配置链接"
|
||||
|
||||
msgid "Unable share to clipboard"
|
||||
msgstr "复制配置链接到剪贴板失败"
|
||||
|
||||
msgid "Share to clipboard successfully"
|
||||
msgstr "成功复制配置链接到剪贴板"
|
||||
|
||||
msgid "Faltal on get option:"
|
||||
msgstr "获取选项错误:"
|
||||
|
||||
msgid "Faltal on set option:"
|
||||
msgstr "获取选项错误:"
|
||||
|
||||
msgid "Check update"
|
||||
msgstr "检查更新"
|
||||
|
||||
msgid "Update..."
|
||||
msgstr "更新中"
|
||||
|
||||
msgid "It is the latest version"
|
||||
msgstr "已是最新版本"
|
||||
|
||||
msgid "Update successful"
|
||||
msgstr "更新成功"
|
||||
|
||||
msgid "Click to update"
|
||||
msgstr "点击更新"
|
||||
|
||||
msgid "Updating..."
|
||||
msgstr "更新中"
|
||||
|
||||
msgid "Unexpected error"
|
||||
msgstr "意外错误"
|
||||
|
||||
msgid "Updating, are you sure to close?"
|
||||
msgstr "正在更新,你确认要关闭吗?"
|
||||
|
||||
msgid "Downloading..."
|
||||
msgstr "下载中"
|
||||
|
||||
msgid "Unpacking..."
|
||||
msgstr "解压中"
|
||||
|
||||
msgid "Moving..."
|
||||
msgstr "移动中"
|
||||
|
||||
msgid "App Update"
|
||||
msgstr "组件更新"
|
||||
|
||||
msgid "Please confirm that your firmware supports FPU."
|
||||
msgstr "请确认你的固件支持FPU。"
|
||||
|
||||
msgid "Make sure there is enough space to install %s"
|
||||
msgstr "确保有足够的空间安装 %s"
|
||||
|
||||
msgid "RUNNING"
|
||||
msgstr "运行中"
|
||||
|
||||
msgid "NOT RUNNING"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "Working..."
|
||||
msgstr "连接正常"
|
||||
|
||||
msgid "Problem detected!"
|
||||
msgstr "连接失败"
|
||||
|
||||
msgid "Very Fast"
|
||||
msgstr "非常快"
|
||||
|
||||
msgid "Fast"
|
||||
msgstr "很快"
|
||||
|
||||
msgid "General"
|
||||
msgstr "一般般"
|
||||
|
||||
msgid "Slow"
|
||||
msgstr "很慢"
|
||||
|
||||
msgid "Very Slow"
|
||||
msgstr "非常慢"
|
||||
|
||||
msgid "Touch Check"
|
||||
msgstr "点我检测"
|
||||
|
||||
|
||||
msgid "Httpupgrade Host"
|
||||
msgstr "HTTPUpgrade 主机名"
|
||||
|
||||
msgid "Httpupgrade Path"
|
||||
msgstr "HTTPUpgrade 路径"
|
||||
|
||||
msgid "Socks5 Server"
|
||||
msgstr "Socks5服务端"
|
||||
|
||||
msgid "Running Status"
|
||||
msgstr "运行状态"
|
||||
|
||||
msgid "Node Check"
|
||||
msgstr "节点检测"
|
||||
|
||||
msgid "Check..."
|
||||
msgstr "检测中..."
|
||||
|
||||
msgid "Clear Log"
|
||||
msgstr "清除日志"
|
||||
|
||||
msgid "Clear"
|
||||
msgstr "清除"
|
||||
|
||||
msgid "To Top"
|
||||
msgstr "置顶"
|
||||
|
||||
msgid "Used with AdGuardHome"
|
||||
msgstr "与AdGuardHome搭配使用"
|
||||
|
||||
msgid "Luci-app-adguardhome require"
|
||||
msgstr "请确保luci-app-adguardhome能正常启用,本插件会联动开启并配置ADG,只需要选择过滤规则其它无需任何设置"
|
992
luci-app-bypass/luci-app-bypass/po/zh_Hans/bypass.po
Normal file
992
luci-app-bypass/luci-app-bypass/po/zh_Hans/bypass.po
Normal file
@ -0,0 +1,992 @@
|
||||
msgid "Base Setting"
|
||||
msgstr "基本设置"
|
||||
|
||||
msgid "Bypass Settings"
|
||||
msgstr "Bypass 设置"
|
||||
|
||||
msgid "Support SS/SSR/XRAY/TROJAN/NAIVEPROXY/SOCKS5/TUN etc."
|
||||
msgstr "支持 SS/SSR/Xray/Trojan/NavieProxy/Socks5/TUN 等协议"
|
||||
|
||||
msgid "Bypass RUNNING"
|
||||
msgstr "Bypass 客户端运行中"
|
||||
|
||||
msgid "Bypass NOT RUNNING"
|
||||
msgstr "Bypass 客户端未运行"
|
||||
|
||||
msgid "Main Server"
|
||||
msgstr "TCP主服务器"
|
||||
|
||||
msgid "Client"
|
||||
msgstr "客户端"
|
||||
|
||||
msgid "Enable"
|
||||
msgstr "启用"
|
||||
|
||||
msgid "Enable Service[Master Switch]"
|
||||
msgstr "启用服务【总开关】"
|
||||
|
||||
msgid "Disable"
|
||||
msgstr "停用"
|
||||
|
||||
msgid "UDP Server"
|
||||
msgstr "游戏模式UDP服务器"
|
||||
|
||||
msgid "Same as Global Server"
|
||||
msgstr "与全局服务器相同"
|
||||
|
||||
msgid "Netflix Server"
|
||||
msgstr "Netflix服务器"
|
||||
|
||||
msgid "Netflix Query DNS"
|
||||
msgstr "Netflix查询DNS"
|
||||
|
||||
msgid "Multi Threads Option"
|
||||
msgstr "多线程并发转发"
|
||||
|
||||
msgid "Auto Threads"
|
||||
msgstr "自动(CPU线程数)"
|
||||
|
||||
msgid "1 Thread"
|
||||
msgstr "单线程"
|
||||
|
||||
msgid "2 Threads"
|
||||
msgstr "2 线程"
|
||||
|
||||
msgid "4 Threads"
|
||||
msgstr "4 线程"
|
||||
|
||||
msgid "8 Threads"
|
||||
msgstr "8 线程"
|
||||
|
||||
msgid "16 Threads"
|
||||
msgstr "16 线程"
|
||||
|
||||
msgid "32 Threads"
|
||||
msgstr "32 线程"
|
||||
|
||||
msgid "64 Threads"
|
||||
msgstr "64 线程"
|
||||
|
||||
msgid "128 Threads"
|
||||
msgstr "128 线程"
|
||||
|
||||
msgid "Running Mode"
|
||||
msgstr "运行模式"
|
||||
|
||||
msgid "GFW List Mode"
|
||||
msgstr "GFW列表模式"
|
||||
|
||||
msgid "Smart Mode"
|
||||
msgstr "智能模式(基于ChinaDNS-NG)"
|
||||
|
||||
msgid "Global Mode"
|
||||
msgstr "全局模式"
|
||||
|
||||
msgid "Oversea Mode"
|
||||
msgstr "海外用户回国模式"
|
||||
|
||||
msgid "Proxy Ports"
|
||||
msgstr "需要代理的端口"
|
||||
|
||||
msgid "Load GFW List"
|
||||
msgstr "加载GFW列表"
|
||||
|
||||
msgid "GFW domains Update URL"
|
||||
msgstr "防火墙域名列表更新链接"
|
||||
|
||||
msgid "China IPv4 Update URL"
|
||||
msgstr "中国IPv4段更新链接"
|
||||
|
||||
msgid "China IPv6 Update URL"
|
||||
msgstr "中国IPv6段更新链接"
|
||||
|
||||
msgid "If the domestic DNS does not hijack foreign domain name to domestic IP, No need to be enabled"
|
||||
msgstr "如果国内DNS未劫持国外域名返回国内的IP,不需要启用"
|
||||
|
||||
msgid "anti-AD Update URL"
|
||||
msgstr "去广告更新链接"
|
||||
|
||||
msgid "Enable DNS anti-AD"
|
||||
msgstr "开启DNS去广告"
|
||||
|
||||
msgid "Take over LAN DNS"
|
||||
msgstr "接管局域网DNS"
|
||||
|
||||
msgid "Redirect LAN device DNS to router(Do not disable if you do not understand)"
|
||||
msgstr "将LAN设备DNS重定向到路由器(如果不理解,请不要禁用)"
|
||||
|
||||
msgid "All Ports"
|
||||
msgstr "所有端口(默认)"
|
||||
|
||||
msgid "Only Common Ports"
|
||||
msgstr "仅常用端口(不走P2P流量到代理)"
|
||||
|
||||
msgid "Custom format is 22,53,80,143,443,465,587,853,993,995,9418"
|
||||
msgstr "自定义端口格式为 22,53,80,143,443,465,587,853,993,995,9418"
|
||||
|
||||
msgid "Remote Query DNS"
|
||||
msgstr "远程查询DNS"
|
||||
|
||||
msgid "DNS Query Method"
|
||||
msgstr "DNS查询方式"
|
||||
|
||||
msgid "Bootstrap DNS servers"
|
||||
msgstr "Bootstrap DNS服务器"
|
||||
|
||||
msgid "Bootstrap DNS server is used to resolve IP addresses in the upstream DoH/DoT resolution list"
|
||||
msgstr "Bootstrap DNS服务器用于解析上游DoH/DoT解析列表中的IP地址"
|
||||
|
||||
msgid "Main"
|
||||
msgstr "主要"
|
||||
|
||||
msgid "Google"
|
||||
msgstr "谷歌"
|
||||
|
||||
msgid "Do not use the same DNS server as the global server"
|
||||
msgstr "不要使用与全局服务器相同的DNS"
|
||||
|
||||
msgid "Local Query DNS"
|
||||
msgstr "本地查询DNS"
|
||||
|
||||
msgid "Use SmartDNS query"
|
||||
msgstr "使用SmartDNS查询"
|
||||
|
||||
msgid "Use MOSDNS query"
|
||||
msgstr "使用MOSDNS查询"
|
||||
|
||||
msgid "Ali"
|
||||
msgstr "阿里"
|
||||
|
||||
msgid "Tencent"
|
||||
msgstr "腾讯"
|
||||
|
||||
msgid "BaiDu"
|
||||
msgstr "百度"
|
||||
|
||||
msgid "ISP DNS"
|
||||
msgstr "运营商DNS"
|
||||
|
||||
msgid "ISP"
|
||||
msgstr "运营商"
|
||||
|
||||
msgid "Taiwan"
|
||||
msgstr "台湾"
|
||||
|
||||
msgid "Singapore"
|
||||
msgstr "新加坡"
|
||||
|
||||
msgid "Japan"
|
||||
msgstr "日本"
|
||||
|
||||
msgid "India"
|
||||
msgstr "印度"
|
||||
|
||||
msgid "New York"
|
||||
msgstr "纽约"
|
||||
|
||||
msgid "Germany"
|
||||
msgstr "德国"
|
||||
|
||||
msgid "IPV6 parsing"
|
||||
msgstr "IPV6解析"
|
||||
|
||||
msgid "Use DNS to return IPv6 records"
|
||||
msgstr "使DNS返回IPv6记录"
|
||||
|
||||
msgid "Servers Nodes"
|
||||
msgstr "节点列表"
|
||||
|
||||
msgid "Subscribe"
|
||||
msgstr "节点订阅"
|
||||
|
||||
msgid "User-Agent"
|
||||
msgstr "用户代理(User-Agent)"
|
||||
|
||||
msgid "Servers subscription and manage"
|
||||
msgstr "服务器节点订阅与管理"
|
||||
|
||||
msgid "Auto Update"
|
||||
msgstr "自动更新"
|
||||
|
||||
msgid "Start Run Delay(second)"
|
||||
msgstr "开机时延时启动(秒)"
|
||||
|
||||
msgid "Auto Update Server subscription,GFW list and CHN route"
|
||||
msgstr "自动更新服务器订阅、GFW列表和 CHN路由表"
|
||||
|
||||
msgid "Update time (every day)"
|
||||
msgstr "更新时间 (每天)"
|
||||
|
||||
msgid "Subscribe URL"
|
||||
msgstr "SS/SSR/V2/TROJAN订阅URL"
|
||||
|
||||
msgid "Subscribe Filter Words"
|
||||
msgstr "订阅节点关键字过滤"
|
||||
|
||||
msgid "Filter Words splited by /"
|
||||
msgstr "命中关键字的节点将被丢弃或保留。多个关键字用 / 分隔"
|
||||
|
||||
msgid "Filter Words Mode"
|
||||
msgstr "节点关键字过滤模式"
|
||||
|
||||
msgid "Discard Mode"
|
||||
msgstr "丢弃命中关键词的节点"
|
||||
|
||||
msgid "Keep Mode"
|
||||
msgstr "保留命中关键词的节点"
|
||||
|
||||
msgid "Save Subscribe Setting"
|
||||
msgstr "保存订阅列表及设置"
|
||||
|
||||
msgid "Update Subscribe List"
|
||||
msgstr "更新订阅URL列表"
|
||||
|
||||
msgid "UpdateRule"
|
||||
msgstr "更新规则"
|
||||
|
||||
msgid "Update All Rule List"
|
||||
msgstr "手动更新规则列表"
|
||||
|
||||
msgid "Update subscribe url or Setting list first"
|
||||
msgstr "修改订阅URL和节点关键字后,点击保存才生效"
|
||||
|
||||
msgid "Subscribe Default Auto-Switch"
|
||||
msgstr "订阅新节点故障转移设置"
|
||||
|
||||
msgid "Subscribe new add server default Auto-Switch on"
|
||||
msgstr "订阅加入的新节点默认开启故障转移"
|
||||
|
||||
msgid "Through proxy update"
|
||||
msgstr "通过代理更新"
|
||||
|
||||
msgid "Through proxy update list,Not Recommended"
|
||||
msgstr "通过路由器自身代理更新订阅"
|
||||
|
||||
msgid "Update All Subscribe Servers"
|
||||
msgstr "更新所有订阅服务器节点"
|
||||
|
||||
msgid "Delete All Subscribe Servers"
|
||||
msgstr "删除所有订阅服务器节点"
|
||||
|
||||
msgid "Server Count"
|
||||
msgstr "服务器节点数量"
|
||||
|
||||
msgid "Type"
|
||||
msgstr "类型"
|
||||
|
||||
msgid "Alias"
|
||||
msgstr "别名"
|
||||
|
||||
msgid "None"
|
||||
msgstr "无"
|
||||
|
||||
msgid "Server Port"
|
||||
msgstr "端口"
|
||||
|
||||
msgid "Socket Connected"
|
||||
msgstr "连接测试"
|
||||
|
||||
msgid "TCPing Latency"
|
||||
msgstr "TCPing延迟"
|
||||
|
||||
msgid "connecting"
|
||||
msgstr "连接中"
|
||||
|
||||
msgid "ok"
|
||||
msgstr "成功"
|
||||
|
||||
msgid "fail"
|
||||
msgstr "失败"
|
||||
|
||||
msgid "Apply"
|
||||
msgstr "使用"
|
||||
|
||||
msgid "Auto Switch"
|
||||
msgstr "故障转移"
|
||||
|
||||
msgid "Edit Server"
|
||||
msgstr "编辑服务器配置"
|
||||
|
||||
msgid "Paste ssr url here"
|
||||
msgstr "在此处粘贴ssr://网址"
|
||||
|
||||
msgid "Unable to copy SSR to clipboard."
|
||||
msgstr "无法复制SSR网址到剪贴板。"
|
||||
|
||||
msgid "Copy SSR to clipboard successfully."
|
||||
msgstr "成功复制SSR网址到剪贴板。"
|
||||
|
||||
msgid "Server Node Type"
|
||||
msgstr "服务器节点类型"
|
||||
|
||||
msgid "Using incorrect encryption mothod may causes service fail to start"
|
||||
msgstr "输入不正确的参数组合可能会导致服务无法启动"
|
||||
|
||||
msgid "Alias(optional)"
|
||||
msgstr "别名(可选)"
|
||||
|
||||
msgid "Network interface to use"
|
||||
msgstr "选择使用的网络接口"
|
||||
|
||||
msgid "Redirect traffic to this network interface"
|
||||
msgstr "分流到这个网络接口"
|
||||
|
||||
msgid "Server Address"
|
||||
msgstr "服务器地址"
|
||||
|
||||
msgid "Enable Authentication"
|
||||
msgstr "启用用户名/密码认证"
|
||||
|
||||
msgid "Username"
|
||||
msgstr "用户名"
|
||||
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
|
||||
msgid "Encrypt Method"
|
||||
msgstr "加密方式"
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "插件"
|
||||
|
||||
msgid "Plugin Opts"
|
||||
msgstr "插件参数"
|
||||
|
||||
msgid "Protocol"
|
||||
msgstr "传输协议"
|
||||
|
||||
msgid "Protocol param (optional)"
|
||||
msgstr "传输协议参数(可选)"
|
||||
|
||||
msgid "Authentication type"
|
||||
msgstr "验证类型"
|
||||
|
||||
msgid "Authentication payload"
|
||||
msgstr "验证载荷"
|
||||
|
||||
msgid "Auth Password"
|
||||
msgstr "Auth密码"
|
||||
|
||||
msgid "Obfs Password"
|
||||
msgstr "Obfs密码"
|
||||
|
||||
msgid "NOTE: If the server uses the userpass authentication, the format must be username:password."
|
||||
msgstr "注意: 如果服务器使用 userpass 验证,格式必须是 username:password。"
|
||||
|
||||
msgid "Enable Port Hopping"
|
||||
msgstr "启用端口跃迁"
|
||||
|
||||
|
||||
msgid "Port Hopping Interval(Unit:Second)"
|
||||
msgstr "端口跃迁间隔(单位:秒)"
|
||||
|
||||
msgid "Enable Lazy Mode"
|
||||
msgstr "启用懒狗模式"
|
||||
|
||||
msgid "Enable Obfuscation"
|
||||
msgstr "启用混淆功能"
|
||||
|
||||
msgid "Obfuscation Type"
|
||||
msgstr "混淆类型"
|
||||
|
||||
msgid "Obfuscation Password"
|
||||
msgstr "混淆密码"
|
||||
|
||||
msgid "TUIC User UUID"
|
||||
msgstr "TUIC用户uuid"
|
||||
|
||||
msgid "TUIC Server IP Address"
|
||||
msgstr "TUIC 服务器IP地址"
|
||||
|
||||
msgid "TUIC User Password"
|
||||
msgstr "TUIC用户密钥"
|
||||
|
||||
msgid "native UDP characteristics"
|
||||
msgstr "原生UDP特性"
|
||||
|
||||
msgid "lossless UDP relay using QUIC streams"
|
||||
msgstr "使用 QUIC 流的无损 UDP 中继"
|
||||
|
||||
msgid "native UDP characteristics"
|
||||
msgstr "原生UDP特性"
|
||||
|
||||
msgid "lossless UDP relay using QUIC streams"
|
||||
msgstr "使用 QUIC 流的无损 UDP 中继"
|
||||
|
||||
msgid "Congestion control algorithm"
|
||||
msgstr "拥塞控制算法"
|
||||
|
||||
msgid "Heartbeat interval(second)"
|
||||
msgstr "保活心跳包发送间隔(单位:秒)"
|
||||
|
||||
msgid "Timeout for establishing a connection to server(second)"
|
||||
msgstr "连接超时时间(单位:秒)"
|
||||
|
||||
msgid "Garbage collection interval(second)"
|
||||
msgstr "UDP数据包片残片清理间隔(单位:秒)"
|
||||
|
||||
msgid "Garbage collection lifetime(second)"
|
||||
msgstr "UDP数据包残片在服务器的保留时间(单位:秒)"
|
||||
|
||||
msgid "Disable SNI"
|
||||
msgstr "关闭SNI服务器名称指示"
|
||||
|
||||
msgid "Enable 0-RTT QUIC handshake"
|
||||
msgstr "客户端启用 0-RTT QUIC 连接握手"
|
||||
|
||||
msgid "TUIC send window"
|
||||
msgstr "发送窗口(无需确认即可发送的最大字节数:默认8Mb*2)"
|
||||
|
||||
msgid "TUIC receive window"
|
||||
msgstr "接收窗口(无需确认即可接收的最大字节数:默认8Mb)"
|
||||
|
||||
msgid "Hysterir QUIC parameters"
|
||||
msgstr "QUIC参数"
|
||||
|
||||
msgid "QUIC initStreamReceiveWindow"
|
||||
msgstr "QUIC初始流接收窗口大小。"
|
||||
|
||||
msgid "QUIC maxStreamReceiveWindow"
|
||||
msgstr "QUIC最大的流接收窗口大小"
|
||||
|
||||
msgid "QUIC initConnReceiveWindow"
|
||||
msgstr "QUIC初始的连接接收窗口大小"
|
||||
|
||||
msgid "QUIC maxConnReceiveWindow"
|
||||
msgstr "QUIC最大的连接接收窗口大小"
|
||||
|
||||
msgid "QUIC maxIdleTimeout(Unit:second)"
|
||||
msgstr "QUIC最长空闲超时时间(单位:秒)"
|
||||
|
||||
msgid "The keep-alive period.(Unit:second)"
|
||||
msgstr "心跳包发送间隔(单位:秒)"
|
||||
|
||||
|
||||
msgid "Certificate fingerprint"
|
||||
msgstr "证书指纹"
|
||||
|
||||
msgid "shadowTLS protocol Version"
|
||||
msgstr "ShadowTLS协议版本"
|
||||
|
||||
msgid "TLS 1.3 Strict mode"
|
||||
msgstr "TLS 1.3 限定模式"
|
||||
|
||||
msgid "Disable TCP No_delay"
|
||||
msgstr "禁用TCP无延迟"
|
||||
|
||||
msgid "shadow-TLS SNI"
|
||||
msgstr "服务器名称指示"
|
||||
|
||||
msgid "Shadow-TLS ChainPoxy type"
|
||||
msgstr "代理链类型"
|
||||
|
||||
msgid "Shadowsocks-rust Version"
|
||||
msgstr "shadowsocks rust版本"
|
||||
|
||||
msgid "Vmess Protocol"
|
||||
msgstr "VMESS协议"
|
||||
|
||||
msgid "Shadowsocks password"
|
||||
msgstr "shadowsocks密码"
|
||||
|
||||
msgid "Uplink Capacity(Default:Mbps)"
|
||||
msgstr "上行链路容量(默认:Mbps)"
|
||||
|
||||
msgid "Downlink Capacity(Default:Mbps)"
|
||||
msgstr "下行链路容量(默认:Mbps)"
|
||||
|
||||
msgid "Dual-stack Listening Socket"
|
||||
msgstr "双栈Socket监听"
|
||||
|
||||
|
||||
msgid "DNS Query Mode For Shunt Mode"
|
||||
msgstr "分流模式下的 DNS 查询模式"
|
||||
|
||||
msgid "Anti-pollution DNS Server For Shunt Mode"
|
||||
msgstr "分流模式下的访问国外域名 DNS 服务器"
|
||||
|
||||
msgid "Disable IPv6 In MOSDNS Query Mode (Shunt Mode)"
|
||||
msgstr "禁止 MOSDNS 返回 IPv6 记录 (分流模式)"
|
||||
|
||||
|
||||
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)"
|
||||
msgstr "混淆参数(可选)"
|
||||
|
||||
msgid "VLESS Encryption"
|
||||
msgstr "VLESS 加密"
|
||||
|
||||
msgid "Transport"
|
||||
msgstr "传输协议"
|
||||
|
||||
msgid "allowInsecure"
|
||||
msgstr "允许不安全连接"
|
||||
|
||||
msgid "concurrency"
|
||||
msgstr "TCP 最大并发连接数"
|
||||
|
||||
msgid "xudpConcurrency"
|
||||
msgstr "UDP 最大并发连接数"
|
||||
|
||||
msgid "xudpProxyUDP443"
|
||||
msgstr "对被代理的 UDP/443 流量处理方式"
|
||||
|
||||
msgid "custom_tcpcongestion"
|
||||
msgstr "连接服务器节点的 TCP 拥塞控制算法"
|
||||
|
||||
msgid "comment_tcpcongestion_disable"
|
||||
msgstr "系统默认值"
|
||||
|
||||
msgid "If true, allowss insecure connection at TLS client, e.g., TLS server uses unverifiable certificates."
|
||||
msgstr "是否允许不安全连接。当选择时,将不会检查远端主机所提供的 TLS 证书的有效性。"
|
||||
|
||||
msgid "Flow"
|
||||
msgstr "流控 (Flow)"
|
||||
|
||||
msgid "Concurrency"
|
||||
msgstr "最大并发连接数"
|
||||
|
||||
msgid "Self-signed Certificate"
|
||||
msgstr "自签证书"
|
||||
|
||||
msgid "If you have a self-signed certificate,please check the box"
|
||||
msgstr "如果你使用自签证书,请选择"
|
||||
|
||||
msgid "upload"
|
||||
msgstr "上传证书"
|
||||
|
||||
msgid "Upload"
|
||||
msgstr "上传"
|
||||
|
||||
msgid "Create upload file error"
|
||||
msgstr "创建证书文件失败"
|
||||
|
||||
msgid "No specify upload file"
|
||||
msgstr "没有上传证书"
|
||||
|
||||
msgid "Current Certificate Path"
|
||||
msgstr "当前证书路径"
|
||||
|
||||
msgid "Please confirm the current certificate path"
|
||||
msgstr "请选择确认所传证书,证书不正确将无法运行"
|
||||
|
||||
msgid "TCP Fast Open"
|
||||
msgstr "TCP快速打开"
|
||||
|
||||
msgid "Enable Auto Switch"
|
||||
msgstr "启用故障转移"
|
||||
|
||||
msgid "Local Port"
|
||||
msgstr "本地端口"
|
||||
|
||||
msgid "KcpTun Enable"
|
||||
msgstr "KcpTun 启用"
|
||||
|
||||
msgid "KcpTun Port"
|
||||
msgstr "KcpTun 端口"
|
||||
|
||||
msgid "KcpTun Password"
|
||||
msgstr "KcpTun 密码"
|
||||
|
||||
msgid "KcpTun Param"
|
||||
msgstr "KcpTun 参数"
|
||||
|
||||
msgid "Access Control"
|
||||
msgstr "访问控制"
|
||||
|
||||
msgid "IP Access Control"
|
||||
msgstr "IP访问控制"
|
||||
|
||||
msgid "WAN IP AC"
|
||||
msgstr "WAN IP访问控制"
|
||||
|
||||
msgid "WAN White List IP"
|
||||
msgstr "不走代理的WAN IP"
|
||||
|
||||
msgid "WAN Force Proxy IP"
|
||||
msgstr "强制走代理的WAN IP"
|
||||
|
||||
msgid "LAN IP AC"
|
||||
msgstr "LAN IP访问控制"
|
||||
|
||||
msgid "LAN Access Control"
|
||||
msgstr "内网客户端分流代理控制"
|
||||
|
||||
msgid "Allow listed only"
|
||||
msgstr "仅允许列表内主机"
|
||||
|
||||
msgid "Allow all except listed"
|
||||
msgstr "除列表外主机皆允许"
|
||||
|
||||
msgid "LAN Host List"
|
||||
msgstr "内网主机列表"
|
||||
|
||||
msgid "LAN Force Proxy Host List"
|
||||
msgstr "全局代理的LAN IP"
|
||||
|
||||
msgid "Game Mode Host List"
|
||||
msgstr "增强游戏模式客户端LAN IP"
|
||||
|
||||
msgid "Domain List"
|
||||
msgstr "域名列表"
|
||||
|
||||
msgid "Direct Domain List"
|
||||
msgstr "不走代理的域名"
|
||||
|
||||
msgid "Proxy Domain List"
|
||||
msgstr "强制走代理的域名"
|
||||
|
||||
msgid "These had been joined websites will not proxy."
|
||||
msgstr "加入的域名将不走代理。"
|
||||
|
||||
msgid "These had been joined websites will use proxy."
|
||||
msgstr "加入的域名将走代理。"
|
||||
|
||||
msgid "Not valid domain name, please re-enter!"
|
||||
msgstr "不是有效域名,请重新输入!"
|
||||
|
||||
msgid "Netflix Domain List"
|
||||
msgstr "Netflix分流域名"
|
||||
|
||||
msgid "Oversea Domain List"
|
||||
msgstr "回国模式域名"
|
||||
|
||||
msgid "Preload domain(GFW Only)"
|
||||
msgstr "预加载域名(仅GFW模式)"
|
||||
|
||||
msgid "Advanced Settings"
|
||||
msgstr "高级设置"
|
||||
|
||||
msgid "Server failsafe auto swith settings"
|
||||
msgstr "服务器节点故障故障转移设置"
|
||||
|
||||
msgid "Global SOCKS5 Server"
|
||||
msgstr "SOCKS5服务端(全局)"
|
||||
|
||||
msgid "Enable Process Deamon"
|
||||
msgstr "启用进程自动守护"
|
||||
|
||||
msgid "Switch check cycly(second)"
|
||||
msgstr "故障转移检查周期(秒)"
|
||||
|
||||
msgid "Check timout(second)"
|
||||
msgstr "切换检查超时时间(秒)"
|
||||
|
||||
msgid "Check Try Count"
|
||||
msgstr "切换检查重试次数"
|
||||
|
||||
msgid "Reverse"
|
||||
msgstr "逆序"
|
||||
|
||||
msgid "Taobao Delay"
|
||||
msgstr "淘宝延时"
|
||||
|
||||
msgid "Baidu Delay"
|
||||
msgstr "百度延时"
|
||||
|
||||
msgid "Rule status"
|
||||
msgstr "规则版本"
|
||||
|
||||
msgid "Google Delay"
|
||||
msgstr "谷歌延时"
|
||||
|
||||
msgid "Global SOCKS5 Proxy Server"
|
||||
msgstr "SOCKS5 代理服务端(全局)"
|
||||
|
||||
msgid "Github Delay"
|
||||
msgstr "Github延时"
|
||||
|
||||
msgid "Youtube Delay"
|
||||
msgstr "Youtube延时"
|
||||
|
||||
msgid "Server"
|
||||
msgstr "服务器"
|
||||
|
||||
msgid "SSR Server"
|
||||
msgstr "服务端"
|
||||
|
||||
msgid "Global Setting"
|
||||
msgstr "全局设置"
|
||||
|
||||
msgid "Enable Server"
|
||||
msgstr "启动服务端"
|
||||
|
||||
msgid "Server Setting"
|
||||
msgstr "服务端配置"
|
||||
|
||||
msgid "Server Type"
|
||||
msgstr "服务端类型"
|
||||
|
||||
msgid "Encrypt Method (SS)"
|
||||
msgstr "加密方式 (SS)"
|
||||
|
||||
msgid "Plugin (SS)"
|
||||
msgstr "插件 (SS)"
|
||||
|
||||
msgid "Warning! Please do not reuse the port!"
|
||||
msgstr "警告!请不要重复使用端口!"
|
||||
|
||||
msgid "Enable Once Auth Mode"
|
||||
msgstr "启用一次性认证"
|
||||
|
||||
msgid "Enable Once Auth,the client IP that passed the authentication will be added to the whitelist address, this IP no longer needs to be verified"
|
||||
msgstr "启用一次性认证后会将通过认证的客户端IP地址加入白名单,之后的连接不再进行认证"
|
||||
|
||||
msgid "Connection Timeout"
|
||||
msgstr "连接超时"
|
||||
|
||||
msgid "Unknown"
|
||||
msgstr "未知"
|
||||
|
||||
msgid "Not exist"
|
||||
msgstr "未安装可执行文件"
|
||||
|
||||
msgid "Status"
|
||||
msgstr "状态"
|
||||
|
||||
msgid "Global Client"
|
||||
msgstr "TCP透明代理"
|
||||
|
||||
msgid "Running"
|
||||
msgstr "运行中"
|
||||
|
||||
msgid "Not Running"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "Game Mode UDP Relay"
|
||||
msgstr "游戏模式UDP中继"
|
||||
|
||||
msgid "Local Servers"
|
||||
msgstr "本机服务端"
|
||||
|
||||
msgid "KcpTun Version"
|
||||
msgstr "KcpTun 版本号"
|
||||
|
||||
|
||||
msgid "No Check"
|
||||
msgstr "未检查"
|
||||
|
||||
msgid "Check..."
|
||||
msgstr "正在检查.."
|
||||
|
||||
msgid "Connect OK"
|
||||
msgstr "连接正常"
|
||||
|
||||
msgid "Connect Error"
|
||||
msgstr "连接错误"
|
||||
|
||||
msgid "Check Connect"
|
||||
msgstr "检查连通性"
|
||||
|
||||
msgid "GFW List"
|
||||
msgstr "GFW列表"
|
||||
|
||||
msgid "Refresh Data"
|
||||
msgstr "更新数据"
|
||||
|
||||
msgid "Records"
|
||||
msgstr "条"
|
||||
|
||||
msgid "Refresh..."
|
||||
msgstr "正在更新,请稍候.."
|
||||
|
||||
msgid "Refresh OK!"
|
||||
msgstr "已更新"
|
||||
|
||||
msgid "Refresh Error!"
|
||||
msgstr "更新失败!"
|
||||
|
||||
msgid "No New data!"
|
||||
msgstr "已经最新!"
|
||||
|
||||
msgid "Total Record:"
|
||||
msgstr "总数:"
|
||||
|
||||
msgid "China IPv4 List"
|
||||
msgstr "国内IPv4列表"
|
||||
|
||||
msgid "China IPv6 List"
|
||||
msgstr "国内IPv6列表"
|
||||
|
||||
msgid "Preventing DNS pollution"
|
||||
msgstr "防止DNS污染(测试功能)"
|
||||
|
||||
msgid "China Domains Update URL"
|
||||
msgstr "国内域名列表"
|
||||
|
||||
msgid "Configure block domain list."
|
||||
msgstr "配置屏蔽域名列表(禁止联网)"
|
||||
|
||||
msgid "Domain DNS Block Setting"
|
||||
msgstr "域名屏蔽设置"
|
||||
|
||||
msgid "IP Blacklist Setting"
|
||||
msgstr "IP黑名单屏蔽设置"
|
||||
|
||||
msgid "Set Specific ip blacklist."
|
||||
msgstr "设置指定的IP黑名单屏蔽列表(禁止联网)。"
|
||||
|
||||
msgid "Check Server Port"
|
||||
msgstr "【服务器端口】检查"
|
||||
|
||||
msgid "Check Server"
|
||||
msgstr "检查服务器"
|
||||
|
||||
msgid "Log"
|
||||
msgstr "日志"
|
||||
|
||||
msgid "Finger Print"
|
||||
msgstr "指纹伪造"
|
||||
|
||||
msgid "Shadowsocks2"
|
||||
msgstr "二次加密"
|
||||
|
||||
msgid "From Share URL"
|
||||
msgstr "导入配置信息"
|
||||
|
||||
msgid "Build Share URL"
|
||||
msgstr "导出配置信息"
|
||||
|
||||
msgid "Import Finished"
|
||||
msgstr "导入完成"
|
||||
|
||||
msgid "Not a supported Format"
|
||||
msgstr "不支持此格式"
|
||||
|
||||
msgid "Invalid Share URL Format"
|
||||
msgstr "无效的配置链接"
|
||||
|
||||
msgid "User cancelled"
|
||||
msgstr "用户已取消"
|
||||
|
||||
msgid "Paste Share URL Here"
|
||||
msgstr "在此处粘贴配置链接"
|
||||
|
||||
msgid "Unable share to clipboard"
|
||||
msgstr "复制配置链接到剪贴板失败"
|
||||
|
||||
msgid "Share to clipboard successfully"
|
||||
msgstr "成功复制配置链接到剪贴板"
|
||||
|
||||
msgid "Faltal on get option:"
|
||||
msgstr "获取选项错误:"
|
||||
|
||||
msgid "Faltal on set option:"
|
||||
msgstr "获取选项错误:"
|
||||
|
||||
msgid "Check update"
|
||||
msgstr "检查更新"
|
||||
|
||||
msgid "Update..."
|
||||
msgstr "更新中"
|
||||
|
||||
msgid "It is the latest version"
|
||||
msgstr "已是最新版本"
|
||||
|
||||
msgid "Update successful"
|
||||
msgstr "更新成功"
|
||||
|
||||
msgid "Click to update"
|
||||
msgstr "点击更新"
|
||||
|
||||
msgid "Updating..."
|
||||
msgstr "更新中"
|
||||
|
||||
msgid "Unexpected error"
|
||||
msgstr "意外错误"
|
||||
|
||||
msgid "Updating, are you sure to close?"
|
||||
msgstr "正在更新,你确认要关闭吗?"
|
||||
|
||||
msgid "Downloading..."
|
||||
msgstr "下载中"
|
||||
|
||||
msgid "Unpacking..."
|
||||
msgstr "解压中"
|
||||
|
||||
msgid "Moving..."
|
||||
msgstr "移动中"
|
||||
|
||||
msgid "App Update"
|
||||
msgstr "组件更新"
|
||||
|
||||
msgid "Please confirm that your firmware supports FPU."
|
||||
msgstr "请确认你的固件支持FPU。"
|
||||
|
||||
msgid "Make sure there is enough space to install %s"
|
||||
msgstr "确保有足够的空间安装 %s"
|
||||
|
||||
msgid "RUNNING"
|
||||
msgstr "运行中"
|
||||
|
||||
msgid "NOT RUNNING"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "Working..."
|
||||
msgstr "连接正常"
|
||||
|
||||
msgid "Problem detected!"
|
||||
msgstr "连接失败"
|
||||
|
||||
msgid "Very Fast"
|
||||
msgstr "非常快"
|
||||
|
||||
msgid "Fast"
|
||||
msgstr "很快"
|
||||
|
||||
msgid "General"
|
||||
msgstr "一般般"
|
||||
|
||||
msgid "Slow"
|
||||
msgstr "很慢"
|
||||
|
||||
msgid "Very Slow"
|
||||
msgstr "非常慢"
|
||||
|
||||
msgid "Touch Check"
|
||||
msgstr "点我检测"
|
||||
|
||||
|
||||
msgid "Httpupgrade Host"
|
||||
msgstr "HTTPUpgrade 主机名"
|
||||
|
||||
msgid "Httpupgrade Path"
|
||||
msgstr "HTTPUpgrade 路径"
|
||||
|
||||
msgid "Socks5 Server"
|
||||
msgstr "Socks5服务端"
|
||||
|
||||
msgid "Running Status"
|
||||
msgstr "运行状态"
|
||||
|
||||
msgid "Node Check"
|
||||
msgstr "节点检测"
|
||||
|
||||
msgid "Check..."
|
||||
msgstr "检测中..."
|
||||
|
||||
msgid "Clear Log"
|
||||
msgstr "清除日志"
|
||||
|
||||
msgid "Clear"
|
||||
msgstr "清除"
|
||||
|
||||
msgid "To Top"
|
||||
msgstr "置顶"
|
||||
|
||||
msgid "Used with AdGuardHome"
|
||||
msgstr "与AdGuardHome搭配使用"
|
||||
|
||||
msgid "Luci-app-adguardhome require"
|
||||
msgstr "请确保luci-app-adguardhome能正常启用,本插件会联动开启并配置ADG,只需要选择过滤规则其它无需任何设置"
|
47353
luci-app-bypass/luci-app-bypass/root/etc/bypass/ad_list.txt
Normal file
47353
luci-app-bypass/luci-app-bypass/root/etc/bypass/ad_list.txt
Normal file
File diff suppressed because it is too large
Load Diff
121
luci-app-bypass/luci-app-bypass/root/etc/bypass/black.list
Normal file
121
luci-app-bypass/luci-app-bypass/root/etc/bypass/black.list
Normal file
@ -0,0 +1,121 @@
|
||||
youtu.be
|
||||
ggpht.com
|
||||
googlevideo.com
|
||||
withyoutube.com
|
||||
youtube-nocookie.com
|
||||
youtube.com
|
||||
youtubeeducation.com
|
||||
youtubegaming.com
|
||||
youtubei.googleapis.com
|
||||
youtubekids.com
|
||||
youtubemobilesupport.com
|
||||
ytimg.com
|
||||
|
||||
discordapp.com
|
||||
discordapp.net
|
||||
discord.gg
|
||||
discord.com
|
||||
cdn.registerdisney.go.com
|
||||
disneyplus.com
|
||||
disney-plus.net
|
||||
dssott.com
|
||||
bamgrid.com
|
||||
execute-api.us-east-1.amazonaws.com
|
||||
|
||||
amazonaws.com
|
||||
aiv-cdn.net
|
||||
amazonvideo.com
|
||||
llnwd.net
|
||||
amazonprimevideos.com
|
||||
amazonvideo.cc
|
||||
prime-video.com
|
||||
primevideo.cc
|
||||
primevideo.com
|
||||
primevideo.info
|
||||
primevideo.org
|
||||
primevideo.tv
|
||||
|
||||
tvsuper.com
|
||||
tvb.com
|
||||
|
||||
myvideo.net.tw
|
||||
vidol.tv
|
||||
hinet.net
|
||||
books.com
|
||||
litv.tv
|
||||
pstatic.net
|
||||
app-measurement.com
|
||||
kktv.com.tw
|
||||
gamer.com.tw
|
||||
wetv.vip
|
||||
kktv.me
|
||||
kk.stream
|
||||
|
||||
|
||||
pandora.com
|
||||
spotify.com
|
||||
tunein.com
|
||||
hboasia.com
|
||||
hbogoasia.com
|
||||
hbogoasia.hk
|
||||
hbolb.onwardsmg.com
|
||||
hbounify-prod.evergent.com
|
||||
bcbolthboa-a.akamaihd.net
|
||||
|
||||
|
||||
googleapis.cn
|
||||
googleapis.com
|
||||
google.com.tw
|
||||
google.com.hk
|
||||
google.com
|
||||
googleapis.com
|
||||
googletagmanager.com
|
||||
googleusercontent.com
|
||||
gstatic.com
|
||||
imrworldwide.com
|
||||
bbc.com
|
||||
bbci.co.uk
|
||||
bbc.co.uk
|
||||
api.ipify.org
|
||||
v2fly.org
|
||||
cherrytv.one
|
||||
whrq.net
|
||||
whoer.net
|
||||
|
||||
sms-activate.org
|
||||
instagram.com
|
||||
bit.ly
|
||||
hstock.org
|
||||
|
||||
last.fm
|
||||
cookielaw.org
|
||||
paramount.com
|
||||
maxcdn.com
|
||||
fastly.net
|
||||
|
||||
github.com
|
||||
assets-cdn.github.com
|
||||
raw.githubusercontent.com
|
||||
githubusercontent.com
|
||||
|
||||
dns.sb
|
||||
doh.li
|
||||
containerpi.com
|
||||
test-ipv6.com
|
||||
browserleaks.com
|
||||
cloudflare.com
|
||||
bing.com
|
||||
services.googleapis.cn
|
||||
v2ex.com
|
||||
sspanel.net
|
||||
|
||||
ispip.clang.cn
|
||||
|
||||
twitter.com
|
||||
www.twitter.com
|
||||
|
||||
xn--ngstr-lra8j.com
|
||||
|
||||
midjourney.com
|
||||
chat.openai.com
|
||||
openai.com
|
12520
luci-app-bypass/luci-app-bypass/root/etc/bypass/china.txt
Normal file
12520
luci-app-bypass/luci-app-bypass/root/etc/bypass/china.txt
Normal file
File diff suppressed because it is too large
Load Diff
3409
luci-app-bypass/luci-app-bypass/root/etc/bypass/china_v6.txt
Normal file
3409
luci-app-bypass/luci-app-bypass/root/etc/bypass/china_v6.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,14 @@
|
||||
gvod.aiseejapp.atianqi.com
|
||||
stat.pandora.xiaomi.com
|
||||
upgrade.mishop.pandora.xiaomi.com
|
||||
logonext.tv.kuyun.com
|
||||
config.kuyun.com
|
||||
mishop.pandora.xiaomi.com
|
||||
dvb.pandora.xiaomi.com
|
||||
api.ad.xiaomi.com
|
||||
de.pandora.xiaomi.com
|
||||
data.mistat.xiaomi.com
|
||||
jellyfish.pandora.xiaomi.com
|
||||
gallery.pandora.xiaomi.com
|
||||
o2o.api.xiaomi.com
|
||||
bss.pandora.xiaomi.com
|
72476
luci-app-bypass/luci-app-bypass/root/etc/bypass/domains_cn.txt
Normal file
72476
luci-app-bypass/luci-app-bypass/root/etc/bypass/domains_cn.txt
Normal file
File diff suppressed because it is too large
Load Diff
18457
luci-app-bypass/luci-app-bypass/root/etc/bypass/gfw.list
Normal file
18457
luci-app-bypass/luci-app-bypass/root/etc/bypass/gfw.list
Normal file
File diff suppressed because it is too large
Load Diff
114
luci-app-bypass/luci-app-bypass/root/etc/bypass/gfw_base.list
Normal file
114
luci-app-bypass/luci-app-bypass/root/etc/bypass/gfw_base.list
Normal file
@ -0,0 +1,114 @@
|
||||
91smartyun.pt
|
||||
imrworldwide.com
|
||||
adobe.com
|
||||
bbc.com
|
||||
bbci.co.uk
|
||||
bbc.co.uk
|
||||
api.ipify.org
|
||||
v2fly.org
|
||||
whrq.net
|
||||
whoer.net
|
||||
sms-activate.org
|
||||
amazonaws.com
|
||||
instagram.com
|
||||
bit.ly
|
||||
ampproject.org
|
||||
apple.news
|
||||
aws.amazon.com
|
||||
azureedge.net
|
||||
backpackers.com.tw
|
||||
bitfinex.com
|
||||
buzzfeed.com
|
||||
clockwise.ee
|
||||
cloudfront.net
|
||||
coindesk.com
|
||||
last.fm
|
||||
cookielaw.org
|
||||
paramount.com
|
||||
hstock.org
|
||||
coinsquare.io
|
||||
cryptocompare.com
|
||||
dropboxstatic.com
|
||||
eurecom.fr
|
||||
gdax.com
|
||||
maxcdn.com
|
||||
github.com
|
||||
github.global.ssl.fastly.net
|
||||
raw.githubusercontent.com
|
||||
githubusercontent.com
|
||||
assets-cdn.github.com
|
||||
kknews.cc
|
||||
nutaq.com
|
||||
openairinterface.org
|
||||
skype.com
|
||||
sublimetext.com
|
||||
dns.sb
|
||||
doh.li
|
||||
containerpi.com
|
||||
textnow.com
|
||||
textnow.me
|
||||
trouter.io
|
||||
t66y.com
|
||||
uploaded.net
|
||||
whatsapp.com
|
||||
whatsapp.net
|
||||
wsj.net
|
||||
google.com
|
||||
www.google.com
|
||||
google.com.tw
|
||||
google.com.hk
|
||||
gstatic.com
|
||||
googleusercontent.com
|
||||
googletagmanager.com
|
||||
googlepages.com
|
||||
googlevideo.com
|
||||
googlecode.com
|
||||
googleapis.com
|
||||
googlesource.com
|
||||
googledrive.com
|
||||
ggpht.com
|
||||
youtube.com
|
||||
youtu.be
|
||||
ytimg.com
|
||||
ispip.clang.cn
|
||||
twitter.com
|
||||
www.twitter.com
|
||||
googleapis.cn
|
||||
bing.com
|
||||
services.googleapis.cn
|
||||
test-ipv6.com
|
||||
sspanel.net
|
||||
browserleaks.com
|
||||
cloudflare.com
|
||||
|
||||
xn--ngstr-lra8j.com
|
||||
cdn.registerdisney.go.com
|
||||
disneyplus.com
|
||||
disney-plus.net
|
||||
dssott.com
|
||||
bamgrid.com
|
||||
execute-api.us-east-1.amazonaws.com
|
||||
tvsuper.com
|
||||
tvb.com
|
||||
vidol.tv
|
||||
hinet.net
|
||||
books.com
|
||||
litv.tv
|
||||
pstatic.net
|
||||
app-measurement.com
|
||||
kktv.com.tw
|
||||
gamer.com.tw
|
||||
wetv.vip
|
||||
kktv.me
|
||||
myvideo.net.tw
|
||||
kk.stream
|
||||
|
||||
midjourney.com
|
||||
discord.com
|
||||
facebook.com
|
||||
fastly.net
|
||||
akamai.net
|
||||
akamaiedge.net
|
||||
akamaihd.net
|
||||
edgesuite.net
|
||||
edgekey.net
|
30
luci-app-bypass/luci-app-bypass/root/etc/bypass/netflix.list
Normal file
30
luci-app-bypass/luci-app-bypass/root/etc/bypass/netflix.list
Normal file
@ -0,0 +1,30 @@
|
||||
amazonaws.com
|
||||
aws.amazon.com
|
||||
awsstatic.com
|
||||
fast.com
|
||||
netflix.ca
|
||||
netflix.com
|
||||
netflix.net
|
||||
netflixinvestor.com
|
||||
netflixtechblog.com
|
||||
nflxext.com
|
||||
nflximg.com
|
||||
nflximg.net
|
||||
nflxsearch.net
|
||||
nflxso.net
|
||||
nflxvideo.net
|
||||
netflixdnstest0.com
|
||||
netflixdnstest1.com
|
||||
netflixdnstest2.com
|
||||
netflixdnstest3.com
|
||||
netflixdnstest4.com
|
||||
netflixdnstest5.com
|
||||
netflixdnstest6.com
|
||||
netflixdnstest7.com
|
||||
netflixdnstest8.com
|
||||
netflixdnstest9.com
|
||||
hulu.com
|
||||
huluim.com
|
||||
hbonow.com
|
||||
hbogo.com
|
||||
hbo.com
|
96
luci-app-bypass/luci-app-bypass/root/etc/bypass/oversea.list
Normal file
96
luci-app-bypass/luci-app-bypass/root/etc/bypass/oversea.list
Normal file
@ -0,0 +1,96 @@
|
||||
v.youku.com
|
||||
api.youku.com
|
||||
v2.tudou.com
|
||||
www.tudou.com
|
||||
s.plcloud.music.qq.com
|
||||
i.y.qq.com
|
||||
hot.vrs.sohu.com
|
||||
live.tv.sohu.com
|
||||
pad.tv.sohu.com
|
||||
my.tv.sohu.com
|
||||
hot.vrs.letv.com
|
||||
data.video.qiyi.com
|
||||
cache.video.qiyi.com
|
||||
cache.vip.qiyi.com
|
||||
vv.video.qq.com
|
||||
tt.video.qq.com
|
||||
ice.video.qq.com
|
||||
tjsa.video.qq.com
|
||||
a10.video.qq.com
|
||||
xyy.video.qq.com
|
||||
vcq.video.qq.com
|
||||
vsh.video.qq.com
|
||||
vbj.video.qq.com
|
||||
bobo.video.qq.com
|
||||
flvs.video.qq.com
|
||||
bkvv.video.qq.com
|
||||
info.zb.qq.com
|
||||
geo.js.kankan.xunlei.com
|
||||
web-play.pptv.com
|
||||
web-play.pplive.cn
|
||||
dyn.ugc.pps.tv
|
||||
v.pps.tv
|
||||
inner.kandian.com
|
||||
ipservice.163.com
|
||||
so.open.163.com
|
||||
zb.s.qq.com
|
||||
ip.kankan.xunlei.com
|
||||
vxml.56.com
|
||||
music.sina.com.cn
|
||||
play.baidu.com
|
||||
v.iask.com
|
||||
tv.weibo.com
|
||||
wtv.v.iask.com
|
||||
video.sina.com.cn
|
||||
www.yinyuetai.com
|
||||
api.letv.com
|
||||
live.gslb.letv.com
|
||||
static.itv.letv.com
|
||||
ip.apps.cntv.cn
|
||||
vdn.apps.cntv.cn
|
||||
vdn.live.cntv.cn
|
||||
vip.sports.cntv.cn
|
||||
a.play.api.3g.youku.com
|
||||
i.play.api.3g.youku.com
|
||||
api.3g.youku.com
|
||||
tv.api.3g.youku.com
|
||||
play.api.3g.youku.com
|
||||
play.api.3g.tudou.com
|
||||
tv.api.3g.tudou.com
|
||||
api.3g.tudou.com
|
||||
api.tv.sohu.com
|
||||
access.tv.sohu.com
|
||||
iface.iqiyi.com
|
||||
iface2.iqiyi.com
|
||||
cache.m.iqiyi.com
|
||||
dynamic.app.m.letv.com
|
||||
dynamic.meizi.app.m.letv.com
|
||||
dynamic.search.app.m.letv.com
|
||||
dynamic.live.app.m.letv.com
|
||||
listso.m.areainfo.ppstream.com
|
||||
epg.api.pptv.com
|
||||
play.api.pptv.com
|
||||
m.letv.com
|
||||
interface.bilibili.com
|
||||
3g.music.qq.com
|
||||
mqqplayer.3g.qq.com
|
||||
proxy.music.qq.com
|
||||
proxymc.qq.com
|
||||
ip2.kugou.com
|
||||
ip.kugou.com
|
||||
client.api.ttpod.com
|
||||
mobi.kuwo.cn
|
||||
mobilefeedback.kugou.com
|
||||
tingapi.ting.baidu.com
|
||||
music.baidu.com
|
||||
serviceinfo.sdk.duomi.com
|
||||
music.163.com
|
||||
www.xiami.com
|
||||
spark.api.xiami.com
|
||||
iplocation.geo.qiyi.com
|
||||
sns.video.qq.com
|
||||
v5.pc.duomi.com
|
||||
tms.is.ysten.com
|
||||
internal.check.duokanbox.com
|
||||
openapi.youku.com
|
||||
y.qq.com
|
@ -0,0 +1,16 @@
|
||||
|
||||
91.108.20.0/22
|
||||
91.108.36.0/23
|
||||
91.108.38.0/23
|
||||
|
||||
91.108.12.0/22
|
||||
149.154.164.0/22
|
||||
149.154.172.0/22
|
||||
91.105.192.0/23
|
||||
91.108.4.0/22
|
||||
91.108.8.0/21
|
||||
91.108.16.0/21
|
||||
91.108.56.0/22
|
||||
95.161.64.0/20
|
||||
149.154.160.0/20
|
||||
185.76.151.0/24
|
35
luci-app-bypass/luci-app-bypass/root/etc/bypass/white.list
Normal file
35
luci-app-bypass/luci-app-bypass/root/etc/bypass/white.list
Normal file
@ -0,0 +1,35 @@
|
||||
checkipv6.synology.com
|
||||
checkport.synology.com
|
||||
ddns.synology.com
|
||||
account.synology.com
|
||||
whatismyip.akamai.com
|
||||
checkip.dyndns.org
|
||||
checkipv6.dyndns.org
|
||||
checkip.synology.com
|
||||
teamviewer.com
|
||||
apple.com
|
||||
paypal.com
|
||||
paypalobjects.com
|
||||
api.ipify.org
|
||||
epicgames.com
|
||||
emby.kyarucloud.moe
|
||||
ac.playstation.net
|
||||
dl.playstation.net
|
||||
update.playstation.net
|
||||
|
||||
microsoft.com
|
||||
dyndns.com
|
||||
douyucdn.cn
|
||||
douyucdn2.cn
|
||||
|
||||
steamcontent.com
|
||||
dl.steam.clngaa.com
|
||||
dl.steam.ksyna.com
|
||||
st.dl.bscstorage.net
|
||||
st.dl.eccdnx.com
|
||||
st.dl.pinyuncloud.com
|
||||
cdn.mileweb.cs.steampowered.com.8686c.com
|
||||
cdn-ws.content.steamchina.com
|
||||
cdn-qc.content.steamchina.com
|
||||
cdn-ali.content.steamchina.com
|
||||
epicgames-download1-1251447533.file.myqcloud.com
|
@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
[ "$ACTION" = ifup ] || exit 0
|
||||
[ -f /var/lock/bypass_ready.lock ] || exit 0
|
||||
if uci -q get bypass.@global[0].global_server >/dev/null;then
|
||||
default_device=$(ip route | grep default | awk -F 'dev ' '{print $2}' | awk '{print $1}')
|
||||
[ "$default_device" == "$DEVICE" ] && {
|
||||
LOCK_FILE_DIR=/var/lock
|
||||
[ ! -d ${LOCK_FILE_DIR} ] && mkdir -p ${LOCK_FILE_DIR}
|
||||
LOCK_FILE="${LOCK_FILE_DIR}/bypass_ifup.lock"
|
||||
if [ -s ${LOCK_FILE} ]; then
|
||||
SPID=$(cat ${LOCK_FILE})
|
||||
if [ -e /proc/${SPID}/status ]; then
|
||||
exit 1
|
||||
fi
|
||||
cat /dev/null > ${LOCK_FILE}
|
||||
fi
|
||||
echo $$ > ${LOCK_FILE}
|
||||
|
||||
/etc/init.d/bypass restart
|
||||
echo "bypass: restart when $INTERFACE ifup" > /dev/kmsg
|
||||
|
||||
rm -rf ${LOCK_FILE}
|
||||
}
|
||||
|
||||
fi
|
1447
luci-app-bypass/luci-app-bypass/root/etc/init.d/bypass
Normal file
1447
luci-app-bypass/luci-app-bypass/root/etc/init.d/bypass
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
uci batch <<EOF
|
||||
|
||||
[ -e "/etc/config/ucitrack" ] && {
|
||||
delete ucitrack.@bypass[-1]
|
||||
add ucitrack bypass
|
||||
set ucitrack.@bypass[-1].init=bypass
|
||||
commit ucitrack
|
||||
|
||||
}
|
||||
delete firewall.bypass
|
||||
set firewall.bypass=include
|
||||
set firewall.bypass.type=script
|
||||
set firewall.bypass.path=/var/etc/bypass.include
|
||||
set firewall.bypass.reload=1
|
||||
commit firewall
|
||||
EOF
|
||||
|
||||
chmod +x /etc/init.d/bypass /usr/share/bypass/* >/dev/null 2>&1
|
||||
[ ! -s "/etc/config/bypass" ] && cp -f /usr/share/bypass/bypass_config /etc/config/bypass
|
||||
rm -rf /tmp/luci-modulecache /tmp/luci-indexcache
|
||||
exit 0
|
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/lua
|
||||
require 'nixio'
|
||||
nixio.signal(2,"dfl")
|
||||
if arg[1]==nil or arg[2]==nil then
|
||||
os.exit(1)
|
||||
end
|
||||
addr=arg[1]
|
||||
port=arg[2]
|
||||
t=5
|
||||
if arg[3]~=nil then
|
||||
t=arg[3]
|
||||
end
|
||||
socket=nixio.socket("inet","stream")
|
||||
socket:setopt("socket","rcvtimeo",t)
|
||||
socket:setopt("socket","sndtimeo",t)
|
||||
--print("Detecting ports on server: "..addr..":"..port.."...")
|
||||
if socket:connect(addr,port) then
|
||||
--print("Port open")
|
||||
os.exit(0)
|
||||
else
|
||||
--print("Port closed")
|
||||
os.exit(1)
|
||||
end
|
||||
socket:close()
|
29
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/by-gfw
Normal file
29
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/by-gfw
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
generate_china_banned()
|
||||
{
|
||||
t=`cat $1 | base64 -d | wc -l` 2>/dev/null
|
||||
[[ $t == 0 ]] && cat $1 > /tmp/gfwlist.txt || base64 -d $1 > /tmp/gfwlist.txt
|
||||
# cat /etc/bypass/gfw_base.list >> /tmp/gfwlist.txt
|
||||
rm -f $1
|
||||
sed -i '/^@@|/d' /tmp/gfwlist.txt
|
||||
cat /tmp/gfwlist.txt | sort -u |
|
||||
sed 's#!.\+##; s#|##g; s#@##g; s#http:\/\/##; s#https:\/\/##;' |
|
||||
sed '/\*/d; /apple\.com/d; /sina\.cn/d; /sina\.com\.cn/d; /baidu\.com/d; /byr\.cn/d; /jlike\.com/d; /weibo\.com/d; /zhongsou\.com/d; /youdao\.com/d; /sogou\.com/d; /so\.com/d; /soso\.com/d; /aliyun\.com/d; /taobao\.com/d; /jd\.com/d; /qq\.com/d' |
|
||||
sed '/haosou\.com/d /ip\.cn/d /jike\.com/d /gov\.cn/d /uluai\.com\.cn/d /yahoo\.cn/d /yahoo\.co\.jp/d /yahoo\.com/d /ja\.wikipedia\.org/d /cloudfront\.net/d' |
|
||||
sed '/^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/d' |
|
||||
grep '^[0-9a-zA-Z\.-]\+$' | grep '\.' | sed 's#^\.\+##' | sort -u |
|
||||
awk '
|
||||
BEGIN { prev = "________"; } {
|
||||
cur = $0;
|
||||
if (index(cur, prev) == 1 && substr(cur, 1 + length(prev) ,1) == ".") {
|
||||
} else {
|
||||
print cur;
|
||||
prev = cur;
|
||||
}
|
||||
}' | sort -u
|
||||
|
||||
}
|
||||
|
||||
generate_china_banned /tmp/gfw.b64 > /tmp/gfwnew.txt
|
||||
rm -f /tmp/gfwlist.txt
|
108
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/by-monitor
Normal file
108
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/by-monitor
Normal file
@ -0,0 +1,108 @@
|
||||
#!/bin/sh
|
||||
NAME=bypass
|
||||
|
||||
uci_get_by_name(){
|
||||
ret=$(uci -q get $NAME.$1.$2)
|
||||
echo ${ret:=$3}
|
||||
}
|
||||
|
||||
uci_get_by_type(){
|
||||
ret=$(uci -q get $NAME.@$1[0].$2)
|
||||
echo ${ret:=$3}
|
||||
}
|
||||
|
||||
redir_tcp=$1
|
||||
kcp=$2
|
||||
redir_udp=$3
|
||||
redir_nf=$4
|
||||
dns=$5
|
||||
chinadns=$6
|
||||
socks5=$7
|
||||
server_count=$8
|
||||
server=`cat /tmp/etc/$NAME.include | grep '\-A SS_SPEC_WAN_AC \-d' | grep RETURN | awk '{print$4}' | sed 's/\/.*//'`
|
||||
GLOBAL_SERVER=$(uci_get_by_type global global_server)
|
||||
kcp_port=$(uci_get_by_name $GLOBAL_SERVER kcp_port)
|
||||
server_port=$(uci_get_by_name $GLOBAL_SERVER server_port)
|
||||
password=$(uci_get_by_name $GLOBAL_SERVER kcp_password)
|
||||
kcp_param=$(uci_get_by_name $GLOBAL_SERVER kcp_param)
|
||||
gfw_mode=$(uci_get_by_type global gfw_mode 0)
|
||||
dns_mode=$(uci_get_by_type global dns_mode 1)
|
||||
LOG=/tmp/log/$NAME.log
|
||||
SDNS=/tmp/etc/smartdns
|
||||
DNS_T=$SDNS/smartdns-by.conf
|
||||
MDNS=/tmp/etc/mosdns
|
||||
MDNS_T=$MDNS/mosdns-by.yaml
|
||||
NAME=bypass
|
||||
VAR=/tmp/etc/$NAME
|
||||
[ "$password" != "" ] && password="--key "${password}
|
||||
|
||||
log() {
|
||||
echo "$(date +'%Y-%m-%d %H:%M:%S') $*" >>$LOG
|
||||
}
|
||||
|
||||
re(){
|
||||
/etc/init.d/$NAME stop
|
||||
/etc/init.d/$NAME start
|
||||
}
|
||||
|
||||
while :;do
|
||||
sleep 30
|
||||
#redir tcp
|
||||
|
||||
if [ $redir_tcp -gt 0 ] && [ $(busybox ps -w | grep by-retcp | grep -v grep | wc -l) = 0 ];then
|
||||
log "Redir TCP :$redir_tcp Error. Restart!"
|
||||
re
|
||||
fi
|
||||
#kcptun
|
||||
if [ $kcp = 1 ] && [ $(busybox ps -w | grep kcptun-client | grep -v grep | wc -l) = 0 ];then
|
||||
log "SSR KCPTUN:$kcp Error. Restart!"
|
||||
killall -q -9 kcptun-client >/dev/null 2>&1
|
||||
$(which kcptun-client) -r $server:$kcp_port -l :$server_port $password $kcp_param >/dev/null 2>&1 &
|
||||
fi
|
||||
#redir udp
|
||||
if [ $redir_udp = 1 ];then
|
||||
t=`busybox ps -w | grep by-reudp | grep -v grep | wc -l`
|
||||
if [ $t = 0 ];then
|
||||
log "Redir UDP :$redir_udp Error. Restart!"
|
||||
re
|
||||
fi
|
||||
fi
|
||||
#redir netflix
|
||||
if [ $redir_nf = 1 ] && [ $(busybox ps -w | grep by-nf | grep -v grep | wc -l) = 0 ];then
|
||||
log "Redir Netflix :$redir_nf Error. Restart!"
|
||||
re
|
||||
fi
|
||||
|
||||
#dns
|
||||
if [ "$dns" -eq 1 ] && [ $(busybox ps -w | grep smartdns | grep -v grep | wc -l) = 0 ];then
|
||||
log "SmartDNS :$dns Error. Restart!"
|
||||
kill -9 $(busybox ps -w | grep smartdns | grep -v grep | awk '{print$1}') 2>/dev/null
|
||||
service_start $(which smartdns) -c $DNS_T 2>/dev/null
|
||||
elif [ "$dns" -eq 2 ]&& [ $(busybox ps -w | grep mosdns | grep -v grep | wc -l) = 0 ];then
|
||||
log "MosDNS :$dns Error. Restart!"
|
||||
kill -9 $(busybox ps -w | grep mosdns | grep -v grep | grep $MDNS_T | awk '{print $1}') >/dev/null 2>&1
|
||||
service_start $(which mosdns) start -c $MDNS_T 2>/dev/null
|
||||
fi
|
||||
#chinadns-ng
|
||||
if [ $chinadns = 1 ] && [ $(busybox ps -w | grep chinadns-ng | grep -v grep | wc -l) = 0 ];then
|
||||
log "ChinaDNS-NG :$chinadns Error. Restart!"
|
||||
kill -9 $(busybox ps -w | grep chinadns-ng | grep -v grep | awk '{print$1}') 2>/dev/null
|
||||
if [ "$dns" -eq 1 ] ;then
|
||||
# service_start $(which chinadns-ng) -l 5337 -c '127.0.0.1#5336' -t '127.0.0.1#5335' -4 china_v4 -p 3 -6 china_v6 -f -n $([ $gfw_mode = 1 ] && echo -g /tmp/etc/bypass/gfw.list) >/dev/null 2>&1 &
|
||||
service_start $(which chinadns-ng) -l 5337 -c '127.0.0.1#5336' -t '127.0.0.1#5335' -4 china_v4 -p 3 -6 china_v6 -f -n $([ $gfw_mode = 1 ] && echo -g $VAR/gfw.list) >/dev/null 2>&1 &
|
||||
else
|
||||
bootstrap_dns=$(uci_get_by_type global bootstrap_dns '114.114.114.114')
|
||||
service_start $(which chinadns-ng) -l 5337 -c "${bootstrap_dns}#53" -t '127.0.0.1#5335' -4 china_v4 -p 3 -6 china_v6 -f -n $([ $gfw_mode = 1 ] && echo -g $VAR/gfw.list) >/dev/null 2>&1 &
|
||||
fi
|
||||
fi
|
||||
#localsocks
|
||||
if [ $socks5 = 1 ] && [ $(busybox ps -w | grep by-socks | grep -v grep | wc -l) = 0 ];then
|
||||
log "Global Socks Server :$socks5 Error. Restart!"
|
||||
re
|
||||
fi
|
||||
#server
|
||||
if [ $server_count -gt 0 ] && [ $(busybox ps -w | grep by-server | grep -v grep | wc -l) -lt $server_count ];then
|
||||
log "SSR Server :$server_count Error. Restart!"
|
||||
re
|
||||
fi
|
||||
done
|
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "x$2" = x1 ];then
|
||||
B=1
|
||||
while ! A=$(curl -Lfsm 9 https://fastly.jsdelivr.net/gh/QiuSimons/Netflix_IP@master/getflix.txt || curl -Lfsm 9 https://raw.githubusercontent.com/QiuSimons/Netflix_IP/master/getflix.txt );do
|
||||
[ $B -ge 20 ] && break || let B++
|
||||
sleep 2
|
||||
done
|
||||
for i in $A;do ipset add netflix $i 2>/dev/null;done
|
||||
fi
|
||||
|
||||
if [ "$1" = gfw ];then
|
||||
A=$(cat /etc/bypass/telegram.list)
|
||||
for i in $A;do ipset add blacklist $i 2>/dev/null;done
|
||||
B=1
|
||||
while ! A=$(nslookup -q=TXT _spf.google.com | grep text | sed -e 's/"v=spf1//' -e 's/ ~all"//' -e 's/ include:/\n/g' | grep -v text);do
|
||||
[ $B -ge 20 ] && break || let B++
|
||||
sleep 2
|
||||
done
|
||||
for i in $A;do
|
||||
B=1
|
||||
while ! nslookup -q=TXT $i >/dev/null 2>&1;do
|
||||
[ $B -ge 20 ] && break || let B++
|
||||
sleep 2
|
||||
done
|
||||
B=$(nslookup -q=TXT $i | sed -e 's/"v=spf1//' -e 's/ ~all"//' -e 's/ ip.:/\n/g' | grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}')
|
||||
for i in $B;do ipset add blacklist $i 2>/dev/null;done
|
||||
done
|
||||
fi
|
242
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/by-rules
Normal file
242
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/by-rules
Normal file
@ -0,0 +1,242 @@
|
||||
#!/bin/sh
|
||||
|
||||
RULESDIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
RULESPATH=$RULESDIR/by-rules
|
||||
ipt=$(command -v iptables-legacy || command -v iptables)
|
||||
ip6t=$(command -v ip6tables-legacy || command -v ip6tables)
|
||||
IPT_M="$ipt -t mangle -w"
|
||||
IPT_N="$ipt -t nat -w"
|
||||
IP6T_M="$ipt -t mangle -w"
|
||||
IP6T_N="$ipt -t nat -w"
|
||||
[ -z "$ip6t" -o -z "$(lsmod | grep 'ip6table_nat')" ] && IP6T_N="eval #$IP6T_N"
|
||||
[ -z "$ip6t" -o -z "$(lsmod | grep 'ip6table_mangle')" ] && IP6T_M="eval #$IP6T_M"
|
||||
|
||||
FWI=$(uci -q get firewall.bypass.path) || FWI=/tmp/etc/bypass.include
|
||||
LFILE=/tmp/by_local.ipset
|
||||
LOG=/tmp/log/bypass.log
|
||||
TAG="_SS_SPEC_RULE_"
|
||||
MODE=0
|
||||
DEBUG=''
|
||||
loger() {
|
||||
# 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug
|
||||
logger -st BYPASS[$$] -p$1 $2
|
||||
}
|
||||
log(){
|
||||
echo "$(date +'%Y-%m-%d %H:%M:%S') $*" >> $LOG
|
||||
}
|
||||
|
||||
|
||||
flush_iptables() {
|
||||
local ipts="$ipt -t $1"
|
||||
local DAT=$($ipt-save -t $1)
|
||||
eval $(echo "$DAT" | grep "$TAG" | sed -e 's/^-A/$ipts -D/' -e 's/$/;/')
|
||||
for X in $(echo "$DAT" | awk '/^:SS_SPEC/{print $1}'); do
|
||||
$ipts -F ${X:1} 2>/dev/null && $ipts -X ${X:1}
|
||||
done
|
||||
}
|
||||
|
||||
flush_dns(){
|
||||
while ${IP6T_N} -D PREROUTING -p $1 --dport 53 -m comment --comment $TAG -j REDIRECT --to-ports 53 2>/dev/null;do :;done
|
||||
}
|
||||
|
||||
flush_r(){
|
||||
flush_iptables nat
|
||||
flush_iptables mangle
|
||||
flush_dns udp
|
||||
flush_dns tcp
|
||||
while ip rule del fwmark 1 lookup 100 2>/dev/null;do :;done
|
||||
ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null
|
||||
ipset -X ss_spec_lan_ac 2>/dev/null
|
||||
ipset -X ss_spec_wan_ac 2>/dev/null
|
||||
ipset -X fplan 2>/dev/null
|
||||
ipset -X gmlan 2>/dev/null
|
||||
ipset -X oversea 2>/dev/null
|
||||
ipset -X blacklist 2>/dev/null
|
||||
ipset -X netflix 2>/dev/null
|
||||
ipset -X china_v4 2>/dev/null
|
||||
ipset -X china_v6 2>/dev/null
|
||||
ipset -X by_all 2>/dev/null
|
||||
[ -n "$FWI" ] && echo '#!/bin/sh' >$FWI
|
||||
}
|
||||
|
||||
ipset_r(){
|
||||
${IPT_N} -N SS_SPEC_WAN_FW || return 1
|
||||
${IPT_N} -A SS_SPEC_WAN_FW -p tcp $PROXY_PORTS -j REDIRECT --to-ports $local_port 2>/dev/null
|
||||
[ $MODE = oversea ] && B=1
|
||||
[ $MODE = router -o $MODE = all ] && [ -z "$PROXY_PORTS" ] && B=1
|
||||
[ -n "$NF_SERVER" ] && ipset -N netflix hash:net 2>/dev/null
|
||||
if [ $MODE != all ];then
|
||||
[ -n "$LAN_FP_IP" ] && ipset -N fplan hash:net 2>/dev/null
|
||||
[ -n "$WAN_FW_IP" -o $MODE != router -o -s /etc/bypass/black.list ] && ipset -N blacklist hash:net 2>/dev/null
|
||||
for ip in $LAN_FP_IP;do ipset -! add fplan $ip;done
|
||||
for ip in $WAN_FW_IP;do ipset -! add blacklist $ip;done
|
||||
fi
|
||||
if [ -n "$LAN_GM_IP" -a ! "$B" ];then
|
||||
C=1
|
||||
ipset -N gmlan hash:net 2>/dev/null
|
||||
for ip in $LAN_GM_IP;do ipset -! add gmlan $ip;done
|
||||
fi
|
||||
[ "$A" -o "$C" ] && /usr/share/bypass/chinaipset
|
||||
[ $MODE = router ] && /usr/share/bypass/chinaipset v6
|
||||
cat > $LFILE <<EOF
|
||||
0.0.0.0/8
|
||||
10.0.0.0/8
|
||||
100.64.0.0/10
|
||||
127.0.0.0/8
|
||||
169.254.0.0/16
|
||||
172.16.0.0/12
|
||||
192.0.0.0/24
|
||||
192.0.2.0/24
|
||||
192.88.99.0/24
|
||||
192.168.0.0/16
|
||||
198.18.0.0/15
|
||||
198.51.100.0/24
|
||||
203.0.113.0/24
|
||||
224.0.0.0/4
|
||||
240.0.0.0/4
|
||||
EOF
|
||||
sed -i 's/^/add ss_spec_wan_ac /' $LFILE
|
||||
sed -i '1i\create ss_spec_wan_ac hash:net' $LFILE
|
||||
ipset -F ss_spec_wan_ac 2>/dev/null
|
||||
ipset -R < $LFILE 2>/dev/null
|
||||
rm -f $LFILE
|
||||
for ip in $WAN_BP_IP;do ipset -! add ss_spec_wan_ac $ip;done
|
||||
${IPT_N} -N SS_SPEC_WAN_AC
|
||||
${IPT_N} -A SS_SPEC_WAN_AC -d $server -j RETURN
|
||||
${IPT_N} -A SS_SPEC_WAN_AC -m set --match-set ss_spec_wan_ac dst -j RETURN
|
||||
if ipset list netflix >/dev/null 2>&1;then
|
||||
[ "$(uci -q get bypass.@global[0].nf_proxy)" = 1 ] && ${IPT_N} -A SS_SPEC_WAN_AC -d $NF_SERVER -j SS_SPEC_WAN_FW || ipset -! add ss_spec_wan_ac $NF_SERVER
|
||||
${IPT_N} -A SS_SPEC_WAN_AC -p tcp -m set --match-set netflix dst -j REDIRECT --to-ports $NF_PORT
|
||||
fi
|
||||
${IPT_N} -A SS_SPEC_WAN_AC -m set --match-set ss_spec_wan_ac dst -j RETURN
|
||||
ipset list fplan >/dev/null 2>&1 && ${IPT_N} -A SS_SPEC_WAN_AC -m set --match-set fplan src -j SS_SPEC_WAN_FW
|
||||
ipset list blacklist >/dev/null 2>&1 && ${IPT_N} -A SS_SPEC_WAN_AC -m set --match-set blacklist dst -j SS_SPEC_WAN_FW
|
||||
ipset list gmlan >/dev/null 2>&1 && ${IPT_N} -A SS_SPEC_WAN_AC -m set --match-set gmlan src -m set ! --match-set china_v4 dst -j SS_SPEC_WAN_FW
|
||||
|
||||
case $MODE in
|
||||
router)${IPT_N} -A SS_SPEC_WAN_AC -m set ! --match-set china_v4 dst -j SS_SPEC_WAN_FW;;
|
||||
oversea)
|
||||
ipset -N oversea hash:net 2>/dev/null
|
||||
${IPT_N} -I SS_SPEC_WAN_AC -m set --match-set oversea dst -j SS_SPEC_WAN_FW
|
||||
${IPT_N} -A SS_SPEC_WAN_AC -m set --match-set gmlan src -j SS_SPEC_WAN_FW
|
||||
${IPT_N} -A SS_SPEC_WAN_AC -m set --match-set china_v4 dst -j SS_SPEC_WAN_FW
|
||||
;;
|
||||
all)${IPT_N} -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW;;
|
||||
esac
|
||||
|
||||
if [ "$LAN_AC_IP" ];then
|
||||
ipset -! -R <<-EOF || return 1
|
||||
create ss_spec_lan_ac hash:net
|
||||
$(for ip in ${LAN_AC_IP:1};do echo "add ss_spec_lan_ac $ip";done)
|
||||
EOF
|
||||
case "${LAN_AC_IP:0:1}" in
|
||||
w|W)MATCH_SET="-m set --match-set ss_spec_lan_ac src";;
|
||||
b|B)MATCH_SET="-m set ! --match-set ss_spec_lan_ac src";;
|
||||
esac
|
||||
fi
|
||||
|
||||
${IPT_N} -I PREROUTING 1 -p tcp $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_WAN_AC
|
||||
if [ $y ];then
|
||||
${IPT_N} -I PREROUTING 1 -p udp --dport 53 -m comment --comment $TAG -j REDIRECT --to-ports 53
|
||||
${IPT_N} -I PREROUTING 2 -p tcp --dport 53 -m comment --comment $TAG -j REDIRECT --to-ports 53
|
||||
[ -n "$ip6t" ] && ${IP6T_N} -I PREROUTING 1 -p udp --dport 53 -m comment --comment $TAG -j REDIRECT --to-ports 53
|
||||
[ -n "$ip6t" ] && ${IP6T_N} -I PREROUTING 2 -p tcp --dport 53 -m comment --comment $TAG -j REDIRECT --to-ports 53
|
||||
fi
|
||||
${IPT_N} -I OUTPUT 1 -p tcp -m comment --comment "$TAG" -j SS_SPEC_WAN_AC
|
||||
}
|
||||
|
||||
dns_hijack() {
|
||||
$ipt_n -I SS_SPEC__TPROXY -p udp --dport 53 -j REDIRECT --to-ports 53
|
||||
}
|
||||
tp_rule(){
|
||||
[ -n "$SERVER" ] || return 0
|
||||
ip rule add fwmark 1 lookup 100
|
||||
ip route add local 0.0.0.0/0 dev lo table 100
|
||||
${IPT_M} -N SS_SPEC_TPROXY
|
||||
if ipset list china_v4 >/dev/null 2>&1;then
|
||||
[ $MODE = oversea ] && a= || a=!
|
||||
# error
|
||||
${IPT_M} -A SS_SPEC__TPROXY -p udp -m set $a --match-set china_v4 dst --dport 80 -j DROP
|
||||
${IPT_M} -A SS_SPEC__TPROXY -p udp -m set $a --match-set china_v4 dst --dport 443 -j DROP
|
||||
elif ipset list blacklist >/dev/null 2>&1;then
|
||||
# error
|
||||
${IPT_M} -A SS_SPEC__TPROXY -p udp -m set --match-set blacklist dst --dport 80 -j DROP
|
||||
${IPT_M} -A SS_SPEC__TPROXY -p udp -m set --match-set blacklist dst --dport 443 -j DROP
|
||||
fi
|
||||
${IPT_M} -A SS_SPEC_TPROXY -p udp --dport 53 -j RETURN
|
||||
${IPT_M} -A SS_SPEC_TPROXY -p udp -d $SERVER -j RETURN
|
||||
${IPT_M} -A SS_SPEC_TPROXY -p udp -m set --match-set ss_spec_wan_ac dst -j RETURN
|
||||
ipset list fplan >/dev/null 2>&1 && ${IPT_M} -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set fplan src -j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x1/0x1
|
||||
ipset list blacklist >/dev/null 2>&1 && ${IPT_M} -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set blacklist dst -j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x1/0x1
|
||||
ipset list gmlan >/dev/null 2>&1 && ${IPT_M} -A SS_SPEC_TPROXY -p udp -m set --match-set gmlan src -m set ! --match-set china_v4 dst -j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x1/0x1
|
||||
|
||||
case $MODE in
|
||||
router)${IPT_M} -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set ! --match-set china_v4 dst -j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x1/0x1;;
|
||||
oversea)
|
||||
${IPT_M} -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set oversea src -m dst -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
|
||||
${IPT_M} -A SS_SPEC_TPROXY -p udp -m set --match-set gmlan src -m set -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
|
||||
${IPT_M} -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set china_v4 dst -j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x01/0x01
|
||||
;;
|
||||
all)${IPT_M} -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -j TPROXY --on-port $LOCAL_PORT --tproxy-mark 0x1/0x1;;
|
||||
esac
|
||||
|
||||
ipset -N by_all hash:net 2>/dev/null
|
||||
net=$(uci -qP /tmp/state get network.wan.device) || net=$(uci -qP /tmp/state get network.wan.ifname)
|
||||
[ $net ] || net=127.0.0.1
|
||||
for i in $(ip -4 add show | grep -v $net | grep inet | grep -v 127.0.0.1 | awk '{print$2}');do
|
||||
ipset -! add by_all $i
|
||||
done
|
||||
|
||||
${IPT_M} -I PREROUTING 1 -p udp $MATCH_SET -m set --match-set by_all src -m comment --comment "$TAG" -j SS_SPEC_TPROXY
|
||||
|
||||
|
||||
}
|
||||
|
||||
gen_include(){
|
||||
extract_rules() {
|
||||
echo "*$1"
|
||||
iptables-save -t $1 | grep SS_SPEC | sed "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/"
|
||||
echo 'COMMIT'
|
||||
}
|
||||
cat <<-EOF >> $FWI
|
||||
iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c
|
||||
iptables-restore -n <<-EOT
|
||||
$(extract_rules nat)
|
||||
$(extract_rules mangle)
|
||||
EOT
|
||||
EOF
|
||||
if [ $y ];then
|
||||
sed -i -e 's/-I PREROUTING 1 -p tcp/-I PREROUTING 2 -p tcp/' -e 's/PREROUTING 2 -p tcp -m set/PREROUTING 3 -p tcp -m set/' $FWI
|
||||
cat <<-EOF >> $FWI
|
||||
while ${IP6T_N} -D PREROUTING -p udp --dport 53 -m comment --comment $TAG -j REDIRECT --to-ports 53 2>/dev/null;do :;done
|
||||
while ${IP6T_N} -D PREROUTING -p tcp --dport 53 -m comment --comment $TAG -j REDIRECT --to-ports 53 2>/dev/null;do :;done
|
||||
[ -n "$ip6t" ] && ${IP6T_N} -I PREROUTING 1 -p udp --dport 53 -m comment --comment $TAG -j REDIRECT --to-ports 53
|
||||
[ -n "$ip6t" ] && ${IP6T_N} -I PREROUTING 2 -p tcp --dport 53 -m comment --comment $TAG -j REDIRECT --to-ports 53
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
while getopts ":s:l:S:L:N:P:a:b:w:p:G:D:rczyf" arg;do
|
||||
case $arg in
|
||||
s)server=$OPTARG;;
|
||||
l)local_port=$OPTARG;;
|
||||
S)SERVER=$OPTARG;;
|
||||
L)LOCAL_PORT=$OPTARG;;
|
||||
N)NF_SERVER=$OPTARG;;
|
||||
P)NF_PORT=$OPTARG;;
|
||||
a)LAN_AC_IP=$OPTARG;;
|
||||
b)WAN_BP_IP=$(for ip in $OPTARG;do echo $ip;done);;
|
||||
w)WAN_FW_IP=$OPTARG;;
|
||||
p)LAN_FP_IP=$OPTARG;;
|
||||
G)LAN_GM_IP=$OPTARG;;
|
||||
D)PROXY_PORTS=$OPTARG;;
|
||||
r)MODE=router;A=1;;
|
||||
c)MODE=oversea;A=1;;
|
||||
z)MODE=all;;
|
||||
y)y=1;;
|
||||
f)flush_r;exit 0;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ "$server" -a "$local_port" ] || exit 1
|
||||
flush_r;ipset_r && tp_rule && gen_include || exit 1
|
272
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/by-switch
Normal file
272
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/by-switch
Normal file
@ -0,0 +1,272 @@
|
||||
#!/bin/sh
|
||||
NAME=bypass
|
||||
S=/usr/share/$NAME
|
||||
|
||||
uci_get_by_name(){
|
||||
w=$(uci -q get $NAME.$1.$2)
|
||||
echo ${w:=$3}
|
||||
}
|
||||
|
||||
uci_get_by_type(){
|
||||
w=$(uci -q get $NAME.@$1[0].$2)
|
||||
echo ${w:=$3}
|
||||
}
|
||||
|
||||
log(){
|
||||
echo "$(date +'%Y-%m-%d %H:%M:%S') 自动切换检测: $*" >> /tmp/log/$NAME.log
|
||||
}
|
||||
|
||||
|
||||
get_ip(){
|
||||
i=0
|
||||
if ! echo $ip | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null;then
|
||||
r=1
|
||||
while ! nslookup $ip >/dev/null 2>&1;do
|
||||
[ $r -ge 10 ] && return 1 || let r++
|
||||
sleep 1
|
||||
done
|
||||
ip=$(nslookup $ip 2>/dev/null | grep Address | awk -F' ' '{print$NF}' | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$");i=$?
|
||||
ip=$(echo "$ip" | sed -n 1p)
|
||||
fi
|
||||
return $i
|
||||
}
|
||||
|
||||
f_bin(){
|
||||
w=
|
||||
case $1 in
|
||||
ss)w=$(which ss-local);;
|
||||
ssr)w=$(which ssr-local);;
|
||||
v2ray)w=$(which xray)||w=$(which r2ray);;
|
||||
hysteria2)w=$(which hysteria);;
|
||||
trojan)w=$(which trojan-plus);;
|
||||
naiveproxy)w=$(which naive);;
|
||||
esac
|
||||
echo $w
|
||||
}
|
||||
|
||||
gen_port(){
|
||||
lport=1090
|
||||
while [ $(netstat -tln | grep -c :$lport) != 0 ];do let lport++;done
|
||||
}
|
||||
|
||||
gen_config_file(){
|
||||
pass=$(uci_get_by_name $1 password)
|
||||
timeout=$(uci_get_by_name $1 timeout 60)
|
||||
[ $(uci_get_by_name $1 fast_open 0) = 1 ] && fast=true || fast=false
|
||||
case $type in
|
||||
ss)
|
||||
cat <<-EOF > $J
|
||||
{
|
||||
"server":"$ip",
|
||||
"server_port":$port,
|
||||
"local_address":"0.0.0.0",
|
||||
"local_port":$lport,
|
||||
"password":"$pass",
|
||||
"timeout":$timeout,
|
||||
"method":"$(uci_get_by_name $1 encrypt_method_ss)",
|
||||
"reuse_port":true,
|
||||
"fast_open":$fast
|
||||
}
|
||||
EOF
|
||||
plugin=$(uci_get_by_name $1 plugin)
|
||||
if [ $plugin ];then
|
||||
sed -i "s@$ip\",@$ip\",\n\"plugin\":\"$plugin\",\n\"plugin_opts\":\"$(uci_get_by_name $1 plugin_opts)\",@" $J
|
||||
fi;;
|
||||
ssr)
|
||||
cat <<-EOF > $J
|
||||
{
|
||||
"server":"$ip",
|
||||
"server_port":$port,
|
||||
"local_address":"0.0.0.0",
|
||||
"local_port":$lport,
|
||||
"password":"$pass",
|
||||
"timeout":$timeout,
|
||||
"method":"$(uci_get_by_name $1 encrypt_method)",
|
||||
"protocol":"$(uci_get_by_name $1 protocol)",
|
||||
"protocol_param":"$(uci_get_by_name $1 protocol_param)",
|
||||
"obfs":"$(uci_get_by_name $1 obfs)",
|
||||
"obfs_param":"$(uci_get_by_name $1 obfs_param)",
|
||||
"reuse_port":true,
|
||||
"fast_open":$fast
|
||||
}
|
||||
EOF
|
||||
;;
|
||||
naiveproxy)
|
||||
cat <<-EOF > $J
|
||||
{
|
||||
"listen":"socks://0.0.0.0:$lport",
|
||||
"proxy":"https://$(uci_get_by_name $1 username):$pass@$(uci_get_by_name $1 server):$port",
|
||||
"concurrency":"${3:-1}"
|
||||
}
|
||||
EOF
|
||||
;;
|
||||
|
||||
esac
|
||||
}
|
||||
|
||||
curl_check(){
|
||||
if [ $(uci_get_by_name $1 kcp_enable 0) = 1 ];then
|
||||
log "Skip KCPTUN Node!";return 1
|
||||
fi
|
||||
type=$(uci_get_by_name $1 type)
|
||||
if [ $type = tun ];then
|
||||
curl --interface $(uci_get_by_name $1 iface br-lan) --resolve www.google.com:443:216.239.38.120 -so /dev/null --connect-timeout 20 https://www.google.com;i=$?
|
||||
[ $i = 0 ] || log "Server : $($UCI$1.alias || uci_get_by_name $1 server) cURL check error, Try to switch another server."
|
||||
return $i
|
||||
elif [ $type != socks5 ];then
|
||||
cmd=$(f_bin $type)
|
||||
if [ ! $cmd ];then
|
||||
[ $type = ss -o $type = ssr ] && type=$type-local
|
||||
log "Can't find $(echo $type) program, Skip this Node($($UCI$1.alias || uci_get_by_name $1 server))."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
gen_port
|
||||
J=/var/etc/$NAME-check.json
|
||||
gen_config_file $1
|
||||
IP=127.0.0.1
|
||||
param=
|
||||
case $type in
|
||||
ss|ssr)
|
||||
$cmd -c $J >/dev/null 2>&1 &;;
|
||||
v2ray)
|
||||
$S/gen_xray $1 tcp 0 $lport $ip > $J
|
||||
sed -i 's/\\//g' $J
|
||||
$cmd run -config $J >/dev/null 2>&1 &
|
||||
;;
|
||||
hysteria2)
|
||||
$S/gen_hysteria2 $1 tcp 0 $lport $ip >$J
|
||||
sed -i 's/\\//g' $J
|
||||
$cmd -c $J >/dev/null 2>&1 &;;
|
||||
trojan)
|
||||
$S/gen_config $1 client $lport $ip > $J
|
||||
sed -i 's/\\//g' $J
|
||||
$cmd --config $J >/dev/null 2>&1 &;;
|
||||
naiveproxy)
|
||||
$cmd $J 2>&1 &;;
|
||||
socks5)IP=$ip
|
||||
if [ $(uci_get_by_name $1 auth_enable 0) = 1 ];then
|
||||
username=$(uci_get_by_name $1 username)
|
||||
if [ -n "$username" ];then
|
||||
param="-U $username:$(uci_get_by_name $1 password)"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi;;
|
||||
esac
|
||||
r=1
|
||||
while [ $(netstat -tlnp | grep ${cmd##*/} | grep -c :$lport) = 0 ];do
|
||||
[ $r -ge 10 ] && return 1 || let r++
|
||||
sleep 1
|
||||
done
|
||||
curl -x socks5://$IP:$lport $param --resolve www.google.com:443:216.239.38.120 -so /dev/null --connect-timeout 20 https://www.google.com;i=$?
|
||||
kill -9 $(busybox ps -w | grep -v grep | grep $J | awk '{print$1}') 2>/dev/null
|
||||
rm -f $J
|
||||
[ $i = 0 ] || log "Server : $($UCI$1.alias || uci_get_by_name $1 server) cURL check error, Try to switch another server."
|
||||
return $i
|
||||
}
|
||||
|
||||
test_proxy(){
|
||||
ip=$(uci_get_by_name $1 server)
|
||||
get_ip || return 1
|
||||
port=$(uci_get_by_name $1 server_port)
|
||||
ipset add ss_spec_wan_ac $ip 2>/dev/null
|
||||
a=$?
|
||||
b=$(tcping -c $time_b -i 1 -t 2 -p $port $ip 2>/dev/null | grep 'failed' | awk -F ',' '{print$3}' | awk -F . '{print$1}')
|
||||
if [ -z "$b" -o "$b" -gt 50 ];then
|
||||
b=1
|
||||
else
|
||||
curl_check $1;b=$?
|
||||
fi
|
||||
[ $a = 0 ] && ipset del ss_spec_wan_ac $ip 2>/dev/null
|
||||
return $b
|
||||
}
|
||||
|
||||
check_proxy(){
|
||||
for i in $(seq 1 $(uci_get_by_type global switch_try_count 3));do
|
||||
curl --connect-timeout $time_b -so /dev/null https://www.google.com/generate_204 && return 0
|
||||
a=2
|
||||
ping -c 3 -W 1 223.5.5.5 > /dev/null 2>&1
|
||||
[ $? -eq 0 ] && a=1
|
||||
sleep 1
|
||||
done
|
||||
return $a
|
||||
}
|
||||
|
||||
select_proxy(){
|
||||
SERVER_C=0
|
||||
a=$(uci -X show $NAME | grep =servers)
|
||||
b=$(echo "$a" | wc -l)
|
||||
[ $c -ge $b ] && c=1
|
||||
for i in $(seq $c $b);do
|
||||
d=$(echo "$a" | sed 's/.*\.\(.*\)=.*/\1/' | sed -n ${i}p)
|
||||
([ $d = $SERVER_B ] || [ $(uci_get_by_name $d switch_enable 0) != 1 ]) && continue
|
||||
ip=$(uci_get_by_name $d server)
|
||||
get_ip || continue
|
||||
port=$(uci_get_by_name $d server_port)
|
||||
ipset add ss_spec_wan_ac $ip 2>/dev/null
|
||||
$S/by-check $ip $port $time_b
|
||||
local ret=$?
|
||||
ipset del ss_spec_wan_ac $ip 2>/dev/null
|
||||
if [ "$ret" == "0" ]; then
|
||||
SERVER_C=$d
|
||||
c=$i
|
||||
return 0
|
||||
fi
|
||||
|
||||
done
|
||||
}
|
||||
|
||||
switch_proxy(){
|
||||
/etc/init.d/$NAME restart $1
|
||||
return 0
|
||||
}
|
||||
|
||||
[ "$1" = start ] || exit 1
|
||||
SERVER_A=$(uci_get_by_type global global_server)
|
||||
SERVER_B=$SERVER_A
|
||||
|
||||
SERVER_C=0
|
||||
[ $(uci_get_by_name $SERVER_A kcp_enable 0) = 1 ] && return 1
|
||||
c=1
|
||||
time_a=$(uci_get_by_type global switch_time 300)
|
||||
time_b=$(uci_get_by_type global switch_timeout 5)
|
||||
UCI="uci -q get $NAME."
|
||||
sleep 10
|
||||
while :;do
|
||||
#检测主节点是否能使用
|
||||
check_proxy
|
||||
status=$?
|
||||
if [ "$status" == 2 ]; then
|
||||
log "无法连接到网络,请检查网络是否正常!"
|
||||
return 2
|
||||
fi
|
||||
|
||||
if [ $SERVER_A != $SERVER_B ];then
|
||||
test_proxy $SERVER_A
|
||||
[ $? -eq 0 ] && {
|
||||
#主节点正常,切换到主节点
|
||||
log "${SERVER_A}主节点【$($UCI$SERVER_A.alias || uci_get_by_name $SERVER_A server)】正常,切换到主节点!"
|
||||
SERVER_B=$SERVER_A
|
||||
switch_proxy $SERVER_B
|
||||
[ $? -eq 0 ] && {
|
||||
log "【$($UCI$SERVER_B.alias || uci_get_by_name $SERVER_B server)】节点切换完毕!"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
fi
|
||||
|
||||
if [ "$status" == 0 ]; then
|
||||
return 0
|
||||
elif [ "$status" == "1" ]; then
|
||||
|
||||
log "【$($UCI$SERVER_B.alias || uci_get_by_name $SERVER_B server) 】异常,切换到下一个节点!"
|
||||
select_proxy
|
||||
if [ $SERVER_C != 0 ];then
|
||||
SERVER_B=$SERVER_C
|
||||
log "$($UCI$SERVER_B.alias || uci_get_by_name $SERVER_B server) 正常,切换到此节点!"
|
||||
switch_proxy $SERVER_B
|
||||
fi
|
||||
fi
|
||||
sleep $time_a
|
||||
done
|
@ -0,0 +1,47 @@
|
||||
|
||||
config global
|
||||
list nf_dns 'google_doh'
|
||||
option threads '0'
|
||||
option run_mode 'router'
|
||||
option gfw_mode '1'
|
||||
option adguardhome '0'
|
||||
option dns_mode '1'
|
||||
option ad_list '0'
|
||||
option proxy_ipv6_mode '0'
|
||||
option dns_pollution '0'
|
||||
list dns_remote 'google_doh'
|
||||
list dns_remote 'cloudflare2_tcp'
|
||||
list dns_remote 'quad9_tcp'
|
||||
list dns_local 'alidns_doh'
|
||||
list dns_local 'baidu_tcp'
|
||||
option bootstrap_dns '114.114.114.114'
|
||||
option enable_switch '1'
|
||||
option switch_time '300'
|
||||
option switch_timeout '5'
|
||||
option switch_try_count '3'
|
||||
option monitor_enable '1'
|
||||
option dports '2'
|
||||
option start_delay '60'
|
||||
|
||||
|
||||
config socks5_proxy
|
||||
|
||||
config access_control
|
||||
option lan_ac_mode 'b'
|
||||
|
||||
config server_global
|
||||
|
||||
config global_rules
|
||||
option ad_url 'https://github.com/sirpdboy/iplist/releases/latest/download/ad_list.txt'
|
||||
option gfwlist_url 'https://github.com/sirpdboy/iplist/releases/latest/download/gfwlist.txt'
|
||||
option chnroute_url 'https://github.com/sirpdboy/iplist/releases/latest/download/all_cn.txt'
|
||||
option chnroute6_url 'https://github.com/sirpdboy/iplist/releases/latest/download/all_cn_ipv6.txt'
|
||||
option domains_url 'https://github.com/sirpdboy/iplist/releases/latest/download/domains_cn.txt'
|
||||
|
||||
config server_subscribe
|
||||
option proxy '0'
|
||||
option auto_update_time '4'
|
||||
option filter_words '时间/剩余/QQ群/官网/防失联地址/回国/反馈/到期/流量/更多/邮箱'
|
||||
option switch '1'
|
||||
option insecure '1'
|
||||
option auto_update '0'
|
@ -0,0 +1,23 @@
|
||||
#!/bin/sh
|
||||
[ "x$1" = "xcheck" ] || exit 1
|
||||
NAME=bypass
|
||||
T_FILE=/etc/bypass
|
||||
log(){
|
||||
echo "$(date +'%Y-%m-%d %H:%M:%S') By Check Network :$*" >> /tmp/log/$NAME.log
|
||||
}
|
||||
|
||||
B=0
|
||||
while ! curl -so /dev/null -m 3 www.taobao.com;do
|
||||
[ $B -ge 5 ]&& log "服务重启中...";/etc/init.d/$NAME stop;/etc/init.d/$NAME start
|
||||
log "请检查网络,服务重启倒计时:$((5-B))"
|
||||
let B++
|
||||
sleep 1
|
||||
done
|
||||
if [ -z "$(uci -q get $NAME.@global[0].global_server)" ];then
|
||||
/etc/init.d/$NAME start &
|
||||
elif [ ! -s $T_FILE/china.txt ] || [ ! -s $T_FILE/china_v6.txt ] || [ ! -s $T_FILE/gfw.list ] ;then
|
||||
log "Update IP/GFW files."
|
||||
/usr/share/$NAME/update --First &
|
||||
else
|
||||
/etc/init.d/$NAME start &
|
||||
fi
|
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
if [ "$1" = v6 ];then
|
||||
ipset -N china_v6 hash:net family inet6 2>/dev/null
|
||||
awk '!/^$/&&!/^#/{printf("add china_v6 %s'" "'\n",$0)}' /tmp/etc/bypass/china_v6.txt > /tmp/china_v6.ipset
|
||||
ipset -F china_v6 2>/dev/null
|
||||
ipset -R < /tmp/china_v6.ipset 2>/dev/null
|
||||
else
|
||||
ipset -N china_v4 hash:net 2>/dev/null
|
||||
awk '!/^$/&&!/^#/{printf("add china_v4 %s'" "'\n",$0)}' /tmp/etc/bypass/china.txt > /tmp/china.ipset
|
||||
ipset -F china_v4 2>/dev/null
|
||||
ipset -R < /tmp/china.ipset 2>/dev/null
|
||||
fi
|
||||
rm -f /tmp/china*.ipset
|
@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
[ "$1" = --down ] || exit 1
|
||||
K=/tmp/bypass/bin
|
||||
T=$K/tmp
|
||||
kill -9 $(ps -w | grep $T | grep -v grep | awk '{print$1}') 2>/dev/null
|
||||
mkdir -p $K
|
||||
if [ $2 = 1 ];then
|
||||
while ! curl -m 9 -Lfso $T https://cdn.jsdelivr.net/gh/sirpdboy/list/K2P_16M/xray;do
|
||||
sleep 2
|
||||
done
|
||||
base64 -d $T > $K/xray
|
||||
chmod +x $K/xray
|
||||
fi
|
||||
if [ $3 = 1 ];then
|
||||
while ! curl -m 9 -Lfso $T https://cdn.jsdelivr.net/gh/sirpdboy/list/K2P_16M/xray-plugin;do
|
||||
sleep 2
|
||||
done
|
||||
base64 -d $T > $K/xray-plugin
|
||||
chmod +x $K/xray-plugin
|
||||
fi
|
||||
rm -f $T
|
||||
[ $4 = 0 ] && /etc/init.d/bypass start &
|
618
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/gen_config
Normal file
618
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/gen_config
Normal file
@ -0,0 +1,618 @@
|
||||
#!/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 chain = arg[5] or "0"
|
||||
local chain_local_port = string.split(chain, "/")[2] or "0"
|
||||
|
||||
local server = ucursor:get_all("bypass", server_section)
|
||||
local socks_server = ucursor:get_all("bypass", "@socks5_proxy[0]") or {}
|
||||
local xray_fragment = ucursor:get_all("bypass", "@global_xray_fragment[0]") or {}
|
||||
local xray_noise = ucursor:get_all("bypass", "@xray_noise_packets[0]") or {}
|
||||
local outbound_settings = nil
|
||||
|
||||
local ip_addr = server.server
|
||||
local tls_host = server.tls_host or ip_addr
|
||||
function vmess_vless()
|
||||
outbound_settings = {
|
||||
vnext = {
|
||||
{
|
||||
address = ip_addr,
|
||||
port = tonumber(server.server_port),
|
||||
users = {
|
||||
{
|
||||
id = server.vmess_id,
|
||||
alterId = (server.v2ray_protocol == "vmess" or not server.v2ray_protocol) and tonumber(server.alter_id) or nil,
|
||||
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') or (server.tls == '1') or (server.reality == '1')) and server.tls_flow ~= "none") and server.tls_flow or nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
function trojan_shadowsocks()
|
||||
outbound_settings = {
|
||||
servers = {
|
||||
{
|
||||
address = ip_addr,
|
||||
port = tonumber(server.server_port),
|
||||
password = server.password,
|
||||
method = ((server.v2ray_protocol == "shadowsocks") and server.encrypt_method_ss) or nil,
|
||||
uot = (server.v2ray_protocol == "shadowsocks") and (server.uot == '1') or nil,
|
||||
ivCheck = (server.v2ray_protocol == "shadowsocks") and (server.ivCheck == '1') or nil,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = {
|
||||
secretKey = server.private_key,
|
||||
address = server.local_addresses,
|
||||
peers = {
|
||||
{
|
||||
publicKey = server.peer_pubkey,
|
||||
preSharedKey = server.preshared_key,
|
||||
endpoint = ip_addr .. ":" .. server.server_port
|
||||
keepAlive = tonumber(server.keepaliveperiod),
|
||||
allowedIPs = (server.allowedips) or nil,
|
||||
}
|
||||
},
|
||||
noKernelTun = (server.kernelmode == "1") and true or false,
|
||||
reserved = {server.reserved} or nil,
|
||||
mtu = tonumber(server.mtu)
|
||||
}
|
||||
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,
|
||||
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 = {
|
||||
loglevel = "warning"
|
||||
},
|
||||
-- 初始化 inbounds 表
|
||||
inbounds = {},
|
||||
|
||||
-- 初始化 outbounds 表
|
||||
outbounds = {},
|
||||
}
|
||||
-- 传入连接
|
||||
-- 添加 dokodemo-door 配置,如果 local_port 不为 0
|
||||
if local_port ~= "0" then
|
||||
table.insert(Xray.inbounds, {
|
||||
-- listening
|
||||
port = tonumber(local_port),
|
||||
protocol = "dokodemo-door",
|
||||
settings = {network = proto, followRedirect = true},
|
||||
sniffing = {
|
||||
enabled = true,
|
||||
destOverride = {"http", "tls", "quic"},
|
||||
metadataOnly = false,
|
||||
domainsExcluded = {
|
||||
"courier.push.apple.com",
|
||||
"rbsxbxp-mim.vivox.com",
|
||||
"rbsxbxp.www.vivox.com",
|
||||
"rbsxbxp-ws.vivox.com",
|
||||
"rbspsxp.www.vivox.com",
|
||||
"rbspsxp-mim.vivox.com",
|
||||
"rbspsxp-ws.vivox.com",
|
||||
"rbswxp.www.vivox.com",
|
||||
"rbswxp-mim.vivox.com",
|
||||
"disp-rbspsp-5-1.vivox.com",
|
||||
"disp-rbsxbp-5-1.vivox.com",
|
||||
"proxy.rbsxbp.vivox.com",
|
||||
"proxy.rbspsp.vivox.com",
|
||||
"proxy.rbswp.vivox.com",
|
||||
"rbswp.vivox.com",
|
||||
"rbsxbp.vivox.com",
|
||||
"rbspsp.vivox.com",
|
||||
"rbspsp.www.vivox.com",
|
||||
"rbswp.www.vivox.com",
|
||||
"rbsxbp.www.vivox.com",
|
||||
"rbsxbxp.vivox.com",
|
||||
"rbspsxp.vivox.com",
|
||||
"rbswxp.vivox.com",
|
||||
"Mijia Cloud",
|
||||
"dlg.io.mi.com"
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
-- 开启 socks 代理
|
||||
-- 检查是否启用 socks 代理
|
||||
if proto:find("tcp") and socks_port ~= "0" then
|
||||
table.insert(Xray.inbounds, {
|
||||
-- socks
|
||||
protocol = "socks",
|
||||
port = tonumber(socks_port),
|
||||
settings = {
|
||||
auth = socks_server.socks5_auth,
|
||||
udp = true,
|
||||
mixed = (socks_server.socks5_mixed == '1') and true or false,
|
||||
accounts = (socks_server.socks5_auth ~= "noauth") and {
|
||||
{
|
||||
user = socks_server.socks5_user,
|
||||
pass = socks_server.socks5_pass
|
||||
}
|
||||
} or nil
|
||||
}
|
||||
})
|
||||
end
|
||||
-- 传出连接
|
||||
Xray.outbounds = {
|
||||
{
|
||||
protocol = server.v2ray_protocol,
|
||||
settings = outbound_settings,
|
||||
-- 底层传输配置
|
||||
streamSettings = (server.v2ray_protocol ~= "wireguard") and {
|
||||
network = server.transport or "tcp",
|
||||
security = (server.xtls == '1') and "xtls" or (server.tls == '1') and "tls" or (server.reality == '1') and "reality" or nil,
|
||||
tlsSettings = (server.tls == '1') and {
|
||||
-- tls
|
||||
alpn = server.tls_alpn,
|
||||
fingerprint = server.fingerprint,
|
||||
allowInsecure = (server.insecure == "1"),
|
||||
serverName = server.tls_host,
|
||||
certificates = server.certificate and {
|
||||
usage = "verify",
|
||||
certificateFile = server.certpath
|
||||
} or nil,
|
||||
} or nil,
|
||||
xtlsSettings = (server.xtls == '1') and server.tls_host and {
|
||||
-- xtls
|
||||
allowInsecure = (server.insecure == "1") and true or nil,
|
||||
serverName = server.tls_host,
|
||||
minVersion = "1.3"
|
||||
} or nil,
|
||||
realitySettings = (server.reality == '1') and {
|
||||
publicKey = server.reality_publickey,
|
||||
shortId = server.reality_shortid,
|
||||
spiderX = server.reality_spiderx,
|
||||
fingerprint = server.fingerprint,
|
||||
serverName = server.tls_host
|
||||
} or nil,
|
||||
rawSettings = (server.transport == "raw" or server.transport == "tcp") and {
|
||||
-- tcp
|
||||
header = {
|
||||
type = server.tcp_guise or "none",
|
||||
request = (server.tcp_guise == "http") and {
|
||||
-- request
|
||||
path = {server.http_path} or {"/"},
|
||||
headers = {Host = {server.http_host} or {}}
|
||||
} or nil
|
||||
}
|
||||
} or nil,
|
||||
kcpSettings = (server.transport == "kcp") and {
|
||||
-- kcp
|
||||
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 {
|
||||
-- ws
|
||||
Host = server.ws_host or server.tls_host or nil,
|
||||
path = server.ws_path,
|
||||
maxEarlyData = tonumber(server.ws_ed) or nil,
|
||||
earlyDataHeaderName = server.ws_ed_header or nil
|
||||
} or nil,
|
||||
httpupgradeSettings = (server.transport == "httpupgrade") and {
|
||||
-- httpupgrade
|
||||
host = (server.httpupgrade_host or server.tls_host) or nil,
|
||||
path = server.httpupgrade_path or ""
|
||||
} or nil,
|
||||
splithttpSettings = (server.transport == "splithttp") and {
|
||||
-- splithttp
|
||||
host = (server.splithttp_host or server.tls_host) or nil,
|
||||
path = server.splithttp_path or "/"
|
||||
} 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 "",
|
||||
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,
|
||||
sockopt = {
|
||||
mark = 250,
|
||||
tcpMptcp = (server.mptcp == "1") and true or nil, -- MPTCP
|
||||
tcpNoDelay = (server.mptcp == "1") and true or nil, -- MPTCP
|
||||
tcpcongestion = server.custom_tcpcongestion, -- 连接服务器节点的 TCP 拥塞控制算法
|
||||
dialerProxy = (xray_fragment.fragment == "1" or xray_fragment.noise == "1") and "dialerproxy" or nil
|
||||
}
|
||||
} or nil,
|
||||
mux = (server.v2ray_protocol ~= "wireguard") and {
|
||||
-- mux
|
||||
enabled = (server.mux == "1") and true or false, -- Mux
|
||||
concurrency = tonumber(server.concurrency), -- TCP 最大并发连接数
|
||||
xudpConcurrency = tonumber(server.xudpConcurrency), -- UDP 最大并发连接数
|
||||
xudpProxyUDP443 = server.xudpProxyUDP443 -- 对被代理的 UDP/443 流量处理方式
|
||||
} or nil
|
||||
}
|
||||
}
|
||||
-- 添加带有 fragment 设置的 dialerproxy 配置
|
||||
if xray_fragment.fragment ~= "0" or (xray_fragment.noise ~= "0" and xray_noise.enabled ~= "0") then
|
||||
table.insert(Xray.outbounds, {
|
||||
protocol = "freedom",
|
||||
tag = "dialerproxy",
|
||||
settings = {
|
||||
domainStrategy = (xray_fragment.noise == "1" and xray_noise.enabled == "1") and xray_noise.domainStrategy,
|
||||
fragment = (xray_fragment.fragment == "1") and {
|
||||
packets = (xray_fragment.fragment_packets ~= "") and xray_fragment.fragment_packets or nil,
|
||||
length = (xray_fragment.fragment_length ~= "") and xray_fragment.fragment_length or nil,
|
||||
interval = (xray_fragment.fragment_interval ~= "") and xray_fragment.fragment_interval or nil
|
||||
} or nil,
|
||||
noises = (xray_fragment.noise == "1" and xray_noise.enabled == "1") and {
|
||||
{
|
||||
type = xray_noise.type,
|
||||
packet = xray_noise.packet,
|
||||
delay = xray_noise.delay:find("-") and xray_noise.delay or tonumber(xray_noise.delay)
|
||||
}
|
||||
} or nil
|
||||
},
|
||||
streamSettings = {
|
||||
sockopt = {
|
||||
mark = 250,
|
||||
tcpMptcp = (server.mptcp == "1") and true or nil, -- MPTCP
|
||||
tcpNoDelay = (server.mptcp == "1") and true or nil, -- MPTCP
|
||||
tcpcongestion = server.custom_tcpcongestion -- 连接服务器节点的 TCP 拥塞控制算法
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
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 = server.tls_alpn or {"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 ip_addr 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 = (server.server_port and (server.port_range and (ip_addr .. ":" .. server.server_port .. "," .. server.port_range) or ip_addr .. ":" .. server.server_port) or (server.port_range and ip_addr .. ":" .. server.port_range or ip_addr .. ":443")),
|
||||
bandwidth = (server.uplink_capacity or server.downlink_capacity) and {
|
||||
up = tonumber(server.uplink_capacity) and tonumber(server.uplink_capacity) .. " mbps" or nil,
|
||||
down = tonumber(server.downlink_capacity) and tonumber(server.downlink_capacity) .. " mbps" or nil
|
||||
},
|
||||
socks5 = (proto:find("tcp") and tonumber(socks_port) and tonumber(socks_port) ~= 0) and {
|
||||
listen = "0.0.0.0:" .. tonumber(socks_port),
|
||||
disable_udp = false
|
||||
} or nil,
|
||||
transport = (server.transport_protocol) and {
|
||||
type = (server.transport_protocol) or udp,
|
||||
udp = (server.port_range and (server.hopinterval) and {
|
||||
hopInterval = (server.port_range and (tonumber(server.hopinterval) .. "s") or nil)
|
||||
} or nil)
|
||||
} or nil,
|
||||
--[[
|
||||
tcpTProxy = (proto:find("tcp") and local_port ~= "0") and {
|
||||
listen = "0.0.0.0:" .. tonumber(local_port)
|
||||
} or nil,
|
||||
]]--
|
||||
tcpRedirect = (proto:find("tcp") and local_port ~= "0") and {
|
||||
listen = "0.0.0.0:" .. tonumber(local_port)
|
||||
} or nil,
|
||||
udpTProxy = (proto:find("udp") and local_port ~= "0") and {
|
||||
listen = "0.0.0.0:" .. tonumber(local_port)
|
||||
} or nil,
|
||||
obfs = (server.flag_obfs == "1") and {
|
||||
type = server.obfs_type,
|
||||
salamander = { password = server.salamander }
|
||||
} or nil,
|
||||
quic = (server.flag_quicparam == "1" ) and {
|
||||
initStreamReceiveWindow = (server.initstreamreceivewindow and server.initstreamreceivewindow or nil),
|
||||
maxStreamReceiveWindow = (server.maxstreamseceivewindow and server.maxstreamseceivewindow or nil),
|
||||
initConnReceiveWindow = (server.initconnreceivewindow and server.initconnreceivewindow or nil),
|
||||
maxConnReceiveWindow = (server.maxconnreceivewindow and server.maxconnreceivewindow or nil),
|
||||
maxIdleTimeout = (tonumber(server.maxidletimeout) and tonumber(server.maxidletimeout) .. "s" or nil),
|
||||
keepAlivePeriod = (tonumber(server.keepaliveperiod) and tonumber(server.keepaliveperiod) .. "s" or nil),
|
||||
disablePathMTUDiscovery = (server.disablepathmtudiscovery == "1") and true or false
|
||||
} or nil,
|
||||
auth = server.hy2_auth,
|
||||
tls = (server.tls_host) and {
|
||||
sni = server.tls_host,
|
||||
--alpn = server.tls_alpn or nil,
|
||||
insecure = (server.insecure == "1") and true or false,
|
||||
pinSHA256 = (server.insecure == "1") and server.pinsha256 or nil
|
||||
} or {
|
||||
sni = ip_addr,
|
||||
insecure = (server.insecure == "1") and true or false
|
||||
},
|
||||
fast_open = (server.fast_open == "1") and true or false,
|
||||
lazy = (server.lazy_mode == "1") and true or false
|
||||
}
|
||||
local shadowtls = {
|
||||
client = {
|
||||
server_addr = server.server_port and ip_addr .. ":" .. server.server_port or nil,
|
||||
listen = "127.0.0.1:" .. tonumber(local_port),
|
||||
tls_names = server.shadowtls_sni,
|
||||
password = server.password
|
||||
},
|
||||
v3 = (server.shadowtls_protocol == "v3") and true or false,
|
||||
disable_nodelay = (server.disable_nodelay == "1") and true or false,
|
||||
fastopen = (server.fastopen == "1") and true or false,
|
||||
strict = (server.strict == "1") and true or false
|
||||
}
|
||||
local chain_sslocal = {
|
||||
locals = local_port ~= "0" and {
|
||||
{
|
||||
local_address = "0.0.0.0",
|
||||
local_port = (chain_local_port == "0" and tonumber(server.local_port) or tonumber(chain_local_port)),
|
||||
mode = (proto:find("tcp,udp") and "tcp_and_udp") or proto .. "_only",
|
||||
protocol = "redir",
|
||||
tcp_redir = "redirect",
|
||||
--tcp_redir = "tproxy",
|
||||
udp_redir = "tproxy"
|
||||
},
|
||||
socks_port ~= "0" and {
|
||||
protocol = "socks",
|
||||
local_address = "0.0.0.0",
|
||||
local_port = tonumber(socks_port)
|
||||
} or nil
|
||||
} or {{
|
||||
protocol = "socks",
|
||||
local_address = "0.0.0.0",
|
||||
ocal_port = tonumber(socks_port)
|
||||
}},
|
||||
servers = {
|
||||
{
|
||||
server = "127.0.0.1",
|
||||
server_port = (tonumber(local_port) == 0 and tonumber(chain_local_port) or tonumber(local_port)),
|
||||
method = server.sslocal_method,
|
||||
password = server.sslocal_password
|
||||
}
|
||||
}
|
||||
}
|
||||
local chain_vmess = {
|
||||
inbounds = (local_port ~= "0") and {
|
||||
{
|
||||
port = (chain_local_port == "0" and tonumber(server.local_port) or tonumber(chain_local_port)),
|
||||
protocol = "dokodemo-door",
|
||||
settings = {
|
||||
network = proto,
|
||||
followRedirect = true
|
||||
},
|
||||
streamSettings = {
|
||||
sockopt = {tproxy = "redirect"}
|
||||
},
|
||||
sniffing = {
|
||||
enable = true,
|
||||
destOverride = {"http","tls"}
|
||||
}
|
||||
},
|
||||
(proto:find("tcp") and socks_port ~= "0") and {
|
||||
protocol = "socks",
|
||||
port = tonumber(socks_port)
|
||||
} or nil
|
||||
} or { protocol = "socks",port = tonumber(socks_port) },
|
||||
outbound = {
|
||||
protocol = "vmess",
|
||||
settings = {
|
||||
vnext = {{
|
||||
address = "127.0.0.1",
|
||||
port = (tonumber(local_port) == 0 and tonumber(chain_local_port) or tonumber(local_port)),
|
||||
users = {{
|
||||
id = (server.vmess_uuid),
|
||||
security = server.vmess_method,
|
||||
level = 0
|
||||
}}
|
||||
}}
|
||||
}
|
||||
}
|
||||
}
|
||||
local tuic = {
|
||||
relay = {
|
||||
server = server.server_port and ip_addr .. ":" .. server.server_port,
|
||||
ip = server.tuic_ip,
|
||||
uuid = server.tuic_uuid,
|
||||
password = server.tuic_passwd,
|
||||
certificates = server.certificate and { server.certpath } or nil,
|
||||
udp_relay_mode = server.udp_relay_mode,
|
||||
congestion_control = server.congestion_control,
|
||||
heartbeat = server.heartbeat and server.heartbeat .. "s" or nil,
|
||||
timeout = server.timeout and server.timeout .. "s" or nil,
|
||||
gc_interval = server.gc_interval and server.gc_interval .. "s" or nil,
|
||||
gc_lifetime = server.gc_lifetime and server.gc_lifetime .. "s" or nil,
|
||||
alpn = server.tls_alpn,
|
||||
disable_sni = (server.disable_sni == "1") and true or false,
|
||||
zero_rtt_handshake = (server.zero_rtt_handshake == "1") and true or false,
|
||||
send_window = tonumber(server.send_window),
|
||||
receive_window = tonumber(server.receive_window)
|
||||
},
|
||||
["local"] = {
|
||||
server = tonumber(socks_port) and "[::]:" .. (socks_port == "0" and local_port or tonumber(socks_port)),
|
||||
dual_stack = (server.tuic_dual_stack == "1") and true or nil,
|
||||
max_packet_size = tonumber(server.tuic_max_package_size)
|
||||
}
|
||||
}
|
||||
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,
|
||||
shadowtls = function()
|
||||
local chain_switch = {
|
||||
sslocal = function()
|
||||
if (chain:find("chain")) then
|
||||
print(json.stringify(chain_sslocal, 1))
|
||||
else
|
||||
print(json.stringify(shadowtls, 1))
|
||||
end
|
||||
end,
|
||||
vmess = function()
|
||||
if (chain:find("chain")) then
|
||||
print(json.stringify(chain_vmess, 1))
|
||||
else
|
||||
print(json.stringify(shadowtls, 1))
|
||||
end
|
||||
end
|
||||
}
|
||||
local ChainType = server.chain_type
|
||||
if chain_switch[ChainType] then
|
||||
chain_switch[ChainType]()
|
||||
end
|
||||
end,
|
||||
tuic = function()
|
||||
print(json.stringify(tuic, 1))
|
||||
end
|
||||
}
|
||||
if switch[index] then
|
||||
switch[index]()
|
||||
end
|
||||
end
|
||||
local f = config:new()
|
||||
f:handleIndex(server.type)
|
@ -0,0 +1,121 @@
|
||||
#!/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 node = ucursor:get_all("bypass", server_section)
|
||||
local server_host = node.server
|
||||
local server_port = node.server_port
|
||||
local server = server_host .. ":" .. server_port
|
||||
|
||||
local hysteria = {
|
||||
server = server,
|
||||
protocol = node.transport_protocol or "udp",
|
||||
obfs = node.hy_obfs_password or node.hy_auth_password,
|
||||
auth = (node.hy_auth_type == "base64") and node.hy_auth_password or nil,
|
||||
auth_str = (node.hy_auth_type == "string") and node.hy_auth_password or nil,
|
||||
alpn = node.hy_alpn or nil,
|
||||
server_name = node.tls_host or node.server,
|
||||
insecure = (node.insecure == "1") and true or false,
|
||||
up_mbps = tonumber(node.uplink_capacity) or 10,
|
||||
down_mbps = tonumber(node.downlink_capacity) or 50,
|
||||
retry = -1,
|
||||
retry_interval = 5,
|
||||
recv_window_conn = (node.hy_recv_window_conn) and tonumber(node.hy_recv_window_conn) or nil,
|
||||
recv_window = (node.hy_recv_window) and tonumber(node.hy_recv_window) or nil,
|
||||
disable_mtu_discovery = (node.hy_disable_mtu_discovery) and true or false,
|
||||
socks5 = (proto:find("tcp") and tonumber(socks_port) and tonumber(socks_port) ~= 0) and {
|
||||
listen = "0.0.0.0:" .. tonumber(socks_port),
|
||||
disable_udp = false
|
||||
} or nil,
|
||||
tcpRedirect = (proto:find("tcp") and local_port ~= "0") and {
|
||||
listen = "0.0.0.0:" .. tonumber(local_port)
|
||||
} or nil,
|
||||
|
||||
tproxy_udp = (proto:find("udp") and local_port ~= "0") and {
|
||||
listen = "0.0.0.0:" .. tonumber(local_port),
|
||||
timeout = 60
|
||||
} or nil
|
||||
}
|
||||
local hysteria2 = {
|
||||
server = server,
|
||||
fast_open = (node.fast_open == "1") and true or false,
|
||||
lazy = (node.lazy_mode == "1") and true or false,
|
||||
transport = {
|
||||
type = node.transport_protocol or "udp",
|
||||
udp = {
|
||||
hopInterval = tonumber(node.hopinterval) and tonumber(node.hopinterval) .. "s" or "30s"
|
||||
}
|
||||
},
|
||||
|
||||
obfs = (node.hy2_obfs_password) and {
|
||||
type = "salamander",
|
||||
salamander = {
|
||||
password = node.hy2_obfs_password
|
||||
}
|
||||
} or nil,
|
||||
|
||||
auth = node.hy2_auth_password,
|
||||
tls = {
|
||||
sni = node.tls_host,
|
||||
insecure = (node.insecure == "1") and true or false,
|
||||
pinSHA256 = (node.insecure == "1") and node.pinsha256 or nil
|
||||
},
|
||||
|
||||
quic = {
|
||||
initStreamReceiveWindow = (node.initstreamreceivewindow) and tonumber(node.initstreamreceivewindow) or nil,
|
||||
initConnReceiveWindow = (node.initconnreceivewindow) and tonumber(node.initconnreceivewindow) or nil,
|
||||
maxIdleTimeout = (node.maxidletimeout) and tonumber(node.maxidletimeout) or nil,
|
||||
disablePathMTUDiscovery = (node.disablepathmtudiscovery == "1") and true or false
|
||||
},
|
||||
bandwidth = (node.uplink_capacity or node.downlink_capacity) and {
|
||||
up = tonumber(node.uplink_capacity) and tonumber(node.uplink_capacity) .. " mbps" or nil,
|
||||
down = node.downlink_capacity and node.downlink_capacity .. " mbps" or nil
|
||||
} or nil,
|
||||
socks5 = (proto:find("tcp") and tonumber(socks_port) and tonumber(socks_port) ~= 0) and {
|
||||
listen = "0.0.0.0:" .. tonumber(socks_port),
|
||||
disable_udp = false
|
||||
} or nil,
|
||||
|
||||
--[[
|
||||
tcpTProxy = (proto:find("tcp") and local_port ~= "0") and {
|
||||
listen = "0.0.0.0:" .. tonumber(local_port)
|
||||
} or nil,
|
||||
]]
|
||||
|
||||
tcpRedirect = (proto:find("tcp") and local_port ~= "0") and {
|
||||
listen = "0.0.0.0:" .. tonumber(local_port)
|
||||
} or nil,
|
||||
|
||||
udpTProxy = (proto:find("udp") and local_port ~= "0") and {
|
||||
listen = "0.0.0.0:" .. tonumber(local_port)
|
||||
} or nil
|
||||
}
|
||||
|
||||
local config = {}
|
||||
function config:new(o)
|
||||
o = o or {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
function config:handleIndex(index)
|
||||
local switch = {
|
||||
hysteria = function()
|
||||
print(json.stringify(hysteria, 1))
|
||||
end,
|
||||
hysteria2 = function()
|
||||
print(json.stringify(hysteria2, 1))
|
||||
end,
|
||||
}
|
||||
if switch[index] then
|
||||
switch[index]()
|
||||
end
|
||||
end
|
||||
local f = config:new()
|
||||
f:handleIndex(node.type)
|
@ -0,0 +1,135 @@
|
||||
log:
|
||||
level: info
|
||||
|
||||
plugins:
|
||||
- tag: lazy_cache
|
||||
type: cache
|
||||
args:
|
||||
size: 20000
|
||||
lazy_cache_ttl: 86400
|
||||
|
||||
- tag: geosite_cn
|
||||
type: domain_set
|
||||
args:
|
||||
files:
|
||||
- "/var/etc/bypass/domains_cn.txt"
|
||||
- "/etc/bypass/white.list"
|
||||
|
||||
- tag: geoip_cn
|
||||
type: ip_set
|
||||
args:
|
||||
files:
|
||||
- "/var/etc/bypass/china.txt"
|
||||
- "/var/etc/bypass/china_v6.txt"
|
||||
|
||||
- tag: geosite_no_cn
|
||||
type: domain_set
|
||||
args:
|
||||
files:
|
||||
- "/var/etc/bypass/gfw.list"
|
||||
- "/etc/bypass/black.list"
|
||||
|
||||
- tag: adlist
|
||||
type: domain_set
|
||||
args:
|
||||
files:
|
||||
- "adfile"
|
||||
|
||||
- tag: forward_local
|
||||
type: forward
|
||||
args:
|
||||
concurrent: 2
|
||||
upstreams:
|
||||
- addr: local_dns
|
||||
- tag: forward_remote
|
||||
type: forward
|
||||
args:
|
||||
concurrent: 2
|
||||
upstreams:
|
||||
- addr: remote_dns
|
||||
- tag: local_sequence
|
||||
type: sequence
|
||||
args:
|
||||
- exec: $forward_local
|
||||
|
||||
- tag: remote_sequence_IPv6
|
||||
type: sequence
|
||||
args:
|
||||
- exec: prefer_ipv4
|
||||
- exec: $forward_remote
|
||||
- tag: remote_sequence
|
||||
type: sequence
|
||||
args:
|
||||
- exec: prefer_ipv4
|
||||
- exec: $forward_remote
|
||||
- matches:
|
||||
- qtype 28 65
|
||||
exec: reject 0
|
||||
|
||||
- tag: has_resp_sequence
|
||||
type: sequence
|
||||
args:
|
||||
- matches: has_resp
|
||||
exec: accept
|
||||
|
||||
- tag: query_is_local_ip
|
||||
type: sequence
|
||||
args:
|
||||
- exec: $local_sequence
|
||||
- matches: "!resp_ip $geoip_cn"
|
||||
exec: drop_resp
|
||||
|
||||
|
||||
- tag: query_is_remote
|
||||
type: sequence
|
||||
args:
|
||||
- exec: $IPV6MODE
|
||||
|
||||
- tag: fallback
|
||||
type: fallback
|
||||
args:
|
||||
primary: POLLUTION
|
||||
secondary: query_is_remote
|
||||
threshold: 500
|
||||
always_standby: true
|
||||
|
||||
- tag: query_is_local_domain
|
||||
type: sequence
|
||||
args:
|
||||
- matches: qname $geosite_cn
|
||||
exec: $local_sequence
|
||||
|
||||
- tag: query_is_no_local_domain
|
||||
type: sequence
|
||||
args:
|
||||
- matches: qname $geosite_no_cn
|
||||
exec: $remote_sequence
|
||||
- tag: query_is_reject_domain
|
||||
type: sequence
|
||||
args:
|
||||
- matches: qname $adlist
|
||||
exec: reject 3
|
||||
- tag: main_sequence
|
||||
type: sequence
|
||||
args:
|
||||
- exec: $lazy_cache
|
||||
- exec: jump has_resp_sequence
|
||||
- exec: $query_is_reject_domain
|
||||
- exec: jump has_resp_sequence
|
||||
- exec: $query_is_local_domain
|
||||
- exec: jump has_resp_sequence
|
||||
- exec: $query_is_no_local_domain
|
||||
- exec: jump has_resp_sequence
|
||||
- exec: $fallback
|
||||
|
||||
- tag: udp_server
|
||||
type: udp_server
|
||||
args:
|
||||
entry: main_sequence
|
||||
listen: ":DNS_PORT"
|
||||
|
||||
- tag: tcp_server
|
||||
type: tcp_server
|
||||
args:
|
||||
entry: main_sequence
|
||||
listen: ":DNS_PORT"
|
@ -0,0 +1,44 @@
|
||||
log:
|
||||
level: info
|
||||
plugins:
|
||||
- tag: lazy_cache
|
||||
type: cache
|
||||
args:
|
||||
size: 20000
|
||||
lazy_cache_ttl: 86400
|
||||
|
||||
- tag: forward_google
|
||||
type: forward
|
||||
args:
|
||||
concurrent: 2
|
||||
upstreams:
|
||||
- addr: remote_dns
|
||||
|
||||
- tag: remote_sequence
|
||||
type: sequence
|
||||
args:
|
||||
- exec: $lazy_cache
|
||||
- exec: prefer_ipv4
|
||||
- exec: $forward_google
|
||||
- matches:
|
||||
- qtype 28 65
|
||||
exec: reject 0
|
||||
|
||||
- tag: remote_sequence_IPv6
|
||||
type: sequence
|
||||
args:
|
||||
- exec: $lazy_cache
|
||||
- exec: $forward_google
|
||||
|
||||
- tag: udp_server
|
||||
type: udp_server
|
||||
args:
|
||||
entry: IPV6MODE
|
||||
listen: ":DNS_PORT"
|
||||
|
||||
- tag: tcp_server
|
||||
type: tcp_server
|
||||
args:
|
||||
entry: IPV6MODE
|
||||
listen: ":DNS_PORT"
|
||||
|
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
local ucursor = require "luci.model.uci".cursor()
|
||||
local json = require "luci.jsonc"
|
||||
|
||||
local datatypes = require "luci.cbi.datatypes"
|
||||
|
||||
function is_ipv6(val)
|
||||
local str = val
|
||||
local address = val:match('%[(.*)%]')
|
||||
if address then
|
||||
str = address
|
||||
end
|
||||
if datatypes.ip6addr(str) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function get_ipv6_only(val)
|
||||
local result = ""
|
||||
if is_ipv6(val) then
|
||||
result = val
|
||||
if val:match('%[(.*)%]') then
|
||||
result = val:match('%[(.*)%]')
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local server_section = arg[1]
|
||||
local proto = arg[2]
|
||||
local local_port = arg[3] or "0"
|
||||
local socks_port = arg[4] or "0"
|
||||
|
||||
|
||||
local server = ucursor:get_all("bypass", server_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 = {
|
||||
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 = server.server,
|
||||
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 = server.tls_host,
|
||||
alpn = server.tls_alpn or {"h2", "http/1.1"},
|
||||
curves = "",
|
||||
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
|
||||
}
|
||||
}
|
||||
print(json.stringify(trojan, 1))
|
||||
|
||||
|
381
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/gen_xray
Normal file
381
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/gen_xray
Normal file
@ -0,0 +1,381 @@
|
||||
#!/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 chain = arg[5] or "0"
|
||||
local chain_local_port = string.split(chain, "/")[2] or "0"
|
||||
local server = ucursor:get_all("bypass", server_section)
|
||||
local socks_server = ucursor:get_all("bypass", "@socks5_proxy[0]") or {}
|
||||
local xray_fragment = ucursor:get_all("bypass", "@global_xray_fragment[0]") or {}
|
||||
local xray_noise = ucursor:get_all("bypass", "@xray_noise_packets[0]") or {}
|
||||
local outbound_settings = nil
|
||||
|
||||
local tls_host = server.tls_host or server.server
|
||||
local ip_addr=arg[5] or server.server
|
||||
function vmess_vless()
|
||||
outbound_settings = {
|
||||
vnext = {
|
||||
{
|
||||
address = ip_addr,
|
||||
port = tonumber(server.server_port),
|
||||
users = {
|
||||
{
|
||||
id = server.vmess_id,
|
||||
alterId = (server.v2ray_protocol == "vmess" or not server.v2ray_protocol) and tonumber(server.alter_id) or nil,
|
||||
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') or (server.tls == '1') or (server.reality == '1')) and server.tls_flow or nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
function trojan_shadowsocks()
|
||||
outbound_settings = {
|
||||
servers = {
|
||||
{
|
||||
address = ip_addr,
|
||||
port = tonumber(server.server_port),
|
||||
password = server.password,
|
||||
method = ((server.v2ray_protocol == "shadowsocks") and server.encrypt_method_ss) or nil,
|
||||
uot = (server.v2ray_protocol == "shadowsocks") and (server.uot == '1') or nil,
|
||||
ivCheck = (server.v2ray_protocol == "shadowsocks") and (server.ivCheck == '1') or nil,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = {
|
||||
secretKey = server.private_key,
|
||||
address = server.local_addresses,
|
||||
peers = {
|
||||
{
|
||||
publicKey = server.peer_pubkey,
|
||||
preSharedKey = server.preshared_key,
|
||||
endpoint = ip_addr .. ":" .. server.server_port,
|
||||
keepAlive = tonumber(server.keepaliveperiod),
|
||||
allowedIPs = (server.allowedips) or nil,
|
||||
}
|
||||
},
|
||||
noKernelTun = (server.kernelmode == "1") and true or false,
|
||||
reserved = {server.reserved} or nil,
|
||||
mtu = tonumber(server.mtu)
|
||||
}
|
||||
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,
|
||||
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 = {
|
||||
loglevel = "warning"
|
||||
},
|
||||
|
||||
-- 初始化 inbounds 表
|
||||
inbounds = {},
|
||||
|
||||
-- 初始化 outbounds 表
|
||||
outbounds = {},
|
||||
}
|
||||
-- 传入连接
|
||||
-- 添加 dokodemo-door 配置,如果 local_port 不为 0
|
||||
if local_port ~= "0" then
|
||||
table.insert(Xray.inbounds, {
|
||||
-- listening
|
||||
port = tonumber(local_port),
|
||||
protocol = "dokodemo-door",
|
||||
settings = {network = proto, followRedirect = true},
|
||||
sniffing = {
|
||||
enabled = true,
|
||||
destOverride = {"http", "tls", "quic"},
|
||||
metadataOnly = false,
|
||||
domainsExcluded = {
|
||||
"courier.push.apple.com",
|
||||
"rbsxbxp-mim.vivox.com",
|
||||
"rbsxbxp.www.vivox.com",
|
||||
"rbsxbxp-ws.vivox.com",
|
||||
"rbspsxp.www.vivox.com",
|
||||
"rbspsxp-mim.vivox.com",
|
||||
"rbspsxp-ws.vivox.com",
|
||||
"rbswxp.www.vivox.com",
|
||||
"rbswxp-mim.vivox.com",
|
||||
"disp-rbspsp-5-1.vivox.com",
|
||||
"disp-rbsxbp-5-1.vivox.com",
|
||||
"proxy.rbsxbp.vivox.com",
|
||||
"proxy.rbspsp.vivox.com",
|
||||
"proxy.rbswp.vivox.com",
|
||||
"rbswp.vivox.com",
|
||||
"rbsxbp.vivox.com",
|
||||
"rbspsp.vivox.com",
|
||||
"rbspsp.www.vivox.com",
|
||||
"rbswp.www.vivox.com",
|
||||
"rbsxbp.www.vivox.com",
|
||||
"rbsxbxp.vivox.com",
|
||||
"rbspsxp.vivox.com",
|
||||
"rbswxp.vivox.com",
|
||||
"Mijia Cloud",
|
||||
"dlg.io.mi.com"
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
-- 开启 socks 代理
|
||||
-- 检查是否启用 socks 代理
|
||||
if proto:find("tcp") and socks_port ~= "0" then
|
||||
table.insert(Xray.inbounds, {
|
||||
-- socks
|
||||
protocol = "socks",
|
||||
port = tonumber(socks_port),
|
||||
settings = {
|
||||
auth = socks_server.socks5_auth,
|
||||
udp = true,
|
||||
mixed = (socks_server.socks5_mixed == '1') and true or false,
|
||||
accounts = (socks_server.socks5_auth ~= "noauth") and {
|
||||
{
|
||||
user = socks_server.socks5_user,
|
||||
pass = socks_server.socks5_pass
|
||||
}
|
||||
} or nil
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
-- 传出连接
|
||||
Xray.outbounds = {
|
||||
{
|
||||
protocol = server.v2ray_protocol,
|
||||
settings = outbound_settings,
|
||||
-- 底层传输配置
|
||||
streamSettings = (server.v2ray_protocol ~= "wireguard") and {
|
||||
network = server.transport or "tcp",
|
||||
security = (server.xtls == '1') and "xtls" or (server.tls == '1') and "tls" or (server.reality == '1') and "reality" or nil,
|
||||
tlsSettings = (server.tls == '1') and {
|
||||
-- tls
|
||||
alpn = server.tls_alpn,
|
||||
fingerprint = server.fingerprint,
|
||||
allowInsecure = (server.insecure == "1"),
|
||||
serverName = tls_host,
|
||||
certificates = server.certificate and {
|
||||
usage = "verify",
|
||||
certificateFile = server.certpath
|
||||
} or nil,
|
||||
} or nil,
|
||||
xtlsSettings = (server.xtls == '1') and server.tls_host and {
|
||||
-- xtls
|
||||
allowInsecure = (server.insecure == "1") and true or nil,
|
||||
serverName = server.tls_host,
|
||||
minVersion = "1.3"
|
||||
} or nil,
|
||||
realitySettings = (server.reality == '1') and {
|
||||
publicKey = server.reality_publickey,
|
||||
shortId = server.reality_shortid,
|
||||
spiderX = server.reality_spiderx,
|
||||
fingerprint = server.fingerprint,
|
||||
serverName = server.tls_host
|
||||
} or nil,
|
||||
rawSettings = (server.transport == "raw" or server.transport == "tcp") and {
|
||||
-- tcp
|
||||
header = {
|
||||
type = server.tcp_guise or "none",
|
||||
request = (server.tcp_guise == "http") and {
|
||||
-- request
|
||||
path = {server.http_path} or {"/"},
|
||||
headers = {Host = {server.http_host} or {}}
|
||||
} or nil
|
||||
}
|
||||
} or nil,
|
||||
kcpSettings = (server.transport == "kcp") and {
|
||||
-- kcp
|
||||
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 {
|
||||
-- ws
|
||||
Host = server.ws_host or server.tls_host or nil,
|
||||
path = server.ws_path,
|
||||
maxEarlyData = tonumber(server.ws_ed) or nil,
|
||||
earlyDataHeaderName = server.ws_ed_header or nil
|
||||
} or nil,
|
||||
httpupgradeSettings = (server.transport == "httpupgrade") and {
|
||||
-- httpupgrade
|
||||
host = (server.httpupgrade_host or server.tls_host) or nil,
|
||||
path = server.httpupgrade_path or ""
|
||||
} or nil,
|
||||
splithttpSettings = (server.transport == "splithttp") and {
|
||||
-- splithttp
|
||||
host = (server.splithttp_host or server.tls_host) or nil,
|
||||
path = server.splithttp_path or "/"
|
||||
} 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 "",
|
||||
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,
|
||||
sockopt = {
|
||||
mark = 250,
|
||||
tcpMptcp = (server.mptcp == "1") and true or nil, -- MPTCP
|
||||
tcpNoDelay = (server.mptcp == "1") and true or nil, -- MPTCP
|
||||
tcpcongestion = server.custom_tcpcongestion, -- 连接服务器节点的 TCP 拥塞控制算法
|
||||
dialerProxy = (xray_fragment.fragment == "1" or xray_fragment.noise == "1") and "dialerproxy" or nil
|
||||
}
|
||||
} or nil,
|
||||
mux = (server.v2ray_protocol ~= "wireguard") and {
|
||||
-- mux
|
||||
enabled = (server.mux == "1") and true or false, -- Mux
|
||||
concurrency = tonumber(server.concurrency), -- TCP 最大并发连接数
|
||||
xudpConcurrency = tonumber(server.xudpConcurrency), -- UDP 最大并发连接数
|
||||
xudpProxyUDP443 = server.xudpProxyUDP443 -- 对被代理的 UDP/443 流量处理方式
|
||||
} or nil
|
||||
}
|
||||
}
|
||||
-- 添加带有 fragment 设置的 dialerproxy 配置
|
||||
if xray_fragment.fragment ~= "0" or (xray_fragment.noise ~= "0" and xray_noise.enabled ~= "0") then
|
||||
table.insert(Xray.outbounds, {
|
||||
protocol = "freedom",
|
||||
tag = "dialerproxy",
|
||||
settings = {
|
||||
domainStrategy = (xray_fragment.noise == "1" and xray_noise.enabled == "1") and xray_noise.domainStrategy,
|
||||
fragment = (xray_fragment.fragment == "1") and {
|
||||
packets = (xray_fragment.fragment_packets ~= "") and xray_fragment.fragment_packets or nil,
|
||||
length = (xray_fragment.fragment_length ~= "") and xray_fragment.fragment_length or nil,
|
||||
interval = (xray_fragment.fragment_interval ~= "") and xray_fragment.fragment_interval or nil
|
||||
} or nil,
|
||||
noises = (xray_fragment.noise == "1" and xray_noise.enabled == "1") and {
|
||||
{
|
||||
type = xray_noise.type,
|
||||
packet = xray_noise.packet,
|
||||
delay = xray_noise.delay:find("-") and xray_noise.delay or tonumber(xray_noise.delay)
|
||||
}
|
||||
} or nil
|
||||
},
|
||||
streamSettings = {
|
||||
sockopt = {
|
||||
mark = 250,
|
||||
tcpMptcp = (server.mptcp == "1") and true or nil, -- MPTCP
|
||||
tcpNoDelay = (server.mptcp == "1") and true or nil, -- MPTCP
|
||||
tcpcongestion = server.custom_tcpcongestion -- 连接服务器节点的 TCP 拥塞控制算法
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
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 = server.server,
|
||||
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 = server.tls_host,
|
||||
alpn = server.tls_alpn or {"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
|
||||
}
|
||||
}
|
||||
print(json.stringify(Xray, 1))
|
||||
|
||||
|
@ -0,0 +1,95 @@
|
||||
#!/bin/sh
|
||||
argv1=$1
|
||||
argv2=$2
|
||||
argv3=$3
|
||||
argv4=$4
|
||||
argv5=$5
|
||||
argv6=$6
|
||||
argv7=$7
|
||||
argv8=$8
|
||||
argv9=$9
|
||||
cat <<-EOF >$argv1
|
||||
base {
|
||||
log_debug = off;
|
||||
log_info = off;
|
||||
log = stderr;
|
||||
daemon = on;
|
||||
redirector = iptables;
|
||||
reuseport = on;
|
||||
}
|
||||
EOF
|
||||
tcp() {
|
||||
if [ "$argv7" == "0" ]; then
|
||||
cat <<-EOF >>$argv1
|
||||
redsocks {
|
||||
bind = "0.0.0.0:$argv4";
|
||||
relay = "$argv5:$argv6";
|
||||
type = socks5;
|
||||
autoproxy = 0;
|
||||
timeout = 10;
|
||||
}
|
||||
EOF
|
||||
else
|
||||
cat <<-EOF >>$argv1
|
||||
redsocks {
|
||||
bind = "0.0.0.0:$argv4";
|
||||
relay = "$argv5:$argv6";
|
||||
type = socks5;
|
||||
autoproxy = 0;
|
||||
timeout = 10;
|
||||
login = "$argv8";
|
||||
password = "$argv9";
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
udp() {
|
||||
if [ "$argv7" == "0" ]; then
|
||||
cat <<-EOF >>$argv1
|
||||
redudp {
|
||||
bind = "0.0.0.0:$argv4";
|
||||
relay = "$argv5:$argv6";
|
||||
type = socks5;
|
||||
udp_timeout = 10;
|
||||
}
|
||||
EOF
|
||||
else
|
||||
cat <<-EOF >>$argv1
|
||||
redudp {
|
||||
bind = "0.0.0.0:$argv4";
|
||||
relay = "$argv5:$argv6";
|
||||
type = socks5;
|
||||
udp_timeout = 10;
|
||||
login = "$argv8";
|
||||
password = "$argv9";
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
case "$argv2" in
|
||||
socks5)
|
||||
case "$argv3" in
|
||||
tcp)
|
||||
tcp
|
||||
;;
|
||||
udp)
|
||||
udp
|
||||
;;
|
||||
*)
|
||||
tcp
|
||||
udp
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
cat <<-EOF >>$argv1
|
||||
redsocks {
|
||||
bind = "0.0.0.0:$argv4";
|
||||
type = direct;
|
||||
interface = $argv3;
|
||||
autoproxy = 0;
|
||||
timeout = 10;
|
||||
}
|
||||
EOF
|
||||
;;
|
||||
esac
|
810
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/subscribe
Normal file
810
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/subscribe
Normal file
@ -0,0 +1,810 @@
|
||||
#!/usr/bin/lua
|
||||
------------------------------------------------
|
||||
-- This file is part of the luci-app-bypass subscribe.lua
|
||||
-- @author William Chan <root@williamchan.me>
|
||||
-- @sirpdboy 2025 <herboy2008@gmail.com>
|
||||
------------------------------------------------
|
||||
require "luci.model.uci"
|
||||
require "nixio"
|
||||
require "luci.util"
|
||||
SYS=require "luci.sys"
|
||||
require "luci.jsonc"
|
||||
local datatypes = require "luci.cbi.datatypes"
|
||||
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
|
||||
local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string.char, string.byte, string.format, string.gsub
|
||||
local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify
|
||||
local b64decode = nixio.bin.b64decode
|
||||
local URL = require "url"
|
||||
local cache = {}
|
||||
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', '0')
|
||||
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url', {})
|
||||
local filter_words = ucic:get_first(name, 'server_subscribe', 'filter_words', '过期/时间/剩余/流量')
|
||||
local filter_mode=ucic:get_first(name,'server_subscribe','filter_mode','0')
|
||||
local insecure = ucic:get_first(name, 'server_subscribe', 'insecure', 1)
|
||||
local v2_ss = SYS.exec('type -t -p ss-redir sslocal') ~= "" and "ss" or "v2ray"
|
||||
|
||||
local v2_tj = SYS.exec('type -t -p trojan') ~= "" and "trojan" or "v2ray"
|
||||
local ua = ucic:get_first(name, 'server_subscribe', 'user_agent', '')
|
||||
local log = function(...)
|
||||
local file=io.open("/tmp/log/bypass.log","a")
|
||||
io.output(file)
|
||||
io.write(os.date("%Y-%m-%d %H:%M:%S ").."Subscribe : "..table.concat({...}," ").."\n")
|
||||
io.close(file)
|
||||
end
|
||||
|
||||
-- 分割字符串
|
||||
local function split(full, sep)
|
||||
if full then
|
||||
full = full:gsub("%z", "") -- 这里不是很清楚 有时候结尾带个\0
|
||||
local off, result = 1, {}
|
||||
while true do
|
||||
local nStart, nEnd = full:find(sep, off)
|
||||
if not nEnd then
|
||||
local res = ssub(full, off, slen(full))
|
||||
if #res > 0 then -- 过滤掉 \0
|
||||
tinsert(result, res)
|
||||
end
|
||||
break
|
||||
else
|
||||
tinsert(result, ssub(full, off, nStart - 1))
|
||||
off = nEnd + 1
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
return {}
|
||||
end
|
||||
-- urlencode
|
||||
local function get_urlencode(c)
|
||||
return sformat("%%%02X", sbyte(c))
|
||||
end
|
||||
|
||||
local function urlEncode(szText)
|
||||
local str = szText:gsub("([^0-9a-zA-Z ])", get_urlencode)
|
||||
str = str:gsub(" ", "+")
|
||||
return str
|
||||
end
|
||||
|
||||
local function get_urldecode(h) return schar(tonumber(h,16)) end
|
||||
local function UrlDecode(szText)
|
||||
return (szText and szText:gsub("+", " "):gsub("%%(%x%x)", get_urldecode)) or nil
|
||||
end
|
||||
|
||||
-- trim
|
||||
local function trim(text)
|
||||
if not text or text=="" then return "" end
|
||||
return (sgsub(text,"^%s*(.-)%s*$","%1"))
|
||||
end
|
||||
-- md5
|
||||
local function md5(content)
|
||||
local stdout = SYS.exec('echo \"' .. urlEncode(content) .. '\" | md5sum | cut -d \" \" -f1')
|
||||
-- assert(nixio.errno() == 0)
|
||||
return trim(stdout)
|
||||
end
|
||||
-- base64
|
||||
local function base64Decode(text)
|
||||
local raw = text
|
||||
if not text then return '' end
|
||||
text = text:gsub("%z", "")
|
||||
text = text:gsub("%c", "")
|
||||
text = text:gsub("_", "/")
|
||||
text = text:gsub("-", "+")
|
||||
local mod4 = #text % 4
|
||||
text = text .. string.sub('====', mod4 + 1)
|
||||
local result = b64decode(text)
|
||||
if result then
|
||||
return result:gsub("%z", "")
|
||||
else
|
||||
return raw
|
||||
end
|
||||
end
|
||||
-- 检查数组(table)中是否存在某个字符值
|
||||
-- https://www.04007.cn/article/135.html
|
||||
local function checkTabValue(tab)
|
||||
local revtab = {}
|
||||
for k,v in pairs(tab) do
|
||||
revtab[v] = true
|
||||
end
|
||||
return revtab
|
||||
end
|
||||
-- 处理数据
|
||||
local function processData(szType, content)
|
||||
local result = {type = szType, local_port = 1234, kcp_param = '--nocomp'}
|
||||
if szType == 'ssr' then
|
||||
|
||||
result.type = 'ssr'
|
||||
local dat = split(content, "/%?")
|
||||
local hostInfo = split(dat[1], ':')
|
||||
if dat[1]:match('%[(.*)%]') then
|
||||
result.server = dat[1]:match('%[(.*)%]')
|
||||
else
|
||||
result.server = hostInfo[#hostInfo-5]
|
||||
end
|
||||
result.server_port = hostInfo[#hostInfo-4]
|
||||
result.protocol = hostInfo[#hostInfo-3]
|
||||
result.encrypt_method = hostInfo[#hostInfo-2]
|
||||
result.obfs = hostInfo[#hostInfo-1]
|
||||
result.password = base64Decode(hostInfo[#hostInfo])
|
||||
local params = {}
|
||||
for _, v in pairs(split(dat[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
params[t[1]] = t[2]
|
||||
end
|
||||
result.obfs_param = base64Decode(params.obfsparam)
|
||||
result.protocol_param = base64Decode(params.protoparam)
|
||||
local group = base64Decode(params.group)
|
||||
if group then
|
||||
result.alias = "[" .. group .. "] "
|
||||
end
|
||||
result.alias = result.alias .. base64Decode(params.remarks)
|
||||
elseif szType == 'vmess' then
|
||||
local info = jsonParse(content)
|
||||
result.type = 'v2ray'
|
||||
|
||||
|
||||
|
||||
result.alter_id = info.aid
|
||||
|
||||
result.server = info.add
|
||||
result.server_port = info.port
|
||||
result.v2ray_protocol = 'vmess'
|
||||
result.vmess_id = info.id
|
||||
result.alias = info.ps
|
||||
-- result.mux = 1
|
||||
-- result.concurrency = 8
|
||||
if not info.net then
|
||||
info.net = "tcp"
|
||||
end
|
||||
info.net = string.lower(info.net)
|
||||
result.transport = info.net
|
||||
if info.net == 'ws' then
|
||||
result.ws_host = info.host
|
||||
result.ws_path = info.path
|
||||
end
|
||||
if info.net == 'httpupgrade' then
|
||||
result.httpupgrade_host = info.host
|
||||
result.httpupgrade_path = info.path
|
||||
end
|
||||
if info.net == 'splithttp' then
|
||||
result.splithttp_host = info.host
|
||||
result.splithttp_path = info.path
|
||||
end
|
||||
if info.net == 'h2' then
|
||||
result.h2_host = info.host
|
||||
result.h2_path = info.path
|
||||
end
|
||||
if info.net == 'tcp' then
|
||||
if info.type and info.type ~= "http" then
|
||||
info.type = "none"
|
||||
end
|
||||
result.tcp_guise = info.type
|
||||
result.http_host = info.host
|
||||
result.http_path = info.path
|
||||
end
|
||||
if info.net == 'kcp' or info.net == 'mkcp' then
|
||||
result.kcp_guise = info.type
|
||||
result.mtu = 1350
|
||||
result.tti = 50
|
||||
result.uplink_capacity = 5
|
||||
result.downlink_capacity = 20
|
||||
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.security then
|
||||
result.security = info.security
|
||||
else
|
||||
result.security = "auto"
|
||||
end
|
||||
if info.tls == "tls" or info.tls == "1" then
|
||||
result.tls = "1"
|
||||
result.tls_host = (info.sni and info.sni ~= "") and info.sni or info.host
|
||||
result.insecure = insecure and "1" or "0"
|
||||
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
|
||||
|
||||
result.type = v2_ss
|
||||
|
||||
--SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ]
|
||||
--userinfo = websafe-base64-encode-utf8(method ":" password)
|
||||
--ss://YWVzLTEyOC1nY206dGVzdA@192.168.100.1:8888#Example1
|
||||
--ss://cmM0LW1kNTpwYXNzd2Q@192.168.100.1:8888/?plugin=obfs-local%3Bobfs%3Dhttp#Example2
|
||||
--ss://2022-blake3-aes-256-gcm:YctPZ6U7xPPcU%2Bgp3u%2B0tx%2FtRizJN9K8y%2BuKlW2qjlI%3D@192.168.100.1:8888#Example3
|
||||
--ss://2022-blake3-aes-256-gcm:YctPZ6U7xPPcU%2Bgp3u%2B0tx%2FtRizJN9K8y%2BuKlW2qjlI%3D@192.168.100.1:8888/?plugin=v2ray-plugin%3Bserver#Example3
|
||||
|
||||
local idx_sp = 0
|
||||
local alias = ""
|
||||
if content:find("#") then
|
||||
idx_sp = content:find("#")
|
||||
alias = content:sub(idx_sp + 1, -1)
|
||||
end
|
||||
result.alias = UrlDecode(alias)
|
||||
local info = content:sub(1, idx_sp - 1)
|
||||
if info:find("/%?") then
|
||||
local find_index = info:find("/%?")
|
||||
local query = split(info, "/%?")
|
||||
local params = {}
|
||||
for _, v in pairs(split(query[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
params[t[1]] = t[2]
|
||||
end
|
||||
if params.plugin then
|
||||
local plugin_info = UrlDecode(params.plugin)
|
||||
local idx_pn = plugin_info:find(";")
|
||||
if idx_pn then
|
||||
result.plugin = plugin_info:sub(1, idx_pn - 1)
|
||||
result.plugin_opts = plugin_info:sub(idx_pn + 1, #plugin_info)
|
||||
else
|
||||
result.plugin = plugin_info
|
||||
end
|
||||
end
|
||||
if result.plugin and result.plugin == "simple-obfs" then
|
||||
result.plugin = "obfs-local"
|
||||
end
|
||||
info = info:sub(1, find_index - 1)
|
||||
end
|
||||
|
||||
local hostInfo = split(base64Decode(info), "@")
|
||||
if hostInfo and #hostInfo > 0 then
|
||||
local host_port = hostInfo[#hostInfo]
|
||||
-- [2001:4860:4860::8888]:443
|
||||
-- 8.8.8.8:443
|
||||
if host_port:find(":") then
|
||||
local sp = split(host_port, ":")
|
||||
result.server_port = sp[#sp]
|
||||
|
||||
result.server = sp[1]
|
||||
|
||||
else
|
||||
result.server = host_port
|
||||
end
|
||||
|
||||
local userinfo = nil
|
||||
if #hostInfo > 2 then
|
||||
userinfo = {}
|
||||
for i = 1, #hostInfo - 1 do
|
||||
tinsert(userinfo, hostInfo[i])
|
||||
end
|
||||
userinfo = table.concat(userinfo, '@')
|
||||
else
|
||||
userinfo = base64Decode(hostInfo[1])
|
||||
end
|
||||
|
||||
local method = userinfo:sub(1, userinfo:find(":") - 1)
|
||||
local password = userinfo:sub(userinfo:find(":") + 1, #userinfo)
|
||||
|
||||
result.v2ray_protocol = (v2_ss == "v2ray") and "shadowsocks" or nil
|
||||
result.encrypt_method_ss = method
|
||||
result.password = password
|
||||
|
||||
local aead = false
|
||||
for k, v in ipairs({"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305"}) do
|
||||
if method:lower() == v:lower() then
|
||||
aead = true
|
||||
end
|
||||
end
|
||||
if aead then
|
||||
|
||||
result.type = v2_ss
|
||||
result.v2ray_protocol = 'shadowsocks'
|
||||
result.transport = 'tcp'
|
||||
if method:lower() == "chacha20-ietf-poly1305" then
|
||||
result.method = "chacha20-poly1305"
|
||||
end
|
||||
|
||||
end
|
||||
local aead2022 = false
|
||||
for k, v in ipairs({"2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"}) do
|
||||
if method:lower() == v:lower() then
|
||||
aead2022 = true
|
||||
end
|
||||
end
|
||||
if aead2022 then
|
||||
result.type = v2_ss
|
||||
result.v2ray_protocol = 'shadowsocks'
|
||||
result.transport = 'tcp'
|
||||
end
|
||||
end
|
||||
elseif szType == "trojan" then
|
||||
|
||||
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.alias = UrlDecode(alias)
|
||||
result.type = "trojan"
|
||||
if content:find("@") then
|
||||
local Info = split(content, "@")
|
||||
result.password = UrlDecode(Info[1])
|
||||
local port = "443"
|
||||
Info[2] = (Info[2] or ""):gsub("/%?", "?")
|
||||
local query = split(Info[2], "?")
|
||||
local host_port = query[1]
|
||||
local params = {}
|
||||
for _, v in pairs(split(query[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
params[string.lower(t[1])] = UrlDecode(t[2])
|
||||
end
|
||||
if host_port:find(":") then
|
||||
local sp = split(host_port, ":")
|
||||
port = sp[#sp]
|
||||
result.server = sp[1]
|
||||
else
|
||||
result.server = host_port
|
||||
end
|
||||
|
||||
local peer, sni = nil, ""
|
||||
if params.peer then peer = params.peer end
|
||||
sni = params.sni and params.sni or ""
|
||||
result.server_port = port
|
||||
result.tls = '1'
|
||||
result.tls_host = peer and peer or sni
|
||||
if params.allowinsecure then
|
||||
if params.allowinsecure == "1" or params.allowinsecure == "0" then
|
||||
result.insecure = params.allowinsecure
|
||||
else
|
||||
result.insecure = string.lower(params.allowinsecure) == "true" and "1" or "0"
|
||||
end
|
||||
--log(result.alias .. ' 使用节点AllowInsecure设定: '.. result.insecure)
|
||||
else
|
||||
-- 按照官方的建议 默认验证ssl证书
|
||||
result.insecure = insecure and "1" or "0"
|
||||
end
|
||||
end
|
||||
|
||||
elseif szType == "ssd" then
|
||||
result.type = v2_ss
|
||||
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.plugin_opts = content.plugin_options
|
||||
result.alias = "[" .. content.airport .. "] " .. content.remarks
|
||||
if content.plugin == "simple-obfs" then
|
||||
result.plugin = "obfs-local"
|
||||
else
|
||||
result.plugin = content.plugin
|
||||
end
|
||||
|
||||
elseif szType == "vless" then
|
||||
result.type = "v2ray"
|
||||
result.v2ray_protocol = "vless"
|
||||
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.alias = UrlDecode(alias)
|
||||
if content:find("@") then
|
||||
local Info = split(content, "@")
|
||||
result.vmess_id = UrlDecode(Info[1])
|
||||
local port = "443"
|
||||
Info[2] = (Info[2] or ""):gsub("/%?", "?")
|
||||
local query = split(Info[2], "?")
|
||||
local host_port = query[1]
|
||||
local params = {}
|
||||
for _, v in pairs(split(query[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
params[t[1]] = UrlDecode(t[2])
|
||||
end
|
||||
-- [2001:4860:4860::8888]:443
|
||||
-- 8.8.8.8:443
|
||||
if host_port:find(":") then
|
||||
local sp = split(host_port, ":")
|
||||
port = sp[#sp]
|
||||
result.server = sp[1]
|
||||
else
|
||||
result.server = host_port
|
||||
end
|
||||
|
||||
if not params.type then
|
||||
params.type = "tcp"
|
||||
end
|
||||
params.type = string.lower(params.type)
|
||||
result.transport = params.type
|
||||
if params.type == 'ws' then
|
||||
|
||||
result.ws_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
|
||||
result.ws_path = params.path and UrlDecode(params.path) or "/"
|
||||
elseif result.transport == "httpupgrade" then
|
||||
result.httpupgrade_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
|
||||
result.httpupgrade_path = params.path and UrlDecode(params.path) or "/"
|
||||
elseif result.transport == "splithttp" then
|
||||
result.splithttp_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
|
||||
result.splithttp_path = params.path and UrlDecode(params.path) or "/"
|
||||
-- make it compatible with bullshit, "h2" transport is non-existent at all
|
||||
elseif result.transport == "http" or result.transport == "h2" then
|
||||
|
||||
result.transport = "h2"
|
||||
result.h2_host = params.host and UrlDecode(params.host) or nil
|
||||
result.h2_path = params.path and UrlDecode(params.path) or nil
|
||||
elseif params.type == 'tcp' then
|
||||
result.tcp_guise = params.headerType or "none"
|
||||
if result.tcp_guise == "http" then
|
||||
result.tcp_host = params.host and UrlDecode(params.host) or nil
|
||||
result.tcp_path = params.path and UrlDecode(params.path) or nil
|
||||
end
|
||||
elseif params.type == 'kcp' or params.type == 'mkcp' then
|
||||
params.type = "kcp"
|
||||
result.kcp_guise = params.headerType or "none"
|
||||
result.mtu = 1350
|
||||
result.tti = 50
|
||||
result.uplink_capacity = 5
|
||||
result.downlink_capacity = 20
|
||||
result.read_buffer_size = 2
|
||||
result.write_buffer_size = 2
|
||||
result.seed = params.seed
|
||||
elseif params.type == 'quic' then
|
||||
result.quic_guise = params.headerType or "none"
|
||||
result.quic_key = params.key
|
||||
result.quic_security = params.quicSecurity or "none"
|
||||
elseif params.type == 'grpc' then
|
||||
if params.path then result.serviceName = params.path end
|
||||
if params.serviceName then result.serviceName = params.serviceName end
|
||||
result.grpc_mode = params.mode
|
||||
end
|
||||
|
||||
result.vless_encryption = params.encryption or "none"
|
||||
|
||||
result.tls_flow = params.flow or nil
|
||||
|
||||
result.tls = "0"
|
||||
if params.security == "tls" or params.security == "reality" then
|
||||
result.tls = "1"
|
||||
result.tls_host = (params.sni and params.sni ~= "") and params.sni or params.host
|
||||
result.fingerprint = (params.fp and params.fp ~= "") and params.fp or "chrome"
|
||||
if params.security == "reality" then
|
||||
result.reality = "1"
|
||||
result.tls = "0"
|
||||
result.reality_publickey = params.pbk or nil
|
||||
result.reality_shortId = params.sid or nil
|
||||
result.reality_spiderX = params.spx or nil
|
||||
end
|
||||
end
|
||||
result.xtls = (params.security == "xtls") and "1" or nil
|
||||
result.tls_flow = (result.tls == "1" or result.xtls == "1" or result.reality == "1") and params.flow or nil
|
||||
|
||||
result.server_port = port
|
||||
result.insecure = insecure and "1" or "0"
|
||||
end
|
||||
elseif szType == 'hysteria' then
|
||||
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.alias = UrlDecode(alias)
|
||||
local dat = split(content, '%?')
|
||||
local host_port = dat[1]
|
||||
local params = {}
|
||||
for _, v in pairs(split(dat[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
if #t > 0 then
|
||||
params[t[1]] = t[2]
|
||||
end
|
||||
end
|
||||
-- [2001:4860:4860::8888]:443
|
||||
-- 8.8.8.8:443
|
||||
if host_port:find(":") then
|
||||
local sp = split(host_port, ":")
|
||||
result.server_port = sp[#sp]
|
||||
result.server = sp[1]
|
||||
else
|
||||
result.server = host_port
|
||||
end
|
||||
result.hy_obfs_password = params.obfsParam
|
||||
result.hy_auth_type = "string"
|
||||
result.hy_auth_password = params.auth
|
||||
result.tls_host = params.peer
|
||||
if params.insecure and (params.insecure == "1" or params.insecure == "0") then
|
||||
result.insecure = params.insecure
|
||||
else
|
||||
result.insecure = insecure and "1" or "0"
|
||||
end
|
||||
result.uplink_capacity = params.upmbps
|
||||
result.downlink_capacity = params.downmbps
|
||||
result.type = 'hysteria'
|
||||
elseif szType == 'hysteria2' or szType == 'hy2' then
|
||||
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.alias = UrlDecode(alias)
|
||||
local Info = content
|
||||
if content:find("@") then
|
||||
local contents = split(content, "@")
|
||||
result.hy2_auth_password = UrlDecode(contents[1])
|
||||
Info = (contents[2] or ""):gsub("/%?", "?")
|
||||
end
|
||||
local query = split(Info, "?")
|
||||
local host_port = query[1]
|
||||
local params = {}
|
||||
for _, v in pairs(split(query[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
params[string.lower(t[1])] = UrlDecode(t[2])
|
||||
end
|
||||
-- [2001:4860:4860::8888]:443
|
||||
-- 8.8.8.8:443
|
||||
if host_port:find(":") then
|
||||
local sp = split(host_port, ":")
|
||||
result.server_port = sp[#sp]
|
||||
result.server = sp[1]
|
||||
else
|
||||
result.server = host_port
|
||||
end
|
||||
result.tls_host = params.sni
|
||||
if params.insecure and (params.insecure == "1" or params.insecure == "0") then
|
||||
result.insecure = params.insecure
|
||||
else
|
||||
result.insecure = insecure and "1" or "0"
|
||||
end
|
||||
result.pinSHA256 = params.pinSHA256
|
||||
result.type = "hysteria2"
|
||||
if params["obfs-password"] then
|
||||
result.hy2_obfs_type = "salamander"
|
||||
result.hy2_obfs_password = params["obfs-password"]
|
||||
end
|
||||
else
|
||||
log('暂时不支持' .. szType .. "类型的节点订阅,跳过此节点。")
|
||||
return nil
|
||||
end
|
||||
if not result.alias then
|
||||
if result.server and result.server_port then
|
||||
result.alias = result.server .. ':' .. result.server_port
|
||||
else
|
||||
result.alias = "NULL"
|
||||
end
|
||||
end
|
||||
-- alias 不参与 hashkey 计算
|
||||
local alias = result.alias
|
||||
result.alias = nil
|
||||
local switch_enable = result.switch_enable
|
||||
result.switch_enable = nil
|
||||
result.hashkey = md5(jsonStringify(result))
|
||||
result.alias = alias
|
||||
result.switch_enable = switch_enable
|
||||
return result
|
||||
end
|
||||
|
||||
local function curl(url)
|
||||
if not ua or ua == "" then
|
||||
ua = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36"
|
||||
end
|
||||
local stdout=SYS.exec('curl --retry 3 -m 10 -LfsA "'..ua..'" "'..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
|
||||
return filter_mode=='0'
|
||||
end
|
||||
end
|
||||
return filter_mode=='1'
|
||||
end
|
||||
|
||||
local execute = function()
|
||||
-- exec
|
||||
do
|
||||
local i=0
|
||||
if proxy=='0' then
|
||||
log('服务正在暂停')
|
||||
SYS.init.stop(name)
|
||||
end
|
||||
log('--------------------开始订阅---------------------')
|
||||
for k,url in ipairs(subscribe_url) do
|
||||
i=i+1
|
||||
local raw=curl(url)
|
||||
if #raw > 0 then
|
||||
if i ~= 1 then
|
||||
log('--------------------------------------------------')
|
||||
end
|
||||
log('解析第'..i..'个链接: *')
|
||||
local nodes, szType
|
||||
local num=0
|
||||
local groupHash = md5(url)
|
||||
cache[groupHash] = {}
|
||||
tinsert(nodeResult, {})
|
||||
local index = #nodeResult
|
||||
-- SSD 似乎是这种格式 ssd:// 开头的
|
||||
if raw:find('ssd://') then
|
||||
szType = 'ssd'
|
||||
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 servers = {}
|
||||
-- SS里面包着 干脆直接这样
|
||||
for _, server in ipairs(nodes.servers) do
|
||||
tinsert(servers, setmetatable(server, {__index = extra}))
|
||||
end
|
||||
nodes = servers
|
||||
else
|
||||
-- ssd 外的格式
|
||||
nodes = split(base64Decode(raw):gsub(" ", "\n"), "\n")
|
||||
end
|
||||
for _, v in ipairs(nodes) do
|
||||
if v then
|
||||
xpcall(function ()
|
||||
local result
|
||||
if szType == 'ssd' then
|
||||
result = processData(szType, v)
|
||||
elseif not szType then
|
||||
local node = trim(v)
|
||||
local dat = split(node, "://")
|
||||
if dat and dat[1] and dat[2] then
|
||||
local dat3 = ""
|
||||
if dat[3] then
|
||||
dat3 = "://" .. dat[3]
|
||||
end
|
||||
if dat[1] == 'ss' or dat[1] == 'trojan' then
|
||||
result = processData(dat[1], dat[2] .. dat3)
|
||||
else
|
||||
result = processData(dat[1], base64Decode(dat[2]))
|
||||
end
|
||||
end
|
||||
else
|
||||
log('跳过未知类型: ' .. szType)
|
||||
end
|
||||
-- log(result)
|
||||
if result then
|
||||
-- 中文做地址的 也没有人拿中文域名搞,就算中文域也有Puny Code SB 机场
|
||||
if not result.type then
|
||||
log('丢弃节点:' .. result.alias .. ",找不到可使用二进制.")
|
||||
elseif not result.server or result.alias == "NULL" or check_filer(result) then
|
||||
num=num+1
|
||||
log('丢弃过滤节点: ' .. result.type .. ' 节点: ' .. result.alias )
|
||||
else
|
||||
-- log('成功解析: ' .. result.type ..' 节点: ' .. result.alias)
|
||||
result.grouphashkey = groupHash
|
||||
tinsert(nodeResult[index], result)
|
||||
cache[groupHash][result.hashkey] = nodeResult[index][#nodeResult[index]]
|
||||
end
|
||||
else
|
||||
num=num+1
|
||||
end
|
||||
end, function ()
|
||||
log(v, "解析错误,跳过此节点。")
|
||||
end
|
||||
)
|
||||
end
|
||||
end
|
||||
log('第'..i..'个链接成功解析节点数量: '..#nodes-num)
|
||||
else
|
||||
log('第'..i..'个链接获取内容为空,可能是订阅地址失效或是网络问题')
|
||||
end
|
||||
end
|
||||
end
|
||||
-- diff
|
||||
do
|
||||
if next(nodeResult) == nil then
|
||||
log("更新失败,没有可用的节点信息")
|
||||
if proxy == '0' then
|
||||
log('订阅失败, 恢复服务')
|
||||
SYS.init.start(name)
|
||||
end
|
||||
return
|
||||
end
|
||||
local add, del = 0, 0
|
||||
ucic:foreach(name, uciType, function(old)
|
||||
if old.grouphashkey or old.hashkey then -- 没有 hash 的不参与删除
|
||||
if not nodeResult[old.grouphashkey] or not nodeResult[old.grouphashkey][old.hashkey] then
|
||||
ucic:delete(name, old['.name'])
|
||||
del = del + 1
|
||||
else
|
||||
local dat = nodeResult[old.grouphashkey][old.hashkey]
|
||||
ucic:tset(name, old['.name'], dat)
|
||||
-- 标记一下
|
||||
setmetatable(nodeResult[old.grouphashkey][old.hashkey], {__index = {_ignore = true}})
|
||||
end
|
||||
else
|
||||
if not old.alias then
|
||||
if old.server or old.server_port then
|
||||
old.alias = old.server .. ':' .. old.server_port
|
||||
log('忽略手动添加的节点: ' .. old.alias)
|
||||
else
|
||||
ucic:delete(name, old['.name'])
|
||||
end
|
||||
else
|
||||
log('忽略手动添加的节点: ' .. old.alias)
|
||||
end
|
||||
end
|
||||
end)
|
||||
for k, v in ipairs(nodeResult) do
|
||||
-- 如果订阅节点中有相同的节点信息 需要先去重。
|
||||
for kk, vv in ipairs(v) do
|
||||
if not vv._ignore then
|
||||
local section = ucic:add(name, uciType)
|
||||
ucic:tset(name, section, vv)
|
||||
ucic:set(name, section, "switch_enable", switch)
|
||||
add = add + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
log('--------------------------------------------------')
|
||||
log('新增节点数量: ' .. add, '删除节点数量: ' .. del)
|
||||
local globalServer = ucic:get_first(name, 'global', 'global_server', '')
|
||||
if globalServer ~= "nil" then
|
||||
local firstServer = ucic:get_first(name, uciType)
|
||||
if firstServer then
|
||||
local nowserver=ucic:get(name, globalServer, 'alias', '')
|
||||
if not ucic:get(name, globalServer) then
|
||||
ucic:set(name, ucic:get_first(name, 'global'), 'global_server', ucic:get_first(name, uciType))
|
||||
ucic:commit(name)
|
||||
log('当前主服务器节点为空,自动更换到第一个节点。')
|
||||
else
|
||||
log('维持当前主服务器节点: '..ucic:get(name, globalServer, 'alias', ''))
|
||||
end
|
||||
else
|
||||
ucic:delete(name,ucic:get_first(name,'global'),'global_server')
|
||||
ucic:delete(name,ucic:get_first(name,'global'),'udp_relay_server')
|
||||
ucic:delete(name,ucic:get_first(name,'global'),'nf_server')
|
||||
ucic:commit(name)
|
||||
log('没有服务器节点了,停止服务')
|
||||
SYS.exec("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &")
|
||||
end
|
||||
end
|
||||
ucic:commit(name)
|
||||
|
||||
if globalServer == "nil" then
|
||||
SYS.init.stop(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if subscribe_url and #subscribe_url > 0 then
|
||||
|
||||
if SYS.call('curl -so /dev/null -m 5 www.baidu.com')~=0 then
|
||||
log("网络不通,停止更新订阅")
|
||||
return
|
||||
end
|
||||
|
||||
xpcall(execute, function(e)
|
||||
log(e)
|
||||
log(debug.traceback())
|
||||
log('发生错误, 正在恢复服务')
|
||||
end)
|
||||
local enabled = ucic:get_first(name, 'global', 'enabled', 0)
|
||||
if enabled == 0 then
|
||||
log('服务没有启用!')
|
||||
SYS.init.stop(name)
|
||||
--SYS.exec("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &")
|
||||
end
|
||||
log('--------------------订阅完毕---------------------')
|
||||
|
||||
end
|
94
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/update
Normal file
94
luci-app-bypass/luci-app-bypass/root/usr/share/bypass/update
Normal file
@ -0,0 +1,94 @@
|
||||
#!/bin/sh
|
||||
[ "$1" = --First ] && A=Y || A=N
|
||||
LOCKU=/tmp/lock/bypass-update.lock
|
||||
[ -f $LOCKU ] && exit 1
|
||||
touch $LOCKU
|
||||
DIR=/usr/share/bypass
|
||||
TMP=/etc/bypass
|
||||
TMP2=/tmp/etc/bypass
|
||||
LOG=/tmp/log/bypass.log
|
||||
chnroute_url=$(uci -q get bypass.@global_rules[0].chnroute_url)
|
||||
chnroute6_url=$(uci -q get bypass.@global_rules[0].chnroute6_url)
|
||||
domains_url=$(uci -q get bypass.@global_rules[0].domains_url)
|
||||
gfwlist_url="$(uci -q get bypass.@global_rules[0].gfwlist_url)"
|
||||
ad_url="$(uci -q get bypass.@global_rules[0].ad_url)"
|
||||
google_status=$(curl -I -4 -m 3 -o /dev/null -s -w %{http_code} http://www.google.com/generate_204)
|
||||
[ "$google_status" -ne "204" ] && proxy="https://ghproxy.com/"
|
||||
log(){
|
||||
echo "$(date +'%Y-%m-%d %H:%M:%S') $*" >> $LOG
|
||||
}
|
||||
|
||||
echo '------------Update start------------' >> $LOG
|
||||
[ ! -d $TMP ] && mkdir -p $TMP 2>/dev/null
|
||||
[ ! -d $TMP2 ] && mkdir -p $TMP2 2>/dev/null
|
||||
|
||||
echo -e "\e[1;32mDownloading "$proxy${chnroute_url}"\e[0m"
|
||||
curl --connect-timeout 5 -m 60 --ipv4 -kfSLo "/tmp/china.txt" ""$proxy"${chnroute_url}"
|
||||
[[ -f /tmp/china.txt && $? == 0 ]] && {
|
||||
if ! cmp -s /tmp/china.txt $TMP/china.txt;then
|
||||
cp -f /tmp/china.txt $TMP/china.txt
|
||||
mv /tmp/china.txt $TMP2/china.txt
|
||||
log "By Update : Updated China IPv4 List Total Number of Items :`cat /etc/bypass/china.txt | wc -l` "
|
||||
[ $A = N ] && ipset list china_v4 >/dev/null 2>&1 && $DIR/chinaipset
|
||||
|
||||
else
|
||||
log "By Update : China IPv4 List Total Number of Items :` cat /etc/bypass/china.txt | wc -l` "
|
||||
fi
|
||||
}
|
||||
|
||||
echo -e "\e[1;32mDownloading "$proxy${chnroute6_url}"\e[0m"
|
||||
curl --connect-timeout 5 -m 60 --ipv4 -kfSLo "/tmp/china_v6.txt" ""$proxy"${chnroute6_url}"
|
||||
[[ -f /tmp/china_v6.txt && $? == 0 ]] && {
|
||||
if ! cmp -s /tmp/china_v6.txt $TMP/china_v6.txt;then
|
||||
cp -f /tmp/china_v6.txt $TMP/china_v6.txt
|
||||
mv /tmp/china_v6.txt $TMP2/china_v6.txt
|
||||
log "By Update : Updated China IPv6 List Total Number of Items :` cat /etc/bypass/china_v6.txt | wc -l` "
|
||||
[ $A = N ] && ipset list china_v6 >/dev/null 2>&1 && $DIR/chinaipset v6
|
||||
else
|
||||
log "By Update : China IPv6 List Total Number of Items :`cat /etc/bypass/china_v6.txt | wc -l)` "
|
||||
fi
|
||||
}
|
||||
|
||||
echo -e "\e[1;32mDownloading "$proxy${gfwlist_url}"\e[0m"
|
||||
curl --connect-timeout 5 -m 60 --ipv4 -kfSLo "/tmp/gfw.b64" ""$proxy"${gfwlist_url}"
|
||||
[[ -f /tmp/gfw.b64 && $? == 0 ]] && {
|
||||
$DIR/by-gfw >/dev/null 2>&1
|
||||
if ! cmp -s /tmp/gfwnew.txt $TMP/gfw.list ;then
|
||||
cp -f /tmp/gfwnew.txt $TMP/gfw.list >/dev/null 2>&1
|
||||
mv /tmp/gfwnew.txt $TMP2/gfw.list
|
||||
log "By Update : Updated GFW List Total Number of Items : `cat /etc/bypass/gfw.list | wc -l` "
|
||||
else
|
||||
log "By Update : GFW List Total Number of Items : `cat /etc/bypass/gfw.list | wc -l` "
|
||||
fi
|
||||
}
|
||||
|
||||
echo -e "\e[1;32mDownloading "$proxy${domains_url}"\e[0m"
|
||||
curl --connect-timeout 5 -m 60 --ipv4 -kfSLo "/tmp/domains_cn.txt" ""$proxy"${domains_url}"
|
||||
|
||||
[[ -f /tmp/domains_cn.txt && $? == 0 ]] && {
|
||||
if ! cmp -s /tmp/domains_cn.txt $TMP/domains_cn.txt;then
|
||||
cp -f /tmp/domains_cn.txt $TMP/domains_cn.txt
|
||||
mv /tmp/domains_cn.txt $TMP2/domains_cn.txt
|
||||
log "By Update : Updated China Domains List Total Number of Items :` cat /etc/bypass/domains_cn.txt | wc -l` "
|
||||
else
|
||||
log "By Update : China Domains Total Number of Items :`cat /etc/bypass/domains_cn.txt | wc -l)` "
|
||||
fi
|
||||
}
|
||||
|
||||
echo -e "\e[1;32mDownloading "$proxy${ad_url}"\e[0m"
|
||||
curl --connect-timeout 5 -m 60 --ipv4 -kfSLo "/tmp/ad_list.txt" "$proxy${ad_url}"
|
||||
|
||||
[[ -f /tmp/ad_list.txt && $? == 0 ]] && {
|
||||
if ! cmp -s /tmp/ad_list.txt $TMP/ad_list.txt;then
|
||||
cp -f /tmp/ad_list.txt $TMP/ad_list.txt
|
||||
mv /tmp/ad_list.txt $TMP2/ad_list.txt
|
||||
log "By Update : anti-AD Update List Total Number of Items :` cat /etc/bypass/ad_list.txt | wc -l` "
|
||||
else
|
||||
log "By Update : anti-AD List Total Number of Items :`cat /etc/bypass/ad_list.txt | wc -l)` "
|
||||
fi
|
||||
}
|
||||
log "By Update : Check or update IPV4/IPV6/GFW/AD list complete! "
|
||||
echo '------------Update end------------' >> $LOG
|
||||
rm -f $LOCKU /tmp/china*.txt /tmp/gfwnew.txt /tmp/gfw.b64 /tmp/ad_list.txt /tmp/domains_cn.txt
|
||||
|
||||
[ $A = Y ] && /etc/init.d/bypass start &
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"luci-app-bypass": {
|
||||
"description": "Grant UCI access for luci-app-bypass",
|
||||
"read": {
|
||||
"uci": [ "bypass" ]
|
||||
},
|
||||
"write": {
|
||||
"uci": [ "bypass" ]
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"config": "bypass",
|
||||
"init": "bypass"
|
||||
}
|
Loading…
Reference in New Issue
Block a user