luci-app-vssr: update source code

This commit is contained in:
CN_SZTL 2020-01-28 17:12:47 +08:00
parent f2adf0cf4f
commit 5603e5369a
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
37 changed files with 11916 additions and 1403 deletions

View File

@ -31,7 +31,7 @@ luci-app-autoipsetadder source: [rufengsuixing/luci-app-autoipsetadder](https://
luci-app-adguardhome source: [rufengsuixing/luci-app-adguardhome](https://github.com/rufengsuixing/luci-app-adguardhome).<br/>
Rclone-OpenWrt source: [ElonH/Rclone-OpenWrt](https://github.com/ElonH/Rclone-OpenWrt).<br/>
luci-app-usb3disable source: [rufengsuixing/luci-app-usb3disable](https://github.com/rufengsuixing/luci-app-usb3disable).<br/>
luci-app-vssr source: [jerrykuku/luci-app-vssr](https://github.com/jerrykuku/luci-app-vssr).<br/>
luci-app-vssr source: [Leo-Jo-My/luci-app-vssr](https://github.com/Leo-Jo-My/luci-app-vssr).<br/>
luci-app-diskman source: [lisaac/luci-app-diskman](https://github.com/lisaac/luci-app-diskman).<br/>
NanoPi R1s(h5) support: [jerrykuku/openwrt-nanopi-r1s-h5](https://github.com/jerrykuku/openwrt-nanopi-r1s-h5).<br/>
NanoPi support: [speedyworldclub/nlede](https://github.com/speedyworldclub/nlede).<br/>

View File

@ -1,10 +1,14 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-vssr
PKG_VERSION:=1.03
PKG_RELEASE:=20200118-1
PKG_VERSION:=1.06
PKG_RELEASE:=20200125-4
PKG_CONFIG_DEPENDS:= CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun:kcptun \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Socks \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Socks
@ -12,10 +16,26 @@ include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)/config
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks
bool "Include Shadowsocks New Version"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray
bool "Include V2ray"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan
bool "Include Trojan"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun
bool "Include Kcptun"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Socks
bool "Include Shadowsocks Socks and Tunnel"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server
bool "Include ShadowsocksR Server"
default n
@ -29,10 +49,14 @@ define Package/luci-app-vssr
SECTION:=luci
CATEGORY:=LuCI
SUBMENU:=3. Applications
TITLE:=A New SS/SSR/V2Ray LuCI interface
TITLE:=A New SS/SSR/V2Ray/Trojan LuCI interface
PKGARCH:=all
DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +bash +pdnsd-alt +wget +luasocket +jshn +lua-cjson +coreutils-nohup +python3-maxminddb +curl \
DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +bash +pdnsd-alt +wget +luasocket +jshn +lua-cjson +coreutils-nohup +python3-maxminddb +curl\
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan \
+PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun:kcptun-client \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Socks:shadowsocks-libev-ss-local \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks:shadowsocks-libev-ss-redir \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-server \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Socks:shadowsocksr-libev-ssr-local
endef
@ -78,3 +102,4 @@ exit 0
endef
$(eval $(call BuildPackage,luci-app-vssr))

View File

@ -1,357 +0,0 @@
-- Copyright (C) 2018 jerrykuku <jerrykuku@qq.com>
-- Licensed to the public under the GNU General Public License v3.
module("luci.controller.vssr", package.seeall)
function index()
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"), _("vssr"), 10).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
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
end
entry({"admin", "services", "vssr", "log"}, cbi("vssr/log"), _("Log"), 30).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情况
end
-- 执行订阅
function get_subscribe()
local cjson = require "cjson"
local e = {}
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
local cmd1 = 'uci set vssr.@server_subscribe[0].auto_update="' ..
auto_update .. '"'
local cmd2 = 'uci set vssr.@server_subscribe[0].auto_update_time="' ..
auto_update_time .. '"'
local cmd3 = 'uci set vssr.@server_subscribe[0].proxy="' .. proxy .. '"'
luci.sys.call('uci delete vssr.@server_subscribe[0].subscribe_url ')
luci.sys.call(cmd1)
luci.sys.call(cmd2)
luci.sys.call(cmd3)
for k, v in ipairs(cjson.decode(subscribe_url)) do
luci.sys.call(
'uci add_list vssr.@server_subscribe[0].subscribe_url="' .. v ..
'"')
end
luci.sys.call('uci commit vssr')
luci.sys.call(
"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.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"]
local t1 = luci.sys.exec(
"ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*.[0-9]' | awk -F '=' '{print$2}'" %
s["server"])
e["t1"] = t1
table.insert(server_table, e)
end)
luci.http.prepare_content("application/json")
luci.http.write_json(server_table)
end
-- 切换节点
function change_node()
local e = {}
local uci = luci.model.uci.cursor()
local sid = luci.http.formvalue("set")
local name = ""
uci:foreach("vssr", "global", function(s) name = s[".name"] end)
e.status = false
e.sid = sid
if sid ~= "" then
uci:set("vssr", name, "global_server", sid)
uci:commit("vssr")
luci.sys.call("/etc/init.d/vssr restart")
e.status = true
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
-- 检测全局服务器状态
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
-- 检测PDNSD状态
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
-- 检测国外通道
--[[ http=require("socket.http")
http.TIMEOUT = 1
result=http.request("http://ip111cn.appspot.com/?z="..math.random(1,100000))
if result then
e.google = result
else
e.google = false
end
result1=http.request("http://45.32.164.128/ip.php?z="..math.random(1,100000))
if result1 then
e.outboard = result1
else
e.outboard = false
end
--]]
-- 检测Socks5
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 refresh_data()
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://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt -O /tmp/gfw.b64"
else
refresh_cmd = "wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64"
end
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")
if tonumber(icount) > 1000 then
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")
retstring = tostring(math.ceil(tonumber(icount) / 2))
else
retstring = "0"
end
else
retstring = "-1"
end
luci.sys.exec("rm -f /tmp/gfwnew.txt ")
else
retstring = "-1"
end
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")
if sret == 0 and tonumber(icount) > 1000 then
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")
retstring = tostring(tonumber(icount))
else
retstring = "0"
end
else
retstring = "-1"
end
luci.sys.exec("rm -f /tmp/china_ssr.txt ")
else
if nixio.fs.access("/usr/bin/wget-ssl") then
refresh_cmd =
"wget --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt | grep ^\\|\\|[^\\*]*\\^$ | sed -e 's:||:address\\=\\/:' -e 's:\\^:/127\\.0\\.0\\.1:' > /tmp/ad.conf"
else
refresh_cmd = "wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf"
end
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
if sret == 0 then
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")
else
oldcount = 0
end
if tonumber(icount) ~= tonumber(oldcount) then
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")
end
else
retstring = "0"
end
else
retstring = "-1"
end
luci.sys.exec("rm -f /tmp/ad.conf ")
else
retstring = "-1"
end
end
luci.http.prepare_content("application/json")
luci.http.write_json({ret = retstring, retcount = icount})
end
-- 检测单个节点状态并返回连接速度
function check_port()
local e = {}
-- e.index=luci.http.formvalue("host")
local t1 = luci.sys.exec(
"ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*.[0-9]' | awk -F '=' '{print$2}'" %
luci.http.formvalue("host"))
luci.http.prepare_content("application/json")
luci.http.write_json({ret = 1, used = t1})
end
function JudgeIPString(ipStr)
if type(ipStr) ~= "string" then return false end
-- 判断长度
local len = string.len(ipStr)
if len < 7 or len > 15 then -- 长度不对
return false
end
-- 判断出现的非数字字符
local point = string.find(ipStr, "%p", 1) -- 字符"."出现的位置
local pointNum = 0 -- 字符"."出现的次数 正常ip有3个"."
while point ~= nil do
if string.sub(ipStr, point, point) ~= "." then -- 得到非数字符号不是字符"."
return false
end
pointNum = pointNum + 1
point = string.find(ipStr, "%p", point + 1)
if pointNum > 3 then return false end
end
if pointNum ~= 3 then -- 不是正确的ip格式
return false
end
-- 判断数字对不对
local num = {}
for w in string.gmatch(ipStr, "%d+") do
num[#num + 1] = w
local kk = tonumber(w)
if kk == nil or kk > 255 then -- 不是数字或超过ip正常取值范围了
return false
end
end
if #num ~= 4 then -- 不是4段数字
return false
end
return ipStr
end
-- 检测 当前节点ip 和 网站访问情况
function check_ip()
local e = {}
http = require("socket.http")
http.TIMEOUT = 1
result = luci.sys.exec("curl -s https://api.ip.sb/ip")
if JudgeIPString(result) then
local cmd = '/usr/share/vssr/getip.sh ' .. result
e.outboard = result
e.outboardip = luci.sys.exec(cmd)
else
e.outboard = false
end
-- 检测国内通道
e.baidu = false
sret1 = luci.sys.call("/usr/bin/ssr-check www.baidu.com 80 3 1")
if sret1 == 0 then e.baidu = true end
e.taobao = false
sret2 = luci.sys.call("/usr/bin/ssr-check www.taobao.com 80 3 1")
if sret2 == 0 then e.taobao = true end
-- 检测国外通道
e.google = false
sret3 = luci.sys.call("/usr/bin/ssr-check www.google.com 80 3 1")
if sret3 == 0 then e.google = true end
e.youtube = false
sret4 = luci.sys.call("/usr/bin/ssr-check www.youtube.com 80 3 1")
if sret4 == 0 then e.youtube = true end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
-- 获取节点国旗 iso code
function get_flag()
local e = {}
local host = luci.http.formvalue("host")
local remark = luci.http.formvalue("remark")
local cmd1 = '/usr/share/vssr/getflag.sh "' .. remark .. '" ' .. host
e.host = host
e.flag = luci.sys.exec(cmd1)
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end

View File

@ -62,43 +62,29 @@ 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.default = 3
s = m:section(TypedSection, "server_subscribe", translate("Servers subscription and manage"))
-- [[ SOCKS5 Proxy ]]--
if nixio.fs.access("/usr/bin/ssr-local") then
s = m:section(TypedSection, "socks5_proxy", translate("SOCKS5 Proxy"))
s.anonymous = true
o = s:option(Flag, "auto_update", translate("Auto Update"))
o = s:option(ListValue, "server", translate("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.description = translate("Auto Update Server subscription, GFW list and CHN route")
o = s:option(Value, "local_port", translate("Local Port"))
o.datatype = "port"
o.default = 1080
o.rmempty = false
o = s:option(ListValue, "auto_update_time", translate("Update time (every day)"))
for t = 0,23 do
o:value(t, t..":00")
end
o.default=2
o.rmempty = false
o = s:option(DynamicList, "subscribe_url", translate("Subscribe URL"))
o.rmempty = true
o = s:option(Flag, "proxy", translate("Through proxy update"))
o.rmempty = false
o.description = translate("Through proxy update list, Not Recommended ")
o = s:option(DummyValue, "", "")
o.rawhtml = true
o.template = "vssr/update_subscribe"
o = s:option(Button,"delete",translate("Delete all severs"))
o.inputstyle = "reset"
o.write = function()
uci:delete_all("vssr", "servers", function(s) return true end)
uci:commit("vssr")
luci.sys.call("/etc/init.d/vssr stop")
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "vssr", "servers"))
end
-- [[ 更新设置 ]]--
@ -116,4 +102,6 @@ o.template = "vssr/refresh"
o.value =ip_count .. " " .. translate("Records")
return m

View File

@ -48,7 +48,7 @@ obfs = {
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")
m.redirect = luci.dispatcher.build_url("admin/vpn/vssr/servers")
if m.uci:get(vssr, sid) ~= "servers" then
luci.http.redirect(m.redirect)
return
@ -65,11 +65,16 @@ o.template = "vssr/ssrurl"
o.value = sid
o = s:option(ListValue, "type", translate("Server Node Type"))
o:value("ssr", translate("ShadowsocksR"))
if nixio.fs.access("/usr/sbin/trojan") then
o:value("trojan", translate("Trojan"))
end
if nixio.fs.access("/usr/bin/v2ray/v2ray") then
o:value("ss", translate("Shadowsocks New Version"))
o:value("v2ray", translate("V2Ray"))
o:value("v2ray", translate("V2Ray"))
end
o:value("ssr", translate("ShadowsocksR"))
if nixio.fs.access("/usr/bin/ss-redir") then
o:value("ss", translate("Shadowsocks"))
end
o.description = translate(
"Using incorrect encryption mothod may causes service fail to start")
@ -99,7 +104,7 @@ o.password = true
o.rmempty = true
o:depends("type", "ssr")
o:depends("type", "ss")
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.rmempty = true
@ -241,6 +246,7 @@ 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"))
@ -297,6 +303,7 @@ o.rmempty = true
o = s:option(Flag, "insecure", translate("allowInsecure"))
o.rmempty = true
o:depends("type", "v2ray")
o:depends("type", "trojan")
-- [[ TLS ]]--
o = s:option(Flag, "tls", translate("TLS"))
@ -321,6 +328,7 @@ o.rmempty = true
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.rmempty = false

View File

@ -42,7 +42,7 @@ obfs = {
m = Map(vssr, translate("Edit vssr Server"))
m.redirect = luci.dispatcher.build_url("admin/services/vssr/server")
m.redirect = luci.dispatcher.build_url("admin/vpn/vssr/server")
if m.uci:get(vssr, sid) ~= "server_config" then
luci.http.redirect(m.redirect)
return

View File

@ -70,7 +70,7 @@ 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.extedit = luci.dispatcher.build_url("admin/vpn/vssr/server/%s")
function sec.create(...)
local sid = TypedSection.create(...)
if sid then

View File

@ -29,7 +29,7 @@ s.des = server_count
s.current = uci:get("vssr", name, "global_server")
s.servers = cjson.encode(server_table)
s.template = "vssr/tblsection"
s.extedit = luci.dispatcher.build_url("admin/services/vssr/servers/%s")
s.extedit = luci.dispatcher.build_url("admin/vpn/vssr/servers/%s")
function s.create(...)
local sid = TypedSection.create(...)
if sid then
@ -59,3 +59,4 @@ end
m:section(SimpleSection).template = "vssr/status2"
return m

View File

@ -1,32 +0,0 @@
local vssr = "vssr"
local uci = luci.model.uci.cursor()
local server_table = {}
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"))
s.anonymous = true
o = s:option(Flag, "enable_server", translate("Enable Servers"))
o.rmempty = false
o = s:option(Value, "Socks_user", translate("Socks user"))
o.default="user"
o.rmempty = true
o = s:option(Value, "Socks_pass", translate("Socks pass"))
o.default="password"
o.password = true
o.rmempty = true
o = s:option(Value, "local_port", translate("Local Port"))
o.datatype = "port"
o.default = 1080
o.rmempty = false
end
return m

View File

@ -1,11 +1,13 @@
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
-- Licensed to the public under the GNU General Public License v3.
local IPK_Version="3.0.9"
local IPK_Version="202000109"
local m, s, o
local redir_run=0
local reudp_run=0
local sock5_run=0
local ssock5_run=0
local v2sock5_run=0
local server_run=0
local kcptun_run=0
local tunnel_run=0
@ -73,6 +75,13 @@ end
if luci.sys.call("pidof ssr-local >/dev/null") == 0 then
sock5_run=1
end
if luci.sys.call("pidof ss-local >/dev/null") == 0 then
ssock5_run=1
end
if luci.sys.call("ps -w | grep v2-ssr-local | grep -v grep >/dev/null") == 0 then
v2sock5_run=1
end
if luci.sys.call("pidof kcptun-client >/dev/null") == 0 then
kcptun_run=1
@ -118,8 +127,20 @@ else
s.value = translate("Not Running")
end
if nixio.fs.access("/usr/bin/ss-local") then
s=m:field(DummyValue,"ssock5_run",translate("SSOCKS5 Proxy"))
s.rawhtml = true
if ssock5_run == 1 then
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
else
s.value = translate("Not Running")
end
end
if nixio.fs.access("/usr/bin/ssr-local") then
s=m:field(DummyValue,"sock5_run",translate("SOCKS5 Proxy"))
s=m:field(DummyValue,"sock5_run",translate("SSR SOCKS5 Proxy"))
s.rawhtml = true
if sock5_run == 1 then
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
@ -128,6 +149,15 @@ s.value = translate("Not Running")
end
end
if nixio.fs.access("/usr/bin/v2ray/v2ray") then
s=m:field(DummyValue,"ssock5_run",translate("V2SOCKS5 Proxy"))
s.rawhtml = true
if v2sock5_run == 1 then
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
else
s.value = translate("Not Running")
end
end
if nixio.fs.access("/usr/bin/ssr-server") then
s=m:field(DummyValue,"server_run",translate("Global SSR Server"))
s.rawhtml = true
@ -151,30 +181,9 @@ else
s.value = translate("Not Running")
end
end
s=m:field(DummyValue,"google",translate("Google Connectivity"))
s.value = translate("No Check")
s.template = "vssr/check"
s=m:field(DummyValue,"baidu",translate("Baidu Connectivity"))
s.value = translate("No Check")
s.template = "vssr/check"
if gfwmode==1 then
s=m:field(DummyValue,"gfw_data",translate("GFW List Data"))
s=m:field(DummyValue,"version",translate("IPK Version"))
s.rawhtml = true
s.template = "vssr/refresh"
s.value =tostring(math.ceil(gfw_count)) .. " " .. translate("Records")
s.value =IPK_Version
end
s=m:field(DummyValue,"ip_data",translate("China IP Data"))
s.rawhtml = true
s.template = "vssr/refresh"
s.value =ip_count .. " " .. translate("Records")
s=m:field(DummyValue,"check_port",translate("Check Server Port"))
s.template = "vssr/checkport"
s.value =translate("No Check")
return m

View File

@ -0,0 +1,75 @@
local vssr = "vssr"
local uci = luci.model.uci.cursor()
local server_table = {}
local gfwmode=0
local gfw_count=0
local ip_count=0
if nixio.fs.access("/etc/dnsmasq.ssr/gfw_list.conf") then
gfwmode=1
end
local sys = require "luci.sys"
if gfwmode==1 then
gfw_count = tonumber(sys.exec("cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l"))/2
end
m = Map(vssr)
m:section(SimpleSection).template = "vssr/status"
-- [[ 节点订阅 ]]--
s = m:section(TypedSection, "server_subscribe", translate("Subscription"))
s.anonymous = true
o = s:option(Flag, "auto_update", translate("Auto Update"))
o.rmempty = false
o.description = translate("Auto Update Server subscription, GFW list and CHN route")
o = s:option(ListValue, "auto_update_time", translate("Update time (every day)"))
for t = 0,23 do
o:value(t, t..":00")
end
o.default=2
o.rmempty = false
o = s:option(DynamicList, "subscribe_url", translate("Subscribe URL"))
o.rmempty = true
o = s:option(Flag, "proxy", translate("Through proxy update"))
o.rmempty = false
o.description = translate("Through proxy update list, Not Recommended ")
o = s:option(DummyValue, "", "")
o.rawhtml = true
o.template = "vssr/update_subscribe"
o = s:option(Button,"delete",translate("Delete all severs"))
o.inputstyle = "reset"
o.write = function()
uci:delete_all("vssr", "servers", function(s) return true end)
uci:commit("vssr")
luci.sys.call("uci commit vssrsr && /etc/init.d/vssr stop")
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "vssr", "servers"))
return
end
m:section(SimpleSection).template = "vssr/status2"
return m

View File

@ -7,7 +7,7 @@
btn.disabled = true;
btn.value = '<%:Check...%>';
murl=urlname;
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "vssr","check")%>',
XHR.get('<%=luci.dispatcher.build_url("admin", "vpn", "vssr","check")%>',
{ set:murl },
function(x,rv)
{

View File

@ -6,7 +6,7 @@
{
btn.disabled = true;
btn.value = '<%:Check...%>';
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "vssr","checkports")%>',
XHR.get('<%=luci.dispatcher.build_url("admin", "vpn", "vssr","checkports")%>',
null,
function(x,rv)
{

View File

@ -7,7 +7,7 @@
btn.disabled = true;
btn.value = '<%:Refresh...%> ';
murl=dataname;
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "vssr","refresh")%>',
XHR.get('<%=luci.dispatcher.build_url("admin", "vpn", "vssr","refresh")%>',
{ set:murl },
function(x,rv)
{

View File

@ -11,7 +11,7 @@ local dsp = require "luci.dispatcher"
//<![CDATA[
var pings = document.getElementsByClassName('pingtime');
for(var i = 0; i < pings.length; i++) {
XHR.get('<%=dsp.build_url("admin/services/vssr/ping")%>', {
XHR.get('<%=dsp.build_url("admin/vpn/vssr/ping")%>', {
index: i,
domain: pings[i].getAttribute("hint")
},

View File

@ -2,11 +2,10 @@
<script type="text/javascript">//<![CDATA[
function getFlag(remark,hosts, sid) {
$.get('<%=luci.dispatcher.build_url("admin", "services", "vssr","flag")%>',
function getFlag(hosts, sid) {
$.get('<%=luci.dispatcher.build_url("admin", "vpn", "vssr","flag")%>',
{
host: hosts,
remark: remark
host: hosts
},
function (data, status) {
document.getElementById('cbid.vssr.' + sid + '.flag').value = data.flag.replace(/[\r\n]/g, "");;
@ -99,7 +98,7 @@
var s = document.getElementById(urlname + '-status');
if (!s)
return false;
var ssrurl = prompt("<%:Paste Node Link Here%> ssr:// | ss:// | vmess://", "");
var ssrurl = prompt("在这里黏贴配置链接 ssr:// | ss:// | vmess:// | trojan://", "");
if (ssrurl == null || ssrurl == "") {
s.innerHTML = "<font color='red'><%:User Cancel%></font>";
return false;
@ -119,7 +118,6 @@
if (ssu[0] == "ssr") {
var sstr = b64decsafe(ssu[1]);
var ploc = sstr.indexOf("/?");
var rema = "";
document.getElementById('cbid.vssr.' + sid + '.type').value = "ssr";
document.getElementById('cbid.vssr.' + sid + '.type').dispatchEvent(event);
var url0, param = "";
@ -146,12 +144,11 @@
document.getElementById('cbid.vssr.' + sid + '.password').value = b64decsafe(ssm[6]);
document.getElementById('cbid.vssr.' + sid + '.obfs_param').value = dictvalue(pdict, 'obfsparam');
document.getElementById('cbid.vssr.' + sid + '.protocol_param').value = dictvalue(pdict, 'protoparam');
getFlag(ssm[1], sid);
var rem = pdict['remarks'];
if (typeof (rem) != 'undefined' && rem != '' && rem.length > 0)
rema = b64decutf8safe(rem);
document.getElementById('cbid.vssr.' + sid + '.alias').value = b64decutf8safe(rem);
getFlag(rema,ssm[1], sid);
s.innerHTML = "<font color='green'><%:Import%>ShadowsocksR<%:Configuration Succeeded%></font>";
return false;
} else if (ssu[0] == "ss") {
@ -163,7 +160,7 @@
url0 = ssu[1]
}
var sstr = b64decsafe(url0);
var rema = "";
document.getElementById('cbid.vssr.' + sid + '.type').value = "ss";
@ -176,18 +173,43 @@
document.getElementById('cbid.vssr.' + sid + '.server_port').value = part2[1];
document.getElementById('cbid.vssr.' + sid + '.password').value = part1[1];
document.getElementById('cbid.vssr.' + sid + '.encrypt_method_ss').value = part1[0];
getFlag(part2[0], sid);
if (param != undefined) {
rema = decodeURI(param)
document.getElementById('cbid.vssr.' + sid + '.alias').value = decodeURI(param);
}
getFlag(rema,part2[0], sid);
s.innerHTML = "<font color='green'><%:Import%>Shadowsocks<%:Configuration Succeeded%></font>";
return false;
} else if (ssu[0] == "trojan") {
var ploc = ssu[1].indexOf("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = ssu[1].substr(ploc + 1);
} else {
url0 = ssu[1]
}
var sstr = b64decsafe(url0);
document.getElementById('cbid.shadowsocksr.' + sid + '.type').value = "trojan";
document.getElementById('cbid.shadowsocksr.' + sid + '.type').dispatchEvent(event);
var team = sstr.split('@');
console.log(param);
var part1 = team[0].split(':');
var part2 = team[1].split(':');
document.getElementById('cbid.shadowsocksr.' + sid + '.server').value = part2[0];
document.getElementById('cbid.shadowsocksr.' + sid + '.server_port').value = part2[1];
document.getElementById('cbid.shadowsocksr.' + sid + '.password').value = part1[1];
if (param != undefined) {
document.getElementById('cbid.shadowsocksr.' + sid + '.alias').value = decodeURI(param);
}
s.innerHTML = "<font color='green'>导入Trojan配置信息成功</font>";
return false;
} else if (ssu[0] == "vmess") {
var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?");
var rema = "";
document.getElementById('cbid.vssr.' + sid + '.type').value = "v2ray";
document.getElementById('cbid.vssr.' + sid + '.type').dispatchEvent(event);
var url0, param = "";
@ -227,7 +249,7 @@
break;
}
getFlag(ssm.ps,ssm.add, sid);
getFlag(ssm.add, sid);
@ -241,6 +263,8 @@
<input type="button" class="cbi-button cbi-button-apply" value="<%:Import Configuration%>"
onclick="return import_ssr_url(this, '<%=self.option%>', '<%=self.value%>')" />
<input type="button" class="cbi-button cbi-button-apply" value="<%:Export SSR%>" onclick="return export_ssr_url(this,'<%=self.option%>','<%=self.value%>')" /><span id="<%=self.option%>-status"></span>
<span id="<%=self.option%>-status"></span>
<%+cbi/valuefooter%>
<%+cbi/valuefooter%>

View File

@ -1,3 +1,4 @@
<%
math.randomseed(os.time())
-%>
@ -5,24 +6,53 @@ math.randomseed(os.time())
<head>
<link rel="stylesheet" href="/luci-static/vssr/css/vssr.css??v=<%=math.random(1,100000)%>">
<script src="<%=media%>/js/jquery.min.js?v=git-19.190.55614-35357e4"></script>
</head>
<body>
<body>
<div class="pure-g status">
<div class="pure-u-1-4">
<div class="pure-u-1-6">
<div class="block pure-g">
<div class="pure-u-3-5">
<h4 id="vssr_status"><%:Client%><br /><span class="red"><%:Not Running%></span></h4>
</div>
<div class="pure-u-2-5">
<div class="img-con">
<img src="/luci-static/vssr/img/client.svg">
<img src="https://i.imgur.com/wzbtvXp.png" >
</div>
</div>
</div>
</div>
<div class="pure-u-1-4">
<div class="pure-u-1-6">
<div class="block pure-g">
<div class="pure-u-3-5">
<h4 id="google_status"><%:Visit foreign websites%><br /><span class="red"><%:Problem detected%></span></h4>
</div>
<div class="pure-u-2-5">
<div class="img-con">
<img src="https://i.imgur.com/3mE04AZ.png">
</div>
</div>
</div>
</div>
<div class="pure-u-1-6">
<div class="block pure-g">
<div class="pure-u-3-5">
<h4 id="baidu_status"><%:Visit domestic website%><br /><span class="red"><%:Problem detected%></span></h4>
</div>
<div class="pure-u-2-5">
<div class="img-con">
<img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjEsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0i5Zu+5bGCXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTAwIDEwMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCgkuc3Qwe2ZpbGw6IzMzODhGRjt9DQoJLnN0MXtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiNGRkZGRkY7fQ0KPC9zdHlsZT4NCjxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjUwIiBjeT0iNTAiIHI9IjUwIi8+DQo8ZyBpZD0i5pCc57SiX+eGiuaOjF82Nmljb24iPg0KCTxnIGlkPSJsb2dvIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjEuMjEyMTIxLCA5MC45MDkwOTEpIj4NCgkJPHBhdGggaWQ9IkZpbGwtMSIgY2xhc3M9InN0MSIgZD0iTS03OS43LTU1LjRjNC41LDAsOC41LTUuNCw4LjUtMTEuOWMwLTYuNS0zLjctMTEuOS04LjUtMTEuOWMtNC41LDAtOC41LDUuNC04LjUsMTEuOQ0KCQkJQy04Ny45LTYwLjctODQuMi01NS40LTc5LjctNTUuNCIvPg0KCQk8cGF0aCBpZD0iRmlsbC0zIiBjbGFzcz0ic3QxIiBkPSJNLTU5LjktNTQuNWM2LjIsMC44LDEwLjItNS43LDExLTEwLjhjMC44LTQuOC0zLjEtMTAuOC03LjYtMTEuNmMtNC4yLTEuMS05LjksNS45LTEwLjIsMTAuNQ0KCQkJQy02Ny4yLTYxLTY2LjEtNTUuNC01OS45LTU0LjUiLz4NCgkJPHBhdGggaWQ9IkZpbGwtNSIgY2xhc3M9InN0MSIgZD0iTS05NS4zLTM4LjZjOC41LTEuNyw3LjEtMTEuNiw3LjEtMTMuOWMtMC4zLTMuNC00LjItOS4zLTkuOS04LjhjLTYuOCwwLjYtNy42LDEwLjItNy42LDEwLjINCgkJCUMtMTA2LjktNDYuNi0xMDMuOC0zNi45LTk1LjMtMzguNiIvPg0KCQk8cGF0aCBpZD0iRmlsbC03IiBjbGFzcz0ic3QxIiBkPSJNLTM1LjItNDYuM2MwLTIuNS0yLTkuNi05LjMtOS42Yy03LjQsMC04LjUsNi44LTguNSwxMS42YzAsNC41LDAuMywxMSw5LjYsMTAuOA0KCQkJQy0zNC40LTMzLjgtMzUuMi00NC0zNS4yLTQ2LjMiLz4NCgkJPHBhdGggaWQ9IkZpbGwtOSIgY2xhc3M9InN0MSIgZD0iTS04Ni41LTIxLjRjLTAuMywwLjYtMC44LDIuNS0wLjMsNGMwLjgsMy40LDQsMy43LDQsMy43aDQuMnYtMTAuOGgtNC44DQoJCQlDLTg1LjEtMjMuNi04Ni4yLTIxLjktODYuNS0yMS40Ii8+DQoJCTxwYXRoIGlkPSJGaWxsLTExIiBjbGFzcz0ic3QxIiBkPSJNLTUzLjEtOS41aC0xMi43Yy00LjgtMS4xLTUuMS00LjgtNS4xLTQuOHYtMTMuOWg1LjF2MTIuNWMwLjMsMS40LDIsMS43LDIsMS43aDUuNHYtMTMuOWg1LjQNCgkJCVYtOS41eiBNLTczLjItOS4ySC04NGMtNC44LTAuOC02LjgtNC4yLTYuOC00LjhjLTAuMy0wLjYtMS43LTMuMS0wLjgtNy42YzItNi41LDcuOS03LjEsNy45LTcuMWg1Ljd2LTcuMWg0LjgNCgkJCUMtNzMuMi0zNS44LTczLjItOS4yLTczLjItOS4yeiBNLTQ0LjYtMjUuM2MwLDAtOS42LTcuNC0xNS4zLTE1LjNjLTcuNi0xMS42LTE4LjQtNy4xLTIxLjgtMS4xYy0zLjQsNS45LTkuMSw5LjktOS45LDEwLjgNCgkJCWMtMC44LDAuOC0xMS42LDYuOC05LjEsMTcuM0MtOTguMS0zLjItODkuOS0zLjUtODkuOS0zLjVzNi4yLDAuNiwxMy4zLTEuMWM3LjEtMS43LDEzLjMsMC4zLDEzLjMsMC4zUy00Ni42LDEuMy00Mi05LjcNCgkJCUMtMzcuNS0xOS43LTQ0LjYtMjUuMy00NC42LTI1LjNMLTQ0LjYtMjUuM3oiLz4NCgk8L2c+DQo8L2c+DQo8L3N2Zz4NCg==">
</div>
</div>
</div>
</div>
<div class="pure-u-1-6">
<div class="block pure-g">
<div class="pure-u-3-5">
<h4 id="game_status"><%:Game Mode%><br /><span class="red"><%:Not Running%></span></h4>
@ -34,7 +64,7 @@ math.randomseed(os.time())
</div>
</div>
</div>
<div class="pure-u-1-4">
<div class="pure-u-1-6">
<div class="block pure-g">
<div class="pure-u-3-5">
<h4 id="pdnsd_status">PDNSD<br /><span class="red"><%:Not Running%></span></h4>
@ -46,14 +76,14 @@ math.randomseed(os.time())
</div>
</div>
</div>
<div class="pure-u-1-4">
<div class="pure-u-1-6">
<div class="block pure-g">
<div class="pure-u-3-5">
<h4 id="socks5_status">SOCKS5<br /><span class="red"><%:Not Running%></span></h4>
</div>
<div class="pure-u-2-5">
<div class="img-con">
<img src="/luci-static/vssr/img/socks5.svg">
<img src="https://i.imgur.com/bYz9YoR.png" >
</div>
</div>
</div>
@ -64,14 +94,14 @@ math.randomseed(os.time())
const $$ = document;
function get_state(){
$.get('<%=url([[admin]], [[services]], [[vssr]], [[run]])%>',
$.get('<%=url([[admin]], [[vpn]], [[vssr]], [[run]])%>',
function (data) {
console.log(data);
}, "json");
}
//get_state();
//<![CDATA[
XHR.poll(5, '<%=url([[admin]], [[services]], [[vssr]], [[run]])%>', null,
XHR.poll(5, '<%=url([[admin]], [[vpn]], [[vssr]], [[run]])%>', null,
function (x, data) {
var tb = document.getElementById('vssr_status');
var tb1 = document.getElementById('google_status');
@ -84,6 +114,16 @@ math.randomseed(os.time())
tb.innerHTML = '<%:Client%><br><span class="green"><%:Running%></span>';
} else {
tb.innerHTML = '<%:Client%><br><span class="red"><%:Not Running%></span>';
}
if (data.google) {
tb1.innerHTML = '<%:Visit foreign websites%><br><span class="green"><%:Working...%></span>';
} else {
tb1.innerHTML = '<%:Visit foreign websites%><br><span class="red"><%:Problem detected%></span>';
}
if (data.baidu) {
tb2.innerHTML = '<%:Visit domestic website%><br><span class="green"><%:Working...%></span>';
} else {
tb2.innerHTML = '<%:Visit domestic website%><br><span class="red"><%:Problem detected%></span>';
}
if (data.game) {
tb3.innerHTML = '<%:Game Mode%><br><span class="green"><%:Running%></span>';
@ -108,4 +148,4 @@ math.randomseed(os.time())
</script>
</body>
</html>
</html></fieldset>

View File

@ -9,7 +9,7 @@ math.randomseed(os.time())
<div class="pure-g">
<div class="pure-u-1-2">
<span class="flag"><img src="/luci-static/vssr/flags/4x3/un.svg" class="pure-img"></span> <span
class="status-info">获取中...</span>
class="status-info"></span>
</div>
<div class="pure-u-1-2">
<div class="icon-con">
@ -36,10 +36,10 @@ math.randomseed(os.time())
$(window).resize(resize);
$(document).ready(function () {
resize();
$.getJSON("<%=url([[admin]], [[services]], [[vssr]], [[ip]])%>", function (data) {
$.getJSON("<%=url([[admin]], [[vpn]], [[vssr]], [[ip]])%>", function (data) {
wirte_status(data);
});
XHR.poll(5, '<%=url([[admin]], [[services]], [[vssr]], [[ip]])%>', null,
XHR.poll(5, '<%=url([[admin]], [[vpn]], [[vssr]], [[ip]])%>', null,
function (x, data) {
wirte_status(data);
}

View File

@ -5,8 +5,8 @@
</fieldset>
<!-- tblsection -->
<fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<button class="cbi-button cbi-button-check "><%:Ping All Servers%></button><span class="panel-title">总计
<%- print(self.des)-%>个节点</span>
<button class="cbi-button cbi-button-check "><%:Ping All Servers%></button><span class="panel-title"><%:Node list%> <%:total%>
&nbsp; <%- print(self.des)-%><%:Nodes%></span>
<div class="cbi-section-node">
<%- local count = 0 -%>
<div class="cbi-section-table pure-g p-in5">
@ -35,7 +35,7 @@
</div>
<a class="cbi-button ssr-button " type="button" value="" onclick="apply_node('<%=section%>')"
alt="应用" title="应用"><span class="icon-edit"></span> 应用</a>
alt="<%:Apply%>" title="<%:Apply%>"><span class="icon-edit"></span> <%:Apply%></a>
<%- if self.extedit then -%>
<a class="cbi-button ssr-button " type="button" value="" <%- if type(self.extedit) == "string" then
%> onclick="location.href='<%=self.extedit:format(section)%>'" <%- elseif type(self.extedit) == "function" then
@ -93,6 +93,7 @@
</fieldset>
<!-- /tblsection -->
<script type="text/javascript">
var servers = '<%= self.servers%>';
servers = JSON.parse(servers.replace(/\t/g,""));
$.each(servers, function (i, val) {
@ -109,6 +110,7 @@
$(id).find(".type .tp").text(val.type);
$(id).find(".type").addClass("flag-icon-" + val.flag);
$(id).find(".alias").text(val.alias);
$(id).attr("server", val.server);
$(id).attr("server_port", val.server_port);
});
@ -117,7 +119,7 @@
function apply_node(node) {
$("#cbi-apply-vssr1").show();
$.get('<%=luci.dispatcher.build_url("admin", "services", "vssr","change")%>',
$.get('<%=luci.dispatcher.build_url("admin", "vpn", "vssr","change")%>',
{
set: node
},
@ -132,6 +134,11 @@
});
}
$(document).ready(function () {
/*$.get('<%=luci.dispatcher.build_url("admin", "vpn", "vssr","allserver")%>',
function (data) {
}, "json");*/
setTimeout(function() { check(); }, 500);
function check() {
$(".host_con").html("");
@ -146,7 +153,7 @@
function check_port(hosts, ports, target) {
$.get('<%=luci.dispatcher.build_url("admin", "services", "vssr","checkport")%>',
$.get('<%=luci.dispatcher.build_url("admin", "vpn", "vssr","checkport")%>',
{
host: hosts,
port: ports
@ -188,6 +195,19 @@
return false;
});
//转换 emoji
});
</script>
</script>
<fieldset class="cbi-section">
<tr>
<td colspan="4" width="100%">
<p align="center"> <img src="https://i.imgur.com/9ejUjam.gif"
</p></script>

View File

@ -60,7 +60,7 @@
//console.log(data);
$.ajax({
type: "post",
url: "<%=luci.dispatcher.build_url('admin', 'services', 'vssr','subscribe')%>",
url: "<%=luci.dispatcher.build_url('admin', 'vpn', 'vssr','subscribe')%>",
dataType : "json",
data: data,
success: function (d) {
@ -102,7 +102,7 @@
}
console.log(noChange);
if (noChange > 10) {
window.location.href="<%=luci.dispatcher.build_url('admin', 'services', 'vssr','servers')%>"
window.location.href="<%=luci.dispatcher.build_url('admin', 'vpn', 'vssr','servers')%>"
return false;
} else {
setTimeout("get_realtime_log();", 250);

View File

@ -1,11 +1,6 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\n"
msgid "vssr"
msgstr "Hello World"
msgid "Client"
msgstr "客户端"
msgid "Enable"
msgstr "启用"
@ -13,26 +8,126 @@ msgstr "启用"
msgid "Disable"
msgstr "停用"
msgid "Enable Servers"
msgstr "开启服务"
msgid "Socks user"
msgstr "用户名"
msgid "Socks pass"
msgstr "密码"
msgid "Ping All Servers"
msgstr "PING 所有节点"
msgid "vssr Server"
msgstr "vssr 服务端"
msgid "SSR SOCKS5 Proxy"
msgstr "SSR SOCKS5代理"
msgid "Subscription"
msgstr "订阅管理"
msgid "Subscribing,Please do not refresh!"
msgstr "订阅,请不要刷新!"
msgid "Check Try Count"
msgstr "切换检查重试次数"
msgid "Log"
msgstr "日志"
msgid "Running"
msgstr "运行中"
msgid "Bypass Domain List"
msgstr "不走代理的域名"
msgid "Black Domain List"
msgstr "强制走代理的域名"
msgid "Node List"
msgstr "节点列表"
msgid "END SUBSCRIBE"
msgstr "结束订阅"
msgid "Update Setting"
msgstr "更新设置"
msgid "AlterId"
msgstr "额外ID"
msgid "Save And Start Subscribe"
msgstr "保存并开始订阅"
msgid "VmessId (UUID)"
msgstr "用户ID(UUID)"
msgid "Transport"
msgstr "传输方式"
msgid "Configuration Url"
msgstr "配置链接"
msgid "Import Configuration"
msgstr "导入配置信息"
msgid "Apply"
msgstr "应用"
msgid "total"
msgstr "总计"
msgid "Node list"
msgstr "节点列表"
msgid "Nodes"
msgstr "个节点"
msgid "Client"
msgstr "客户端"
msgid "Visit foreign websites"
msgstr "访问国外网站"
msgid "Visit domestic website"
msgstr "访问国内网站"
msgid "Problem detected"
msgstr "无法访问"
msgid "Working..."
msgstr "连接正常"
msgid "Not Running"
msgstr "未运行"
msgid "Game Mode"
msgstr "游戏模式"
msgid "V2ray SOCKS5 Proxy"
msgstr "V2ray SOCKS5代理"
msgid "Edit vssr Server"
msgstr "编辑服务器配置"
msgid "ShadowSocksR is running"
msgstr "ShadowSocksR 客户端运行中"
msgid "ShadowSocksR is not running"
msgstr "ShadowSocksR 客户端未运行"
msgid "Global Setting"
msgstr "全局设置"
msgid "Global Server"
msgstr "全局服务器"
msgid "vssr SOCK5 Proxy is running"
msgstr "vssr SOCK5代理运行中"
msgid "ShadowSocksR SOCK5 Proxy is running"
msgstr "ShadowSocksR SOCK5代理运行中"
msgid "UDP Relay Server"
msgstr "UDP中继服务器"
@ -122,19 +217,19 @@ msgid "LAN Host List"
msgstr "内网主机列表"
msgid "SSR Client"
msgstr "基本设置"
msgstr "客户端"
msgid "SSR Server"
msgstr "服务端"
msgid "vssr Server"
msgstr "vssr 服务端"
msgid "ShadowSocksR Server"
msgstr "ShadowSocksR 服务端"
msgid "vssr Server is running"
msgstr "vssr 服务端运行中"
msgid "ShadowSocksR Server is running"
msgstr "ShadowSocksR 服务端运行中"
msgid "vssr Server is not running"
msgstr "vssr 服务端未运行"
msgid "ShadowSocksR Server is not running"
msgstr "ShadowSocksR 服务端未运行"
msgid "Enable Server"
msgstr "启动服务端"
@ -166,14 +261,14 @@ msgstr "Kcptun可执行文件格式不正确请确认是否正确下载了路
msgid "Enable Process Monitor"
msgstr "启用进程监控"
msgid "Edit vssr Server"
msgid "Edit ShadowSocksR Server"
msgstr "编辑服务器配置"
msgid "Alias"
msgstr "别名"
msgid "V2ray SOCKS5 Proxy"
msgstr "V2ray SOCKS5代理"
msgid "SOCKS5 Proxy"
msgstr "SOCKS5代理"
msgid "Server"
msgstr "服务器"
@ -190,6 +285,9 @@ msgstr "未知"
msgid "Running Status"
msgstr "运行状态"
msgid "vssr"
msgstr "Hello World"
msgid "Global Client"
msgstr "TCP透明代理"
@ -383,8 +481,8 @@ msgstr "通过代理更新"
msgid "GFW List"
msgstr "GFW列表"
msgid "Basic Settings"
msgstr "基本设置支持SS/SSR/V2RAY"
msgid "ShadowSocksR Plus+ Settings"
msgstr "ShadowSocksR Plus+ 设置支持SS/SSR/V2RAY"
msgid "Main Server"
msgstr "主服务器"
@ -405,28 +503,25 @@ msgid "Auto Update Server subscription, GFW list and CHN route"
msgstr "自动更新服务器订阅、GFW列表和 CHN路由表"
msgid "Subscribe URL"
msgstr "SSR/V2RAY订阅URL地址"
msgstr "SS/SSR/V2RAY订阅URL地址"
msgid "Update"
msgstr "更新"
msgid "Save And Start Subscribe"
msgstr "保存并开始订阅"
msgid "Server Count"
msgstr "节点数量"
msgstr "服务器节点数量"
msgid "IP black-and-white list"
msgstr "黑白名单"
msgstr "IP黑白名单"
msgid "WAN IP AC"
msgstr "广域网访问控制"
msgstr "WAN IP访问控制"
msgid "WAN White List IP"
msgstr "不走代理的广域网 IP"
msgstr "不走代理的WAN IP"
msgid "WAN Force Proxy IP"
msgstr "强制走代理的广域网 IP"
msgstr "强制走代理的WAN IP"
msgid "LAN Bypassed Host List"
msgstr "不走代理的局域网LAN IP"
@ -456,16 +551,13 @@ msgid "Please refer to the following writing"
msgstr "每行一个域名,无需写前面的 HTTP(S):// ,提交后即时生效"
msgid "Servers subscription and manage"
msgstr "服务器节点订阅管理支持SSR/V2ray 订阅)"
msgid "Subscription"
msgstr "节点订阅"
msgid "Through proxy update list, Not Recommended"
msgstr "通过路由器自身代理更新订阅(不推荐)"
msgid "LAN IP AC"
msgstr "局域网访问控制"
msgstr "LAN IP访问控制"
msgid "Game Mode UDP Server"
msgstr "游戏模式UDP中继服务器"
@ -480,7 +572,7 @@ msgid "Delete all severs"
msgstr "删除所有服务器"
msgid "Severs Nodes"
msgstr "节点列表"
msgstr "服务器节点"
msgid "Use Local DNS Service listen port 5335"
msgstr "使用本机端口为5335的DNS服务"
@ -521,90 +613,6 @@ msgstr "所有端口(默认)"
msgid "Only Common Ports"
msgstr "仅常用端口不走P2P流量到代理"
msgid "Ping Latency"
msgstr "Ping延迟"
msgid "Bypass Domain List"
msgstr "直连域名"
msgid "Black Domain List"
msgstr "代理域名"
msgid "Socks user"
msgstr "用户名"
msgid "Socks pass"
msgstr "密码"
msgid "Enable Servers"
msgstr "开启服务"
msgid "Subscribing,Please do not refresh!"
msgstr "请勿刷新本页面,正在订阅中 ..."
msgid "Apply"
msgstr "应用"
msgid "Edit"
msgstr "修改"
msgid "Delete"
msgstr "删除"
msgid "Ping All Servers"
msgstr "Ping 所有节点"
msgid "Check Ip And Access"
msgstr "Ip地址检查"
msgid "Test From Internal"
msgstr "从国内测试"
msgid "Test From Abroad"
msgstr "从国外测试"
msgid "Test From Google"
msgstr "从谷歌测试"
msgid "Baidu"
msgstr "百度搜索"
msgid "Connection OK"
msgstr "访问正常"
msgid "Cannot Access"
msgstr "无法访问"
msgid "Unavailable"
msgstr "无法获取"
msgid "Connection Timeout"
msgstr "连接超时"
msgid "Update Setting"
msgstr "更新设置"
msgid "Paste Node Link Here"
msgstr "在这里粘贴配置链接"
msgid "User Cancel"
msgstr "用户取消"
msgid "Invalid Format"
msgstr "无效的格式"
msgid "Import Configuration"
msgstr "导入配置信息"
msgid "Import"
msgstr "导入"
msgid "Configuration Succeeded"
msgstr "配置信息成功"
msgid "Import Configuration"
msgstr "导入配置信息"
msgid "Configuration Url"
msgstr "配置链接"

View File

@ -0,0 +1 @@
0xDEADBEEF

View File

@ -9,6 +9,7 @@ config global
option enable_switch '1'
option switch_timeout '5'
option switch_time '667'
option switch_try_count '3'
config socks5_proxy
option server 'nil'

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@ add_cron() {
sed -i '/vssr.log/d' $CRON_FILE
echo '0 1 * * 0 echo "" > /tmp/vssr.log' >>$CRON_FILE
[ -n "$(grep -w "/usr/share/vssr/subscribe.sh" $CRON_FILE)" ] && sed -i '/\/usr\/share\/vssr\/subscribe.sh/d' $CRON_FILE
[ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/bin/lua /usr/share/vssr/subscribe.lua" >> $CRON_FILE
[ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/share/vssr/subscribe.sh" >>$CRON_FILE
[ -z "$(grep -w "/usr/share/vssr/update.sh" $CRON_FILE)" ] && echo "0 5 * * 0 /usr/share/vssr/update.sh" >>$CRON_FILE
crontab $CRON_FILE
}
@ -60,68 +60,100 @@ del_cron() {
}
run_mode=$(uci_get_by_type global run_mode)
gen_config_file() {
local host=$(uci_get_by_name $1 server)
if echo $host | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
hostip=${host}
elif [ "$host" != "${host#*:[0-9a-fA-F]}" ]; then
hostip=${host}
else
hostip=`ping ${host} -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1`
if echo $hostip | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
hostip=${hostip}
else
hostip=$(cat /etc/ssr_ip)
fi
fi
[ $2 = "0" -a $kcp_flag = "1" ] && hostip="127.0.0.1"
if [ $2 = "0" ]; then
re_type="tcp"
config_file=$CONFIG_FILE
server_obj=$GLOBAL_SERVER
elif [ $2 = "1" ]; then
re_type="udp"
config_file=$CONFIG_UDP_FILE
server_obj=$UDP_RELAY_SERVER
fi
if [ $(uci_get_by_name $1 fast_open 0) = "1" ]; then
fastopen="true"
else
fastopen="false"
fi
local stype=$(uci_get_by_name $1 type)
lua /usr/share/vssr/genconfig_${stype}.lua ${server_obj} ${re_type} $(uci_get_by_name $1 local_port) ${hostip} >${config_file}
sed -i 's/\\//g' $config_file
local host=$(uci_get_by_name $1 server)
if echo $host|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
hostip=${host}
elif [ "$host" != "${host#*:[0-9a-fA-F]}" ] ;then
hostip=${host}
else
hostip=`ping ${host} -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1`
if echo $hostip|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
hostip=${hostip}
else
hostip=`cat /etc/ssr_ip`
fi
fi
[ $2 = "0" -a $kcp_flag = "1" ] && hostip="127.0.0.1"
if [ $2 = "0" ] ;then
config_file=$CONFIG_FILE
elif [ $2 = "1" ]; then
config_file=$CONFIG_UDP_FILE
else
config_file=$CONFIG_SOCK5_FILE
fi
if [ $(uci_get_by_name $1 fast_open 0) = "1" ] ;then
fastopen="true";
else
fastopen="false";
fi
local stype=$(uci_get_by_name $1 type)
if [ "$stype" == "ss" ] ;then
cat <<-EOF >$config_file
{
"server": "$hostip",
"server_port": $(uci_get_by_name $1 server_port),
"local_address": "0.0.0.0",
"local_port": $(uci_get_by_name $1 local_port),
"password": "$(uci_get_by_name $1 password)",
"timeout": $(uci_get_by_name $1 timeout 60),
"method": "$(uci_get_by_name $1 encrypt_method_ss)",
"reuse_port": true,
"fast_open": $fastopen
}
EOF
elif [ "$stype" == "ssr" ] ;then
cat <<-EOF >$config_file
{
"server": "$hostip",
"server_port": $(uci_get_by_name $1 server_port),
"local_address": "0.0.0.0",
"local_port": $(uci_get_by_name $1 local_port),
"password": "$(uci_get_by_name $1 password)",
"timeout": $(uci_get_by_name $1 timeout 60),
"method": "$(uci_get_by_name $1 encrypt_method)",
"protocol": "$(uci_get_by_name $1 protocol)",
"protocol_param": "$(uci_get_by_name $1 protocol_param)",
"obfs": "$(uci_get_by_name $1 obfs)",
"obfs_param": "$(uci_get_by_name $1 obfs_param)",
"reuse_port": true,
"fast_open": $fastopen
}
EOF
elif [ "$stype" == "v2ray" ] ;then
lua /usr/share/vssr/genv2config.lua $GLOBAL_SERVER tcp $(uci_get_by_name $1 local_port) > /var/etc/v2-ssr-retcp.json
sed -i 's/\\//g' /var/etc/v2-ssr-retcp.json
elif [ "$stype" == "trojan" ] ;then
lua /usr/share/vssr/gentrojanconfig.lua $GLOBAL_SERVER nat $(uci_get_by_name $1 local_port) > /var/etc/trojan-ssr-retcp.json
sed -i 's/\\//g' /var/etc/trojan-ssr-retcp.json
fi
}
get_arg_out() {
case "$(uci_get_by_type access_control router_proxy 1)" in
1) echo "-o" ;;
2) echo "-O" ;;
1) echo "-o";;
2) echo "-O";;
esac
}
start_rules() {
local server=$(uci_get_by_name $GLOBAL_SERVER server)
#resolve name
if echo $server | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
server=${server}
elif [ "$server" != "${server#*:[0-9a-fA-F]}" ]; then
server=${server}
if echo $server|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
server=${server}
elif [ "$server" != "${server#*:[0-9a-fA-F]}" ] ;then
server=${server}
else
server=`ping ${server} -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1`
if echo $server | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
echo $server >/etc/ssr_ip
else
server=$(cat /etc/ssr_ip)
fi
server=`ping ${server} -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1`
if echo $server|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
echo $server >/etc/ssr_ip
else
server=`cat /etc/ssr_ip`
fi
fi
kcp_server=$server
local kcp_enable=$(uci_get_by_name $GLOBAL_SERVER kcp_enable 0)
@ -185,19 +217,19 @@ start_rules() {
start_pdnsd() {
local usr_dns="$1"
local usr_port="$2"
local usr_port="$2"
local tcp_dns_list="208.67.222.222, 208.67.220.220"
[ -z "$usr_dns" ] && usr_dns="8.8.8.8"
[ -z "$usr_port" ] && usr_port="53"
[ -d /var/etc ] || mkdir -p /var/etc
[ -d /var/etc ] || mkdir -p /var/etc
if [ ! -d /var/pdnsd ]; then
mkdir -p /var/pdnsd
echo -ne "pd13\000\000\000\000" >/var/pdnsd/pdnsd.cache
chown -R nobody:nogroup /var/pdnsd
fi
if [ ! -d /var/pdnsd ];then
mkdir -p /var/pdnsd
echo -ne "pd13\000\000\000\000" >/var/pdnsd/pdnsd.cache
chown -R nobody:nogroup /var/pdnsd
fi
cat >/var/etc/pdnsd.conf <<EOF
global {
@ -241,16 +273,16 @@ EOF
start_redir() {
case "$(uci_get_by_name $GLOBAL_SERVER auth_enable)" in
1 | on | true | yes | enabled) ARG_OTA="-A" ;;
*) ARG_OTA="" ;;
1|on|true|yes|enabled) ARG_OTA="-A";;
*) ARG_OTA="";;
esac
#deal kcp
local kcp_enable=$(uci_get_by_name $GLOBAL_SERVER kcp_enable 0)
if [ $kcp_enable = "1" ]; then
[ ! -f "/usr/bin/kcptun-client" ] && return 1
local kcp_str=$(/usr/bin/kcptun-client -v | grep kcptun | wc -l)
if [ $kcp_enable = "1" ] ;then
[ ! -f "/usr/bin/kcptun-client" ] && return 1
local kcp_str=`/usr/bin/kcptun-client -v |grep kcptun|wc -l`
[ "0" = $kcp_str ] && return 1
local kcp_port=$(uci_get_by_name $GLOBAL_SERVER kcp_port)
local server_port=$(uci_get_by_name $GLOBAL_SERVER server_port)
@ -259,90 +291,100 @@ start_redir() {
[ "$password" != "" ] && password="--key "${password}
service_start /usr/bin/kcptun-client \
-r $kcp_server:$kcp_port \
-l :$server_port $password $kcp_param
-l :$server_port $password $kcp_param
kcp_enable_flag=1
fi
gen_config_file $GLOBAL_SERVER 0
local stype=$(uci_get_by_name $GLOBAL_SERVER type)
if [ "$stype" == "ss" -o "$stype" == "v2ray" ]; then
sscmd="/usr/bin/v2ray/v2ray"
elif [ "$stype" == "ssr" ]; then
sscmd="/usr/bin/ssr-redir"
fi
local utype=$(uci_get_by_name $UDP_RELAY_SERVER type)
if [ "$utype" == "ss" -o "$utype" == "v2ray" ]; then
ucmd="/usr/bin/v2ray/v2ray"
elif [ "$utype" == "ssr" ]; then
ucmd="/usr/bin/ssr-redir"
fi
if [ "$(uci_get_by_type global threads 0)" = "0" ]; then
threads=$(cat /proc/cpuinfo | grep 'processor' | wc -l)
else
threads=$(uci_get_by_type global threads)
fi
gen_config_file $GLOBAL_SERVER 0
local stype=$(uci_get_by_name $GLOBAL_SERVER type)
if [ "$stype" == "ss" ] ;then
sscmd="/usr/bin/ss-redir"
elif [ "$stype" == "ssr" ] ;then
sscmd="/usr/bin/ssr-redir"
elif [ "$stype" == "v2ray" ] ;then
sscmd="/usr/bin/v2ray/v2ray"
elif [ "$stype" == "trojan" ] ;then
sscmd="/usr/sbin/trojan"
fi
local utype=$(uci_get_by_name $UDP_RELAY_SERVER type)
if [ "$utype" == "ss" ] ;then
ucmd="/usr/bin/ss-redir"
elif [ "$utype" == "ssr" ] ;then
ucmd="/usr/bin/ssr-redir"
elif [ "$utype" == "v2ray" ] ;then
ucmd="/usr/bin/v2ray/v2ray"
elif [ "$utype" == "trojan" ] ;then
ucmd="/usr/sbin/trojan"
fi
if [ "$(uci_get_by_type global threads 0)" = "0" ] ;then
threads=$(cat /proc/cpuinfo | grep 'processor' | wc -l)
else
threads=$(uci_get_by_type global threads)
fi
#转发TCP
redir_tcp=1
local last_config_file=$CONFIG_FILE
if [ "$stype" == "ssr" ]; then
if [ "$stype" == "ss" -o "$stype" == "ssr" ] ;then
local last_config_file=$CONFIG_FILE
local pid_file="/var/run/ssr-retcp.pid"
for i in $(seq 1 $threads)
do
$sscmd -c $CONFIG_FILE $ARG_OTA -f /var/run/ssr-retcp_$i.pid >/dev/null 2>&1
done
local pid_file="/var/run/ssr-retcp.pid"
for i in $(seq 1 $threads); do
$sscmd -c $last_config_file $ARG_OTA -f /var/run/ssr-retcp_$i.pid >/dev/null 2>&1
done
echo "$(date "+%Y-%m-%d %H:%M:%S") Shadowsocks/ShadowsocksR $threads 线程 已启动!" >> /tmp/vssr.log
elif [ "$stype" == "v2ray" ] ;then
$sscmd -config /var/etc/v2-ssr-retcp.json >/dev/null 2>&1 &
echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd -version | head -1) 已启动!" >> /tmp/vssr.log
echo "$(date "+%Y-%m-%d %H:%M:%S") SSR $threads 线程 已启动!" >> /tmp/vssr.log
elif [ "$stype" == "v2ray" -o "$stype" == "ss" ]; then
$sscmd -config $last_config_file >/dev/null 2>&1 &
echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd -version | head -1) 已启动!" >> /tmp/vssr.log
elif [ "$stype" == "trojan" ] ;then
$sscmd --config /var/etc/trojan-ssr-retcp.json >/dev/null 2>&1 &
echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd --version 2>&1 | head -1) 已启动!" >> /tmp/vssr.log
fi
#转发UDP
if [ -n "$UDP_RELAY_SERVER" ]; then
redir_udp=1
gen_config_file $UDP_RELAY_SERVER 1
last_config_file=$CONFIG_UDP_FILE
echo $utype
if [ "$utype" == "ssr" ]; then
case "$(uci_get_by_name $UDP_RELAY_SERVER auth_enable)" in
1 | on | true | yes | enabled) ARG_OTA="-A" ;;
*) ARG_OTA="" ;;
esac
pid_file="/var/run/ssr-reudp.pid"
#echo $ucmd >> /tmp/vssr.log
$ucmd -c $last_config_file $ARG_OTA -U -f /var/run/ssr-reudp.pid >/tmp/vssr.log 2>&1
#echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd -version | head -1) UDP已启动!" >> /tmp/vssr.log
elif [ "$utype" == "ss" -o "$utype" == "v2ray" ]; then
$ucmd -config $last_config_file >/dev/null 2>&1 &
fi
fi
if [ -n "$UDP_RELAY_SERVER" ] ;then
redir_udp=1
if [ "$utype" == "ss" -o "$utype" == "ssr" ] ;then
case "$(uci_get_by_name $UDP_RELAY_SERVER auth_enable)" in
1|on|true|yes|enabled) ARG_OTA="-A";;
*) ARG_OTA="";;
esac
gen_config_file $UDP_RELAY_SERVER 1
last_config_file=$CONFIG_UDP_FILE
pid_file="/var/run/ssr-reudp.pid"
$ucmd -c $last_config_file $ARG_OTA -U -f /var/run/ssr-reudp.pid >/dev/null 2>&1
elif [ "$utype" == "v2ray" ] ; then
lua /usr/share/vssr/genv2config.lua $UDP_RELAY_SERVER udp $(uci_get_by_name $UDP_RELAY_SERVER local_port) > /var/etc/v2-ssr-reudp.json
sed -i 's/\\//g' /var/etc/v2-ssr-reudp.json
$ucmd -config /var/etc/v2-ssr-reudp.json >/dev/null 2>&1 &
elif [ "$utype" == "trojan" ] ;then
lua /usr/share/vssr/gentrojanconfig.lua $GLOBAL_SERVER client 10801 > /var/etc/trojan-ssr-reudp.json
sed -i 's/\\//g' /var/etc/trojan-ssr-reudp.json
$ucmd --config /var/etc/trojan-ssr-reudp.json >/dev/null 2>&1 &
ipt2socks -U -4 -b 0.0.0.0 -s 127.0.0.1 -p 10801 -l $(uci_get_by_name $UDP_RELAY_SERVER local_port) >/dev/null 2>&1 &
fi
fi
#deal with dns
if [ "$(uci_get_by_type global pdnsd_enable)" = "1" ]; then
local dnsstr="$(uci_get_by_type global tunnel_forward 8.8.4.4:53)"
local dnsserver=$(echo "$dnsstr" | awk -F ':' '{print $1}')
local dnsport=$(echo "$dnsstr" | awk -F ':' '{print $2}')
if [ "$run_mode" = "gfw" ]; then
ipset add gfwlist $dnsserver 2>/dev/null
elif [ "$run_mode" = "oversea" ]; then
ipset add oversea $dnsserver 2>/dev/null
else
ipset add ss_spec_wan_ac $dnsserver nomatch 2>/dev/null
fi
start_pdnsd $dnsserver $dnsport
pdnsd_enable_flag=1
fi
if [ "$(uci_get_by_type global enable_switch)" = "1" ]; then
if [ "$(uci_get_by_name $GLOBAL_SERVER switch_enable)" = "1" ]; then
if [ -z "$switch_server" ]; then
if [ "$(uci_get_by_type global pdnsd_enable)" = "1" ] ;then
local dnsstr="$(uci_get_by_type global tunnel_forward 8.8.4.4:53)"
local dnsserver=`echo "$dnsstr"|awk -F ':' '{print $1}'`
local dnsport=`echo "$dnsstr"|awk -F ':' '{print $2}'`
if [ "$run_mode" = "gfw" ]; then
ipset add gfwlist $dnsserver 2>/dev/null
elif [ "$run_mode" = "oversea" ]; then
ipset add oversea $dnsserver 2>/dev/null
else
ipset add ss_spec_wan_ac $dnsserver nomatch 2>/dev/null
fi
start_pdnsd $dnsserver $dnsport
pdnsd_enable_flag=1
fi
if [ "$(uci_get_by_type global enable_switch)" = "1" ] ;then
if [ "$(uci_get_by_name $GLOBAL_SERVER switch_enable)" = "1" ] ;then
if [ -z "$switch_server" ] ;then
local switch_time=$(uci_get_by_type global switch_time)
local switch_timeout=$(uci_get_by_type global switch_timeout)
service_start /usr/bin/vssr-switch start $switch_time $switch_timeout
@ -354,13 +396,12 @@ start_redir() {
return $?
}
gen_service_file() {
if [ $(uci_get_by_name $1 fast_open) = "1" ]; then
fastopen="true"
if [ $(uci_get_by_name $1 fast_open) = "1" ] ;then
fastopen="true";
else
fastopen="false"
fi
fastopen="false";
fi
cat <<-EOF >$2
{
"server": "0.0.0.0",
@ -374,40 +415,40 @@ gen_service_file() {
"obfs_param": "$(uci_get_by_name $1 obfs_param)",
"fast_open": $fastopen
}
EOF
EOF
}
start_service() {
[ $(uci_get_by_name $1 enable) = "0" ] && return 1
let server_count=server_count+1
if [ $server_count = 1 ]; then
iptables -N SSR-SERVER-RULE &&
iptables -t filter -I INPUT -j SSR-SERVER-RULE
fi
[ $(uci_get_by_name $1 enable) = "0" ] && return 1
let server_count=server_count+1
if [ $server_count = 1 ] ;then
iptables -N SSR-SERVER-RULE && \
iptables -t filter -I INPUT -j SSR-SERVER-RULE
fi
gen_service_file $1 /var/etc/${NAME}_${server_count}.json
/usr/bin/ssr-server -c /var/etc/${NAME}_${server_count}.json -u -f /var/run/ssr-server${server_count}.pid >/dev/null 2>&1
iptables -t filter -A SSR-SERVER-RULE -p tcp --dport $(uci_get_by_name $1 server_port) -j ACCEPT
iptables -t filter -A SSR-SERVER-RULE -p udp --dport $(uci_get_by_name $1 server_port) -j ACCEPT
return 0
gen_service_file $1 /var/etc/${NAME}_${server_count}.json
/usr/bin/ssr-server -c /var/etc/${NAME}_${server_count}.json -u -f /var/run/ssr-server${server_count}.pid >/dev/null 2>&1
iptables -t filter -A SSR-SERVER-RULE -p tcp --dport $(uci_get_by_name $1 server_port) -j ACCEPT
iptables -t filter -A SSR-SERVER-RULE -p udp --dport $(uci_get_by_name $1 server_port) -j ACCEPT
return 0
}
gen_serv_include() {
FWI=$(uci get firewall.vssr.path 2>/dev/null)
[ -n "$FWI" ] || return 0
if [ ! -f $FWI ]; then
echo '#!/bin/sh' >$FWI
fi
extract_rules() {
echo "*filter"
iptables-save -t filter | grep SSR-SERVER-RULE | sed -e "s/^-A INPUT/-I INPUT/"
echo 'COMMIT'
}
FWI=$(uci get firewall.vssr.path 2>/dev/null)
[ -n "$FWI" ] || return 0
if [ ! -f $FWI ] ;then
echo '#!/bin/sh' >$FWI
fi
extract_rules() {
echo "*filter"
iptables-save -t filter | grep SSR-SERVER-RULE|sed -e "s/^-A INPUT/-I INPUT/"
echo 'COMMIT'
}
cat <<-EOF >>$FWI
iptables-save -c | grep -v "SSR-SERVER" | iptables-restore -c
iptables-restore -n <<-EOT
$(extract_rules)
EOT
EOF
iptables-save -c | grep -v "SSR-SERVER" | iptables-restore -c
iptables-restore -n <<-EOT
$(extract_rules)
EOT
EOF
}
start_server() {
@ -420,22 +461,32 @@ start_server() {
gen_serv_include
return 0
}
start_local() {
local local_server=$(uci_get_by_type socks5_proxy enable_server)
local local_port=$(uci_get_by_type socks5_proxy local_port)
local Socks_user=$(uci_get_by_type socks5_proxy Socks_user)
local Socks_pass=$(uci_get_by_type socks5_proxy Socks_pass)
[ "$local_server" = "0" ] && return 1
local local_server=$(uci_get_by_type socks5_proxy server)
local http_enable=$(uci_get_by_type socks5_proxy http_enable)
local stype=$(uci_get_by_name $local_server type)
[ "$local_server" = "nil" ] && return 1
mkdir -p /var/run /var/etc
gen_config_file $local_server 2
if [ "$stype" == "ssr" ] ;then
/usr/bin/ssr-local -c $CONFIG_SOCK5_FILE -u \
-l $(uci_get_by_type socks5_proxy local_port 1080) \
-b $(uci_get_by_type socks5_proxy local_address 0.0.0.0) \
-f /var/run/ssr-local.pid >/dev/null 2>&1
local_enable=1
elif [ "$stype" == "ss" ] ;then
/usr/bin/ss-local -c $CONFIG_SOCK5_FILE -u \
-l $(uci_get_by_type socks5_proxy local_port 1080) \
-b $(uci_get_by_type socks5_proxy local_address 0.0.0.0) \
-f /var/run/ss-local.pid >/dev/null 2>&1
local_enable=2
elif [ "$stype" == "v2ray" ] ;then
lua /usr/share/vssr/genv2config_local.lua $local_server tcp $(uci_get_by_name $local_server local_port) $(uci_get_by_type socks5_proxy local_port 1080) > /var/etc/v2-ssr-local.json
sed -i 's/\\//g' /var/etc/v2-ssr-local.json
/usr/bin/v2ray/v2ray -config /var/etc/v2-ssr-local.json >/dev/null 2>&1 &
local_enable=3
fi
lua /usr/share/vssr/genconfig_v2ray_s.lua "socks" ${local_port} ${Socks_user} ${Socks_pass} >$CONFIG_SOCK5_FILE
sed -i 's/\\//g' $config_file
/usr/bin/v2ray/v2ray -config $CONFIG_SOCK5_FILE >/dev/null 2>&1 &
local_enable=1
}
rules() {
@ -443,87 +494,95 @@ rules() {
mkdir -p /var/run /var/etc
UDP_RELAY_SERVER=$(uci_get_by_type global udp_relay_server)
[ "$UDP_RELAY_SERVER" = "same" ] && UDP_RELAY_SERVER=$GLOBAL_SERVER
if start_rules; then
return 0
if start_rules ;then
return 0
else
return 1
return 1
fi
}
start() {
if [ -z "$switch_server" ]; then
GLOBAL_SERVER=$(uci_get_by_type global global_server)
start() {
if [ -z "$switch_server" ] ;then
GLOBAL_SERVER=$(uci_get_by_type global global_server)
else
GLOBAL_SERVER=$switch_server
switch_enable=1
GLOBAL_SERVER=$switch_server
switch_enable=1
fi
if rules; then
start_redir
mkdir -p /tmp/dnsmasq.d && cp -a /etc/dnsmasq.ssr /tmp/ && cp -a /etc/dnsmasq.oversea /tmp/
if ! [ "$run_mode" = "oversea" ]; then
cat >/tmp/dnsmasq.d/dnsmasq-ssr.conf <<EOF
if rules ;then
start_redir
mkdir -p /tmp/dnsmasq.d && cp -a /etc/dnsmasq.ssr /tmp/ && cp -a /etc/dnsmasq.oversea /tmp/
if ! [ "$run_mode" = "oversea" ] ;then
cat > /tmp/dnsmasq.d/dnsmasq-ssr.conf <<EOF
conf-dir=/tmp/dnsmasq.ssr
EOF
else
cat >/tmp/dnsmasq.d/dnsmasq-ssr.conf <<EOF
else
cat > /tmp/dnsmasq.d/dnsmasq-ssr.conf <<EOF
conf-dir=/tmp/dnsmasq.oversea
EOF
fi
/usr/share/vssr/gfw2ipset.sh
/etc/init.d/dnsmasq restart >/dev/null 2>&1
fi
/usr/share/vssr/gfw2ipset.sh
/etc/init.d/dnsmasq restart >/dev/null 2>&1
fi
start_server
start_local
if [ $(uci_get_by_type global monitor_enable) = 1 ]; then
let total_count=server_count+redir_tcp+redir_udp+tunnel_enable+kcp_enable_flag+local_enable+pdnsd_enable_flag+switch_enable
if [ $total_count -gt 0 ]; then
#param:server(count) redir_tcp(0:no,1:yes) redir_udp tunnel kcp local gfw
service_start /usr/bin/vssr-monitor $server_count $redir_tcp $redir_udp $tunnel_enable $kcp_enable_flag $local_enable $pdnsd_enable_flag $switch_enable
fi
if [ $(uci_get_by_type global monitor_enable) = 1 ] ;then
let total_count=server_count+redir_tcp+redir_udp+tunnel_enable+kcp_enable_flag+local_enable+pdnsd_enable_flag+switch_enable
if [ $total_count -gt 0 ]
then
#param:server(count) redir_tcp(0:no,1:yes) redir_udp tunnel kcp local gfw
service_start /usr/bin/vssr-monitor $server_count $redir_tcp $redir_udp $tunnel_enable $kcp_enable_flag $local_enable $pdnsd_enable_flag $switch_enable
fi
fi
ENABLE_SERVER=$(uci_get_by_type global global_server)
[ "$ENABLE_SERVER" = "nil" ] && return 1
}
boot() {
(/usr/share/vssr/chinaipset.sh && sleep 5 && start >/dev/null 2>&1) &
}
stop() {
/usr/bin/vssr-rules -f
srulecount=$(iptables -L | grep SSR-SERVER-RULE | wc -l)
if [ $srulecount -gt 0 ]; then
iptables -F SSR-SERVER-RULE
iptables -t filter -D INPUT -j SSR-SERVER-RULE
iptables -X SSR-SERVER-RULE 2>/dev/null
srulecount=`iptables -L|grep SSR-SERVER-RULE|wc -l`
if [ $srulecount -gt 0 ] ;then
iptables -F SSR-SERVER-RULE
iptables -t filter -D INPUT -j SSR-SERVER-RULE
iptables -X SSR-SERVER-RULE 2>/dev/null
fi
if [ -z "$switch_server" ]; then
kill -9 $(busybox ps -w | grep vssr-switch | grep -v grep | awk '{print $1}') >/dev/null 2>&1
if [ -z "$switch_server" ] ;then
kill -9 $(busybox ps -w | grep vssr-switch | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
if [ $(uci_get_by_type global monitor_enable) = 1 ]; then
kill -9 $(busybox ps -w | grep vssr-monitor | grep -v grep | awk '{print $1}') >/dev/null 2>&1
if [ $(uci_get_by_type global monitor_enable) = 1 ] ;then
kill -9 $(busybox ps -w | grep vssr-monitor | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
killall -q -9 vssr-monitor
killall -q -9 ss-redir
killall -q -9 ssr-redir
killall -q -9 ssr-local
killall -q -9 ss-local
killall -q -9 v2ray
killall -q -9 trojan
killall -q -9 ipt2socks
killall -q -9 ssr-server
killall -q -9 kcptun-client
killall -q -9 ssr-local
if [ -f /var/run/pdnsd.pid ]; then
kill $(cat /var/run/pdnsd.pid) >/dev/null 2>&1
else
kill -9 $(busybox ps -w | grep pdnsd | grep -v grep | awk '{print $1}') >/dev/null 2>&1
if [ -f /var/run/pdnsd.pid ] ;then
kill $(cat /var/run/pdnsd.pid) >/dev/null 2>&1
else
kill -9 $(busybox ps -w | grep pdnsd | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
if [ -f "/tmp/dnsmasq.d/dnsmasq-ssr.conf" ]; then
rm -f /tmp/dnsmasq.d/dnsmasq-ssr.conf
/etc/init.d/dnsmasq restart >/dev/null 2>&1
fi
del_cron
fi
del_cron
}

View File

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/sh
#
# Copyright (C) 2017 openwrt-ssr
# Copyright (C) 2017 yushi studio <ywb94@qq.com>
@ -7,6 +7,7 @@
# See /LICENSE for more information.
#
NAME=vssr
uci_get_by_name() {
@ -26,8 +27,8 @@ tunnel_process=$4
kcp_process=$5
local_process=$6
pdnsd_process=$7
if [ -z "$pdnsd_process" ]; then
pdnsd_process=0
if [ -z "$pdnsd_process" ] ;then
pdnsd_process=0
fi
i=0
@ -42,85 +43,117 @@ kcp_param=$(uci_get_by_name $GLOBAL_SERVER kcp_param)
sock5_port=$(uci_get_by_type socks5_proxy local_port 1080)
if echo $server | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
if echo $server|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
server=${server}
else
server=$(cat /etc/ssr_ip)
else
server=`cat /etc/ssr_ip`
fi
while [ "1" = "1" ]; do #这里是个死循环
sleep 30
#redir tcp
if [ $redir_tcp_process -gt 0 ]; then
icount=$(busybox ps -w | grep vssr_t | grep -v grep | wc -l)
if [ $icount = 0 ]; then
while [ "1" = "1" ] #死循环
do
sleep 30
#redir tcp
if [ $redir_tcp_process -gt 0 ] ;then
icount=`busybox ps -w | grep ssr-retcp |grep -v grep| wc -l`
if [ $icount = 0 ] ;then
logger -t "$NAME" "ssr redir tcp error.restart!"
/etc/init.d/vssr restart
/etc/init.d/vssr restart
exit 0
fi
fi
#redir udp
if [ $redir_udp_process -gt 0 ]; then
icount=$(busybox ps -w | grep vssr_u | grep -v grep | wc -l)
if [ $icount = 0 ]; then
logger -t "$NAME" "ssr redir udp error.restart!"
/etc/init.d/vssr restart
exit 0
fi
fi
#tunnel
if [ $tunnel_process -gt 0 ]; then
icount=$(busybox ps -w | grep ssr-tunnel | grep -v grep | wc -l)
if [ $icount = 0 ]; then
logger -t "$NAME" "ssr tunnel error.restart!"
/etc/init.d/vssr restart
exit 0
fi
fi
#server
if [ $server_process_count -gt 0 ]; then
icount=$(busybox ps -w | grep ssr-server | grep -v grep | wc -l)
if [ $icount -lt $server_process_count ]; then
logger -t "$NAME" "ssr server error.restart!"
killall -q -9 ssr-server
for i in $(seq $server_process_count); do
/usr/bin/ssr-server -c /var/etc/vssr_$i.json -u -f /var/run/ssr-server$i.pid
done
fi
fi
#kcptun
if [ $kcp_process -gt 0 ]; then
icount=$(busybox ps -w | grep kcptun-client | grep -v grep | wc -l)
if [ $icount -lt $kcp_process ]; then
logger -t "$NAME" "ssr kcptun error.restart!"
killall -q -9 kcptun-client
(/usr/bin/kcptun-client -r $server:$kcp_port -l :$server_port $password $kcp_param &)
fi
fi
#local
# if [ $local_process -gt 0 ] ;then
# icount=`busybox ps -w | grep ssr-local |grep -v grep| wc -l`
# if [ $icount -lt $local_process ]
# then
# logger -t "$NAME" "ssr local error.restart!"
# killall -q -9 ssr-local
# ( /usr/bin/ssr-local -c /var/etc/vssr_s.json -u -l $sock5_port -f /var/run/ssr-local.pid &)
# fi
# fi
#pdnsd
if [ $pdnsd_process -gt 0 ]; then
icount=$(busybox ps -w | grep pdnsd | grep -v grep | wc -l)
if [ $icount -lt $pdnsd_process ]; then
logger -t "$NAME" "pdnsd tunnel error.restart!"
if [ -f /var/run/pdnsd.pid ]; then
kill $(cat /var/run/pdnsd.pid) >/dev/null 2>&1
else
kill -9 $(ps | grep pdnsd | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
fi
#redir udp
if [ $redir_udp_process -gt 0 ] ;then
icount=`busybox ps -w | grep ssr-reudp|grep -v grep| wc -l`
if [ $icount = 0 ] ;then
logger -t "$NAME" "ssr redir udp error.restart!"
/etc/init.d/vssr restart
exit 0
fi
fi
#tunnel
if [ $tunnel_process -gt 0 ] ;then
icount=`busybox ps -w | grep ssr-tunnel |grep -v grep| wc -l`
if [ $icount = 0 ] ;then
logger -t "$NAME" "ssr tunnel error.restart!"
/etc/init.d/vssr restart
exit 0
fi
fi
#server
if [ $server_process_count -gt 0 ] ;then
icount=`busybox ps -w | grep ssr-server |grep -v grep| wc -l`
if [ $icount -lt $server_process_count ] #如果进程挂掉就重启它
then
logger -t "$NAME" "ssr server error.restart!"
killall -q -9 ssr-server
for i in `seq $server_process_count`
do
/usr/bin/ssr-server -c /var/etc/vssr_$i.json -u -f /var/run/ssr-server$i.pid
done
fi
fi
#kcptun
if [ $kcp_process -gt 0 ] ;then
icount=`busybox ps -w | grep kcptun-client |grep -v grep| wc -l`
if [ $icount -lt $kcp_process ] #如果进程挂掉就重启它
then
logger -t "$NAME" "ssr kcptun error.restart!"
killall -q -9 kcptun-client
(/usr/sbin/pdnsd -c /var/etc/pdnsd.conf -d &)
fi
fi
( /usr/bin/kcptun-client -r $server:$kcp_port -l :$server_port $password $kcp_param &)
fi
fi
#local
if [ $local_process -eq 1 ] ;then
icount=`ps -w | grep ssr-local |grep -v grep| wc -l`
if [ $icount -lt $local_process ] #如果进程挂掉就重启它
then
logger -t "$NAME" "ssr local error.restart!"
echo "$(date "+%Y-%m-%d %H:%M:%S") ssr local error.restart!" >> ${logfile}
killall -q -9 ssr-local
( /usr/bin/ssr-local -c /var/etc/vssr_s.json -u -l $sock5_port -f /var/run/ssr-local.pid &)
fi
fi
#local
if [ $local_process -eq 2 ] ;then
local_processs=1
icount=`ps -w | grep ss-local |grep -v grep| wc -l`
if [ $icount -lt $local_processs ] #如果进程挂掉就重启它
then
logger -t "$NAME" "ss local error.restart!"
echo "$(date "+%Y-%m-%d %H:%M:%S") ss local error.restart!" >> ${logfile}
killall -q -9 ss-local
( /usr/bin/ss-local -c /var/etc/vssr_s.json -u -l $sock5_port -f /var/run/ss-local.pid &)
fi
fi
#local
if [ $local_process -eq 3 ] ;then
local_processs=1
icount=`ps -w | grep v2-ssr-local |grep -v grep| wc -l`
if [ $icount -lt $local_processs ] #如果进程挂掉就重启它
then
logger -t "$NAME" "v2ray local error.restart!"
echo "$(date "+%Y-%m-%d %H:%M:%S") v2ray local error.restart!" >> ${logfile}
kill -9 $(ps | grep v2-ssr-local | grep -v grep | awk '{print $1}') >/dev/null 2>&1
( /usr/bin/v2ray/v2ray -config /var/etc/v2-ssr-local.json >/dev/null 2>&1 &)
fi
fi
#pdnsd
if [ $pdnsd_process -gt 0 ] ;then
icount=`busybox ps -w | grep pdnsd |grep -v grep| wc -l`
if [ $icount -lt $pdnsd_process ] #如果进程挂掉就重启它
then
logger -t "$NAME" "pdnsd tunnel error.restart!"
if [ -f /var/run/pdnsd.pid ] ;then
kill $(cat /var/run/pdnsd.pid) >/dev/null 2>&1
else
kill -9 $(ps | grep pdnsd | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
( /usr/sbin/pdnsd -c /var/etc/pdnsd.conf -d &)
fi
fi
done

View File

@ -14,9 +14,7 @@ FWI=$(uci get firewall.vssr.path 2>/dev/null) # firewall include file
usage() {
cat <<-EOF
Usage: vssr-rules [options]
Valid options are:
-s <server_ip> ip address of vssr remote server
-l <local_port> port number of vssr local server
-S <server_ip> ip address of vssr remote UDP server
@ -386,4 +384,4 @@ fi
flush_r && fw_rule && ipset_r && ac_rule && tp_rule && gen_include
[ "$?" = 0 ] || loger 3 "Start failed!"
exit $?
exit $?

View File

@ -16,17 +16,18 @@ NAME=vssr
ENABLE_SERVER=nil
CONFIG_SWTICH_FILE=/var/etc/${NAME}_t.json
[ -n "$1" ] && cycle_time=$1
[ -n "$2" ] && switch_time=$2
uci_get_by_name() {
local ret=$(uci get $NAME.$1.$2 2>/dev/null)
echo ${ret:=$3}
local ret=$(uci get $NAME.$1.$2 2>/dev/null)
echo ${ret:=$3}
}
uci_get_by_type() {
local ret=$(uci get $NAME.@$1[0].$2 2>/dev/null)
echo ${ret:=$3}
local ret=$(uci get $NAME.@$1[0].$2 2>/dev/null)
echo ${ret:=$3}
}
DEFAULT_SERVER=$(uci_get_by_type global global_server)
@ -34,138 +35,149 @@ CURRENT_SERVER=$DEFAULT_SERVER
#判断代理是否正常
check_proxy() {
/usr/bin/ssr-check www.google.com 80 $switch_time 1
if [ "$?" == "0" ]; then
return 0
else
/usr/bin/ssr-check www.baidu.com 80 $switch_time 1
local result=0
local try_count=$(uci_get_by_type global switch_try_count 3)
for i in $(seq 1 $try_count)
do
/usr/bin/ssr-check www.google.com 80 $switch_time 1
if [ "$?" == "0" ]; then
#goole不通baidu通则不正常
return 1
# echo "$(date "+%Y-%m-%d %H:%M:%S") Check Google Proxy Success, count=$i" >> /tmp/vssr.log
result=0
break
else
return 2
# echo "$(date "+%Y-%m-%d %H:%M:%S") Check Google Proxy Fail, count=$i" >> /tmp/vssr.log
/usr/bin/ssr-check www.baidu.com 80 $switch_time 1
if [ "$?" == "0" ]; then
result=1
else
result=2
fi
fi
fi
return 0
sleep 1;
done
return $result;
}
test_proxy() {
local servername=$(uci_get_by_name $1 server)
local serverport=$(uci_get_by_name $1 server_port)
ret=$(ping -c 3 $servername | grep 'loss' | awk -F ',' '{ print $3 }' | awk -F "%" '{ print $1 }')
[ -z "$ret" ] && return 1
[ "$ret" -gt "50" ] && return 1
ipset add ss_spec_wan_ac $servername 2>/dev/null
ret=$?
/usr/bin/ssr-check $servername $serverport $switch_time
local ret2=$?
if [ "$ret" = "0" ]; then
ipset del ss_spec_wan_ac $servername 2>/dev/null
fi
if [ "$ret2" = "0" ]; then
return 0
else
return 1
fi
local servername=$(uci_get_by_name $1 server)
local serverport=$(uci_get_by_name $1 server_port)
ret=$(ping -c 3 $servername | grep 'loss' | awk -F ',' '{ print $3 }' | awk -F "%" '{ print $1 }')
[ -z "$ret" ] && return 1
[ "$ret" -gt "50" ] && return 1
ipset add ss_spec_wan_ac $servername 2>/dev/null
ret=$?
/usr/bin/ssr-check $servername $serverport $switch_time
local ret2=$?
if [ "$ret" = "0" ] ;then
ipset del ss_spec_wan_ac $servername 2>/dev/null
fi
if [ "$ret2" = "0" ] ;then
return 0
else
return 1
fi
}
search_proxy() {
let server_count=server_count+1
[ "$normal_flag" = "1" -a "$server_count" -le "$server_locate" ] && return 0
[ "$(uci_get_by_name $1 switch_enable)" != "1" ] && return 1
[ $ENABLE_SERVER != nil ] && return 0
[ "$1" = "$CURRENT_SERVER" ] && return 0
local servername=$(uci_get_by_name $1 server)
local serverport=$(uci_get_by_name $1 server_port)
ipset add ss_spec_wan_ac $servername 2>/dev/null
ret=$?
/usr/bin/ssr-check $servername $serverport $switch_time
local ret2=$?
if [ "$ret" = "0" ]; then
ipset del ss_spec_wan_ac $servername 2>/dev/null
fi
if [ "$ret2" = "0" ]; then
server_locate=$server_count
ENABLE_SERVER=$1
return 0
else
return 1
fi
let server_count=server_count+1
[ "$normal_flag" = "1" -a "$server_count" -le "$server_locate" ] && return 0
[ "$(uci_get_by_name $1 switch_enable)" != "1" ] && return 1
[ $ENABLE_SERVER != nil ] && return 0
[ "$1" = "$CURRENT_SERVER" ] && return 0
local servername=$(uci_get_by_name $1 server)
local serverport=$(uci_get_by_name $1 server_port)
ipset add ss_spec_wan_ac $servername 2>/dev/null
ret=$?
/usr/bin/ssr-check $servername $serverport $switch_time
local ret2=$?
if [ "$ret" = "0" ] ;then
ipset del ss_spec_wan_ac $servername 2>/dev/null
fi
if [ "$ret2" = "0" ] ;then
server_locate=$server_count
ENABLE_SERVER=$1
return 0
else
return 1
fi
}
#选择可用的代理
select_proxy() {
config_load $NAME
ENABLE_SERVER=nil
mkdir -p /var/run /var/etc
server_count=0
config_foreach search_proxy servers
config_load $NAME
ENABLE_SERVER=nil
mkdir -p /var/run /var/etc
server_count=0
config_foreach search_proxy servers
}
#切换代理
switch_proxy() {
/etc/init.d/ssr restart $1
return 0
/etc/init.d/vssr restart $1
return 0
}
start() {
#不支持kcptun启用时的切换
[ $(uci_get_by_name $DEFAULT_SERVER kcp_enable) = "1" ] && return 1
#不支持kcptun启用时的切换
[ $(uci_get_by_name $DEFAULT_SERVER kcp_enable) = "1" ] && return 1
while [ "1" = "1" ]; do #死循环
sleep $cycle_time
while [ "1" = "1" ] #死循环
do
sleep $cycle_time
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
#判断当前代理是否为缺省服务器
if [ "$CURRENT_SERVER" != "$DEFAULT_SERVER" ]; then
#echo "not default proxy"
echo "$(date "+%Y-%m-%d %H:%M:%S") 当前为备用节点,尝试切换为主节点。" >>/tmp/vssr.log
#检查缺省服务器是否正常
if test_proxy $DEFAULT_SERVER; then
#echo "switch to default proxy"
echo "$(date "+%Y-%m-%d %H:%M:%S") 主节点不可用." >>/tmp/vssr.log
#缺省服务器正常,切换回来
CURRENT_SERVER=$DEFAULT_SERVER
switch_proxy $CURRENT_SERVER
echo "$(date "+%Y-%m-%d %H:%M:%S") 切换为默认节点 ["$(uci_get_by_name $CURRENT_SERVER server)"]" >>/tmp/vssr.log
continue
else
echo "$(date "+%Y-%m-%d %H:%M:%S") 主节点不可用,继续使用当前备用节点。" >>/tmp/vssr.log
fi
#判断当前代理是否为缺省服务器
if [ "$CURRENT_SERVER" != "$DEFAULT_SERVER" ] ;then
#echo "not default proxy"
echo "$(date "+%Y-%m-%d %H:%M:%S") Current server is not default Main server, try to switch back." >> /tmp/vssr.log
#检查缺省服务器是否正常
if test_proxy $DEFAULT_SERVER ;then
#echo "switch to default proxy"
echo "$(date "+%Y-%m-%d %H:%M:%S") Main server is avilable." >> /tmp/vssr.log
#缺省服务器正常,切换回来
CURRENT_SERVER=$DEFAULT_SERVER
switch_proxy $CURRENT_SERVER
echo "$(date "+%Y-%m-%d %H:%M:%S") switch to default ["$(uci_get_by_name $CURRENT_SERVER server)"] proxy!" >> /tmp/vssr.log
continue
else
echo "$(date "+%Y-%m-%d %H:%M:%S") Main server is NOT avilable.Continue using current server." >> /tmp/vssr.log
fi
fi
#判断当前代理是否正常
check_proxy
current_ret=$?
#判断当前代理是否正常
check_proxy
current_ret=$?
if [ "$current_ret" = "1" ]; then
#当前代理错误,判断有无可用的服务器
#echo "current error"
echo "$(date "+%Y-%m-%d %H:%M:%S") 当前节点不可用,尝试切换其他节点。" >>/tmp/vssr.log
if [ "$current_ret" = "1" ] ;then
#当前代理错误,判断有无可用的服务器
#echo "current error"
echo "$(date "+%Y-%m-%d %H:%M:%S") Current server error, try to switch another server." >> /tmp/vssr.log
select_proxy
if [ "$ENABLE_SERVER" != nil ]; then
#有其他服务器可用,进行切换
#echo $(uci_get_by_name $new_proxy server)
echo "$(date "+%Y-%m-%d %H:%M:%S") 另外一个节点可用,即将切换节点。" >>/tmp/vssr.log
CURRENT_SERVER=$ENABLE_SERVER
switch_proxy $CURRENT_SERVER
normal_flag=1
echo "$(date "+%Y-%m-%d %H:%M:%S") 切换节点成功。" >>/tmp/vssr.log
else
switch_proxy $CURRENT_SERVER
normal_flag=1
echo "$(date "+%Y-%m-%d %H:%M:%S") 尝试重启当前节点。" >>/tmp/vssr.log
fi
else
normal_flag=0
#echo "$(date "+%Y-%m-%d %H:%M:%S") vssr No Problem." >> /tmp/vssr.log
fi
select_proxy
if [ "$ENABLE_SERVER" != nil ] ;then
#有其他服务器可用,进行切换
#echo $(uci_get_by_name $new_proxy server)
echo "$(date "+%Y-%m-%d %H:%M:%S") Another server is avilable, now switching server." >> /tmp/vssr.log
CURRENT_SERVER=$ENABLE_SERVER
switch_proxy $CURRENT_SERVER
normal_flag=1
echo "$(date "+%Y-%m-%d %H:%M:%S") ShadowsocksR server switch OK" >> /tmp/vssr.log
else
switch_proxy $CURRENT_SERVER
normal_flag=1
echo "$(date "+%Y-%m-%d %H:%M:%S") Try restart current server." >> /tmp/vssr.log
fi
else
normal_flag=0
echo "$(date "+%Y-%m-%d %H:%M:%S") ShadowsocksR No Problem." >> /tmp/vssr.log
fi
done
done
}

View File

View File

@ -0,0 +1,37 @@
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 trojan = {
run_type = "nat",
local_addr = "0.0.0.0",
local_port = tonumber(local_port),
remote_addr = server.server,
remote_port = tonumber(server.server_port),
-- 传入连接
password = {server.password},
-- 传出连接
ssl = {
verify = true,
verify_hostname = true,
cert = (server.certificate == "1") and server.certpath or "",
cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RSA-AES128-GCM-SHA256:RSA-AES256-GCM-SHA384:RSA-AES128-SHA:RSA-AES256-SHA:RSA-3DES-EDE-SHA",
sni = server.tls_host,
alpn = {"h2", "http/1.1"},
curve = "",
reuse_session = true,
session_ticket = true,
},
tcp = {
no_delay = true,
keep_alive = true,
fast_open = (server.fast_open == "1") and true or false,
fast_open_qlen = 20
}
}
print(json.stringify(trojan, 1))

View File

@ -0,0 +1,95 @@
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 v2ray = {
log = {
-- error = "/var/vssr.log",
loglevel = "warning"
},
-- 传入连接
inbound = {
port = local_port,
protocol = "dokodemo-door",
settings = {
network = proto,
followRedirect = true
},
sniffing = {
enabled = true,
destOverride = { "http", "tls" }
}
},
-- 传出连接
outbound = {
protocol = "vmess",
settings = {
vnext = {
{
address = server.server,
port = tonumber(server.server_port),
users = {
{
id = server.vmess_id,
alterId = tonumber(server.alter_id),
security = server.security
}
}
}
}
},
-- 底层传输配置
streamSettings = {
network = server.transport,
security = (server.tls == '1') and "tls" or "none",
tlsSettings = {allowInsecure = (server.insecure == "1") and true or false,},
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 {
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,
concurrency = tonumber(server.concurrency)
}
},
-- 额外传出连接
outboundDetour = {
{
protocol = "freedom",
tag = "direct",
settings = { keep = "" }
}
}
}
print(json.stringify(v2ray, 1))

View File

@ -0,0 +1,107 @@
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]+1
local socks_port = arg[4]
local server = ucursor:get_all("vssr", server_section)
local v2ray = {
log = {
-- error = "/var/vssr.log",
loglevel = "warning"
},
-- 传入连接
inbound = {
port = local_port,
protocol = "dokodemo-door",
settings = {
network = proto,
followRedirect = true
},
sniffing = {
enabled = true,
destOverride = { "http", "tls" }
}
},
-- 开启 socks 和 http 代理
inboundDetour = (proto == "tcp") and {
{
protocol = "socks",
port = socks_port,
settings = {
auth = "noauth",
udp = true
}
}
} or nil,
-- 传出连接
outbound = {
protocol = "vmess",
settings = {
vnext = {
{
address = server.server,
port = tonumber(server.server_port),
users = {
{
id = server.vmess_id,
alterId = tonumber(server.alter_id),
security = server.security
}
}
}
}
},
-- 底层传输配置
streamSettings = {
network = server.transport,
security = (server.tls == '1') and "tls" or "none",
tlsSettings = {allowInsecure = (server.insecure == "1") and true or false,},
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 {
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,
concurrency = tonumber(server.concurrency)
}
},
-- 额外传出连接
outboundDetour = {
{
protocol = "freedom",
tag = "direct",
settings = { keep = "" }
}
}
}
print(json.stringify(v2ray, 1))

View File

@ -30,5 +30,10 @@ else
hostip=$(cat /etc/ssr_ip)
fi
fi
$python -c "import maxminddb;import json;reader = maxminddb.open_database('/usr/share/vssr/GeoLite2-Country.mmdb');aa = reader.get('${hostip}');reader.close();print(aa['country']['iso_code'].lower())"
$python -c "import maxminddb;
import json;
reader = maxminddb.open_database('/usr/share/vssr/GeoLite2-Country.mmdb');
aa = reader.get('${hostip}');
reader.close();
print(aa['country']['iso_code'].lower())"
fi

View File

@ -1,349 +0,0 @@
#!/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'
require 'luci.sys'
-- these global functions are accessed all the time by the event handler
-- so caching them is worth the effort
local tinsert = table.insert
local ssub, slen, schar, srep, sbyte, sformat, sgsub =
string.sub, string.len, string.char, string.rep, string.byte, string.format, string.gsub
local cache = {}
local nodeResult = setmetatable({}, { __index = cache }) -- update result
local name = 'vssr'
local uciType = 'servers'
local ucic = luci.model.uci.cursor()
local proxy = ucic:get_first(name, 'server_subscribe', 'proxy', '0')
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({ ... }, " "))
end
-- 分割字符串
local function split(full, sep)
full = full:gsub("%z", "") -- 这里不是很清楚 有时候结尾带个\0
local off, result = 1, {}
while true do
local nEnd = full:find(sep, off)
if not nEnd then
local res = ssub(full, off, slen(full))
if #res > 0 then -- 过滤掉 \0
tinsert(result, res)
end
break
else
tinsert(result, ssub(full, off, nEnd - 1))
off = nEnd + slen(sep)
end
end
return result
end
-- urlencode
local function get_urlencode(c)
return sformat("%%%02X", sbyte(c))
end
local function urlEncode(szText)
local str = szText:gsub("([^0-9a-zA-Z ])", get_urlencode)
str = str:gsub(" ", "+")
return str
end
local function get_urldecode(h)
return schar(tonumber(h, 16))
end
local function UrlDecode(szText)
return szText: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"))
end
-- md5
local function md5(content)
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, safe)
local raw = text
if not text then return '' end
text = text:gsub("%z", "")
if safe then
text = text:gsub("_", "/")
text = text:gsub("-", "+")
local mod4 = #text % 4
text = text .. string.sub('====', mod4 + 1)
end
local result = nixio.bin.b64decode(text)
if result then
return result:gsub("%z", "")
else
return raw
end
end
-- 处理数据
local function processData(szType, content)
local result = {
auth_enable = '0',
switch_enable = '1',
type = szType,
local_port = 1234,
timeout = 60, -- 不太确定 好像是死的
fast_open = 0,
kcp_enable = 0,
kcp_port = 0,
kcp_param = '--nocomp'
}
local hash
if type(content) == 'string' then
hash = md5(content)
else
hash = md5(luci.jsonc.stringify(content))
end
result.hashkey = hash
-- 如果节点内容为空,返回无效的节点信息
if content == '' then
result.server = ''
return result, hash
end
if szType == 'ssr' then
local dat = split(content, "/\\?")
local hostInfo = split(dat[1], ':')
result.server = hostInfo[1]
result.server_port = hostInfo[2]
result.protocol = hostInfo[3]
result.encrypt_method = hostInfo[4]
result.obfs = hostInfo[5]
result.password = base64Decode(hostInfo[6], true)
local params = {}
for k, v in pairs(split(dat[2], '&')) do
local t = split(v, '=')
params[t[1]] = t[2]
end
result.obfs_param = base64Decode(params.bfsparam, true)
result.protocol_param = base64Decode(params.protoparam, true)
local group = base64Decode(params.group, true)
if group then
result.alias = "[" .. group .. "] "
end
result.alias = result.alias .. base64Decode(params.remarks, true)
elseif szType == 'vmess' then
local info = luci.jsonc.parse(content)
result.type = 'v2ray'
result.server = info.add
result.server_port = info.port
result.tcp_guise = "none"
result.transport = info.net
result.alter_id = info.aid
result.vmess_id = info.id
result.alias = info.ps
result.ws_host = info.host
result.ws_path = info.path
result.h2_host = info.host
result.h2_path = info.path
if not info.security then
result.security = "auto"
end
if info.tls == "tls" or info.tls == "1" then
result.tls = "1"
else
result.tls = "0"
end
elseif szType == "ss" then
local info = content:sub(1, content:find("#") - 1)
local alias = content:sub(content:find("#") + 1, #content)
local hostInfo = split(base64Decode(info, true), "@")
local host = split(hostInfo[2], ":")
local userinfo = base64Decode(hostInfo[1], true)
local method = userinfo:sub(1, userinfo:find(":") - 1)
local password = userinfo:sub(userinfo:find(":") + 1, #userinfo)
result.alias = UrlDecode(alias)
result.type = "ss"
result.server = host[1]
if host[2]:find("/\\?") then
local query = split(host[2], "/\\?")
result.server_port = query[1]
-- local params = {}
-- for k, v in pairs(split(query[2], '&')) do
-- local t = split(v, '=')
-- params[t[1]] = t[2]
-- end
-- 这里似乎没什么用 我看数据结构没有写插件的支持 先抛弃
else
result.server_port = host[2]
end
result.encrypt_method_ss = method
result.password = password
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.alias = "[" .. content.airport .. "] " .. content.remarks
end
local flag = luci.sys.exec('/usr/share/'..name..'/getflag.sh "'..result.alias..'" '..result.server)
result.flag = string.gsub(flag, '\n', '')
return result, hash
end
-- wget
local function wget(url)
local stdout = luci.sys.exec('wget-ssl --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36" --no-check-certificate -t 3 -T 10 -O- "' .. url .. '"')
return trim(stdout)
end
local execute = function()
-- exec
do
-- subscribe_url = {'https://www.google.comc'}
if proxy == '0' then -- 不使用代理更新的话先暂停
log('服务正在暂停')
luci.sys.init.stop(name)
end
for k, url in ipairs(subscribe_url) do
local raw = wget(url)
if #raw > 0 then
local node, szType
local groupHash = md5(url)
cache[groupHash] = {}
tinsert(nodeResult, {})
local index = #nodeResult
-- SSD 似乎是这种格式 ssd:// 开头的
if raw:find('ssd://') then
szType = 'ssd'
local nEnd = select(2, raw:find('ssd://'))
node = base64Decode(raw:sub(nEnd + 1, #raw), true)
node = luci.jsonc.parse(node)
local extra = {
airport = node.airport,
port = node.port,
encryption = node.encryption,
password = node.password
}
local servers = {}
-- SS里面包着 干脆直接这样
for _, server in ipairs(node.servers) do
tinsert(servers, setmetatable(server, { __index = extra }))
end
node = servers
else
-- ssd 外的格式
node = split(base64Decode(raw, true):gsub(" ", "\n"), "\n")
end
for _, v in ipairs(node) do
if v then
v = trim(v)
local result, hash
if szType == 'ssd' then
result, hash = processData(szType, v)
elseif not szType then
local dat = split(v, "://")
if dat and dat[1] and dat[2] then
if dat[1] == 'ss' then
result, hash = processData(dat[1], dat[2])
else
result, hash = processData(dat[1], base64Decode(dat[2], true))
end
end
else
log('跳过未知类型: ' .. szType)
end
-- log(hash, result)
if hash and result then
if result.alias:find("过期时间") or
result.alias:find("剩余流量") or
result.alias:find("QQ群") or
result.alias:find("官网") or
result.server == ''
then
log('丢弃无效节点: ' .. result.type ..' 节点, ' .. result.alias)
else
log('成功解析: ' .. result.type ..' 节点, ' .. result.alias)
result.grouphashkey = groupHash
tinsert(nodeResult[index], result)
cache[groupHash][hash] = nodeResult[index][#nodeResult[index]]
end
end
end
end
log('成功解析节点数量: ' ..#node)
end
end
end
-- diff
do
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
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
log('忽略手动添加的节点: ' .. old.alias)
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)
add = add + 1
end
end
end
ucic:commit(name)
-- 如果服务器已经不见了把帮换一个
local globalServer = ucic:get_first(name, 'global', 'global_server', '')
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:commit(name)
log('当前主服务器已更新,正在自动更换。')
end
end
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
log('新增节点数量: ' ..add, '删除节点数量: ' .. del)
log("END SUBSCRIBE")
log('更新成功服务正在启动')
end
end
if subscribe_url and #subscribe_url > 0 then
xpcall(execute, function(e)
log(e)
log(debug.traceback())
log('发生错误, 正在恢复服务')
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

View File

@ -0,0 +1,269 @@
#!/bin/bash
# Copyright (C) 2017 XiaoShan https://www.mivm.cn
. /usr/share/libubox/jshn.sh
urlsafe_b64decode() {
local d="====" data=$(echo $1 | sed 's/_/\//g; s/-/+/g')
local mod4=$((${#data} % 4))
[ $mod4 -gt 0 ] && data=${data}${d:mod4}
echo $data | base64 -d
}
urldecode() {
: "${*//+/ }"
echo -e "${_//%/\\x}"
}
echo_date() {
echo $(TZ=UTC-8 date -R +%Y-%m-%d\ %X):$1
}
Server_Update() {
local uci_set="uci -q set $name.$1."
local flag=$(/usr/share/$name/getflag.sh "$ssr_remarks" $ssr_host)
${uci_set}grouphashkey="$ssr_grouphashkey"
${uci_set}hashkey="$ssr_hashkey"
${uci_set}alias="[$ssr_group] $ssr_remarks"
${uci_set}auth_enable="0"
${uci_set}switch_enable="1"
${uci_set}type="$ssr_type"
${uci_set}flag="$flag"
${uci_set}server="$ssr_host"
${uci_set}server_port="$ssr_port"
${uci_set}local_port="1234"
uci -q get $name.@servers[$1].timeout >/dev/null || ${uci_set}timeout="60"
${uci_set}password="$ssr_passwd"
${uci_set}encrypt_method="$ssr_method"
${uci_set}protocol="$ssr_protocol"
${uci_set}protocol_param="$ssr_protoparam"
${uci_set}obfs="$ssr_obfs"
${uci_set}obfs_param="$ssr_obfsparam"
${uci_set}fast_open="0"
${uci_set}kcp_enable="0"
${uci_set}kcp_port="0"
${uci_set}kcp_param="--nocomp"
if [ "$ssr_type" = "v2ray" ]; then
#v2ray
${uci_set}alter_id="$ssr_alter_id"
${uci_set}vmess_id="$ssr_vmess_id"
${uci_set}transport="$ssr_transport"
if [ "$ssr_transport" = "tcp" ]; then
${uci_set}tcp_guise="$ssr_tcp_guise"
fi
if [ "$ssr_transport" = "ws" ]; then
${uci_set}ws_host="$ssr_ws_host"
${uci_set}ws_path="$ssr_ws_path"
fi
if [ "$ssr_transport" = "h2" ]; then
${uci_set}h2_host="$ssr_ws_host"
${uci_set}h2_path="$ssr_ws_path"
fi
${uci_set}tls="$ssr_tls"
${uci_set}insecure="$ssr_insecure"
${uci_set}security="auto"
${uci_set}alias="$ssr_remarks"
fi
if [ "$ssr_type" = "ss" ]; then
${uci_set}encrypt_method_ss="$ss_method"
${uci_set}alias="$ssr_remarks"
fi
}
name=vssr
subscribe_url=($(uci get $name.@server_subscribe[0].subscribe_url)) #订阅服务器地址
[ ${#subscribe_url[@]} -eq 0 ] && exit 1
[ $(uci -q get $name.@server_subscribe[0].proxy || echo 0) -eq 0 ] && /etc/init.d/$name stop >/dev/null 2>&1
log_name=${name}_subscribe
for ((o = 0; o < ${#subscribe_url[@]}; o++)); do
echo_date "${subscribe_url[o]} 获取订阅"
echo_date "开始更新在线订阅列表..."
echo_date "开始下载订阅链接到本地临时文件,请稍等..."
subscribe_data=$(wget-ssl --user-agent="User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36" --no-check-certificate -t 10 -T 10 -O- ${subscribe_url[o]})
curl_code=$?
# 计算group的hashkey
ssr_grouphashkey=$(echo "${subscribe_url[o]}" | md5sum | cut -d ' ' -f1)
if [ ! $curl_code -eq 0 ]; then
subscribe_data=$(wget-ssl --no-check-certificate -t 10 -T 10 -O- ${subscribe_url[o]})
curl_code=$?
fi
if [ $curl_code -eq 0 ]; then
echo_date "下载订阅成功..."
echo_date "开始解析节点信息..."
ssr_url=($(echo $subscribe_data | base64 -d | sed 's/\r//g')) # 解码数据并删除 \r 换行符
subscribe_max=$(echo ${ssr_url[0]} | grep -i MAX= | awk -F = '{print $2}')
subscribe_max_x=()
if [ -n "$subscribe_max" ]; then
while [ ${#subscribe_max_x[@]} -ne $subscribe_max ]; do
if [ ${#ssr_url[@]} -ge 10 ]; then
if [ $((${RANDOM:0:2} % 2)) -eq 0 ]; then
temp_x=${RANDOM:0:1}
else
temp_x=${RANDOM:0:2}
fi
else
temp_x=${RANDOM:0:1}
fi
[ $temp_x -lt ${#ssr_url[@]} -a -z "$(echo "${subscribe_max_x[*]}" | grep -w $temp_x)" ] && subscribe_max_x[${#subscribe_max_x[@]}]="$temp_x"
done
else
subscribe_max=${#ssr_url[@]}
fi
echo_date "共计$subscribe_max个节点"
ssr_group=$(urlsafe_b64decode $(urlsafe_b64decode ${ssr_url[$((${#ssr_url[@]} - 1))]//ssr:\/\//} | sed 's/&/\n/g' | grep group= | awk -F = '{print $2}'))
if [ -z "$ssr_group" ]; then
ssr_group="default"
fi
if [ -n "$ssr_group" ]; then
subscribe_i=0
subscribe_n=0
subscribe_o=0
subscribe_x=""
temp_host_o=()
curr_ssr=$(uci show $name | grep @servers | grep -c server=)
for ((x = 0; x < $curr_ssr; x++)); do # 循环已有服务器信息,匹配当前订阅群组
temp_alias=$(uci -q get $name.@servers[$x].grouphashkey | grep "$ssr_grouphashkey")
[ -n "$temp_alias" ] && temp_host_o[${#temp_host_o[@]}]=$(uci get $name.@servers[$x].hashkey)
done
for ((x = 0; x < $subscribe_max; x++)); do # 循环链接
[ ${#subscribe_max_x[@]} -eq 0 ] && temp_x=$x || temp_x=${subscribe_max_x[x]}
result=$(echo ${ssr_url[temp_x]} | grep "ss")
subscribe_url_type=$(echo "$ssr_url" | awk -F ':' '{print $1}')
if [ "$subscribe_url_type" = "ss" ]; then
temp_info=${ssr_url[temp_x]//ss:\/\//} # 解码 SS 链接
# 计算hashkey
ssr_hashkey=$(echo "$temp_info" | md5sum | cut -d ' ' -f1)
info=$(urlsafe_b64decode $(echo "$temp_info" | awk -F '@' '{print $1}'))
temp_info_array=(${info//:/ })
ssr_type="ss"
ss_method=${temp_info_array[0]}
ssr_passwd=${temp_info_array[1]}
info=$(echo "$temp_info" | awk -F '@' '{print $2}' | awk -F '#' '{print $1}')
temp_info_array=(${info//:/ })
ssr_host=${temp_info_array[0]}
ssr_port=${temp_info_array[1]}
ssr_remarks=$(urldecode $(echo "$temp_info" | awk -F '#' '{print $2}'))
fi
if [ "$subscribe_url_type" = "ssr" ]; then
temp_info=$(urlsafe_b64decode ${ssr_url[temp_x]//ssr:\/\//}) # 解码 SSR 链接
# 计算hashkey
ssr_hashkey=$(echo "$temp_info" | md5sum | cut -d ' ' -f1)
info=${temp_info///?*/}
temp_info_array=(${info//:/ })
ssr_type="ssr"
ssr_host=${temp_info_array[0]}
ssr_port=${temp_info_array[1]}
ssr_protocol=${temp_info_array[2]}
ssr_method=${temp_info_array[3]}
ssr_obfs=${temp_info_array[4]}
ssr_passwd=$(urlsafe_b64decode ${temp_info_array[5]})
info=${temp_info:$((${#info} + 2))}
info=(${info//&/ })
ssr_protoparam=""
ssr_obfsparam=""
ssr_remarks="$temp_x"
for ((i = 0; i < ${#info[@]}; i++)); do # 循环扩展信息
temp_info=($(echo ${info[i]} | sed 's/=/ /g'))
case "${temp_info[0]}" in
protoparam)
ssr_protoparam=$(urlsafe_b64decode ${temp_info[1]})
;;
obfsparam)
ssr_obfsparam=$(urlsafe_b64decode ${temp_info[1]})
;;
remarks)
ssr_remarks=$(urlsafe_b64decode ${temp_info[1]})
;;
esac
done
fi
if [ "$subscribe_url_type" = "vmess" ]; then
temp_info=$(urlsafe_b64decode ${ssr_url[temp_x]//vmess:\/\//}) # 解码 Vmess 链接
# 计算hashkey
ssr_hashkey=$(echo "$temp_info" | md5sum | cut -d ' ' -f1)
ssr_type="v2ray"
json_load "$temp_info"
json_get_var ssr_host add
json_get_var ssr_port port
json_get_var ssr_alter_id aid
json_get_var ssr_vmess_id id
json_get_var ssr_transport net
json_get_var ssr_remarks ps
ssr_tcp_guise="none"
json_get_var ssr_ws_host host
json_get_var ssr_ws_path path
json_get_var ssr_tls tls
if [ "$ssr_tls" == "tls" -o "$ssr_tls" == "1" ]; then
ssr_tls="1"
ssr_insecure="1"
else
ssr_tls="0"
fi
fi
if [ -z "ssr_remarks" ]; then # 没有备注的话则生成一个
ssr_remarks="$ssr_host:$ssr_port"
fi
uci_name_tmp=$(uci show $name | grep -w "$ssr_hashkey" | awk -F . '{print $2}')
if [ -z "$uci_name_tmp" ]; then # 判断当前服务器信息是否存在
uci_name_tmp=$(uci add $name servers)
subscribe_n=$(($subscribe_n + 1))
fi
Server_Update $uci_name_tmp
subscribe_x=$subscribe_x$ssr_hashkey" "
ssrtype=$(echo $ssr_type | tr '[a-z]' '[A-Z]')
echo_date "$ssrtype节点:【$ssr_remarks"
# SSR
# echo "服务器地址: $ssr_host"
# echo "服务器端口 $ssr_port"
# echo "密码: $ssr_passwd"
# echo "SS加密: $ss_method"
# echo "加密: $ssr_method"
# echo "协议: $ssr_protocol"
# echo "协议参数: $ssr_protoparam"
# echo "混淆: $ssr_obfs"
# echo "混淆参数: $ssr_obfsparam"
# echo "备注: $ssr_remarks"
done
for ((x = 0; x < ${#temp_host_o[@]}; x++)); do # 新旧服务器信息匹配,如果旧服务器信息不存在于新服务器信息则删除
if [ -z "$(echo "$subscribe_x" | grep -w ${temp_host_o[x]})" ]; then
uci_name_tmp=$(uci show $name | grep ${temp_host_o[x]} | awk -F . '{print $2}')
uci delete $name.$uci_name_tmp
subscribe_o=$(($subscribe_o + 1))
fi
done
echo_date "本次更新订阅来源 【$ssr_group】 服务器数量: ${#ssr_url[@]} 新增服务器: $subscribe_n 删除服务器: $subscribe_o"
echo_date "在线订阅列表更新完成!请等待网页自动刷新!"
subscribe_log="$ssr_group 服务器订阅更新成功 服务器数量: ${#ssr_url[@]} 新增服务器: $subscribe_n 删除服务器: $subscribe_o"
logger -st $log_name[$$] -p6 "$subscribe_log"
uci commit $name
else
echo_date "${subscribe_url[$o]} 订阅数据解析失败 无法获取 Group"
logger -st $log_name[$$] -p3 "${subscribe_url[$o]} 订阅数据解析失败 无法获取 Group"
fi
else
echo_date "${subscribe_url[$o]} 订阅数据获取失败 错误代码: $curl_code"
logger -st $log_name[$$] -p3 "${subscribe_url[$o]} 订阅数据获取失败 错误代码: $curl_code"
fi
done
echo "END SUBSCRIBE"
/etc/init.d/$name restart >/dev/null 2>&1

View File

@ -308,20 +308,22 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
padding: 8px;
}
.cbi-section-table-row {
position: relative;
background: #edf3f8;
margin: 10px !important;
padding: 8px 15px 8px 70px;
box-shadow: 0 0 5px 0 rgba(136, 152, 170, .75);
border-radius: .5rem;
border: 0;
color: #525f7f;
text-align: left;
line-height: 1.7em;
overflow: hidden;
letter-spacing: normal;
transition: all 0.2s;
.cbi-section-table-row {
position: relative;
background: #99CCFF;
margin: 10px;
padding: 8px 15px 10px 65px;
box-shadow: 0 0 1rem 0 rgba(136,152,170,.75);
border-radius: .5rem;
border: 0;
color: #336699;
text-align: left;
line-height: 1.7em;
white-space: nowrap;
     text-overflow: ellipsis;
overflow: hidden;
transition: all 0.3s;
}
.cbi-section-table-row:hover{
background: #fff;
@ -456,13 +458,17 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
margin-top: 1rem;
}
.cbi-button-check {
color: #fff !important;
background-color: #337ab7 !important;
border-color: #2e6da4 !important;
float: right;
margin-right: 18px;
margin-top: 1rem;
.cbi-button-check {
color: #fff !important;
background-color: #336633 !important;
border-color: #2e6da4 !important;
font-size:12px;
padding:0.5rem 0.8rem;
float:right;
margin-right:10px;
margin-top:-0.3rem;
}
.cbi-section-table-cell {
@ -494,6 +500,22 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
footer.mobile-hide{
display: block;
}
.cbi-button-add{
position:fixed;
padding: 0.3rem 0.5rem;
z-index:1000;
width:70px !important;
height:70px;
bottom:90px;
right:80px;
font-size:20px;
border-radius:50%;
display:block;
background-color: #336633!important;
border-color: #CC6699 !important;
box-shadow: 0 0 1rem 0 rgba(136,152,170,.75);
}
.mar-10 {margin-left: 50px; margin-right: 10px;}
@ -523,6 +545,8 @@ footer.mobile-hide{
text-align: right;
}
@media screen and (max-width: 1900px) {
.pure-u-1-5 {
width: 25%;
@ -574,7 +598,7 @@ footer.mobile-hide{
font-size: 16px;
border-radius: 50%;
display: block;
background-color: #fb6340 !important;
background-color: #fb6340!important;
border-color: #fb6340 !important;
box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .75);
}
@ -677,4 +701,4 @@ footer.mobile-hide{
height: 2.5em;
text-align: right;
}
}
}