luci-app-vssr: sync with upstream source
This commit is contained in:
parent
07d7c2060a
commit
98f1d9ec3d
@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-vssr
|
||||
PKG_VERSION:=1.17
|
||||
PKG_RELEASE:=20200827
|
||||
PKG_VERSION:=1.17-1
|
||||
PKG_RELEASE:=20200830
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
|
||||
@ -1,121 +1,108 @@
|
||||
-- Copyright (C) 2018 jerrykuku <jerrykuku@qq.com>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
module("luci.controller.vssr", package.seeall)
|
||||
module('luci.controller.vssr', package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/vssr") then return end
|
||||
if not nixio.fs.access('/etc/config/vssr') then
|
||||
return
|
||||
end
|
||||
|
||||
if nixio.fs.access("/usr/bin/ssr-redir") then
|
||||
entry({"admin", "services", "vssr"},
|
||||
alias("admin", "services", "vssr", "client"), _("Hello World"), 0).dependent =
|
||||
true -- 首页
|
||||
entry({"admin", "services", "vssr", "client"}, cbi("vssr/client"),
|
||||
_("SSR Client"), 10).leaf = true -- 基本设置
|
||||
entry({"admin", "services", "vssr", "servers"}, cbi("vssr/servers"),
|
||||
_("Severs Nodes"), 11).leaf = true -- 服务器节点
|
||||
entry({"admin", "services", "vssr", "servers"},
|
||||
arcombine(cbi("vssr/servers"), cbi("vssr/client-config")),
|
||||
_("Severs Nodes"), 11).leaf = true -- 编辑节点
|
||||
entry({"admin", "services", "vssr", "control"}, cbi("vssr/control"),
|
||||
_("Access Control"), 12).leaf = true -- 访问控制
|
||||
if nixio.fs.access("/usr/bin/v2ray/v2ray") then
|
||||
entry({"admin", "services", "vssr", "socks5"}, cbi("vssr/socks5"),
|
||||
_("Socks5"), 13).leaf = true -- Socks5代理
|
||||
if nixio.fs.access('/usr/bin/ssr-redir') then
|
||||
entry({'admin', 'services', 'vssr'}, alias('admin', 'services', 'vssr', 'client'), _('Hello World'), 0).dependent = true -- 首页
|
||||
entry({'admin', 'services', 'vssr', 'client'}, cbi('vssr/client'), _('SSR Client'), 10).leaf = true -- 基本设置
|
||||
entry({'admin', 'services', 'vssr', 'servers'}, cbi('vssr/servers'), _('Severs Nodes'), 11).leaf = true -- 服务器节点
|
||||
entry({'admin', 'services', 'vssr', 'servers'}, arcombine(cbi('vssr/servers'), cbi('vssr/client-config')), _('Severs Nodes'), 11).leaf = true -- 编辑节点
|
||||
entry({'admin', 'services', 'vssr', 'control'}, cbi('vssr/control'), _('Access Control'), 12).leaf = true -- 访问控制
|
||||
if nixio.fs.access('/usr/bin/v2ray/v2ray') then
|
||||
entry({'admin', 'services', 'vssr', 'socks5'}, cbi('vssr/socks5'), _('Socks5'), 13).leaf = true -- Socks5代理
|
||||
end
|
||||
entry({"admin", "services", "vssr", "advanced"}, cbi("vssr/advanced"),
|
||||
_("Advanced Settings"), 14).leaf = true -- 高级设置
|
||||
elseif nixio.fs.access("/usr/bin/ssr-server") then
|
||||
entry({"admin", "services", "vssr"},
|
||||
alias("admin", "services", "vssr", "server"), _("vssr"), 10).dependent =
|
||||
true
|
||||
entry({'admin', 'services', 'vssr', 'advanced'}, cbi('vssr/advanced'), _('Advanced Settings'), 14).leaf = true -- 高级设置
|
||||
elseif nixio.fs.access('/usr/bin/ssr-server') then
|
||||
entry({'admin', 'services', 'vssr'}, alias('admin', 'services', 'vssr', 'server'), _('vssr'), 10).dependent = true
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
if nixio.fs.access("/usr/bin/ssr-server") then
|
||||
entry({"admin", "services", "vssr", "server"},
|
||||
arcombine(cbi("vssr/server"), cbi("vssr/server-config")),
|
||||
_("SSR Server"), 20).leaf = true
|
||||
if nixio.fs.access('/usr/bin/ssr-server') then
|
||||
entry({'admin', 'services', 'vssr', 'server'}, arcombine(cbi('vssr/server'), cbi('vssr/server-config')), _('SSR Server'), 20).leaf = true
|
||||
end
|
||||
|
||||
entry({"admin", "services", "vssr", "log"}, cbi("vssr/log"), _("Log"), 30).leaf =
|
||||
true
|
||||
entry({"admin", "services", "vssr", "licence"}, template("vssr/licence"),
|
||||
_("Licence"), 40).leaf = true
|
||||
entry({'admin', 'services', 'vssr', 'log'}, cbi('vssr/log'), _('Log'), 30).leaf = true
|
||||
entry({'admin', 'services', 'vssr', 'licence'}, template('vssr/licence'), _('Licence'), 40).leaf = true
|
||||
|
||||
entry({"admin", "services", "vssr", "refresh"}, call("refresh_data")) -- 更新白名单和GFWLIST
|
||||
entry({"admin", "services", "vssr", "checkport"}, call("check_port")) -- 检测单个端口并返回Ping
|
||||
entry({"admin", "services", "vssr", "run"}, call("act_status")) -- 检测全局服务器状态
|
||||
entry({"admin", "services", "vssr", "change"}, call("change_node")) -- 切换节点
|
||||
entry({"admin", "services", "vssr", "allserver"}, call("get_servers")) -- 获取所有节点Json
|
||||
entry({"admin", "services", "vssr", "subscribe"}, call("get_subscribe")) -- 执行订阅
|
||||
entry({"admin", "services", "vssr", "flag"}, call("get_flag")) -- 获取节点国旗 iso code
|
||||
entry({"admin", "services", "vssr", "ip"}, call("check_ip")) -- 获取ip情况
|
||||
entry({"admin", "services", "vssr", "switch"}, call("switch")) -- 设置节点为自动切换
|
||||
entry({'admin', 'services', 'vssr', 'refresh'}, call('refresh_data')) -- 更新白名单和GFWLIST
|
||||
entry({'admin', 'services', 'vssr', 'checkport'}, call('check_port')) -- 检测单个端口并返回Ping
|
||||
entry({'admin', 'services', 'vssr', 'run'}, call('act_status')) -- 检测全局服务器状态
|
||||
entry({'admin', 'services', 'vssr', 'change'}, call('change_node')) -- 切换节点
|
||||
entry({'admin', 'services', 'vssr', 'allserver'}, call('get_servers')) -- 获取所有节点Json
|
||||
entry({'admin', 'services', 'vssr', 'subscribe'}, call('get_subscribe')) -- 执行订阅
|
||||
entry({'admin', 'services', 'vssr', 'flag'}, call('get_flag')) -- 获取节点国旗 iso code
|
||||
entry({'admin', 'services', 'vssr', 'ip'}, call('check_ip')) -- 获取ip情况
|
||||
entry({'admin', 'services', 'vssr', 'switch'}, call('switch')) -- 设置节点为自动切换
|
||||
end
|
||||
|
||||
-- 执行订阅
|
||||
function get_subscribe()
|
||||
local cjson = require "luci.jsonc"
|
||||
local cjson = require 'luci.jsonc'
|
||||
local e = {}
|
||||
local name = "vssr"
|
||||
local name = 'vssr'
|
||||
local uci = luci.model.uci.cursor()
|
||||
local auto_update = luci.http.formvalue("auto_update")
|
||||
local auto_update_time = luci.http.formvalue("auto_update_time")
|
||||
local proxy = luci.http.formvalue("proxy")
|
||||
local subscribe_url = luci.http.formvalue("subscribe_url")
|
||||
if subscribe_url ~= "[]" then
|
||||
uci:delete(name, "@server_subscribe[0]", subscribe_url)
|
||||
uci:set(name, "@server_subscribe[0]", "auto_update", auto_update)
|
||||
uci:set(name, "@server_subscribe[0]", "auto_update_time",
|
||||
auto_update_time)
|
||||
uci:set(name, "@server_subscribe[0]", "proxy", proxy)
|
||||
uci:set_list(name, "@server_subscribe[0]", "subscribe_url",
|
||||
cjson.parse(subscribe_url))
|
||||
local auto_update = luci.http.formvalue('auto_update')
|
||||
local auto_update_time = luci.http.formvalue('auto_update_time')
|
||||
local proxy = luci.http.formvalue('proxy')
|
||||
local subscribe_url = luci.http.formvalue('subscribe_url')
|
||||
if subscribe_url ~= '[]' then
|
||||
uci:delete(name, '@server_subscribe[0]', subscribe_url)
|
||||
uci:set(name, '@server_subscribe[0]', 'auto_update', auto_update)
|
||||
uci:set(name, '@server_subscribe[0]', 'auto_update_time', auto_update_time)
|
||||
uci:set(name, '@server_subscribe[0]', 'proxy', proxy)
|
||||
uci:set_list(name, '@server_subscribe[0]', 'subscribe_url', cjson.parse(subscribe_url))
|
||||
uci:commit(name)
|
||||
luci.sys.exec(
|
||||
"nohup /usr/bin/lua /usr/share/vssr/subscribe.lua >/www/check_update.htm 2>/dev/null &")
|
||||
luci.sys.exec('nohup /usr/bin/lua /usr/share/vssr/subscribe.lua >/www/check_update.htm 2>/dev/null &')
|
||||
e.error = 0
|
||||
else
|
||||
e.error = 1
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.prepare_content('application/json')
|
||||
luci.http.write_json(e)
|
||||
|
||||
end
|
||||
|
||||
-- 获取所有节点
|
||||
function get_servers()
|
||||
local uci = luci.model.uci.cursor()
|
||||
local server_table = {}
|
||||
uci:foreach("vssr", "servers", function(s)
|
||||
local e = {}
|
||||
e["name"] = s[".name"]
|
||||
table.insert(server_table, e)
|
||||
end)
|
||||
luci.http.prepare_content("application/json")
|
||||
uci:foreach(
|
||||
'vssr',
|
||||
'servers',
|
||||
function(s)
|
||||
local e = {}
|
||||
e['name'] = s['.name']
|
||||
table.insert(server_table, e)
|
||||
end
|
||||
)
|
||||
luci.http.prepare_content('application/json')
|
||||
luci.http.write_json(server_table)
|
||||
end
|
||||
|
||||
-- 切换节点
|
||||
function change_node()
|
||||
local sockets = require "socket"
|
||||
local sockets = require 'socket'
|
||||
local e = {}
|
||||
local uci = luci.model.uci.cursor()
|
||||
local sid = luci.http.formvalue("set")
|
||||
local server = luci.http.formvalue("server")
|
||||
local sid = luci.http.formvalue('set')
|
||||
local server = luci.http.formvalue('server')
|
||||
e.status = false
|
||||
e.sid = sid
|
||||
if sid ~= "" and server ~= "" then
|
||||
uci:set("vssr", '@global[0]', server .. '_server', sid)
|
||||
if (server ~= "global" and server ~= "udp_relay") then
|
||||
uci:set("vssr", '@global[0]', 'v2ray_flow', "1")
|
||||
if sid ~= '' and server ~= '' then
|
||||
uci:set('vssr', '@global[0]', server .. '_server', sid)
|
||||
if (server ~= 'global' and server ~= 'udp_relay') then
|
||||
uci:set('vssr', '@global[0]', 'v2ray_flow', '1')
|
||||
end
|
||||
uci:commit("vssr")
|
||||
luci.sys.call("/etc/init.d/vssr restart >/www/restartlog.htm 2>&1")
|
||||
uci:commit('vssr')
|
||||
luci.sys.call('/etc/init.d/vssr restart >/www/restartlog.htm 2>&1')
|
||||
e.status = true
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.prepare_content('application/json')
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
@ -123,18 +110,18 @@ end
|
||||
function switch()
|
||||
local e = {}
|
||||
local uci = luci.model.uci.cursor()
|
||||
local sid = luci.http.formvalue("node")
|
||||
local isSwitch = uci:get("vssr", sid, "switch_enable")
|
||||
local toSwitch = (isSwitch == "1") and "0" or "1"
|
||||
uci:set("vssr", sid, "switch_enable", toSwitch)
|
||||
uci:commit("vssr")
|
||||
if isSwitch == "1" then
|
||||
local sid = luci.http.formvalue('node')
|
||||
local isSwitch = uci:get('vssr', sid, 'switch_enable')
|
||||
local toSwitch = (isSwitch == '1') and '0' or '1'
|
||||
uci:set('vssr', sid, 'switch_enable', toSwitch)
|
||||
uci:commit('vssr')
|
||||
if isSwitch == '1' then
|
||||
e.switch = false
|
||||
else
|
||||
e.switch = true
|
||||
end
|
||||
e.status = true
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.prepare_content('application/json')
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
@ -143,33 +130,30 @@ function act_status()
|
||||
math.randomseed(os.time())
|
||||
local e = {}
|
||||
-- 全局服务器
|
||||
e.global = luci.sys.call(
|
||||
"busybox ps -w | grep vssr_t | grep -v grep >/dev/null") == 0
|
||||
e.global = luci.sys.call('busybox ps -w | grep vssr_t | grep -v grep >/dev/null') == 0
|
||||
-- 检测PDNSD状态
|
||||
e.pdnsd = luci.sys.call("pidof pdnsd >/dev/null") == 0
|
||||
e.pdnsd = luci.sys.call('pidof pdnsd >/dev/null') == 0
|
||||
-- 检测游戏模式状态
|
||||
e.game = luci.sys.call(
|
||||
"busybox ps -w | grep vssr_u | grep -v grep >/dev/null") == 0
|
||||
e.game = luci.sys.call('busybox ps -w | grep vssr_u | grep -v grep >/dev/null') == 0
|
||||
-- 检测Socks5
|
||||
e.socks5 = luci.sys.call(
|
||||
"busybox ps -w | grep vssr_s | grep -v grep >/dev/null") == 0
|
||||
luci.http.prepare_content("application/json")
|
||||
e.socks5 = luci.sys.call('busybox ps -w | grep vssr_s | grep -v grep >/dev/null') == 0
|
||||
luci.http.prepare_content('application/json')
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
-- 检测单个节点状态并返回连接速度
|
||||
function check_port()
|
||||
local sockets = require "socket"
|
||||
local vssr = require "vssrutil"
|
||||
local set = luci.http.formvalue("host")
|
||||
local port = luci.http.formvalue("port")
|
||||
local retstring = ""
|
||||
local sockets = require 'socket'
|
||||
local vssr = require 'vssrutil'
|
||||
local set = luci.http.formvalue('host')
|
||||
local port = luci.http.formvalue('port')
|
||||
local retstring = ''
|
||||
local t0 = sockets.gettime()
|
||||
ret = vssr.check_site(set, port)
|
||||
local t1 = sockets.gettime()
|
||||
retstring = tostring(ret) == "true" and "1" or "0"
|
||||
retstring = tostring(ret) == 'true' and '1' or '0'
|
||||
local tt = t1 - t0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.prepare_content('application/json')
|
||||
luci.http.write_json({ret = retstring, used = math.floor(tt * 1000 + 0.5)})
|
||||
end
|
||||
|
||||
@ -177,142 +161,141 @@ function get_iso(ip)
|
||||
local mm = require 'maxminddb'
|
||||
local db = mm.open('/usr/share/vssr/GeoLite2-Country.mmdb')
|
||||
local res = db:lookup(ip)
|
||||
return string.lower(res:get("country", "iso_code"))
|
||||
return string.lower(res:get('country', 'iso_code'))
|
||||
end
|
||||
|
||||
function get_cname(ip)
|
||||
local mm = require 'maxminddb'
|
||||
local db = mm.open('/usr/share/vssr/GeoLite2-Country.mmdb')
|
||||
local res = db:lookup(ip)
|
||||
return string.lower(res:get("country", "names", "zh-CN"))
|
||||
return string.lower(res:get('country', 'names', 'zh-CN'))
|
||||
end
|
||||
|
||||
-- 获取当前代理状态 与节点ip
|
||||
function check_ip()
|
||||
local e = {}
|
||||
local d = {}
|
||||
local vssr = require "vssrutil"
|
||||
local vssr = require 'vssrutil'
|
||||
local port = 80
|
||||
local ip = vssr.wget("http://api.ipify.org/")
|
||||
d.flag = "un"
|
||||
d.country = "Unknown"
|
||||
if (ip ~= "") then
|
||||
local ip = vssr.wget('http://api.ipify.org/')
|
||||
d.flag = 'un'
|
||||
d.country = 'Unknown'
|
||||
if (ip ~= '') then
|
||||
local status, code = pcall(get_iso, ip)
|
||||
if (status) then d.flag = code end
|
||||
if (status) then
|
||||
d.flag = code
|
||||
end
|
||||
local status1, country = pcall(get_cname, ip)
|
||||
if (status1) then d.country = country end
|
||||
if (status1) then
|
||||
d.country = country
|
||||
end
|
||||
end
|
||||
e.outboard = ip
|
||||
e.outboardip = d
|
||||
e.baidu = vssr.check_site("www.baidu.com", port)
|
||||
e.taobao = vssr.check_site("www.taobao.com", port)
|
||||
e.google = vssr.check_site("www.google.com", port)
|
||||
e.youtube = vssr.check_site("www.youtube.com", port)
|
||||
luci.http.prepare_content("application/json")
|
||||
e.baidu = vssr.check_site('www.baidu.com', port)
|
||||
e.taobao = vssr.check_site('www.taobao.com', port)
|
||||
e.google = vssr.check_site('www.google.com', port)
|
||||
e.youtube = vssr.check_site('www.youtube.com', port)
|
||||
luci.http.prepare_content('application/json')
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
-- 获取节点国旗 iso code
|
||||
function get_flag()
|
||||
local e = {}
|
||||
local vssr = require "vssrutil"
|
||||
local host = luci.http.formvalue("host")
|
||||
local remark = luci.http.formvalue("remark")
|
||||
local vssr = require 'vssrutil'
|
||||
local host = luci.http.formvalue('host')
|
||||
local remark = luci.http.formvalue('remark')
|
||||
e.host = host
|
||||
e.flag = vssr.get_flag(remark, host)
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.prepare_content('application/json')
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
-- 刷新检测文件
|
||||
function refresh_data()
|
||||
local set = luci.http.formvalue("set")
|
||||
local set = luci.http.formvalue('set')
|
||||
local icount = 0
|
||||
|
||||
if set == "gfw_data" then
|
||||
if nixio.fs.access("/usr/bin/wget-ssl") then
|
||||
refresh_cmd =
|
||||
"wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64"
|
||||
if set == 'gfw_data' then
|
||||
if nixio.fs.access('/usr/bin/wget-ssl') then
|
||||
refresh_cmd = 'wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64'
|
||||
else
|
||||
refresh_cmd = "wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64"
|
||||
refresh_cmd = 'wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64'
|
||||
end
|
||||
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
|
||||
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
|
||||
if sret == 0 then
|
||||
luci.sys.call("/usr/bin/vssr-gfw")
|
||||
icount = luci.sys.exec("cat /tmp/gfwnew.txt | wc -l")
|
||||
luci.sys.call('/usr/bin/vssr-gfw')
|
||||
icount = luci.sys.exec('cat /tmp/gfwnew.txt | wc -l')
|
||||
if tonumber(icount) > 1000 then
|
||||
oldcount = luci.sys.exec(
|
||||
"cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l")
|
||||
oldcount = luci.sys.exec('cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l')
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec(
|
||||
"cp -f /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf")
|
||||
luci.sys.exec('cp -f /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf')
|
||||
retstring = tostring(math.ceil(tonumber(icount) / 2))
|
||||
else
|
||||
retstring = "0"
|
||||
retstring = '0'
|
||||
end
|
||||
else
|
||||
retstring = "-1"
|
||||
retstring = '-1'
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/gfwnew.txt ")
|
||||
luci.sys.exec('rm -f /tmp/gfwnew.txt ')
|
||||
else
|
||||
retstring = "-1"
|
||||
retstring = '-1'
|
||||
end
|
||||
elseif set == "ip_data" then
|
||||
elseif set == 'ip_data' then
|
||||
refresh_cmd =
|
||||
"wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' 2>/dev/null| awk -F\\| '/CN\\|ipv4/ { printf(\"%s/%d\\n\", $4, 32-log($5)/log(2)) }' > /tmp/china_ssr.txt"
|
||||
sret = luci.sys.call(refresh_cmd)
|
||||
icount = luci.sys.exec("cat /tmp/china_ssr.txt | wc -l")
|
||||
icount = luci.sys.exec('cat /tmp/china_ssr.txt | wc -l')
|
||||
if sret == 0 and tonumber(icount) > 1000 then
|
||||
oldcount = luci.sys.exec("cat /etc/china_ssr.txt | wc -l")
|
||||
oldcount = luci.sys.exec('cat /etc/china_ssr.txt | wc -l')
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/china_ssr.txt /etc/china_ssr.txt")
|
||||
luci.sys.exec('cp -f /tmp/china_ssr.txt /etc/china_ssr.txt')
|
||||
retstring = tostring(tonumber(icount))
|
||||
else
|
||||
retstring = "0"
|
||||
retstring = '0'
|
||||
end
|
||||
else
|
||||
retstring = "-1"
|
||||
retstring = '-1'
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/china_ssr.txt ")
|
||||
luci.sys.exec('rm -f /tmp/china_ssr.txt ')
|
||||
else
|
||||
local need_process = 0
|
||||
if nixio.fs.access("/usr/bin/wget-ssl") then
|
||||
refresh_cmd =
|
||||
"wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf"
|
||||
if nixio.fs.access('/usr/bin/wget-ssl') then
|
||||
refresh_cmd = 'wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf'
|
||||
need_process = 1
|
||||
else
|
||||
refresh_cmd = "wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf"
|
||||
refresh_cmd = 'wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf'
|
||||
end
|
||||
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
|
||||
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
|
||||
if sret == 0 then
|
||||
if need_process == 1 then
|
||||
luci.sys.call("/usr/bin/vssr-ad")
|
||||
luci.sys.call('/usr/bin/vssr-ad')
|
||||
end
|
||||
icount = luci.sys.exec("cat /tmp/ad.conf | wc -l")
|
||||
icount = luci.sys.exec('cat /tmp/ad.conf | wc -l')
|
||||
if tonumber(icount) > 1000 then
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
|
||||
oldcount = luci.sys.exec(
|
||||
"cat /etc/dnsmasq.ssr/ad.conf | wc -l")
|
||||
if nixio.fs.access('/etc/dnsmasq.ssr/ad.conf') then
|
||||
oldcount = luci.sys.exec('cat /etc/dnsmasq.ssr/ad.conf | wc -l')
|
||||
else
|
||||
oldcount = 0
|
||||
end
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/ad.conf /etc/dnsmasq.ssr/ad.conf")
|
||||
luci.sys.exec('cp -f /tmp/ad.conf /etc/dnsmasq.ssr/ad.conf')
|
||||
retstring = tostring(math.ceil(tonumber(icount)))
|
||||
if oldcount == 0 then
|
||||
luci.sys.call("/etc/init.d/dnsmasq restart")
|
||||
luci.sys.call('/etc/init.d/dnsmasq restart')
|
||||
end
|
||||
else
|
||||
retstring = "0"
|
||||
retstring = '0'
|
||||
end
|
||||
else
|
||||
retstring = "-1"
|
||||
retstring = '-1'
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/ad.conf")
|
||||
luci.sys.exec('rm -f /tmp/ad.conf')
|
||||
else
|
||||
retstring = "-1"
|
||||
retstring = '-1'
|
||||
end
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.prepare_content('application/json')
|
||||
luci.http.write_json({ret = retstring, retcount = icount})
|
||||
end
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
local vssr = "vssr"
|
||||
local vssr = 'vssr'
|
||||
local uci = luci.model.uci.cursor()
|
||||
local server_table = {}
|
||||
|
||||
@ -8,129 +8,135 @@ local ip_count = 0
|
||||
local ad_count = 0
|
||||
local server_count = 0
|
||||
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/gfw_list.conf") then gfwmode = 1 end
|
||||
if nixio.fs.access('/etc/dnsmasq.ssr/gfw_list.conf') then
|
||||
gfwmode = 1
|
||||
end
|
||||
|
||||
local sys = require "luci.sys"
|
||||
local sys = require 'luci.sys'
|
||||
|
||||
if gfwmode == 1 then
|
||||
gfw_count =
|
||||
tonumber(sys.exec("cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l")) / 2
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
|
||||
ad_count = tonumber(sys.exec("cat /etc/dnsmasq.ssr/ad.conf | wc -l"))
|
||||
gfw_count = tonumber(sys.exec('cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l')) / 2
|
||||
if nixio.fs.access('/etc/dnsmasq.ssr/ad.conf') then
|
||||
ad_count = tonumber(sys.exec('cat /etc/dnsmasq.ssr/ad.conf | wc -l'))
|
||||
end
|
||||
end
|
||||
|
||||
if nixio.fs.access("/etc/china_ssr.txt") then
|
||||
ip_count = sys.exec("cat /etc/china_ssr.txt | wc -l")
|
||||
if nixio.fs.access('/etc/china_ssr.txt') then
|
||||
ip_count = sys.exec('cat /etc/china_ssr.txt | wc -l')
|
||||
end
|
||||
|
||||
|
||||
uci:foreach("vssr", "servers", function(s)
|
||||
server_count = server_count + 1
|
||||
end)
|
||||
uci:foreach(
|
||||
'vssr',
|
||||
'servers',
|
||||
function(s)
|
||||
server_count = server_count + 1
|
||||
end
|
||||
)
|
||||
|
||||
m = Map(vssr)
|
||||
|
||||
-- [[ 服务器节点故障自动切换设置 ]]--
|
||||
|
||||
s = m:section(TypedSection, "global",
|
||||
translate("Server failsafe auto swith settings"))
|
||||
s = m:section(TypedSection, 'global', translate('Server failsafe auto swith settings'))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "monitor_enable", translate("Enable Process Deamon"))
|
||||
o = s:option(Flag, 'monitor_enable', translate('Enable Process Deamon'))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "enable_switch", translate("Enable Auto Switch"))
|
||||
o = s:option(Flag, 'enable_switch', translate('Enable Auto Switch'))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "switch_time", translate("Switch check cycly(second)"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("enable_switch", "1")
|
||||
o = s:option(Value, 'switch_time', translate('Switch check cycly(second)'))
|
||||
o.datatype = 'uinteger'
|
||||
o:depends('enable_switch', '1')
|
||||
o.default = 3600
|
||||
|
||||
o = s:option(Value, "switch_timeout", translate("Check timout(second)"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("enable_switch", "1")
|
||||
o = s:option(Value, 'switch_timeout', translate('Check timout(second)'))
|
||||
o.datatype = 'uinteger'
|
||||
o:depends('enable_switch', '1')
|
||||
o.default = 5
|
||||
|
||||
o = s:option(Value, "switch_try_count", translate("Check Try Count"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("enable_switch", "1")
|
||||
o = s:option(Value, 'switch_try_count', translate('Check Try Count'))
|
||||
o.datatype = 'uinteger'
|
||||
o:depends('enable_switch', '1')
|
||||
o.default = 3
|
||||
|
||||
-- [[ 节点订阅 ]]--
|
||||
|
||||
s = m:section(TypedSection, "server_subscribe",
|
||||
translate("Servers subscription and manage"))
|
||||
s = m:section(TypedSection, 'server_subscribe', translate('Servers subscription and manage'))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "auto_update", translate("Auto Update"))
|
||||
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.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 = 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 = s:option(DynamicList, 'subscribe_url', translate('Subscribe URL'))
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Flag, "proxy", translate("Through proxy update"))
|
||||
o = s:option(Flag, 'proxy', translate('Through proxy update'))
|
||||
o.rmempty = false
|
||||
o.description = translate("Through proxy update list, Not Recommended ")
|
||||
o.description = translate('Through proxy update list, Not Recommended ')
|
||||
|
||||
o = s:option(DummyValue, "", "")
|
||||
o = s:option(DummyValue, '', '')
|
||||
o.rawhtml = true
|
||||
o.template = "vssr/update_subscribe"
|
||||
o.template = 'vssr/update_subscribe'
|
||||
|
||||
o = s:option(Button,"delete",translate("Delete All Subscribe Severs"))
|
||||
o.inputstyle = "reset"
|
||||
o.description = string.format(translate("Server Count") .. ": %d", server_count)
|
||||
o = s:option(Button, 'delete', translate('Delete All Subscribe Severs'))
|
||||
o.inputstyle = 'reset'
|
||||
o.description = string.format(translate('Server Count') .. ': %d', server_count)
|
||||
o.write = function()
|
||||
uci:delete_all("vssr", "servers", function(s)
|
||||
if s.hashkey or s.isSubscribe then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end)
|
||||
uci:save("vssr")
|
||||
uci:commit("vssr")
|
||||
luci.sys.exec("/etc/init.d/vssr restart")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "vssr", "servers"))
|
||||
return
|
||||
uci:delete_all(
|
||||
'vssr',
|
||||
'servers',
|
||||
function(s)
|
||||
if s.hashkey or s.isSubscribe then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
)
|
||||
uci:save('vssr')
|
||||
uci:commit('vssr')
|
||||
luci.sys.exec('/etc/init.d/vssr restart')
|
||||
luci.http.redirect(luci.dispatcher.build_url('admin', 'services', 'vssr', 'servers'))
|
||||
return
|
||||
end
|
||||
|
||||
-- [[ adblock ]]--
|
||||
s = m:section(TypedSection, "global", translate("adblock settings"))
|
||||
s = m:section(TypedSection, 'global', translate('adblock settings'))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "adblock", translate("Enable adblock"))
|
||||
o = s:option(Flag, 'adblock', translate('Enable adblock'))
|
||||
o.rmempty = false
|
||||
|
||||
-- [[ 更新设置 ]]--
|
||||
|
||||
s = m:section(TypedSection, "socks5_proxy", translate("Update Setting"))
|
||||
s = m:section(TypedSection, 'socks5_proxy', translate('Update Setting'))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Button, "gfw_data", translate("GFW List Data"))
|
||||
o = s:option(Button, 'gfw_data', translate('GFW List Data'))
|
||||
o.rawhtml = true
|
||||
o.template = "vssr/refresh"
|
||||
o.value = tostring(math.ceil(gfw_count)) .. " " .. translate("Records")
|
||||
o.template = 'vssr/refresh'
|
||||
o.value = tostring(math.ceil(gfw_count)) .. ' ' .. translate('Records')
|
||||
|
||||
o = s:option(Button, "ip_data", translate("China IP Data"))
|
||||
o = s:option(Button, 'ip_data', translate('China IP Data'))
|
||||
o.rawhtml = true
|
||||
o.template = "vssr/refresh"
|
||||
o.value = ip_count .. " " .. translate("Records")
|
||||
o.template = 'vssr/refresh'
|
||||
o.value = ip_count .. ' ' .. translate('Records')
|
||||
|
||||
if uci:get_first('vssr', 'global', 'adblock', '') == '1' then
|
||||
o = s:option(Button, "ad_data", translate("Advertising Data"))
|
||||
o = s:option(Button, 'ad_data', translate('Advertising Data'))
|
||||
o.rawhtml = true
|
||||
o.template = "vssr/refresh"
|
||||
o.value = ad_count .. " " .. translate("Records")
|
||||
o.template = 'vssr/refresh'
|
||||
o.value = ad_count .. ' ' .. translate('Records')
|
||||
end
|
||||
|
||||
return m
|
||||
|
||||
@ -1,95 +1,141 @@
|
||||
-- Copyright (C) 2017 yushi studio <ywb94@qq.com> github.com/ywb94
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
local m, s, o, kcp_enable
|
||||
local vssr = "vssr"
|
||||
local vssr = 'vssr'
|
||||
local uci = luci.model.uci.cursor()
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
local fs = require 'nixio.fs'
|
||||
local sys = require 'luci.sys'
|
||||
local sid = arg[1]
|
||||
local uuid = luci.sys.exec("cat /proc/sys/kernel/random/uuid")
|
||||
local uuid = luci.sys.exec('cat /proc/sys/kernel/random/uuid')
|
||||
|
||||
local function isKcptun(file)
|
||||
if not fs.access(file, "rwx", "rx", "rx") then fs.chmod(file, 755) end
|
||||
if not fs.access(file, 'rwx', 'rx', 'rx') then
|
||||
fs.chmod(file, 755)
|
||||
end
|
||||
|
||||
local str = sys.exec(file .. " -v | awk '{printf $1}'")
|
||||
return (str:lower() == "kcptun")
|
||||
return (str:lower() == 'kcptun')
|
||||
end
|
||||
|
||||
local server_table = {}
|
||||
local encrypt_methods = {
|
||||
"none", "table", "rc4", "rc4-md5-6", "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",
|
||||
"cast5-cfb", "des-cfb", "idea-cfb", "rc2-cfb", "seed-cfb", "salsa20",
|
||||
"chacha20", "chacha20-ietf"
|
||||
'none',
|
||||
'table',
|
||||
'rc4',
|
||||
'rc4-md5-6',
|
||||
'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',
|
||||
'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", -- 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"
|
||||
'aes-128-gcm',
|
||||
'aes-192-gcm',
|
||||
'aes-256-gcm',
|
||||
'chacha20-ietf-poly1305',
|
||||
'xchacha20-ietf-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", "verify_deflate", "auth_sha1_v4", "auth_aes128_sha1",
|
||||
"auth_aes128_md5", "auth_chain_a", "auth_chain_b", "auth_chain_c",
|
||||
"auth_chain_d", "auth_chain_e", "auth_chain_f"
|
||||
'origin',
|
||||
'verify_deflate',
|
||||
'auth_sha1_v4',
|
||||
'auth_aes128_sha1',
|
||||
'auth_aes128_md5',
|
||||
'auth_chain_a',
|
||||
'auth_chain_b',
|
||||
'auth_chain_c',
|
||||
'auth_chain_d',
|
||||
'auth_chain_e',
|
||||
'auth_chain_f'
|
||||
}
|
||||
|
||||
obfs = {
|
||||
"plain", "http_simple", "http_post", "random_head", "tls1.2_ticket_auth"
|
||||
'plain',
|
||||
'http_simple',
|
||||
'http_post',
|
||||
'random_head',
|
||||
'tls1.2_ticket_auth'
|
||||
}
|
||||
local securitys = {"auto", "none", "aes-128-gcm", "chacha20-poly1305"}
|
||||
local securitys = {'auto', 'none', 'aes-128-gcm', 'chacha20-poly1305'}
|
||||
|
||||
m = Map(vssr, translate("Edit vssr Server"))
|
||||
m.redirect = luci.dispatcher.build_url("admin/services/vssr/servers")
|
||||
if m.uci:get(vssr, sid) ~= "servers" then
|
||||
m = Map(vssr, translate('Edit vssr Server'))
|
||||
m.redirect = luci.dispatcher.build_url('admin/services/vssr/servers')
|
||||
if m.uci:get(vssr, sid) ~= 'servers' then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
-- [[ Servers Setting ]]--
|
||||
s = m:section(NamedSection, sid, "servers")
|
||||
s = m:section(NamedSection, sid, 'servers')
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(DummyValue, "ssr_url", translate("Configuration Url"))
|
||||
o = s:option(DummyValue, 'ssr_url', translate('Configuration Url'))
|
||||
o.rawhtml = true
|
||||
o.template = "vssr/ssrurl"
|
||||
o.template = 'vssr/ssrurl'
|
||||
o.value = sid
|
||||
|
||||
o = s:option(ListValue, "type", translate("Server Node Type"))
|
||||
o:value("ssr", translate("ShadowsocksR"))
|
||||
o = s:option(ListValue, 'type', translate('Server Node Type'))
|
||||
o:value('ssr', translate('ShadowsocksR'))
|
||||
|
||||
if nixio.fs.access("/usr/bin/v2ray/v2ray") or nixio.fs.access("/usr/bin/v2ray") then
|
||||
o:value("ss", translate("Shadowsocks New Version"))
|
||||
o:value("v2ray", translate("V2Ray"))
|
||||
if nixio.fs.access('/usr/bin/v2ray/v2ray') or nixio.fs.access('/usr/bin/v2ray') then
|
||||
o:value('ss', translate('Shadowsocks New Version'))
|
||||
o:value('v2ray', translate('V2Ray'))
|
||||
end
|
||||
|
||||
if nixio.fs.access("/usr/sbin/trojan") then
|
||||
o:value("trojan", translate("Trojan"))
|
||||
if nixio.fs.access('/usr/sbin/trojan') then
|
||||
o:value('trojan', translate('Trojan'))
|
||||
end
|
||||
|
||||
o.description = translate(
|
||||
"Using incorrect encryption mothod may causes service fail to start")
|
||||
o.description = translate('Using incorrect encryption mothod may causes service fail to start')
|
||||
|
||||
o = s:option(Value, "alias", translate("Alias(optional)"))
|
||||
o = s:option(Value, 'alias', translate('Alias(optional)'))
|
||||
|
||||
o = s:option(Value, "flag", translate("Area"))
|
||||
o.description = translate("请自己指定。格式:cn us hk 等")
|
||||
o = s:option(Value, 'flag', translate('Area'))
|
||||
o.description = translate('请自己指定。格式:cn us hk 等')
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "server", translate("Server Address"))
|
||||
o.datatype = "host"
|
||||
o = s:option(Value, 'server', translate('Server Address'))
|
||||
o.datatype = 'host'
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server_port", translate("Server Port"))
|
||||
o.datatype = "port"
|
||||
o = s:option(Value, 'server_port', translate('Server Port'))
|
||||
o.datatype = 'port'
|
||||
o.rmempty = false
|
||||
|
||||
-- o = s:option(Value, "timeout", translate("Connection Timeout"))
|
||||
@ -97,277 +143,284 @@ o.rmempty = false
|
||||
-- o.default = 60
|
||||
-- o.rmempty = false
|
||||
|
||||
o = s:option(Value, "password", translate("Password"))
|
||||
o = s:option(Value, 'password', translate('Password'))
|
||||
o.password = true
|
||||
o.rmempty = true
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "ss")
|
||||
o:depends("type", "trojan")
|
||||
o:depends('type', 'ssr')
|
||||
o:depends('type', 'ss')
|
||||
o:depends('type', 'trojan')
|
||||
|
||||
o = s:option(Value, "peer", translate("Peer"))
|
||||
o.datatype = "host"
|
||||
o = s:option(Value, 'peer', translate('Peer'))
|
||||
o.datatype = 'host'
|
||||
o.rmempty = true
|
||||
o:depends("type", "trojan")
|
||||
o:depends('type', 'trojan')
|
||||
|
||||
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
|
||||
for _, v in ipairs(encrypt_methods) do o:value(v) end
|
||||
o = s:option(ListValue, 'encrypt_method', translate('Encrypt Method'))
|
||||
for _, v in ipairs(encrypt_methods) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = true
|
||||
o:depends("type", "ssr")
|
||||
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 = s:option(ListValue, 'encrypt_method_ss', translate('Encrypt Method'))
|
||||
for _, v in ipairs(encrypt_methods_ss) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = true
|
||||
o:depends("type", "ss")
|
||||
o:depends('type', 'ss')
|
||||
|
||||
-- Shadowsocks Plugin
|
||||
o = s:option(Value, "plugin", translate("Plugin"))
|
||||
o = s:option(Value, 'plugin', translate('Plugin'))
|
||||
o.rmempty = true
|
||||
o:depends("type", "ss")
|
||||
o:depends('type', 'ss')
|
||||
|
||||
o = s:option(Value, "plugin_opts", translate("Plugin Opts"))
|
||||
o = s:option(Value, 'plugin_opts', translate('Plugin Opts'))
|
||||
o.rmempty = true
|
||||
o:depends("type", "ss")
|
||||
o:depends('type', 'ss')
|
||||
|
||||
o = s:option(ListValue, "protocol", translate("Protocol"))
|
||||
for _, v in ipairs(protocol) do o:value(v) end
|
||||
o = s:option(ListValue, 'protocol', translate('Protocol'))
|
||||
for _, v in ipairs(protocol) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = true
|
||||
o:depends("type", "ssr")
|
||||
o:depends('type', 'ssr')
|
||||
|
||||
o = s:option(Value, "protocol_param", translate("Protocol param(optional)"))
|
||||
o:depends("type", "ssr")
|
||||
o = s:option(Value, 'protocol_param', translate('Protocol param(optional)'))
|
||||
o:depends('type', 'ssr')
|
||||
|
||||
o = s:option(ListValue, "obfs", translate("Obfs"))
|
||||
for _, v in ipairs(obfs) do o:value(v) end
|
||||
o = s:option(ListValue, 'obfs', translate('Obfs'))
|
||||
for _, v in ipairs(obfs) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = true
|
||||
o:depends("type", "ssr")
|
||||
o:depends('type', 'ssr')
|
||||
|
||||
o = s:option(Value, "obfs_param", translate("Obfs param(optional)"))
|
||||
o:depends("type", "ssr")
|
||||
o = s:option(Value, 'obfs_param', translate('Obfs param(optional)'))
|
||||
o:depends('type', 'ssr')
|
||||
|
||||
-- AlterId
|
||||
o = s:option(Value, "alter_id", translate("AlterId"))
|
||||
o.datatype = "port"
|
||||
o = s:option(Value, 'alter_id', translate('AlterId'))
|
||||
o.datatype = 'port'
|
||||
o.default = 16
|
||||
o.rmempty = true
|
||||
o:depends("type", "v2ray")
|
||||
o:depends('type', 'v2ray')
|
||||
|
||||
-- VmessId
|
||||
o = s:option(Value, "vmess_id", translate("VmessId (UUID)"))
|
||||
o = s:option(Value, 'vmess_id', translate('VmessId (UUID)'))
|
||||
o.rmempty = true
|
||||
o.default = uuid
|
||||
o:depends("type", "v2ray")
|
||||
o:depends('type', 'v2ray')
|
||||
|
||||
-- 加密方式
|
||||
o = s:option(ListValue, "security", translate("Encrypt Method"))
|
||||
for _, v in ipairs(securitys) do o:value(v, v:upper()) end
|
||||
o = s:option(ListValue, 'security', translate('Encrypt Method'))
|
||||
for _, v in ipairs(securitys) do
|
||||
o:value(v, v:upper())
|
||||
end
|
||||
o.rmempty = true
|
||||
o:depends("type", "v2ray")
|
||||
o:depends('type', 'v2ray')
|
||||
|
||||
-- 传输协议
|
||||
o = s:option(ListValue, "transport", translate("Transport"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("kcp", "mKCP")
|
||||
o:value("ws", "WebSocket")
|
||||
o:value("h2", "HTTP/2")
|
||||
o:value("quic", "QUIC")
|
||||
o = s:option(ListValue, 'transport', translate('Transport'))
|
||||
o:value('tcp', 'TCP')
|
||||
o:value('kcp', 'mKCP')
|
||||
o:value('ws', 'WebSocket')
|
||||
o:value('h2', 'HTTP/2')
|
||||
o:value('quic', 'QUIC')
|
||||
o.rmempty = true
|
||||
o:depends("type", "v2ray")
|
||||
o:depends('type', 'v2ray')
|
||||
|
||||
-- [[ TCP部分 ]]--
|
||||
|
||||
-- TCP伪装
|
||||
o = s:option(ListValue, "tcp_guise", translate("Camouflage Type"))
|
||||
o:depends("transport", "tcp")
|
||||
o:value("none", translate("None"))
|
||||
o:value("http", "HTTP")
|
||||
o = s:option(ListValue, 'tcp_guise', translate('Camouflage Type'))
|
||||
o:depends('transport', 'tcp')
|
||||
o:value('none', translate('None'))
|
||||
o:value('http', 'HTTP')
|
||||
o.rmempty = true
|
||||
|
||||
-- HTTP域名
|
||||
o = s:option(DynamicList, "http_host", translate("HTTP Host"))
|
||||
o:depends("tcp_guise", "http")
|
||||
o = s:option(DynamicList, 'http_host', translate('HTTP Host'))
|
||||
o:depends('tcp_guise', 'http')
|
||||
o.rmempty = true
|
||||
|
||||
-- HTTP路径
|
||||
o = s:option(DynamicList, "http_path", translate("HTTP Path"))
|
||||
o:depends("tcp_guise", "http")
|
||||
o = s:option(DynamicList, 'http_path', translate('HTTP Path'))
|
||||
o:depends('tcp_guise', 'http')
|
||||
o.rmempty = true
|
||||
|
||||
-- [[ WS部分 ]]--
|
||||
|
||||
-- WS域名
|
||||
o = s:option(Value, "ws_host", translate("WebSocket Host"))
|
||||
o:depends("transport", "ws")
|
||||
o = s:option(Value, 'ws_host', translate('WebSocket Host'))
|
||||
o:depends('transport', 'ws')
|
||||
o.rmempty = true
|
||||
|
||||
-- WS路径
|
||||
o = s:option(Value, "ws_path", translate("WebSocket Path"))
|
||||
o:depends("transport", "ws")
|
||||
o = s:option(Value, 'ws_path', translate('WebSocket Path'))
|
||||
o:depends('transport', 'ws')
|
||||
o.rmempty = true
|
||||
|
||||
-- [[ H2部分 ]]--
|
||||
|
||||
-- H2域名
|
||||
o = s:option(DynamicList, "h2_host", translate("HTTP/2 Host"))
|
||||
o:depends("transport", "h2")
|
||||
o = s:option(DynamicList, 'h2_host', translate('HTTP/2 Host'))
|
||||
o:depends('transport', 'h2')
|
||||
o.rmempty = true
|
||||
|
||||
-- H2路径
|
||||
o = s:option(Value, "h2_path", translate("HTTP/2 Path"))
|
||||
o:depends("transport", "h2")
|
||||
o = s:option(Value, 'h2_path', translate('HTTP/2 Path'))
|
||||
o:depends('transport', 'h2')
|
||||
o.rmempty = true
|
||||
|
||||
-- [[ QUIC部分 ]]--
|
||||
|
||||
o = s:option(ListValue, "quic_security", translate("QUIC Security"))
|
||||
o:depends("transport", "quic")
|
||||
o = s:option(ListValue, 'quic_security', translate('QUIC Security'))
|
||||
o:depends('transport', 'quic')
|
||||
o.rmempty = true
|
||||
o:value("none", translate("None"))
|
||||
o:value("aes-128-gcm", translate("aes-128-gcm"))
|
||||
o:value("chacha20-poly1305", translate("chacha20-poly1305"))
|
||||
o:value('none', translate('None'))
|
||||
o:value('aes-128-gcm', translate('aes-128-gcm'))
|
||||
o:value('chacha20-poly1305', translate('chacha20-poly1305'))
|
||||
|
||||
o = s:option(Value, "quic_key", translate("QUIC Key"))
|
||||
o:depends("transport", "quic")
|
||||
o = s:option(Value, 'quic_key', translate('QUIC Key'))
|
||||
o:depends('transport', 'quic')
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(ListValue, "quic_guise", translate("Header"))
|
||||
o:depends("transport", "quic")
|
||||
o = s:option(ListValue, 'quic_guise', translate('Header'))
|
||||
o:depends('transport', 'quic')
|
||||
o.rmempty = true
|
||||
o:value("none", translate("None"))
|
||||
o:value("srtp", translate("VideoCall (SRTP)"))
|
||||
o:value("utp", translate("BitTorrent (uTP)"))
|
||||
o:value("wechat-video", translate("WechatVideo"))
|
||||
o:value("dtls", "DTLS 1.2")
|
||||
o:value("wireguard", "WireGuard")
|
||||
o:value('none', translate('None'))
|
||||
o:value('srtp', translate('VideoCall (SRTP)'))
|
||||
o:value('utp', translate('BitTorrent (uTP)'))
|
||||
o:value('wechat-video', translate('WechatVideo'))
|
||||
o:value('dtls', 'DTLS 1.2')
|
||||
o:value('wireguard', 'WireGuard')
|
||||
-- [[ mKCP部分 ]]--
|
||||
|
||||
o = s:option(ListValue, "kcp_guise", translate("Camouflage Type"))
|
||||
o:depends("transport", "kcp")
|
||||
o:value("none", translate("None"))
|
||||
o:value("srtp", translate("VideoCall (SRTP)"))
|
||||
o:value("utp", translate("BitTorrent (uTP)"))
|
||||
o:value("wechat-video", translate("WechatVideo"))
|
||||
o:value("dtls", "DTLS 1.2")
|
||||
o:value("wireguard", "WireGuard")
|
||||
o = s:option(ListValue, 'kcp_guise', translate('Camouflage Type'))
|
||||
o:depends('transport', 'kcp')
|
||||
o:value('none', translate('None'))
|
||||
o:value('srtp', translate('VideoCall (SRTP)'))
|
||||
o:value('utp', translate('BitTorrent (uTP)'))
|
||||
o:value('wechat-video', translate('WechatVideo'))
|
||||
o:value('dtls', 'DTLS 1.2')
|
||||
o:value('wireguard', 'WireGuard')
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "mtu", translate("MTU"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("transport", "kcp")
|
||||
o = s:option(Value, 'mtu', translate('MTU'))
|
||||
o.datatype = 'uinteger'
|
||||
o:depends('transport', 'kcp')
|
||||
o.default = 1350
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "tti", translate("TTI"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("transport", "kcp")
|
||||
o = s:option(Value, 'tti', translate('TTI'))
|
||||
o.datatype = 'uinteger'
|
||||
o:depends('transport', 'kcp')
|
||||
o.default = 50
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "uplink_capacity", translate("Uplink Capacity"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("transport", "kcp")
|
||||
o = s:option(Value, 'uplink_capacity', translate('Uplink Capacity'))
|
||||
o.datatype = 'uinteger'
|
||||
o:depends('transport', 'kcp')
|
||||
o.default = 5
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "downlink_capacity", translate("Downlink Capacity"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("transport", "kcp")
|
||||
o = s:option(Value, 'downlink_capacity', translate('Downlink Capacity'))
|
||||
o.datatype = 'uinteger'
|
||||
o:depends('transport', 'kcp')
|
||||
o.default = 20
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "read_buffer_size", translate("Read Buffer Size"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("transport", "kcp")
|
||||
o = s:option(Value, 'read_buffer_size', translate('Read Buffer Size'))
|
||||
o.datatype = 'uinteger'
|
||||
o:depends('transport', 'kcp')
|
||||
o.default = 2
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "write_buffer_size", translate("Write Buffer Size"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("transport", "kcp")
|
||||
o = s:option(Value, 'write_buffer_size', translate('Write Buffer Size'))
|
||||
o.datatype = 'uinteger'
|
||||
o:depends('transport', 'kcp')
|
||||
o.default = 2
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Flag, "congestion", translate("Congestion"))
|
||||
o:depends("transport", "kcp")
|
||||
o = s:option(Flag, 'congestion', translate('Congestion'))
|
||||
o:depends('transport', 'kcp')
|
||||
o.rmempty = true
|
||||
|
||||
-- [[ allowInsecure ]]--
|
||||
o = s:option(Flag, "insecure", translate("allowInsecure"))
|
||||
o = s:option(Flag, 'insecure', translate('allowInsecure'))
|
||||
o.rmempty = true
|
||||
o:depends("type", "v2ray")
|
||||
o:depends("type", "trojan")
|
||||
o:depends('type', 'v2ray')
|
||||
o:depends('type', 'trojan')
|
||||
|
||||
-- [[ TLS ]]--
|
||||
o = s:option(Flag, "tls", translate("TLS"))
|
||||
o = s:option(Flag, 'tls', translate('TLS'))
|
||||
o.rmempty = true
|
||||
o.default = "0"
|
||||
o:depends("type", "v2ray")
|
||||
o:depends("type", "trojan")
|
||||
o.default = '0'
|
||||
o:depends('type', 'v2ray')
|
||||
o:depends('type', 'trojan')
|
||||
|
||||
-- [[ Mux ]]--
|
||||
o = s:option(Flag, "mux", translate("Mux"))
|
||||
o = s:option(Flag, 'mux', translate('Mux'))
|
||||
o.rmempty = true
|
||||
o.default = "0"
|
||||
o:depends("type", "v2ray")
|
||||
o.default = '0'
|
||||
o:depends('type', 'v2ray')
|
||||
|
||||
o = s:option(Value, "concurrency", translate("Concurrency"))
|
||||
o.datatype = "uinteger"
|
||||
o = s:option(Value, 'concurrency', translate('Concurrency'))
|
||||
o.datatype = 'uinteger'
|
||||
o.rmempty = true
|
||||
o.default = "8"
|
||||
o:depends("mux", "1")
|
||||
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
|
||||
o.default = '8'
|
||||
o:depends('mux', '1')
|
||||
o = s:option(Flag, 'fast_open', translate('TCP Fast Open'))
|
||||
o.rmempty = true
|
||||
o.default = "0"
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "ss")
|
||||
o:depends("type", "trojan")
|
||||
o.default = '0'
|
||||
o:depends('type', 'ssr')
|
||||
o:depends('type', 'ss')
|
||||
o:depends('type', 'trojan')
|
||||
|
||||
o = s:option(Flag, "switch_enable", translate("Enable Auto Switch"))
|
||||
o = s:option(Flag, 'switch_enable', translate('Enable Auto Switch'))
|
||||
o.rmempty = false
|
||||
o.default = "1"
|
||||
o.default = '1'
|
||||
|
||||
o = s:option(Value, "local_port", translate("Local Port"))
|
||||
o.datatype = "port"
|
||||
o = s:option(Value, 'local_port', translate('Local Port'))
|
||||
o.datatype = 'port'
|
||||
o.default = 1234
|
||||
o.rmempty = false
|
||||
|
||||
if nixio.fs.access("/usr/bin/kcptun-client") then
|
||||
|
||||
kcp_enable = s:option(Flag, "kcp_enable", translate("KcpTun Enable"),
|
||||
translate("bin:/usr/bin/kcptun-client"))
|
||||
if nixio.fs.access('/usr/bin/kcptun-client') then
|
||||
kcp_enable = s:option(Flag, 'kcp_enable', translate('KcpTun Enable'), translate('bin:/usr/bin/kcptun-client'))
|
||||
kcp_enable.rmempty = true
|
||||
kcp_enable.default = "0"
|
||||
kcp_enable:depends("type", "ssr")
|
||||
kcp_enable:depends("type", "ss")
|
||||
kcp_enable.default = '0'
|
||||
kcp_enable:depends('type', 'ssr')
|
||||
kcp_enable:depends('type', 'ss')
|
||||
|
||||
o = s:option(Value, "kcp_port", translate("KcpTun Port"))
|
||||
o.datatype = "port"
|
||||
o = s:option(Value, 'kcp_port', translate('KcpTun Port'))
|
||||
o.datatype = 'port'
|
||||
o.default = 4000
|
||||
function o.validate(self, value, section)
|
||||
local kcp_file = "/usr/bin/kcptun-client"
|
||||
local kcp_file = '/usr/bin/kcptun-client'
|
||||
local enable = kcp_enable:formvalue(section) or kcp_enable.disabled
|
||||
if enable == kcp_enable.enabled then
|
||||
if not fs.access(kcp_file) then
|
||||
return nil, translate("Haven't a Kcptun executable file")
|
||||
elseif not isKcptun(kcp_file) then
|
||||
return nil, translate("Not a Kcptun executable file")
|
||||
return nil, translate('Not a Kcptun executable file')
|
||||
end
|
||||
end
|
||||
|
||||
return value
|
||||
end
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "ss")
|
||||
o:depends('type', 'ssr')
|
||||
o:depends('type', 'ss')
|
||||
|
||||
o = s:option(Value, "kcp_password", translate("KcpTun Password"))
|
||||
o = s:option(Value, 'kcp_password', translate('KcpTun Password'))
|
||||
o.password = true
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "ss")
|
||||
|
||||
o = s:option(Value, "kcp_param", translate("KcpTun Param"))
|
||||
o.default = "--nocomp"
|
||||
o:depends("type", "ssr")
|
||||
o:depends("type", "ss")
|
||||
o:depends('type', 'ssr')
|
||||
o:depends('type', 'ss')
|
||||
|
||||
o = s:option(Value, 'kcp_param', translate('KcpTun Param'))
|
||||
o.default = '--nocomp'
|
||||
o:depends('type', 'ssr')
|
||||
o:depends('type', 'ss')
|
||||
end
|
||||
|
||||
return m
|
||||
|
||||
@ -2,151 +2,188 @@
|
||||
-- Copyright (C) 2018 lean <coolsnowwolf@gmail.com> github.com/coolsnowwolf
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
local m, s, sec, o, kcp_enable
|
||||
local vssr = "vssr"
|
||||
local vssr = 'vssr'
|
||||
local gfwmode = 0
|
||||
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/gfw_list.conf") then gfwmode = 1 end
|
||||
if nixio.fs.access('/etc/dnsmasq.ssr/gfw_list.conf') then
|
||||
gfwmode = 1
|
||||
end
|
||||
|
||||
local uci = luci.model.uci.cursor()
|
||||
|
||||
m = Map(vssr)
|
||||
|
||||
m:section(SimpleSection).template = "vssr/status_top"
|
||||
m:section(SimpleSection).template = 'vssr/status_top'
|
||||
|
||||
local server_table = {}
|
||||
local tw_table = {}
|
||||
local tvb_table = {}
|
||||
uci:foreach(vssr, "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
|
||||
|
||||
if s.flag == "tw" then
|
||||
uci:foreach(
|
||||
vssr,
|
||||
'servers',
|
||||
function(s)
|
||||
if s.alias then
|
||||
tw_table[s[".name"]] = "[%s]:%s" % {string.upper(s.type), s.alias}
|
||||
server_table[s['.name']] = '[%s]:%s' % {string.upper(s.type), s.alias}
|
||||
elseif s.server and s.server_port then
|
||||
tw_table[s[".name"]] = "[%s]:%s:%s" %
|
||||
{
|
||||
string.upper(s.type), s.server, s.server_port
|
||||
server_table[s['.name']] =
|
||||
'[%s]:%s:%s' %
|
||||
{
|
||||
string.upper(s.type),
|
||||
s.server,
|
||||
s.server_port
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
if s.flag == "hk" then
|
||||
if s.alias then
|
||||
tvb_table[s[".name"]] = "[%s]:%s" % {string.upper(s.type), s.alias}
|
||||
elseif s.server and s.server_port then
|
||||
tvb_table[s[".name"]] = "[%s]:%s:%s" %
|
||||
{
|
||||
string.upper(s.type), s.server, s.server_port
|
||||
}
|
||||
if s.flag == 'tw' then
|
||||
if s.alias then
|
||||
tw_table[s['.name']] = '[%s]:%s' % {string.upper(s.type), s.alias}
|
||||
elseif s.server and s.server_port then
|
||||
tw_table[s['.name']] =
|
||||
'[%s]:%s:%s' %
|
||||
{
|
||||
string.upper(s.type),
|
||||
s.server,
|
||||
s.server_port
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
if s.flag == 'hk' then
|
||||
if s.alias then
|
||||
tvb_table[s['.name']] = '[%s]:%s' % {string.upper(s.type), s.alias}
|
||||
elseif s.server and s.server_port then
|
||||
tvb_table[s['.name']] =
|
||||
'[%s]:%s:%s' %
|
||||
{
|
||||
string.upper(s.type),
|
||||
s.server,
|
||||
s.server_port
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
)
|
||||
|
||||
local key_table = {}
|
||||
for key, _ in pairs(server_table) do table.insert(key_table, key) end
|
||||
for key, _ in pairs(server_table) do
|
||||
table.insert(key_table, key)
|
||||
end
|
||||
|
||||
local key_table_tw = {}
|
||||
for key, _ in pairs(tw_table) do table.insert(key_table_tw, key) end
|
||||
for key, _ in pairs(tw_table) do
|
||||
table.insert(key_table_tw, key)
|
||||
end
|
||||
|
||||
local key_table_tvb = {}
|
||||
for key, _ in pairs(tvb_table) do table.insert(key_table_tvb, key) end
|
||||
for key, _ in pairs(tvb_table) do
|
||||
table.insert(key_table_tvb, key)
|
||||
end
|
||||
|
||||
table.sort(key_table)
|
||||
table.sort(key_table_tw)
|
||||
table.sort(key_table_tvb)
|
||||
local route_name = {
|
||||
"youtube_server", "tw_video_server", "netflix_server", "disney_server",
|
||||
"prime_server", "tvb_server", "custom_server"
|
||||
'youtube_server',
|
||||
'tw_video_server',
|
||||
'netflix_server',
|
||||
'disney_server',
|
||||
'prime_server',
|
||||
'tvb_server',
|
||||
'custom_server'
|
||||
}
|
||||
local route_label = {
|
||||
"Youtube Proxy", "TaiWan Video Proxy", "Netflix Proxy", "Diseny+ Proxy",
|
||||
"Prime Video Proxy", "TVB Video Proxy", "Custom Proxy"
|
||||
'Youtube Proxy',
|
||||
'TaiWan Video Proxy',
|
||||
'Netflix Proxy',
|
||||
'Diseny+ Proxy',
|
||||
'Prime Video Proxy',
|
||||
'TVB Video Proxy',
|
||||
'Custom Proxy'
|
||||
}
|
||||
|
||||
-- [[ Global Setting ]]--
|
||||
s = m:section(TypedSection, "global",
|
||||
translate("Basic Settings [SS|SSR|V2ray|Trojan]"))
|
||||
s = m:section(TypedSection, 'global', translate('Basic Settings [SS|SSR|V2ray|Trojan]'))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(ListValue, "global_server", translate("Main Server"))
|
||||
o:value("nil", translate("Disable"))
|
||||
for _, key in pairs(key_table) do o:value(key, server_table[key]) end
|
||||
o.default = "nil"
|
||||
o = s:option(ListValue, 'global_server', translate('Main Server'))
|
||||
o:value('nil', translate('Disable'))
|
||||
for _, key in pairs(key_table) do
|
||||
o:value(key, server_table[key])
|
||||
end
|
||||
o.default = 'nil'
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "udp_relay_server", translate("Game Mode UDP Server"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("same", translate("Same as Main Server"))
|
||||
for _, key in pairs(key_table) do o:value(key, server_table[key]) end
|
||||
o = s:option(ListValue, 'udp_relay_server', translate('Game Mode UDP Server'))
|
||||
o:value('', translate('Disable'))
|
||||
o:value('same', translate('Same as Main Server'))
|
||||
for _, key in pairs(key_table) do
|
||||
o:value(key, server_table[key])
|
||||
end
|
||||
|
||||
o = s:option(Flag, "v2ray_flow", translate("Open v2ray route"))
|
||||
o = s:option(Flag, 'v2ray_flow', translate('Open v2ray route'))
|
||||
o.rmempty = false
|
||||
o.description = translate("When open v2ray routed,Apply may take more time.")
|
||||
o.description = translate('When open v2ray routed,Apply may take more time.')
|
||||
|
||||
for i, v in pairs(route_name) do
|
||||
o = s:option(ListValue, v, translate(route_label[i]))
|
||||
o:value("nil", translate("Same as Main Server"))
|
||||
if (v == "tw_video_server") then
|
||||
for _, key in pairs(key_table_tw) do o:value(key, tw_table[key]) end
|
||||
elseif (v == "tvb_server") then
|
||||
o:value('nil', translate('Same as Main Server'))
|
||||
if (v == 'tw_video_server') then
|
||||
for _, key in pairs(key_table_tw) do
|
||||
o:value(key, tw_table[key])
|
||||
end
|
||||
elseif (v == 'tvb_server') then
|
||||
for _, key in pairs(key_table_tvb) do
|
||||
o:value(key, tvb_table[key])
|
||||
end
|
||||
else
|
||||
for _, key in pairs(key_table) do o:value(key, server_table[key]) end
|
||||
for _, key in pairs(key_table) do
|
||||
o:value(key, server_table[key])
|
||||
end
|
||||
end
|
||||
o:depends("v2ray_flow", "1")
|
||||
o.default = "nil"
|
||||
o:depends('v2ray_flow', '1')
|
||||
o.default = 'nil'
|
||||
end
|
||||
|
||||
o = s:option(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.default = "0"
|
||||
o = s:option(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.default = '0'
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "run_mode", translate("Running Mode"))
|
||||
o:value("gfw", translate("GFW List Mode"))
|
||||
o:value("router", translate("IP Route Mode"))
|
||||
o:value("all", translate("Global Mode"))
|
||||
o:value("oversea", translate("Oversea Mode"))
|
||||
o.default = "router"
|
||||
o = s:option(ListValue, "dports", translate("Proxy Ports"))
|
||||
o:value("1", translate("All Ports"))
|
||||
o:value("2", translate("Only Common Ports"))
|
||||
o = s:option(ListValue, 'run_mode', translate('Running Mode'))
|
||||
o:value('gfw', translate('GFW List Mode'))
|
||||
o:value('router', translate('IP Route Mode'))
|
||||
o:value('all', translate('Global Mode'))
|
||||
o:value('oversea', translate('Oversea Mode'))
|
||||
o.default = 'router'
|
||||
o = s:option(ListValue, 'dports', translate('Proxy Ports'))
|
||||
o:value('1', translate('All Ports'))
|
||||
o:value('2', translate('Only Common Ports'))
|
||||
o.default = 1
|
||||
|
||||
o = s:option(ListValue, "pdnsd_enable", translate("Resolve Dns Mode"))
|
||||
o:value("1", translate("Use Pdnsd tcp query and cache"))
|
||||
o:value("0", translate("Use Local DNS Service listen port 5335"))
|
||||
o = s:option(ListValue, 'pdnsd_enable', translate('Resolve Dns Mode'))
|
||||
o:value('1', translate('Use Pdnsd tcp query and cache'))
|
||||
o:value('0', translate('Use Local DNS Service listen port 5335'))
|
||||
o.default = 1
|
||||
|
||||
o = s:option(Value, "tunnel_forward", translate("Anti-pollution DNS Server"))
|
||||
o:value("8.8.4.4:53", translate("Google Public DNS (8.8.4.4)"))
|
||||
o:value("8.8.8.8:53", translate("Google Public DNS (8.8.8.8)"))
|
||||
o:value("208.67.222.222:53", translate("OpenDNS (208.67.222.222)"))
|
||||
o:value("208.67.220.220:53", translate("OpenDNS (208.67.220.220)"))
|
||||
o:value("209.244.0.3:53", translate("Level 3 Public DNS (209.244.0.3)"))
|
||||
o:value("209.244.0.4:53", translate("Level 3 Public DNS (209.244.0.4)"))
|
||||
o:value("4.2.2.1:53", translate("Level 3 Public DNS (4.2.2.1)"))
|
||||
o:value("4.2.2.2:53", translate("Level 3 Public DNS (4.2.2.2)"))
|
||||
o:value("4.2.2.3:53", translate("Level 3 Public DNS (4.2.2.3)"))
|
||||
o:value("4.2.2.4:53", translate("Level 3 Public DNS (4.2.2.4)"))
|
||||
o:value("1.1.1.1:53", translate("Cloudflare DNS (1.1.1.1)"))
|
||||
o:value("114.114.114.114:53", translate("Oversea Mode DNS-1 (114.114.114.114)"))
|
||||
o:value("114.114.115.115:53", translate("Oversea Mode DNS-2 (114.114.115.115)"))
|
||||
o:depends("pdnsd_enable", "1")
|
||||
o = s:option(Value, 'tunnel_forward', translate('Anti-pollution DNS Server'))
|
||||
o:value('8.8.4.4:53', translate('Google Public DNS (8.8.4.4)'))
|
||||
o:value('8.8.8.8:53', translate('Google Public DNS (8.8.8.8)'))
|
||||
o:value('208.67.222.222:53', translate('OpenDNS (208.67.222.222)'))
|
||||
o:value('208.67.220.220:53', translate('OpenDNS (208.67.220.220)'))
|
||||
o:value('209.244.0.3:53', translate('Level 3 Public DNS (209.244.0.3)'))
|
||||
o:value('209.244.0.4:53', translate('Level 3 Public DNS (209.244.0.4)'))
|
||||
o:value('4.2.2.1:53', translate('Level 3 Public DNS (4.2.2.1)'))
|
||||
o:value('4.2.2.2:53', translate('Level 3 Public DNS (4.2.2.2)'))
|
||||
o:value('4.2.2.3:53', translate('Level 3 Public DNS (4.2.2.3)'))
|
||||
o:value('4.2.2.4:53', translate('Level 3 Public DNS (4.2.2.4)'))
|
||||
o:value('1.1.1.1:53', translate('Cloudflare DNS (1.1.1.1)'))
|
||||
o:value('114.114.114.114:53', translate('Oversea Mode DNS-1 (114.114.114.114)'))
|
||||
o:value('114.114.115.115:53', translate('Oversea Mode DNS-2 (114.114.115.115)'))
|
||||
o:depends('pdnsd_enable', '1')
|
||||
|
||||
m:section(SimpleSection).template = "vssr/status_bottom"
|
||||
m:section(SimpleSection).template = 'vssr/status_bottom'
|
||||
return m
|
||||
|
||||
@ -1,45 +1,55 @@
|
||||
local m, s, o
|
||||
local NXFS = require "nixio.fs"
|
||||
local NXFS = require 'nixio.fs'
|
||||
|
||||
m = Map("vssr", translate("IP black-and-white list"))
|
||||
m = Map('vssr', translate('IP black-and-white list'))
|
||||
|
||||
s = m:section(TypedSection, "access_control")
|
||||
s = m:section(TypedSection, 'access_control')
|
||||
s.anonymous = true
|
||||
|
||||
-- Part of WAN
|
||||
s:tab("wan_ac", translate("WAN IP AC"))
|
||||
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_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"
|
||||
o = s:taboption('wan_ac', DynamicList, 'wan_fw_ips', translate('WAN Force Proxy IP'))
|
||||
o.datatype = 'ip4addr'
|
||||
|
||||
-- Part of LAN
|
||||
s:tab("lan_ac", translate("LAN IP AC"))
|
||||
s:tab('lan_ac', translate('LAN IP AC'))
|
||||
|
||||
o = s:taboption("lan_ac", DynamicList, "lan_ac_ips",
|
||||
translate("LAN Bypassed 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_ac_ips', translate('LAN Bypassed 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_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_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)
|
||||
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
|
||||
)
|
||||
|
||||
-- Part of Self
|
||||
-- s:tab("self_ac", translate("Router Self AC"))
|
||||
@ -49,36 +59,43 @@ end)
|
||||
-- o:value("2", translatef("Forwarded Proxy"))
|
||||
-- o.rmempty = false
|
||||
|
||||
s:tab("esc", translate("Bypass Domain List"))
|
||||
s:tab('esc', translate('Bypass Domain List'))
|
||||
|
||||
local escconf = "/etc/config/white.list"
|
||||
o = s:taboption("esc", TextValue, "escconf")
|
||||
local escconf = '/etc/config/white.list'
|
||||
o = s:taboption('esc', TextValue, 'escconf')
|
||||
o.rows = 13
|
||||
o.wrap = "off"
|
||||
o.wrap = 'off'
|
||||
o.rmempty = true
|
||||
o.cfgvalue = function(self, section) return NXFS.readfile(escconf) or "" end
|
||||
o.write = function(self, section, value)
|
||||
NXFS.writefile(escconf, value:gsub("\r\n", "\n"))
|
||||
o.cfgvalue = function(self, section)
|
||||
return NXFS.readfile(escconf) or ''
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
NXFS.writefile(escconf, value:gsub('\r\n', '\n'))
|
||||
end
|
||||
o.remove = function(self, section, value)
|
||||
NXFS.writefile(escconf, '')
|
||||
end
|
||||
o.remove = function(self, section, value) NXFS.writefile(escconf, "") end
|
||||
|
||||
s:tab("block", translate("Black Domain List"))
|
||||
s:tab('block', translate('Black Domain List'))
|
||||
|
||||
local blockconf = "/etc/config/black.list"
|
||||
o = s:taboption("block", TextValue, "blockconf")
|
||||
local blockconf = '/etc/config/black.list'
|
||||
o = s:taboption('block', TextValue, 'blockconf')
|
||||
o.rows = 13
|
||||
o.wrap = "off"
|
||||
o.wrap = 'off'
|
||||
o.rmempty = true
|
||||
o.cfgvalue = function(self, section) return NXFS.readfile(blockconf) or " " end
|
||||
o.write = function(self, section, value)
|
||||
NXFS.writefile(blockconf, value:gsub("\r\n", "\n"))
|
||||
o.cfgvalue = function(self, section)
|
||||
return NXFS.readfile(blockconf) or ' '
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
NXFS.writefile(blockconf, value:gsub('\r\n', '\n'))
|
||||
end
|
||||
o.remove = function(self, section, value)
|
||||
NXFS.writefile(blockconf, '')
|
||||
end
|
||||
o.remove = function(self, section, value) NXFS.writefile(blockconf, "") end
|
||||
|
||||
s:tab("proxy", translate("Custom Proxy Domain Name"))
|
||||
s:tab('proxy', translate('Custom Proxy Domain Name'))
|
||||
|
||||
o = s:taboption("proxy", DynamicList, "proxy_domain_name",
|
||||
translate("Proxy Domain Name"))
|
||||
o.datatype = "hostname"
|
||||
o = s:taboption('proxy', DynamicList, 'proxy_domain_name', translate('Proxy Domain Name'))
|
||||
o.datatype = 'hostname'
|
||||
|
||||
return m
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
local fs = require "nixio.fs"
|
||||
local conffile = "/tmp/ssrpro.log"
|
||||
local fs = require 'nixio.fs'
|
||||
local conffile = '/tmp/ssrpro.log'
|
||||
|
||||
f = SimpleForm("logview")
|
||||
f = SimpleForm('logview')
|
||||
|
||||
t = f:field(TextValue, "conf")
|
||||
t = f:field(TextValue, 'conf')
|
||||
t.rmempty = true
|
||||
t.rows = 20
|
||||
function t.cfgvalue()
|
||||
luci.sys.exec(
|
||||
"[ -f /tmp/vssr.log ] && sed '1!G;h;$!d' /tmp/vssr.log > /tmp/ssrpro.log")
|
||||
return fs.readfile(conffile) or ""
|
||||
luci.sys.exec("[ -f /tmp/vssr.log ] && sed '1!G;h;$!d' /tmp/vssr.log > /tmp/ssrpro.log")
|
||||
return fs.readfile(conffile) or ''
|
||||
end
|
||||
t.readonly = "readonly"
|
||||
t.readonly = 'readonly'
|
||||
|
||||
return f
|
||||
|
||||
@ -1,67 +1,90 @@
|
||||
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
local m, s, o
|
||||
local vssr = "vssr"
|
||||
local vssr = 'vssr'
|
||||
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"
|
||||
'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 protocol = {"origin"}
|
||||
local protocol = {'origin'}
|
||||
|
||||
obfs = {"plain", "http_simple", "http_post"}
|
||||
obfs = {'plain', 'http_simple', 'http_post'}
|
||||
|
||||
m = Map(vssr, translate("Edit vssr Server"))
|
||||
m = Map(vssr, translate('Edit vssr Server'))
|
||||
|
||||
m.redirect = luci.dispatcher.build_url("admin/services/vssr/server")
|
||||
if m.uci:get(vssr, sid) ~= "server_config" then
|
||||
m.redirect = luci.dispatcher.build_url('admin/services/vssr/server')
|
||||
if m.uci:get(vssr, sid) ~= 'server_config' then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
-- [[ Server Setting ]]--
|
||||
s = m:section(NamedSection, sid, "server_config")
|
||||
s = m:section(NamedSection, sid, 'server_config')
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(Flag, "enable", translate("Enable"))
|
||||
o = s:option(Flag, 'enable', translate('Enable'))
|
||||
o.default = 1
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server_port", translate("Server Port"))
|
||||
o.datatype = "port"
|
||||
o = s:option(Value, 'server_port', translate('Server Port'))
|
||||
o.datatype = 'port'
|
||||
o.default = 8388
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "timeout", translate("Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o = s:option(Value, 'timeout', translate('Connection Timeout'))
|
||||
o.datatype = 'uinteger'
|
||||
o.default = 60
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "password", translate("Password"))
|
||||
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 = s:option(ListValue, 'encrypt_method', translate('Encrypt Method'))
|
||||
for _, v in ipairs(encrypt_methods) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "protocol", translate("Protocol"))
|
||||
for _, v in ipairs(protocol) do o:value(v) end
|
||||
o = s:option(ListValue, 'protocol', translate('Protocol'))
|
||||
for _, v in ipairs(protocol) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "obfs", translate("Obfs"))
|
||||
for _, v in ipairs(obfs) do o:value(v) end
|
||||
o = s:option(ListValue, 'obfs', translate('Obfs'))
|
||||
for _, v in ipairs(obfs) do
|
||||
o:value(v)
|
||||
end
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "obfs_param", translate("Obfs param(optional)"))
|
||||
o = s:option(Value, 'obfs_param', translate('Obfs param(optional)'))
|
||||
|
||||
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
|
||||
o = s:option(Flag, 'fast_open', translate('TCP Fast Open'))
|
||||
o.rmempty = false
|
||||
|
||||
return m
|
||||
|
||||
@ -1,43 +1,68 @@
|
||||
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
local m, sec, o
|
||||
local vssr = "vssr"
|
||||
local vssr = 'vssr'
|
||||
local uci = luci.model.uci.cursor()
|
||||
local ipkg = require("luci.model.ipkg")
|
||||
local ipkg = require('luci.model.ipkg')
|
||||
|
||||
m = Map(vssr, translate("vssr Server"))
|
||||
m = Map(vssr, translate('vssr Server'))
|
||||
|
||||
local encrypt_methods = {
|
||||
"table", "rc4", "rc4-md5", "rc4-md5-6", "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"
|
||||
'table',
|
||||
'rc4',
|
||||
'rc4-md5',
|
||||
'rc4-md5-6',
|
||||
'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 protocol = {
|
||||
"origin", "verify_deflate", "auth_sha1_v4", "auth_aes128_sha1",
|
||||
"auth_aes128_md5", "auth_chain_a"
|
||||
'origin',
|
||||
'verify_deflate',
|
||||
'auth_sha1_v4',
|
||||
'auth_aes128_sha1',
|
||||
'auth_aes128_md5',
|
||||
'auth_chain_a'
|
||||
}
|
||||
|
||||
obfs = {
|
||||
"plain", "http_simple", "http_post", "random_head", "tls1.2_ticket_auth",
|
||||
"tls1.2_ticket_fastauth"
|
||||
'plain',
|
||||
'http_simple',
|
||||
'http_post',
|
||||
'random_head',
|
||||
'tls1.2_ticket_auth',
|
||||
'tls1.2_ticket_fastauth'
|
||||
}
|
||||
|
||||
-- [[ Global Setting ]]--
|
||||
sec = m:section(TypedSection, "server_global", translate("Global Setting"))
|
||||
sec = m:section(TypedSection, 'server_global', translate('Global Setting'))
|
||||
sec.anonymous = true
|
||||
|
||||
o = sec:option(Flag, "enable_server", translate("Enable Server"))
|
||||
o = sec:option(Flag, 'enable_server', translate('Enable Server'))
|
||||
o.rmempty = false
|
||||
|
||||
-- [[ Server Setting ]]--
|
||||
sec = m:section(TypedSection, "server_config", translate("Server Setting"))
|
||||
sec = m:section(TypedSection, 'server_config', translate('Server Setting'))
|
||||
sec.anonymous = true
|
||||
sec.addremove = true
|
||||
sec.template = "cbi/tblsection"
|
||||
sec.extedit = luci.dispatcher.build_url("admin/services/vssr/server/%s")
|
||||
sec.template = 'cbi/tblsection'
|
||||
sec.extedit = luci.dispatcher.build_url('admin/services/vssr/server/%s')
|
||||
function sec.create(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
@ -46,23 +71,31 @@ function sec.create(...)
|
||||
end
|
||||
end
|
||||
|
||||
o = sec:option(Flag, "enable", translate("Enable"))
|
||||
function o.cfgvalue(...) return Value.cfgvalue(...) or translate("0") end
|
||||
o = sec:option(Flag, 'enable', translate('Enable'))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or translate('0')
|
||||
end
|
||||
o.rmempty = false
|
||||
|
||||
o = sec:option(DummyValue, "server_port", translate("Server Port"))
|
||||
function o.cfgvalue(...) return Value.cfgvalue(...) or "?" end
|
||||
|
||||
o = sec:option(DummyValue, "encrypt_method", translate("Encrypt Method"))
|
||||
o = sec:option(DummyValue, 'server_port', translate('Server Port'))
|
||||
function o.cfgvalue(...)
|
||||
local v = Value.cfgvalue(...)
|
||||
return v and v:upper() or "?"
|
||||
return Value.cfgvalue(...) or '?'
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "protocol", translate("Protocol"))
|
||||
function o.cfgvalue(...) return Value.cfgvalue(...) or "?" end
|
||||
o = sec:option(DummyValue, 'encrypt_method', translate('Encrypt Method'))
|
||||
function o.cfgvalue(...)
|
||||
local v = Value.cfgvalue(...)
|
||||
return v and v:upper() or '?'
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "obfs", translate("Obfs"))
|
||||
function o.cfgvalue(...) return Value.cfgvalue(...) or "?" end
|
||||
o = sec:option(DummyValue, 'protocol', translate('Protocol'))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or '?'
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, 'obfs', translate('Obfs'))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or '?'
|
||||
end
|
||||
|
||||
return m
|
||||
|
||||
@ -1,35 +1,45 @@
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
local m, s, o
|
||||
local vssr = "vssr"
|
||||
local json = require "luci.jsonc"
|
||||
local vssr = 'vssr'
|
||||
local json = require 'luci.jsonc'
|
||||
|
||||
local uci = luci.model.uci.cursor()
|
||||
local server_count = 0
|
||||
local server_table = {}
|
||||
uci:foreach("vssr", "servers", function(s)
|
||||
server_count = server_count + 1
|
||||
s["name"] = s[".name"]
|
||||
table.insert(server_table, s)
|
||||
end)
|
||||
uci:foreach(
|
||||
'vssr',
|
||||
'servers',
|
||||
function(s)
|
||||
server_count = server_count + 1
|
||||
s['name'] = s['.name']
|
||||
table.insert(server_table, s)
|
||||
end
|
||||
)
|
||||
|
||||
local name = ""
|
||||
uci:foreach("vssr", "global", function(s) name = s[".name"] end)
|
||||
local name = ''
|
||||
uci:foreach(
|
||||
'vssr',
|
||||
'global',
|
||||
function(s)
|
||||
name = s['.name']
|
||||
end
|
||||
)
|
||||
|
||||
m = Map(vssr)
|
||||
|
||||
m:section(SimpleSection).template = "vssr/status_top"
|
||||
m:section(SimpleSection).template = 'vssr/status_top'
|
||||
|
||||
-- [[ Servers List ]]--
|
||||
s = m:section(TypedSection, "servers")
|
||||
s = m:section(TypedSection, 'servers')
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
s.sortable = false
|
||||
|
||||
s.des = server_count
|
||||
s.current = uci:get("vssr", name, "global_server")
|
||||
s.current = uci:get('vssr', name, 'global_server')
|
||||
s.servers = json.stringify(server_table)
|
||||
s.template = "vssr/tblsection"
|
||||
s.extedit = luci.dispatcher.build_url("admin/services/vssr/servers/%s")
|
||||
s.template = 'vssr/tblsection'
|
||||
s.extedit = luci.dispatcher.build_url('admin/services/vssr/servers/%s')
|
||||
function s.create(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
@ -38,6 +48,6 @@ function s.create(...)
|
||||
end
|
||||
end
|
||||
|
||||
m:section(SimpleSection).template = "vssr/status_bottom"
|
||||
m:section(SimpleSection).template = 'vssr/status_bottom'
|
||||
|
||||
return m
|
||||
|
||||
@ -1,38 +1,37 @@
|
||||
local vssr = "vssr"
|
||||
local vssr = 'vssr'
|
||||
local uci = luci.model.uci.cursor()
|
||||
local server_table = {}
|
||||
|
||||
local sys = require "luci.sys"
|
||||
local sys = require 'luci.sys'
|
||||
|
||||
m = Map(vssr)
|
||||
|
||||
-- [[ SOCKS5 Proxy ]]--
|
||||
if nixio.fs.access("/usr/bin/v2ray/v2ray") then
|
||||
s = m:section(TypedSection, "socks5_proxy", translate("V2ray SOCKS5 Proxy"))
|
||||
if nixio.fs.access('/usr/bin/v2ray/v2ray') then
|
||||
s = m:section(TypedSection, 'socks5_proxy', translate('V2ray SOCKS5 Proxy'))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "enable_server", translate("Enable Servers"))
|
||||
o = s:option(Flag, 'enable_server', translate('Enable Servers'))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "enable_auth", translate("Enable Auth"))
|
||||
o = s:option(Flag, 'enable_auth', translate('Enable Auth'))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "Socks_user", translate("Socks user"))
|
||||
o.default = "user"
|
||||
o = s:option(Value, 'Socks_user', translate('Socks user'))
|
||||
o.default = 'user'
|
||||
o.rmempty = true
|
||||
o:depends("enable_auth", "1")
|
||||
o:depends('enable_auth', '1')
|
||||
|
||||
o = s:option(Value, "Socks_pass", translate("Socks pass"))
|
||||
o.default = "password"
|
||||
o = s:option(Value, 'Socks_pass', translate('Socks pass'))
|
||||
o.default = 'password'
|
||||
o.password = true
|
||||
o.rmempty = true
|
||||
o:depends("enable_auth", "1")
|
||||
o:depends('enable_auth', '1')
|
||||
|
||||
o = s:option(Value, "local_port", translate("Local Port"))
|
||||
o.datatype = "port"
|
||||
o = s:option(Value, 'local_port', translate('Local Port'))
|
||||
o.datatype = 'port'
|
||||
o.default = 1080
|
||||
o.rmempty = false
|
||||
|
||||
end
|
||||
|
||||
return m
|
||||
|
||||
@ -151,7 +151,6 @@ start() {
|
||||
#当前代理错误,判断有无可用的服务器
|
||||
#echo "current error"
|
||||
echo "$(date "+%Y-%m-%d %H:%M:%S") 当前节点不可用,尝试切换其他节点。" >>/tmp/vssr.log
|
||||
|
||||
select_proxy
|
||||
if [ "$ENABLE_SERVER" != nil ]; then
|
||||
#有其他服务器可用,进行切换
|
||||
|
||||
@ -10,11 +10,9 @@ local _M = {}
|
||||
-- Return String:iso_code
|
||||
function _M.get_flag(remark, host)
|
||||
local nixio = require "nixio"
|
||||
local ip = require "luci.ip"
|
||||
|
||||
local iso_table = {
|
||||
"US", "US", "US", "US", "US", "HK", "HK", "TW", "TW", "TW", "TW", "TW",
|
||||
"JP", "JP", "JP", "GB", "GB", "DE", "DE", "FR", "IN", "TR", "SG", "SG",
|
||||
"US", "US", "US", "US", "US", "HK", "HK", "TW", "TW", "TW", "TW", "TW",
|
||||
"JP", "JP", "JP", "GB", "GB", "DE", "DE", "FR", "IN", "TR", "SG", "SG",
|
||||
"KR", "KR", "KR", "KR", "RU", "IE", "CA", "CA", "AU", "CH", "AU", "AR","RU",
|
||||
"AC", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS",
|
||||
"AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH",
|
||||
@ -41,10 +39,9 @@ function _M.get_flag(remark, host)
|
||||
}
|
||||
|
||||
local emoji_table = {
|
||||
"美国", "US", "洛杉矶","芝加哥","达拉斯", "香港","HK", "台湾", "TW", "TAIWAN","彰化","台北",
|
||||
"日本", "JP", "JAPAN", "英国", "UK", "德国", "DE", "法国", "印度", "土耳其", "新加坡", "SG",
|
||||
"美国", "US", "洛杉矶","芝加哥","达拉斯", "香港","HK", "台湾", "TW", "TAIWAN","彰化","台北",
|
||||
"日本", "JP", "JAPAN", "英国", "UK", "德国", "DE", "法国", "印度", "土耳其", "新加坡", "SG",
|
||||
"韩国", "首尔", "KR", "KOREA", "俄罗斯", "爱尔兰", "CANADA", "加拿大","SYDNEY", "瑞士", "澳大利亚", "阿根廷","RU",
|
||||
|
||||
"🇦🇨", "🇦🇩", "🇦🇪", "🇦🇫", "🇦🇬", "🇦🇮",
|
||||
"🇦🇱", "🇦🇲", "🇦🇴", "🇦🇶", "🇦🇷", "🇦🇸",
|
||||
"🇦🇹", "🇦🇺", "🇦🇼", "🇦🇽", "🇦🇿", "🇧🇦",
|
||||
|
||||
@ -1,22 +1,21 @@
|
||||
local ucursor = require"luci.model.uci".cursor()
|
||||
local json = require "luci.jsonc"
|
||||
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]
|
||||
local host = arg[4]
|
||||
|
||||
local server = ucursor:get_all("vssr", server_section)
|
||||
local server = ucursor:get_all('vssr', server_section)
|
||||
|
||||
local ss = {
|
||||
server = host,
|
||||
server_port = server.server_port,
|
||||
local_address = "0.0.0.0",
|
||||
local_address = '0.0.0.0',
|
||||
local_port = local_port,
|
||||
password = server.password,
|
||||
timeout = (server.timeout ~= nil) and server.timeout or 60,
|
||||
method = server.encrypt_method_ss,
|
||||
reuse_port = true,
|
||||
fast_open = (server.fast_open == "1") and true or false,
|
||||
fast_open = (server.fast_open == '1') and true or false,
|
||||
plugin = (server.plugin ~= nil) and server.plugin or nil,
|
||||
plugin_opts = (server.plugin ~= nil) and server.plugin_opts or nil
|
||||
}
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
local ucursor = require"luci.model.uci".cursor()
|
||||
local json = require "luci.jsonc"
|
||||
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]
|
||||
local host = arg[4]
|
||||
|
||||
local server = ucursor:get_all("vssr", server_section)
|
||||
local server = ucursor:get_all('vssr', server_section)
|
||||
|
||||
local ssr = {
|
||||
server = host,
|
||||
server_port = server.server_port,
|
||||
local_address = "0.0.0.0",
|
||||
local_address = '0.0.0.0',
|
||||
local_port = local_port,
|
||||
password = server.password,
|
||||
timeout = (server.timeout ~= nil) and server.timeout or 60,
|
||||
@ -20,6 +19,6 @@ local ssr = {
|
||||
obfs = server.obfs,
|
||||
obfs_param = server.obfs_param,
|
||||
reuse_port = true,
|
||||
fast_open = (server.fast_open == "1") and true or false
|
||||
fast_open = (server.fast_open == '1') and true or false
|
||||
}
|
||||
print(json.stringify(ssr, 1))
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
local ucursor = require"luci.model.uci".cursor()
|
||||
local json = require "luci.jsonc"
|
||||
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]
|
||||
|
||||
local server = ucursor:get_all("vssr", server_section)
|
||||
local server = ucursor:get_all('vssr', server_section)
|
||||
|
||||
local trojan = {
|
||||
log_level = 3,
|
||||
run_type = proto,
|
||||
local_addr = "0.0.0.0",
|
||||
local_addr = '0.0.0.0',
|
||||
local_port = tonumber(local_port),
|
||||
remote_addr = server.server,
|
||||
remote_port = tonumber(server.server_port),
|
||||
@ -18,14 +18,14 @@ local trojan = {
|
||||
password = {server.password},
|
||||
-- 传出连接
|
||||
ssl = {
|
||||
verify = (server.insecure == "0") and true or false,
|
||||
verify_hostname = (server.tls == "1") and false or true,
|
||||
cert = "",
|
||||
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",
|
||||
cipher_tls13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384",
|
||||
verify = (server.insecure == '0') and true or false,
|
||||
verify_hostname = (server.tls == '1') and false or true,
|
||||
cert = '',
|
||||
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',
|
||||
cipher_tls13 = 'TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384',
|
||||
sni = server.peer,
|
||||
alpn = {"h2", "http/1.1"},
|
||||
curve = "",
|
||||
alpn = {'h2', 'http/1.1'},
|
||||
curve = '',
|
||||
reuse_session = true,
|
||||
session_ticket = false
|
||||
},
|
||||
@ -33,7 +33,7 @@ local trojan = {
|
||||
no_delay = true,
|
||||
keep_alive = true,
|
||||
reuse_port = true,
|
||||
fast_open = (server.fast_open == "1") and true or false,
|
||||
fast_open = (server.fast_open == '1') and true or false,
|
||||
fast_open_qlen = 20
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,129 +1,170 @@
|
||||
local ucursor = require"luci.model.uci".cursor()
|
||||
local name = "vssr"
|
||||
local json = require "luci.jsonc"
|
||||
local ucursor = require 'luci.model.uci'.cursor()
|
||||
local name = 'vssr'
|
||||
local json = require 'luci.jsonc'
|
||||
local server_section = arg[1]
|
||||
local proto = arg[2]
|
||||
local local_port = arg[3]
|
||||
local host = arg[4]
|
||||
local main_port = arg[5]
|
||||
|
||||
local outbounds_table = {}
|
||||
local rules_table = {}
|
||||
|
||||
local v2ray_flow = ucursor:get_first(name, 'global', 'v2ray_flow', '0')
|
||||
local proxy_domain_name = ucursor:get_list(name, "@access_control[0]",
|
||||
"proxy_domain_name")
|
||||
local proxy_domain_name = ucursor:get_list(name, '@access_control[0]', 'proxy_domain_name')
|
||||
local flow_table = {
|
||||
yotube = {
|
||||
name = "youtube",
|
||||
name = 'youtube',
|
||||
port = 2081,
|
||||
rules = {
|
||||
type = "field",
|
||||
type = 'field',
|
||||
domain = {
|
||||
"youtube", "ggpht.com", "googlevideo.com", "withyoutube.com",
|
||||
"youtu.be", "youtube-nocookie.com", "youtube.com",
|
||||
"youtubeeducation.com", "youtubegaming.com",
|
||||
"youtubei.googleapis.com", "youtubekids.com",
|
||||
"youtubemobilesupport.com", "yt.be", "ytimg.com"
|
||||
'youtube',
|
||||
'ggpht.com',
|
||||
'googlevideo.com',
|
||||
'withyoutube.com',
|
||||
'youtu.be',
|
||||
'youtube-nocookie.com',
|
||||
'youtube.com',
|
||||
'youtubeeducation.com',
|
||||
'youtubegaming.com',
|
||||
'youtubei.googleapis.com',
|
||||
'youtubekids.com',
|
||||
'youtubemobilesupport.com',
|
||||
'yt.be',
|
||||
'ytimg.com'
|
||||
},
|
||||
outboundTag = "youtube"
|
||||
outboundTag = 'youtube'
|
||||
}
|
||||
},
|
||||
tw_video = {
|
||||
name = "tw_video",
|
||||
name = 'tw_video',
|
||||
port = 2082,
|
||||
rules = {
|
||||
type = "field",
|
||||
type = 'field',
|
||||
domain = {
|
||||
"vidol.tv", "hinet.net", "books.com", "litv.tv", "pstatic.net",
|
||||
"app-measurement.com", "kktv.com.tw", "gamer.com.tw", "wetv.vip"
|
||||
'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'
|
||||
},
|
||||
outboundTag = "twvideo"
|
||||
outboundTag = 'tw_video'
|
||||
}
|
||||
},
|
||||
netflix = {
|
||||
name = "netflix",
|
||||
name = 'netflix',
|
||||
port = 2083,
|
||||
rules = {
|
||||
type = "field",
|
||||
type = 'field',
|
||||
domain = {
|
||||
"fast.com", "netflix.ca", "netflix.com", "netflix.net",
|
||||
"netflixinvestor.com", "netflixtechblog.com", "nflxext.com",
|
||||
"nflximg.com", "nflximg.net", "nflxsearch.net", "nflxso.net",
|
||||
"nflxvideo.net"
|
||||
'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'
|
||||
},
|
||||
|
||||
outboundTag = "netflix"
|
||||
outboundTag = 'netflix'
|
||||
}
|
||||
},
|
||||
disney = {
|
||||
name = "disney",
|
||||
name = 'disney',
|
||||
port = 2084,
|
||||
rules = {
|
||||
type = "field",
|
||||
type = 'field',
|
||||
domain = {
|
||||
"cdn.registerdisney.go.com", "disneyplus.com",
|
||||
"disney-plus.net", "dssott.com", "bamgrid.com",
|
||||
"execute-api.us-east-1.amazonaws.com"
|
||||
'cdn.registerdisney.go.com',
|
||||
'disneyplus.com',
|
||||
'disney-plus.net',
|
||||
'dssott.com',
|
||||
'bamgrid.com',
|
||||
'execute-api.us-east-1.amazonaws.com'
|
||||
},
|
||||
outboundTag = "disney"
|
||||
outboundTag = 'disney'
|
||||
}
|
||||
},
|
||||
prime = {
|
||||
name = "prime",
|
||||
name = 'prime',
|
||||
port = 2085,
|
||||
rules = {
|
||||
type = "field",
|
||||
type = 'field',
|
||||
domain = {
|
||||
"aiv-cdn.net", "amazonaws.com", "amazonvideo.com", "llnwd.net",
|
||||
"amazonprimevideos.com", "amazonvideo.cc", "prime-video.com",
|
||||
"primevideo.cc", "primevideo.com", "primevideo.info",
|
||||
"primevideo.org", "primevideo.tv"
|
||||
'aiv-cdn.net',
|
||||
'amazonaws.com',
|
||||
'amazonvideo.com',
|
||||
'llnwd.net',
|
||||
'amazonprimevideos.com',
|
||||
'amazonvideo.cc',
|
||||
'prime-video.com',
|
||||
'primevideo.cc',
|
||||
'primevideo.com',
|
||||
'primevideo.info',
|
||||
'primevideo.org',
|
||||
'primevideo.tv'
|
||||
},
|
||||
outboundTag = "prime"
|
||||
outboundTag = 'prime'
|
||||
}
|
||||
},
|
||||
tvb = {
|
||||
name = "tvb",
|
||||
name = 'tvb',
|
||||
port = 2086,
|
||||
rules = {
|
||||
type = "field",
|
||||
domain = {"tvsuper.com", "tvb.com"},
|
||||
outboundTag = "tvb"
|
||||
type = 'field',
|
||||
domain = {'tvsuper.com', 'tvb.com'},
|
||||
outboundTag = 'tvb'
|
||||
}
|
||||
},
|
||||
custom = {
|
||||
name = "custom",
|
||||
name = 'custom',
|
||||
port = 2087,
|
||||
rules = {
|
||||
type = "field",
|
||||
type = 'field',
|
||||
domain = proxy_domain_name,
|
||||
outboundTag = "custom"
|
||||
outboundTag = 'custom'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gen_outbound(server_node, tags, local_ports)
|
||||
local bound = {}
|
||||
if server_node == nil or server_node == "nil" then
|
||||
if server_node == nil or server_node == 'nil' then
|
||||
bound = nil
|
||||
else
|
||||
|
||||
local server = ucursor:get_all(name, server_node)
|
||||
if server.type ~= "v2ray" then
|
||||
if server.type ~= 'v2ray' then
|
||||
bound = {
|
||||
tag = tags,
|
||||
protocol = "socks",
|
||||
protocol = 'socks',
|
||||
settings = {
|
||||
servers = {
|
||||
{address = "127.0.0.1", port = tonumber(local_ports)}
|
||||
{address = '127.0.0.1', port = tonumber(local_ports)}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
bound = {
|
||||
tag = tags,
|
||||
protocol = "vmess",
|
||||
protocol = 'vmess',
|
||||
settings = {
|
||||
vnext = {
|
||||
{
|
||||
@ -142,39 +183,40 @@ function gen_outbound(server_node, tags, local_ports)
|
||||
-- 底层传输配置
|
||||
streamSettings = {
|
||||
network = server.transport,
|
||||
security = (server.tls == '1') and "tls" or "none",
|
||||
security = (server.tls == '1') and 'tls' or 'none',
|
||||
tlsSettings = {
|
||||
allowInsecure = (server.insecure == "1") and true or
|
||||
false,
|
||||
allowInsecure = (server.insecure == '1') and true or false,
|
||||
serverName = server.ws_host
|
||||
},
|
||||
kcpSettings = (server.transport == "kcp") and {
|
||||
mtu = tonumber(server.mtu),
|
||||
tti = tonumber(server.tti),
|
||||
uplinkCapacity = tonumber(server.uplink_capacity),
|
||||
downlinkCapacity = tonumber(server.downlink_capacity),
|
||||
congestion = (server.congestion == "1") and true or
|
||||
false,
|
||||
readBufferSize = tonumber(server.read_buffer_size),
|
||||
writeBufferSize = tonumber(server.write_buffer_size),
|
||||
header = {type = server.kcp_guise}
|
||||
} or nil,
|
||||
wsSettings = (server.transport == "ws") and
|
||||
(server.ws_path ~= nil or server.ws_host ~= nil) and {
|
||||
path = server.ws_path,
|
||||
headers = (server.ws_host ~= nil) and
|
||||
{Host = server.ws_host} or nil
|
||||
} or nil,
|
||||
httpSettings = (server.transport == "h2") and
|
||||
{path = server.h2_path, host = server.h2_host} or nil,
|
||||
quicSettings = (server.transport == "quic") and {
|
||||
security = server.quic_security,
|
||||
key = server.quic_key,
|
||||
header = {type = server.quic_guise}
|
||||
} or nil
|
||||
kcpSettings = (server.transport == 'kcp') and
|
||||
{
|
||||
mtu = tonumber(server.mtu),
|
||||
tti = tonumber(server.tti),
|
||||
uplinkCapacity = tonumber(server.uplink_capacity),
|
||||
downlinkCapacity = tonumber(server.downlink_capacity),
|
||||
congestion = (server.congestion == '1') and true or false,
|
||||
readBufferSize = tonumber(server.read_buffer_size),
|
||||
writeBufferSize = tonumber(server.write_buffer_size),
|
||||
header = {type = server.kcp_guise}
|
||||
} or
|
||||
nil,
|
||||
wsSettings = (server.transport == 'ws') and (server.ws_path ~= nil or server.ws_host ~= nil) and
|
||||
{
|
||||
path = server.ws_path,
|
||||
headers = (server.ws_host ~= nil) and {Host = server.ws_host} or nil
|
||||
} or
|
||||
nil,
|
||||
httpSettings = (server.transport == 'h2') and {path = server.h2_path, host = server.h2_host} or nil,
|
||||
quicSettings = (server.transport == 'quic') and
|
||||
{
|
||||
security = server.quic_security,
|
||||
key = server.quic_key,
|
||||
header = {type = server.quic_guise}
|
||||
} or
|
||||
nil
|
||||
},
|
||||
mux = {
|
||||
enabled = (server.mux == "1") and true or false,
|
||||
enabled = (server.mux == '1') and true or false,
|
||||
concurrency = tonumber(server.concurrency)
|
||||
}
|
||||
}
|
||||
@ -183,39 +225,37 @@ function gen_outbound(server_node, tags, local_ports)
|
||||
return bound
|
||||
end
|
||||
|
||||
if v2ray_flow == "1" then
|
||||
table.insert(outbounds_table, gen_outbound(server_section, "global", 2080))
|
||||
if v2ray_flow == '1' then
|
||||
table.insert(outbounds_table, gen_outbound(server_section, 'global', 2080))
|
||||
for i, v in pairs(flow_table) do
|
||||
local server = ucursor:get_first(name, 'global', v.name..'_server')
|
||||
table.insert(outbounds_table, gen_outbound(server, v.name,v.port))
|
||||
table.insert(rules_table, (server ~=nil and server ~= "nil") and v.rules or nil)
|
||||
local server = ucursor:get_first(name, 'global', v.name .. '_server')
|
||||
table.insert(outbounds_table, gen_outbound(server, v.name, v.port))
|
||||
table.insert(rules_table, (server ~= nil and server ~= 'nil') and v.rules or nil)
|
||||
end
|
||||
else
|
||||
table.insert(outbounds_table,gen_outbound(server_section, "main", local_port))
|
||||
table.insert(outbounds_table, gen_outbound(server_section, 'main', local_port))
|
||||
end
|
||||
|
||||
|
||||
local v2ray = {
|
||||
log = {
|
||||
-- error = "/var/vssrsss.log",
|
||||
-- access = "/var/v2rays.log",
|
||||
loglevel = "warning"
|
||||
-- access = "/var/v2rays.log",
|
||||
loglevel = 'warning'
|
||||
},
|
||||
-- 传入连接
|
||||
inbounds = {
|
||||
{
|
||||
port = tonumber(local_port),
|
||||
protocol = "dokodemo-door",
|
||||
protocol = 'dokodemo-door',
|
||||
settings = {network = proto, followRedirect = true},
|
||||
sniffing = {enabled = true, destOverride = {"http", "tls"}},
|
||||
sniffing = {enabled = true, destOverride = {'http', 'tls'}},
|
||||
streamSettings = {
|
||||
sockopt = {tproxy = (proto == "tcp") and "redirect" or "tproxy"}
|
||||
sockopt = {tproxy = (proto == 'tcp') and 'redirect' or 'tproxy'}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
-- 传出连接
|
||||
outbounds = outbounds_table,
|
||||
routing = {domainStrategy = "AsIs", rules = rules_table}
|
||||
routing = {domainStrategy = 'AsIs', rules = rules_table}
|
||||
}
|
||||
print(json.stringify(v2ray, 1))
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
local ucursor = require"luci.model.uci".cursor()
|
||||
local name = "vssr"
|
||||
local json = require "luci.jsonc"
|
||||
local proto = "socks"
|
||||
local ucursor = require 'luci.model.uci'.cursor()
|
||||
local name = 'vssr'
|
||||
local json = require 'luci.jsonc'
|
||||
local proto = 'socks'
|
||||
local auth_type = ucursor:get_first(name, 'socks5_proxy', 'enable_auth')
|
||||
local local_port = ucursor:get_first(name, 'socks5_proxy', 'local_port')
|
||||
local Socks_user = ucursor:get_first(name, 'socks5_proxy', 'Socks_user')
|
||||
@ -10,22 +10,20 @@ local Socks_pass = ucursor:get_first(name, 'socks5_proxy', 'Socks_pass')
|
||||
local v2ray = {
|
||||
log = {
|
||||
-- error = "/var/log/v2ray.log",
|
||||
loglevel = "warning"
|
||||
loglevel = 'warning'
|
||||
},
|
||||
-- 传入连接
|
||||
inbound = {
|
||||
port = local_port,
|
||||
protocol = proto,
|
||||
settings = {
|
||||
auth = (auth_type == '1') and "password" or "noauth",
|
||||
accounts = (auth_type == "1") and
|
||||
{{user = (auth_type == '1') and Socks_user, pass = Socks_pass}} or
|
||||
nil
|
||||
auth = (auth_type == '1') and 'password' or 'noauth',
|
||||
accounts = (auth_type == '1') and {{user = (auth_type == '1') and Socks_user, pass = Socks_pass}} or nil
|
||||
}
|
||||
},
|
||||
-- 传出连接
|
||||
outbound = {protocol = "freedom"},
|
||||
outbound = {protocol = 'freedom'},
|
||||
-- 额外传出连接
|
||||
outboundDetour = {{protocol = "blackhole", tag = "blocked"}}
|
||||
outboundDetour = {{protocol = 'blackhole', tag = 'blocked'}}
|
||||
}
|
||||
print(json.stringify(v2ray, 1))
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
------------------------------------------------
|
||||
-- This file is part of the luci-app-ssr-plus subscribe.lua
|
||||
-- @author William Chan <root@williamchan.me>
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
require 'nixio'
|
||||
require 'luci.util'
|
||||
require 'luci.jsonc'
|
||||
@ -13,9 +14,13 @@ require 'luci.sys'
|
||||
-- so caching them is worth the effort
|
||||
local luci = luci
|
||||
local tinsert = table.insert
|
||||
local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len,
|
||||
string.char, string.byte,
|
||||
string.format, string.gsub
|
||||
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 cache = {}
|
||||
@ -25,15 +30,14 @@ local uciType = 'servers'
|
||||
local ucic = luci.model.uci.cursor()
|
||||
local proxy = ucic:get_first(name, 'server_subscribe', 'proxy', '0')
|
||||
local switch = '0'
|
||||
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url',
|
||||
{})
|
||||
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url', {})
|
||||
|
||||
local log = function(...)
|
||||
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({...}, " "))
|
||||
print(os.date('%Y-%m-%d %H:%M:%S ') .. table.concat({...}, ' '))
|
||||
end
|
||||
-- 分割字符串
|
||||
local function split(full, sep)
|
||||
full = full:gsub("%z", "") -- 这里不是很清楚 有时候结尾带个\0
|
||||
full = full:gsub('%z', '') -- 这里不是很清楚 有时候结尾带个\0
|
||||
local off, result = 1, {}
|
||||
while true do
|
||||
local nStart, nEnd = full:find(sep, off)
|
||||
@ -51,43 +55,50 @@ local function split(full, sep)
|
||||
return result
|
||||
end
|
||||
-- urlencode
|
||||
local function get_urlencode(c) return sformat("%%%02X", sbyte(c)) end
|
||||
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(" ", "+")
|
||||
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 get_urldecode(h)
|
||||
return schar(tonumber(h, 16))
|
||||
end
|
||||
local function UrlDecode(szText)
|
||||
return szText:gsub("+", " "):gsub("%%(%x%x)", get_urldecode)
|
||||
return szText:gsub('+', ' '):gsub('%%(%x%x)', get_urldecode)
|
||||
end
|
||||
|
||||
-- trim
|
||||
local function trim(text)
|
||||
if not text or text == "" then return "" end
|
||||
return (sgsub(text, "^%s*(.-)%s*$", "%1"))
|
||||
if not text or text == '' then
|
||||
return ''
|
||||
end
|
||||
return (sgsub(text, '^%s*(.-)%s*$', '%1'))
|
||||
end
|
||||
-- md5
|
||||
local function md5(content)
|
||||
local stdout = luci.sys.exec('echo \"' .. urlEncode(content) ..
|
||||
'\" | md5sum | cut -d \" \" -f1')
|
||||
local stdout = luci.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("_", "/")
|
||||
text = text:gsub("-", "+")
|
||||
if not text then
|
||||
return ''
|
||||
end
|
||||
text = text:gsub('%z', '')
|
||||
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", "")
|
||||
return result:gsub('%z', '')
|
||||
else
|
||||
return raw
|
||||
end
|
||||
@ -106,7 +117,7 @@ local function processData(szType, content)
|
||||
kcp_param = '--nocomp'
|
||||
}
|
||||
if szType == 'ssr' then
|
||||
local dat = split(content, "/%?")
|
||||
local dat = split(content, '/%?')
|
||||
local hostInfo = split(dat[1], ':')
|
||||
result.server = hostInfo[1]
|
||||
result.server_port = hostInfo[2]
|
||||
@ -122,7 +133,9 @@ local function processData(szType, content)
|
||||
result.obfs_param = base64Decode(params.obfsparam)
|
||||
result.protocol_param = base64Decode(params.protoparam)
|
||||
local group = base64Decode(params.group)
|
||||
if group then result.alias = "[" .. group .. "] " end
|
||||
if group then
|
||||
result.alias = '[' .. group .. '] '
|
||||
end
|
||||
result.alias = result.alias .. base64Decode(params.remarks)
|
||||
elseif szType == 'vmess' then
|
||||
local info = jsonParse(content)
|
||||
@ -162,31 +175,33 @@ local function processData(szType, content)
|
||||
result.quic_key = info.key
|
||||
result.quic_security = info.securty
|
||||
end
|
||||
if info.security then result.security = info.security end
|
||||
if info.tls == "tls" or info.tls == "1" then
|
||||
result.tls = "1"
|
||||
if info.security then
|
||||
result.security = info.security
|
||||
end
|
||||
if info.tls == 'tls' or info.tls == '1' then
|
||||
result.tls = '1'
|
||||
result.tls_host = info.host
|
||||
else
|
||||
result.tls = "0"
|
||||
result.tls = '0'
|
||||
end
|
||||
elseif szType == "ss" then
|
||||
elseif szType == 'ss' then
|
||||
local idx_sp = 0
|
||||
local alias = ""
|
||||
if content:find("#") then
|
||||
idx_sp = content:find("#")
|
||||
local alias = ''
|
||||
if content:find('#') then
|
||||
idx_sp = content:find('#')
|
||||
alias = content:sub(idx_sp + 1, -1)
|
||||
end
|
||||
local info = content:sub(1, idx_sp - 1)
|
||||
local hostInfo = split(base64Decode(info), "@")
|
||||
local host = split(hostInfo[2], ":")
|
||||
local hostInfo = split(base64Decode(info), '@')
|
||||
local host = split(hostInfo[2], ':')
|
||||
local userinfo = base64Decode(hostInfo[1])
|
||||
local method = userinfo:sub(1, userinfo:find(":") - 1)
|
||||
local password = userinfo:sub(userinfo:find(":") + 1, #userinfo)
|
||||
local method = userinfo:sub(1, userinfo:find(':') - 1)
|
||||
local password = userinfo:sub(userinfo:find(':') + 1, #userinfo)
|
||||
result.alias = UrlDecode(alias)
|
||||
result.type = "ss"
|
||||
result.type = 'ss'
|
||||
result.server = host[1]
|
||||
if host[2]:find("/%?") then
|
||||
local query = split(host[2], "/%?")
|
||||
if host[2]:find('/%?') then
|
||||
local query = split(host[2], '/%?')
|
||||
result.server_port = query[1]
|
||||
local params = {}
|
||||
for _, v in pairs(split(query[2], '&')) do
|
||||
@ -195,11 +210,10 @@ local function processData(szType, content)
|
||||
end
|
||||
if params.plugin then
|
||||
local plugin_info = UrlDecode(params.plugin)
|
||||
local idx_pn = plugin_info:find(";")
|
||||
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)
|
||||
result.plugin_opts = plugin_info:sub(idx_pn + 1, #plugin_info)
|
||||
else
|
||||
result.plugin = plugin_info
|
||||
end
|
||||
@ -209,46 +223,45 @@ local function processData(szType, content)
|
||||
end
|
||||
result.encrypt_method_ss = method
|
||||
result.password = password
|
||||
|
||||
elseif szType == "trojan" then
|
||||
elseif szType == 'trojan' then
|
||||
local idx_sp = 0
|
||||
local alias = ""
|
||||
if content:find("#") then
|
||||
idx_sp = content:find("#")
|
||||
local alias = ''
|
||||
if content:find('#') then
|
||||
idx_sp = content:find('#')
|
||||
alias = content:sub(idx_sp + 1, -1)
|
||||
end
|
||||
local info = content:sub(1, idx_sp - 1)
|
||||
local hostInfo = split(info, "@")
|
||||
local host = split(hostInfo[2], ":")
|
||||
local hostInfo = split(info, '@')
|
||||
local host = split(hostInfo[2], ':')
|
||||
local password = hostInfo[1]
|
||||
result.alias = UrlDecode(alias)
|
||||
result.type = "trojan"
|
||||
result.type = 'trojan'
|
||||
result.server = host[1]
|
||||
result.insecure = "0"
|
||||
if host[2]:find("?") then
|
||||
local query = split(host[2], "?")
|
||||
result.insecure = '0'
|
||||
if host[2]:find('?') then
|
||||
local query = split(host[2], '?')
|
||||
result.server_port = query[1]
|
||||
local params = {}
|
||||
for _, v in pairs(split(query[2], '&')) do
|
||||
local t = split(v, '=')
|
||||
if t[1] == 'peer' then
|
||||
result.peer = t[2]
|
||||
result.tls = "1"
|
||||
result.tls = '1'
|
||||
end
|
||||
end
|
||||
else
|
||||
result.server_port = host[2]
|
||||
end
|
||||
result.password = password
|
||||
elseif szType == "ssd" then
|
||||
result.type = "ss"
|
||||
elseif szType == 'ssd' then
|
||||
result.type = 'ss'
|
||||
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
|
||||
result.alias = '[' .. content.airport .. '] ' .. content.remarks
|
||||
end
|
||||
if not result.alias then
|
||||
result.alias = result.server .. ':' .. result.server_port
|
||||
@ -261,16 +274,18 @@ local function processData(szType, content)
|
||||
result.hashkey = md5(jsonStringify(result))
|
||||
result.alias = alias
|
||||
result.switch_enable = switch_enable
|
||||
local vssrutil = require "vssrutil"
|
||||
local vssrutil = require 'vssrutil'
|
||||
result.flag = vssrutil.get_flag(result.alias, result.server)
|
||||
|
||||
return result
|
||||
end
|
||||
-- wget
|
||||
local function wget(url)
|
||||
local stdout = luci.sys.exec(
|
||||
'wget-ssl -q --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36" --no-check-certificate -t 3 -T 10 -O- "' ..
|
||||
url .. '"')
|
||||
local stdout =
|
||||
luci.sys.exec(
|
||||
'wget-ssl -q --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36" --no-check-certificate -t 3 -T 10 -O- "' ..
|
||||
url .. '"'
|
||||
)
|
||||
return trim(stdout)
|
||||
end
|
||||
|
||||
@ -309,7 +324,7 @@ local execute = function()
|
||||
nodes = servers
|
||||
else
|
||||
-- ssd 外的格式
|
||||
nodes = split(base64Decode(raw):gsub(" ", "\n"), "\n")
|
||||
nodes = split(base64Decode(raw):gsub(' ', '\n'), '\n')
|
||||
end
|
||||
for _, v in ipairs(nodes) do
|
||||
if v then
|
||||
@ -318,13 +333,12 @@ local execute = function()
|
||||
result = processData(szType, v)
|
||||
elseif not szType then
|
||||
local node = trim(v)
|
||||
local dat = split(node, "://")
|
||||
local dat = split(node, '://')
|
||||
if dat and dat[1] and dat[2] then
|
||||
if dat[1] == 'ss' then
|
||||
result = processData(dat[1], dat[2])
|
||||
else
|
||||
result =
|
||||
processData(dat[1], base64Decode(dat[2]))
|
||||
result = processData(dat[1], base64Decode(dat[2]))
|
||||
end
|
||||
end
|
||||
else
|
||||
@ -332,20 +346,18 @@ local execute = function()
|
||||
end
|
||||
-- log(result)
|
||||
if result then
|
||||
if result.alias:find("过期时间") or
|
||||
result.alias:find("剩余流量") or
|
||||
result.alias:find("QQ群") or
|
||||
result.alias:find("不支持") or
|
||||
result.alias:find("官网") or not result.server then
|
||||
log('丢弃无效节点: ' .. result.type ..
|
||||
' 节点, ' .. result.alias)
|
||||
if
|
||||
result.alias:find('过期时间') or result.alias:find('剩余流量') or result.alias:find('QQ群') or
|
||||
result.alias:find('不支持') or
|
||||
result.alias:find('官网') or
|
||||
not result.server
|
||||
then
|
||||
log('丢弃无效节点: ' .. result.type .. ' 节点, ' .. result.alias)
|
||||
else
|
||||
log('成功解析: ' .. result.type ..
|
||||
' 节点, ' .. result.alias)
|
||||
log('成功解析: ' .. result.type .. ' 节点, ' .. result.alias)
|
||||
result.grouphashkey = groupHash
|
||||
tinsert(nodeResult[index], result)
|
||||
cache[groupHash][result.hashkey] =
|
||||
nodeResult[index][#nodeResult[index]]
|
||||
cache[groupHash][result.hashkey] = nodeResult[index][#nodeResult[index]]
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -356,41 +368,40 @@ local execute = function()
|
||||
end
|
||||
-- diff
|
||||
do
|
||||
assert(next(nodeResult), "node result is empty")
|
||||
assert(next(nodeResult), 'node result is empty')
|
||||
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
|
||||
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
|
||||
local dat = nodeResult[old.grouphashkey][old.hashkey]
|
||||
ucic:tset(name, old['.name'], dat)
|
||||
-- 标记一下
|
||||
setmetatable(nodeResult[old.grouphashkey][old.hashkey],
|
||||
{__index = {_ignore = true}})
|
||||
if (old.alias ~= nil) then
|
||||
log('忽略手动添加的节点: ' .. old.alias)
|
||||
else
|
||||
log('忽略手动添加的无效节点')
|
||||
end
|
||||
end
|
||||
else
|
||||
if (old.alias ~= nil) then
|
||||
log('忽略手动添加的节点: ' .. old.alias)
|
||||
else
|
||||
log('忽略手动添加的无效节点')
|
||||
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)
|
||||
ucic:set(name, section, 'switch_enable', switch)
|
||||
add = add + 1
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
ucic:commit(name)
|
||||
@ -399,36 +410,36 @@ local execute = function()
|
||||
local firstServer = ucic:get_first(name, uciType)
|
||||
if not ucic:get(name, globalServer) then
|
||||
if firstServer then
|
||||
ucic:set(name, ucic:get_first(name, 'global'), 'global_server',
|
||||
firstServer)
|
||||
ucic:set(name, ucic:get_first(name, 'global'), 'global_server', firstServer)
|
||||
ucic:commit(name)
|
||||
log('当前主服务器已更新,正在自动更换。')
|
||||
end
|
||||
end
|
||||
if firstServer then
|
||||
luci.sys.call("/etc/init.d/" .. name ..
|
||||
" restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
luci.sys.call('/etc/init.d/' .. name .. ' restart > /dev/null 2>&1 &') -- 不加&的话日志会出现的更早
|
||||
else
|
||||
luci.sys.call("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
luci.sys.call('/etc/init.d/' .. name .. ' stop > /dev/null 2>&1 &') -- 不加&的话日志会出现的更早
|
||||
end
|
||||
log('新增节点数量: ' .. add, '删除节点数量: ' .. del)
|
||||
log('更新成功服务正在启动')
|
||||
log("END SUBSCRIBE")
|
||||
log('END SUBSCRIBE')
|
||||
end
|
||||
end
|
||||
|
||||
if subscribe_url and #subscribe_url > 0 then
|
||||
xpcall(execute, function(e)
|
||||
log(e)
|
||||
log(debug.traceback())
|
||||
log('发生错误, 正在恢复服务')
|
||||
log("END SUBSCRIBE")
|
||||
local firstServer = ucic:get_first(name, uciType)
|
||||
if firstServer then
|
||||
luci.sys.call("/etc/init.d/" .. name ..
|
||||
" restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
else
|
||||
luci.sys.call("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
xpcall(
|
||||
execute,
|
||||
function(e)
|
||||
log(e)
|
||||
log(debug.traceback())
|
||||
log('发生错误, 正在恢复服务')
|
||||
log('END SUBSCRIBE')
|
||||
local firstServer = ucic:get_first(name, uciType)
|
||||
if firstServer then
|
||||
luci.sys.call('/etc/init.d/' .. name .. ' restart > /dev/null 2>&1 &') -- 不加&的话日志会出现的更早
|
||||
else
|
||||
luci.sys.call('/etc/init.d/' .. name .. ' stop > /dev/null 2>&1 &') -- 不加&的话日志会出现的更早
|
||||
end
|
||||
end
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
------------------------------------------------
|
||||
-- This file is part of the luci-app-ssr-plus update.lua
|
||||
-- By Mattraks
|
||||
------------------------------------------------
|
||||
|
||||
require 'nixio'
|
||||
require 'luci.util'
|
||||
require 'luci.jsonc'
|
||||
@ -12,25 +12,23 @@ local icount = 0
|
||||
local ucic = luci.model.uci.cursor()
|
||||
|
||||
local log = function(...)
|
||||
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({...}, " "))
|
||||
print(os.date('%Y-%m-%d %H:%M:%S ') .. table.concat({...}, ' '))
|
||||
end
|
||||
|
||||
log('正在更新【GFW列表】数据库')
|
||||
if nixio.fs.access("/usr/bin/wget-ssl") then
|
||||
refresh_cmd =
|
||||
"wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64"
|
||||
if nixio.fs.access('/usr/bin/wget-ssl') then
|
||||
refresh_cmd = 'wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64'
|
||||
else
|
||||
refresh_cmd = "wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64"
|
||||
refresh_cmd = 'wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64'
|
||||
end
|
||||
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
|
||||
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
|
||||
if sret == 0 then
|
||||
luci.sys.call("/usr/bin/vssr-gfw")
|
||||
icount = luci.sys.exec("cat /tmp/gfwnew.txt | wc -l")
|
||||
luci.sys.call('/usr/bin/vssr-gfw')
|
||||
icount = luci.sys.exec('cat /tmp/gfwnew.txt | wc -l')
|
||||
if tonumber(icount) > 1000 then
|
||||
oldcount = luci.sys.exec("cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l")
|
||||
oldcount = luci.sys.exec('cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l')
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys
|
||||
.exec("cp -f /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf")
|
||||
luci.sys.exec('cp -f /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf')
|
||||
-- retstring=tostring(math.ceil(tonumber(icount)/2))
|
||||
log('更新成功! 新的总纪录数:' .. icount)
|
||||
else
|
||||
@ -39,22 +37,21 @@ if sret == 0 then
|
||||
else
|
||||
log('更新失败!')
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/gfwnew.txt")
|
||||
luci.sys.exec('rm -f /tmp/gfwnew.txt')
|
||||
else
|
||||
log('更新失败!')
|
||||
end
|
||||
|
||||
log('正在更新【国内IP段】数据库')
|
||||
refresh_cmd =
|
||||
"wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' 2>/dev/null| awk -F\\| '/CN\\|ipv4/ { printf(\"%s/%d\\n\", $4, 32-log($5)/log(2)) }' > /tmp/china_ssr.txt"
|
||||
refresh_cmd = "wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' 2>/dev/null| awk -F\\| '/CN\\|ipv4/ { printf(\"%s/%d\\n\", $4, 32-log($5)/log(2)) }' > /tmp/china_ssr.txt"
|
||||
sret = luci.sys.call(refresh_cmd)
|
||||
icount = luci.sys.exec("cat /tmp/china_ssr.txt | wc -l")
|
||||
icount = luci.sys.exec('cat /tmp/china_ssr.txt | wc -l')
|
||||
if sret == 0 then
|
||||
icount = luci.sys.exec("cat /tmp/china_ssr.txt | wc -l")
|
||||
icount = luci.sys.exec('cat /tmp/china_ssr.txt | wc -l')
|
||||
if tonumber(icount) > 1000 then
|
||||
oldcount = luci.sys.exec("cat /etc/china_ssr.txt | wc -l")
|
||||
oldcount = luci.sys.exec('cat /etc/china_ssr.txt | wc -l')
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/china_ssr.txt /etc/china_ssr.txt")
|
||||
luci.sys.exec('cp -f /tmp/china_ssr.txt /etc/china_ssr.txt')
|
||||
-- retstring=tostring(math.ceil(tonumber(icount)/2))
|
||||
log('更新成功! 新的总纪录数:' .. icount)
|
||||
else
|
||||
@ -63,37 +60,38 @@ if sret == 0 then
|
||||
else
|
||||
log('更新失败!')
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/china_ssr.txt")
|
||||
luci.sys.exec('rm -f /tmp/china_ssr.txt')
|
||||
else
|
||||
log('更新失败!')
|
||||
end
|
||||
|
||||
-- --[[
|
||||
-- --[[
|
||||
if ucic:get_first('vssr', 'global', 'adblock', '') == '1' then
|
||||
log('正在更新【广告屏蔽】数据库')
|
||||
local need_process = 0
|
||||
if nixio.fs.access("/usr/bin/wget-ssl") then
|
||||
refresh_cmd =
|
||||
"wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf"
|
||||
if nixio.fs.access('/usr/bin/wget-ssl') then
|
||||
refresh_cmd = 'wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf'
|
||||
need_process = 1
|
||||
else
|
||||
refresh_cmd = "wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf"
|
||||
refresh_cmd = 'wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf'
|
||||
end
|
||||
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
|
||||
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
|
||||
if sret == 0 then
|
||||
if need_process == 1 then luci.sys.call("/usr/bin/vssr-ad") end
|
||||
icount = luci.sys.exec("cat /tmp/ad.conf | wc -l")
|
||||
if need_process == 1 then
|
||||
luci.sys.call('/usr/bin/vssr-ad')
|
||||
end
|
||||
icount = luci.sys.exec('cat /tmp/ad.conf | wc -l')
|
||||
if tonumber(icount) > 1000 then
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
|
||||
oldcount = luci.sys.exec("cat /etc/dnsmasq.ssr/ad.conf | wc -l")
|
||||
if nixio.fs.access('/etc/dnsmasq.ssr/ad.conf') then
|
||||
oldcount = luci.sys.exec('cat /etc/dnsmasq.ssr/ad.conf | wc -l')
|
||||
else
|
||||
oldcount = 0
|
||||
end
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/ad.conf /etc/dnsmasq.ssr/ad.conf")
|
||||
luci.sys.exec('cp -f /tmp/ad.conf /etc/dnsmasq.ssr/ad.conf')
|
||||
-- retstring=tostring(math.ceil(tonumber(icount)))
|
||||
if oldcount == 0 then
|
||||
luci.sys.call("/etc/init.d/dnsmasq restart")
|
||||
luci.sys.call('/etc/init.d/dnsmasq restart')
|
||||
end
|
||||
log('更新成功! 新的总纪录数:' .. icount)
|
||||
else
|
||||
@ -102,7 +100,7 @@ if ucic:get_first('vssr', 'global', 'adblock', '') == '1' then
|
||||
else
|
||||
log('更新失败!')
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/ad.conf")
|
||||
luci.sys.exec('rm -f /tmp/ad.conf')
|
||||
else
|
||||
log('更新失败!')
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user