luci-app-ssr-plus: bump to 182-1

- Important improvement
Rewrite startup code to speed up startup
Same as global server, no need to start multiple processes
Use unified path and configuration

- Changes
Add Reset default settings
Optimize the use of shadowsocks plugin
Remove the sh script used in update and modify the UI usage
Remove Easylist China from adblock and add NEO DEV HOST
Adjust the parameters used by wget to ensure compatibility

- Fixes
Fix the issue of starting twice after apply in the server node list
Fix the problem that dnsmasq fails to start when the access control list contains wrong entries
This commit is contained in:
Mattraks 2020-12-23 19:13:48 +08:00 committed by CN_SZTL
parent 31d116d5ef
commit 741822539b
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
45 changed files with 1946 additions and 1734 deletions

View File

@ -1,14 +1,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-ssr-plus
PKG_VERSION:=181
PKG_RELEASE:=2
include $(INCLUDE_DIR)/package.mk
PKG_VERSION:=182
PKG_RELEASE:=1
define Package/$(PKG_NAME)/conffiles
/etc/config/shadowsocksr
/etc/ssr/
/etc/ssrplus/
endef
define Package/$(PKG_NAME)/config
@ -56,7 +54,7 @@ PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server
LUCI_TITLE:=SS/SSR/V2Ray/Xray/Trojan/NaiveProxy/Socks5/Tun LuCI interface
LUCI_TITLE:=SS/SSR/V2Ray/Trojan/NaiveProxy/Socks5/Tun LuCI interface
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +pdnsd-alt +wget +lua +libuci-lua \
+microsocks +dns2socks +shadowsocks-libev-ss-local +shadowsocksr-libev-ssr-local +shadowsocks-libev-ss-redir +simple-obfs +tcping +resolveip\

View File

@ -1,30 +1,30 @@
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
-- Licensed to the public under the GNU General Public License v3.
module("luci.controller.shadowsocksr", package.seeall)
function index()
if not nixio.fs.access("/etc/config/shadowsocksr") then
return
end
entry({"admin", "services", "shadowsocksr"}, alias("admin", "services", "shadowsocksr", "client"),_("ShadowSocksR Plus+"), 10).dependent = true
entry({"admin", "services", "shadowsocksr", "client"}, cbi("shadowsocksr/client"),_("SSR Client"), 10).leaf = true
entry({"admin", "services", "shadowsocksr", "servers"}, arcombine(cbi("shadowsocksr/servers", {autoapply = true}), cbi("shadowsocksr/client-config")),_("Severs Nodes"), 20).leaf = true
entry({"admin", "services", "shadowsocksr", "control"},cbi("shadowsocksr/control"), _("Access Control"), 30).leaf = true
entry({"admin", "services", "shadowsocksr", "advanced"},cbi("shadowsocksr/advanced"),_("Advanced Settings"), 50).leaf = true
entry({"admin", "services", "shadowsocksr", "server"},arcombine(cbi("shadowsocksr/server"), cbi("shadowsocksr/server-config")),_("SSR Server"), 60).leaf = true
entry({"admin", "services", "shadowsocksr", "status"},form("shadowsocksr/status"),_("Status"), 70).leaf = true
entry({"admin", "services", "shadowsocksr"}, alias("admin", "services", "shadowsocksr", "client"), _("ShadowSocksR Plus+"), 10).dependent = true
entry({"admin", "services", "shadowsocksr", "client"}, cbi("shadowsocksr/client"), _("SSR Client"), 10).leaf = true
entry({"admin", "services", "shadowsocksr", "servers"}, arcombine(cbi("shadowsocksr/servers", {autoapply = true}), cbi("shadowsocksr/client-config")), _("Severs Nodes"), 20).leaf = true
entry({"admin", "services", "shadowsocksr", "control"}, cbi("shadowsocksr/control"), _("Access Control"), 30).leaf = true
entry({"admin", "services", "shadowsocksr", "advanced"}, cbi("shadowsocksr/advanced"), _("Advanced Settings"), 50).leaf = true
entry({"admin", "services", "shadowsocksr", "server"}, arcombine(cbi("shadowsocksr/server"), cbi("shadowsocksr/server-config")), _("SSR Server"), 60).leaf = true
entry({"admin", "services", "shadowsocksr", "status"}, form("shadowsocksr/status"), _("Status"), 70).leaf = true
entry({"admin", "services", "shadowsocksr", "check"}, call("check_status"))
entry({"admin", "services", "shadowsocksr", "refresh"}, call("refresh_data"))
entry({"admin", "services", "shadowsocksr", "subscribe"}, call("subscribe"))
entry({"admin", "services", "shadowsocksr", "checkport"}, call("check_port"))
entry({"admin", "services", "shadowsocksr", "log"},form("shadowsocksr/log"),_("Log"), 80).leaf = true
entry({"admin", "services", "shadowsocksr","run"},call("act_status")).leaf = true
entry({"admin", "services", "shadowsocksr", "log"}, form("shadowsocksr/log"), _("Log"), 80).leaf = true
entry({"admin", "services", "shadowsocksr", "run"}, call("act_status")).leaf = true
entry({"admin", "services", "shadowsocksr", "ping"}, call("act_ping")).leaf = true
entry({"admin", "services", "shadowsocksr", "reset"}, call("act_reset"))
end
function subscribe()
luci.sys.call("/usr/bin/lua /usr/share/shadowsocksr/subscribe.lua >> /tmp/ssrplus.log 2>&1")
luci.sys.call("/usr/bin/lua /usr/share/shadowsocksr/subscribe.lua >>/var/log/ssrplus.log")
luci.http.prepare_content("application/json")
luci.http.write_json({ret = 1})
end
@ -41,16 +41,16 @@ function act_ping()
local domain = luci.http.formvalue("domain")
local port = luci.http.formvalue("port")
e.index = luci.http.formvalue("index")
local iret = luci.sys.call(" ipset add ss_spec_wan_ac " .. domain .. " 2>/dev/null")
local iret = luci.sys.call("ipset add ss_spec_wan_ac " .. domain .. " 2>/dev/null")
local socket = nixio.socket("inet", "stream")
socket:setopt("socket", "rcvtimeo", 3)
socket:setopt("socket", "sndtimeo", 3)
e.socket = socket:connect(domain, port)
socket:close()
e.ping = luci.sys.exec("ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*.[0-9]' | awk -F '=' '{print$2}'" % domain)
if (e.ping == "") then
e.ping = luci.sys.exec(string.format("echo -n $(tcping -q -c 1 -i 1 -t 2 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null",port, domain))
end
-- e.ping = luci.sys.exec("ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*.[0-9]' | awk -F '=' '{print$2}'" % domain)
-- if (e.ping == "") then
e.ping = luci.sys.exec(string.format("echo -n $(tcping -q -c 1 -i 1 -t 2 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null", port, domain))
-- end
if (iret == 0) then
luci.sys.call(" ipset del ss_spec_wan_ac " .. domain)
end
@ -72,55 +72,9 @@ end
function refresh_data()
local set = luci.http.formvalue("set")
local uci = luci.model.uci.cursor()
local icount = 0
local retstring = 0
local function update(url, file, type, file2)
local Num = 1
refresh_cmd = "wget-ssl --no-check-certificate -t 3 -T 10 -O- " .. url .. " > /tmp/ssr-update." .. type
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
if sret == 0 then
if type == "gfw_data" then
luci.sys.call("/usr/bin/ssr-gfw " .. type)
Num = 2
end
if type == "ad_data" then
luci.sys.call("/usr/bin/ssr-ad " .. type)
end
local new_md5 = luci.sys.exec("echo -n $([ -f '/tmp/ssr-update." .. type .. "' ] && md5sum /tmp/ssr-update." .. type .. " | awk '{print $1}')")
local old_md5 = luci.sys.exec("echo -n $([ -f '" .. file .. "' ] && md5sum " .. file .. " | awk '{print $1}')")
if new_md5 == old_md5 then
retstring = "0"
else
icount = luci.sys.exec("cat /tmp/ssr-update." .. type .. " | wc -l")
luci.sys.exec("cp -f /tmp/ssr-update." .. type .. " " .. file)
if file2 then luci.sys.exec("cp -f /tmp/ssr-update." .. type .. " " .. file2) end
retstring = tostring(tonumber(icount)/Num)
if type == "gfw_data" or type == "ad_data" then
luci.sys.exec("/usr/share/shadowsocksr/gfw2ipset.sh")
else
luci.sys.exec("/usr/share/shadowsocksr/chinaipset.sh /tmp/etc/china_ssr.txt")
end
end
else
retstring = "-1"
end
luci.sys.exec("rm -f /tmp/ssr-update." .. type)
end
if set == "gfw_data" then
update(uci:get_first("shadowsocksr", "global", "gfwlist_url", "https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt"), "/etc/ssr/gfw_list.conf", set, "/tmp/dnsmasq.ssr/gfw_list.conf")
end
if set == "ip_data" then
update(uci:get_first("shadowsocksr", "global", "chnroute_url","https://ispip.clang.cn/all_cn.txt"), "/etc/ssr/china_ssr.txt", set, "/tmp/etc/china_ssr.txt")
end
if set == "ad_data" then
update(uci:get_first("shadowsocksr", "global", "adblock_url","https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt"), "/etc/ssr/ad.conf", set, "/tmp/dnsmasq.ssr/ad.conf")
end
if set == "nfip_data" then
update(uci:get_first("shadowsocksr", "global", "nfip_url","https://raw.githubusercontent.com/QiuSimons/Netflix_IP/master/NF_only.txt"), "/etc/ssr/netflixip.list", set)
end
local retstring = luci.sys.exec("/usr/bin/lua /usr/share/shadowsocksr/update.lua " .. set)
luci.http.prepare_content("application/json")
luci.http.write_json({ret = retstring,retcount = icount})
luci.http.write_json({ret = tonumber(retstring)})
end
function check_port()
@ -134,13 +88,13 @@ function check_port()
if s.alias then
server_name = s.alias
elseif s.server and s.server_port then
server_name = "%s:%s" %{s.server, s.server_port}
server_name = "%s:%s" % {s.server, s.server_port}
end
iret = luci.sys.call("ipset add ss_spec_wan_ac " .. s.server .. " 2>/dev/null")
socket = nixio.socket("inet", "stream")
socket:setopt("socket", "rcvtimeo", 3)
socket:setopt("socket", "sndtimeo", 3)
ret = socket:connect(s.server,s.server_port)
ret = socket:connect(s.server, s.server_port)
if tostring(ret) == "true" then
socket:close()
retstring = retstring .. "<font color = 'green'>[" .. server_name .. "] OK.</font><br />"
@ -154,3 +108,9 @@ function check_port()
luci.http.prepare_content("application/json")
luci.http.write_json({ret = retstring})
end
function act_reset()
nixio.exec("/etc/init.d/shadowsocksr", "reset")
http.redirect(luci.dispatcher.build_url('admin/services/shadowsocksr'))
return
end

View File

@ -1,19 +1,18 @@
local shadowsocksr = "shadowsocksr"
local uci = luci.model.uci.cursor()
local server_table = {}
uci:foreach(shadowsocksr, "servers", function(s)
uci:foreach("shadowsocksr", "servers", function(s)
if s.alias then
server_table[s[".name"]] = "[%s]:%s" %{string.upper(s.type), s.alias}
server_table[s[".name"]] = "[%s]:%s" % {string.upper(s.type), s.alias}
elseif s.server and s.server_port then
server_table[s[".name"]] = "[%s]:%s:%s" %{string.upper(s.type), s.server, s.server_port}
server_table[s[".name"]] = "[%s]:%s:%s" % {string.upper(s.type), s.server, s.server_port}
end
end)
local key_table = {}
for key,_ in pairs(server_table) do
table.insert(key_table,key)
end
local key_table = {}
for key, _ in pairs(server_table) do
table.insert(key_table, key)
end
table.sort(key_table)
@ -49,14 +48,16 @@ o = s:option(Flag, "adblock", translate("Enable adblock"))
o.rmempty = false
o = s:option(Value, "adblock_url", translate("adblock_url"))
o:value("https://neodev.team/lite_host_dnsmasq.conf", translate("NEO DEV HOST Lite"))
o:value("https://neodev.team/host_dnsmasq.conf", translate("NEO DEV HOST Full"))
o:value("https://anti-ad.net/anti-ad-for-dnsmasq.conf", translate("anti-AD"))
o:value("https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt", translate("Easylist China"))
o.default = "https://anti-ad.net/anti-ad-for-dnsmasq.conf"
o.default = "https://neodev.team/lite_host_dnsmasq.conf"
o:depends("adblock", "1")
o.description = translate("Support AdGuardHome and DNSMASQ format list")
o = s:option(Value, "gfwlist_url", translate("gfwlist Update url"))
o:value("https://cdn.jsdelivr.net/gh/v2fly/domain-list-community@release/gfwlist.txt", translate("v2fly/domain-list-community"))
o:value("https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw.txt", translate("Loyalsoldier/v2ray-rules-dat"))
o:value("https://cdn.jsdelivr.net/gh/Loukky/gfwlist-by-loukky/gfwlist.txt", translate("Loukky/gfwlist-by-loukky"))
o:value("https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt", translate("gfwlist/gfwlist"))
o.default = "https://cdn.jsdelivr.net/gh/v2fly/domain-list-community@release/gfwlist.txt"
@ -72,6 +73,10 @@ o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Netflix_IP/getflix.txt", translat
o.default = "https://cdn.jsdelivr.net/gh/QiuSimons/Netflix_IP/NF_only.txt"
o.description = translate("Customize Netflix IP Url")
o = s:option(Button, "reset", translate("Reset to defaults"))
o.rawhtml = true
o.template = "shadowsocksr/reset"
-- [[ SOCKS5 Proxy ]]--
s = m:section(TypedSection, "socks5_proxy", translate("Global SOCKS5 Proxy Server"))
s.anonymous = true
@ -79,7 +84,9 @@ s.anonymous = true
o = s:option(ListValue, "server", translate("Server"))
o:value("nil", translate("Disable"))
o:value("same", translate("Same as Global Server"))
for _,key in pairs(key_table) do o:value(key,server_table[key]) end
for _, key in pairs(key_table) do
o:value(key, server_table[key])
end
o.default = "nil"
o.rmempty = false

View File

@ -1,118 +1,121 @@
-- Copyright (C) 2017 yushi studio <ywb94@qq.com> github.com/ywb94
-- Licensed to the public under the GNU General Public License v3.
require "nixio.fs"
require "luci.sys"
require "luci.http"
local m, s, o,kcp_enable
local shadowsocksr = "shadowsocksr"
local m, s, o, kcp_enable
local sid = arg[1]
local uuid = luci.sys.exec("cat /proc/sys/kernel/random/uuid")
local function isKcptun(file)
if not nixio.fs.access(file, "rwx", "rx", "rx") then
nixio.fs.chmod(file, 755)
end
local str = luci.sys.exec(file .. " -v | awk '{printf $1}'")
return (str:lower() == "kcptun")
if not nixio.fs.access(file, "rwx", "rx", "rx") then
nixio.fs.chmod(file, 755)
end
local str = luci.sys.exec(file .. " -v | awk '{printf $1}'")
return (str:lower() == "kcptun")
end
local server_table = {}
local encrypt_methods = {
"none",
"table",
"rc4",
"rc4-md5-6",
"rc4-md5",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"bf-cfb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"cast5-cfb",
"des-cfb",
"idea-cfb",
"rc2-cfb",
"seed-cfb",
"salsa20",
"chacha20",
"chacha20-ietf",
-- ssr
"none",
"table",
"rc4",
"rc4-md5-6",
"rc4-md5",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"bf-cfb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"cast5-cfb",
"des-cfb",
"idea-cfb",
"rc2-cfb",
"seed-cfb",
"salsa20",
"chacha20",
"chacha20-ietf"
}
local encrypt_methods_ss = {
-- aead
"aes-128-gcm",
"aes-192-gcm",
"aes-256-gcm",
"chacha20-ietf-poly1305",
"xchacha20-ietf-poly1305",
-- stream
"table",
"rc4",
"rc4-md5",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"bf-cfb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"salsa20",
"chacha20",
"chacha20-ietf",
-- aead
"aes-128-gcm",
"aes-192-gcm",
"aes-256-gcm",
"chacha20-ietf-poly1305",
"xchacha20-ietf-poly1305",
-- stream
"table",
"rc4",
"rc4-md5",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"bf-cfb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"salsa20",
"chacha20",
"chacha20-ietf"
}
local protocol = {
"origin",
"verify_deflate",
"auth_sha1_v4",
"auth_aes128_sha1",
"auth_aes128_md5",
"auth_chain_a",
"auth_chain_b",
"auth_chain_c",
"auth_chain_d",
"auth_chain_e",
"auth_chain_f",
-- ssr
"origin",
"verify_deflate",
"auth_sha1_v4",
"auth_aes128_sha1",
"auth_aes128_md5",
"auth_chain_a",
"auth_chain_b",
"auth_chain_c",
"auth_chain_d",
"auth_chain_e",
"auth_chain_f"
}
obfs = {
"plain",
"http_simple",
"http_post",
"random_head",
"tls1.2_ticket_auth",
-- ssr
"plain",
"http_simple",
"http_post",
"random_head",
"tls1.2_ticket_auth"
}
local securitys = {
"auto",
"none",
"aes-128-gcm",
"chacha20-poly1305"
-- vmess
"auto",
"none",
"aes-128-gcm",
"chacha20-poly1305"
}
local flows = {
"xtls-rprx-origin",
"xtls-rprx-origin-udp443",
"xtls-rprx-direct",
"xtls-rprx-direct-udp443",
"xtls-rprx-splice",
"xtls-rprx-splice-udp443"
-- xlts
"xtls-rprx-origin",
"xtls-rprx-origin-udp443",
"xtls-rprx-direct",
"xtls-rprx-direct-udp443",
"xtls-rprx-splice",
"xtls-rprx-splice-udp443"
}
m = Map(shadowsocksr, translate("Edit ShadowSocksR Server"))
m = Map("shadowsocksr", translate("Edit ShadowSocksR Server"))
m.redirect = luci.dispatcher.build_url("admin/services/shadowsocksr/servers")
if m.uci:get(shadowsocksr, sid) ~= "servers" then
luci.http.redirect(m.redirect)
return
if m.uci:get("shadowsocksr", sid) ~= "servers" then
luci.http.redirect(m.redirect)
return
end
-- [[ Servers Setting ]]--
@ -120,29 +123,31 @@ s = m:section(NamedSection, sid, "servers")
s.anonymous = true
s.addremove = false
o = s:option(DummyValue,"ssr_url","SS/SSR/V2RAY/TROJAN URL")
o = s:option(DummyValue, "ssr_url", "SS/SSR/V2RAY/TROJAN URL")
o.rawhtml = true
o.template = "shadowsocksr/ssrurl"
o.value =sid
o.value = sid
o = s:option(ListValue, "type", translate("Server Node Type"))
o:value("ssr", translate("ShadowsocksR"))
if nixio.fs.access("/usr/bin/ss-redir") then
o:value("ss", translate("Shadowsocks New Version"))
if nixio.fs.access("/usr/bin/ssr-redir") then
o:value("ssr", translate("ShadowsocksR"))
end
if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/bin/xray/xray") or nixio.fs.access("/usr/bin/v2ray/v2ray") or nixio.fs.access("/usr/bin/v2ray") then
o:value("v2ray", translate("V2Ray"))
o:value("vless", translate("VLESS"))
if nixio.fs.access("/usr/bin/ss-redir") then
o:value("ss", translate("Shadowsocks New Version"))
end
if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/bin/v2ray") then
o:value("vmess", translate("Vmess"))
o:value("vless", translate("VLESS"))
end
if nixio.fs.access("/usr/sbin/trojan") then
o:value("trojan", translate("Trojan"))
o:value("trojan", translate("Trojan"))
end
if nixio.fs.access("/usr/bin/naive") then
o:value("naiveproxy", translate("NaiveProxy"))
o:value("naiveproxy", translate("NaiveProxy"))
end
if nixio.fs.access("/usr/sbin/redsocks2") then
o:value("socks5", translate("Socks5"))
o:value("tun", translate("Network Tunnel"))
o:value("socks5", translate("Socks5"))
o:value("tun", translate("Network Tunnel"))
end
o.description = translate("Using incorrect encryption mothod may causes service fail to start")
@ -150,7 +155,9 @@ o = s:option(Value, "alias", translate("Alias(optional)"))
o = s:option(ListValue, "iface", translate("Network interface to use"))
for _, e in ipairs(luci.sys.net.devices()) do
if e ~= "lo" then o:value(e) end
if e ~= "lo" then
o:value(e)
end
end
o:depends("type", "tun")
o.description = translate("Redirect traffic to this network interface")
@ -160,7 +167,7 @@ o.datatype = "host"
o.rmempty = false
o:depends("type", "ssr")
o:depends("type", "ss")
o:depends("type", "v2ray")
o:depends("type", "vmess")
o:depends("type", "vless")
o:depends("type", "trojan")
o:depends("type", "naiveproxy")
@ -171,7 +178,7 @@ o.datatype = "port"
o.rmempty = false
o:depends("type", "ssr")
o:depends("type", "ss")
o:depends("type", "v2ray")
o:depends("type", "vmess")
o:depends("type", "vless")
o:depends("type", "trojan")
o:depends("type", "naiveproxy")
@ -185,7 +192,7 @@ o:depends("type", "socks5")
o = s:option(Value, "username", translate("Username"))
o.rmempty = true
o:depends("type", "naiveproxy")
o:depends("type", "socks5")
o:depends({type = "socks5", auth_enable = true})
o = s:option(Value, "password", translate("Password"))
o.password = true
@ -194,29 +201,57 @@ o:depends("type", "ssr")
o:depends("type", "ss")
o:depends("type", "trojan")
o:depends("type", "naiveproxy")
o:depends("type", "socks5")
o:depends({type = "socks5", auth_enable = true})
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods) do o:value(v) end
for _, v in ipairs(encrypt_methods) do
o:value(v)
end
o.rmempty = true
o:depends("type", "ssr")
o = s:option(ListValue, "encrypt_method_ss", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods_ss) do o:value(v) end
for _, v in ipairs(encrypt_methods_ss) do
o:value(v)
end
o.rmempty = true
o:depends("type", "ss")
-- Shadowsocks Plugin
o = s:option(Value, "plugin", translate("Plugin"))
o = s:option(ListValue, "plugin", translate("Obfs"))
o:value("", translate("None"))
if nixio.fs.access("/usr/bin/obfs-local") then
o:value("obfs-local", translate("simple-obfs"))
end
if nixio.fs.access("/usr/bin/v2ray-plugin") then
o:value("v2ray-plugin", translate("v2ray-plugin"))
end
o.rmempty = true
o:depends("type", "ss")
o = s:option(Value, "plugin_opts", translate("Plugin Opts"))
o = s:option(ListValue, "simple_obfs", translate("Plugin Opts"))
o:value("obfs=tls;obfs-host=", translate("TLS"))
o:value("obfs=http;obfs-host=", translate("HTTP"))
o:depends("plugin", "obfs-local")
o.rmempty = true
o:depends("type", "ss")
o = s:option(ListValue, "v2ray_plugin", translate("Plugin Opts"))
o:value("tls;host=", translate("TLS"))
o:value("mode=quic;host=", translate("QUIC"))
o:value("none", translate("HTTP"))
o:depends("plugin", "v2ray-plugin")
o.rmempty = true
o = s:option(Value, "plugin_opts", translate("Plugin Opts"), translate("Please fill in the Host, for example: www.baidu.com"))
o.rmempty = true
o:depends({type = "ss", plugin = "obfs-local"})
o:depends({type = "ss", v2ray_plugin = "tls;host="})
o:depends({type = "ss", v2ray_plugin = "mode=quic;host="})
o = s:option(ListValue, "protocol", translate("Protocol"))
for _, v in ipairs(protocol) do o:value(v) end
for _, v in ipairs(protocol) do
o:value(v)
end
o.rmempty = true
o:depends("type", "ssr")
@ -224,7 +259,9 @@ o = s:option(Value, "protocol_param", translate("Protocol param(optional)"))
o:depends("type", "ssr")
o = s:option(ListValue, "obfs", translate("Obfs"))
for _, v in ipairs(obfs) do o:value(v) end
for _, v in ipairs(obfs) do
o:value(v)
end
o.rmempty = true
o:depends("type", "ssr")
@ -236,13 +273,13 @@ o = s:option(Value, "alter_id", translate("AlterId"))
o.datatype = "port"
o.default = 16
o.rmempty = true
o:depends("type", "v2ray")
o:depends("type", "vmess")
-- VmessId
o = s:option(Value, "vmess_id", translate("Vmess/VLESS ID (UUID)"))
o.rmempty = true
o.default = uuid
o:depends("type", "v2ray")
o:depends("type", "vmess")
o:depends("type", "vless")
-- VLESS Encryption
@ -253,9 +290,11 @@ o:depends("type", "vless")
-- 加密方式
o = s:option(ListValue, "security", translate("Encrypt Method"))
for _, v in ipairs(securitys) do o:value(v, v:upper()) end
for _, v in ipairs(securitys) do
o:value(v, v:upper())
end
o.rmempty = true
o:depends("type", "v2ray")
o:depends("type", "vmess")
-- 传输协议
o = s:option(ListValue, "transport", translate("Transport"))
@ -265,11 +304,10 @@ o:value("ws", "WebSocket")
o:value("h2", "HTTP/2")
o:value("quic", "QUIC")
o.rmempty = true
o:depends("type", "v2ray")
o:depends("type", "vmess")
o:depends("type", "vless")
-- [[ TCP部分 ]]--
-- TCP伪装
o = s:option(ListValue, "tcp_guise", translate("Camouflage Type"))
o:depends("transport", "tcp")
@ -288,10 +326,9 @@ o:depends("tcp_guise", "http")
o.rmempty = true
-- [[ WS部分 ]]--
-- WS域名
o = s:option(Value, "ws_host", translate("WebSocket Host"))
o:depends("transport", "ws")
o:depends({transport = "ws", tls = false})
o.rmempty = true
-- WS路径
@ -312,7 +349,6 @@ o:depends("transport", "h2")
o.rmempty = true
-- [[ QUIC部分 ]]--
o = s:option(ListValue, "quic_security", translate("QUIC Security"))
o:depends("transport", "quic")
o:value("none", translate("None"))
@ -331,19 +367,18 @@ o:value("none", translate("None"))
o:value("srtp", translate("VideoCall (SRTP)"))
o:value("utp", translate("BitTorrent (uTP)"))
o:value("wechat-video", translate("WechatVideo"))
o:value("dtls", "DTLS 1.2")
o:value("wireguard", "WireGuard")
o:value("dtls", translate("DTLS 1.2"))
o:value("wireguard", translate("WireGuard"))
-- [[ mKCP部分 ]]--
o = s:option(ListValue, "kcp_guise", translate("Camouflage Type"))
o:depends("transport", "kcp")
o:value("none", translate("None"))
o:value("srtp", translate("VideoCall (SRTP)"))
o:value("utp", translate("BitTorrent (uTP)"))
o:value("wechat-video", translate("WechatVideo"))
o:value("dtls", "DTLS 1.2")
o:value("wireguard", "WireGuard")
o:value("dtls", translate("DTLS 1.2"))
o:value("wireguard", translate("WireGuard"))
o.rmempty = true
o = s:option(Value, "mtu", translate("MTU"))
@ -383,55 +418,56 @@ o.default = 2
o.rmempty = true
o = s:option(Value, "seed", translate("Obfuscate password (optional)"))
o:depends({type="vless", transport="kcp"})
o:depends({type = "vless", transport = "kcp"})
o.rmempty = true
o = s:option(Flag, "congestion", translate("Congestion"))
o:depends("transport", "kcp")
o.rmempty = true
-- [[ allowInsecure ]]--
o = s:option(Flag, "insecure", translate("allowInsecure"))
o.rmempty = false
o:depends("type", "v2ray")
o:depends("type", "vless")
o:depends("type", "trojan")
o.default = "0"
o.description = translate("If true, allowss insecure connection at TLS client, e.g., TLS server uses unverifiable certificates.")
-- [[ TLS ]]--
o = s:option(Flag, "tls", translate("TLS"))
o.rmempty = true
o.default = "0"
o:depends("type", "v2ray")
o:depends("type", "vless")
o:depends("type", "vmess")
o:depends({type = "vless", xtls = false})
o:depends("type", "trojan")
o = s:option(Value, "tls_host", translate("TLS Host"))
--o:depends("type", "trojan")
o:depends("tls", "1")
o.rmempty = true
-- XTLS
if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/bin/xray/xray") then
o = s:option(Flag, "xtls", translate("XTLS"))
o.rmempty = true
o.default = "0"
o:depends({type="vless", tls=true})
if nixio.fs.access("/usr/bin/xray") then
o = s:option(Flag, "xtls", translate("XTLS"))
o.rmempty = true
o.default = "0"
o:depends({type = "vless", transport = "tcp", tls = false})
end
-- Flow
o = s:option(Value, "vless_flow", translate("Flow"))
for _, v in ipairs(flows) do o:value(v, v) end
for _, v in ipairs(flows) do
o:value(v, v)
end
o.rmempty = true
o.default = "xtls-rprx-origin"
o:depends("xtls", "1")
o.default = "xtls-rprx-splice"
o:depends("xtls", true)
o = s:option(Value, "tls_host", translate("TLS Host"))
o:depends("type", "trojan")
o:depends("tls", true)
o:depends("xtls", true)
o.rmempty = true
-- [[ allowInsecure ]]--
o = s:option(Flag, "insecure", translate("allowInsecure"))
o.rmempty = false
o:depends("tls", true)
o:depends("xtls", true)
o.description = translate("If true, allowss insecure connection at TLS client, e.g., TLS server uses unverifiable certificates.")
-- [[ Mux ]]--
o = s:option(Flag, "mux", translate("Mux"))
o.rmempty = true
o.default = "0"
o:depends("type", "v2ray")
o:depends({type="vless", xtls=false})
o.rmempty = false
o:depends("type", "vmess")
o:depends({type = "vless", xtls = false})
o = s:option(Value, "concurrency", translate("Concurrency"))
o.datatype = "uinteger"
@ -444,7 +480,7 @@ o = s:option(Flag, "certificate", translate("Self-signed Certificate"))
o.rmempty = true
o.default = "0"
o:depends("type", "trojan")
o:depends("type", "v2ray")
o:depends("type", "vmess")
o:depends("type", "vless")
o.description = translate("If you have a self-signed certificate,please check the box")
@ -455,31 +491,31 @@ o:depends("certificate", 1)
cert_dir = "/etc/ssl/private/"
local path
luci.http.setfilehandler(
function(meta, chunk, eof)
if not fd then
if (not meta) or (not meta.name) or (not meta.file) then return end
fd = nixio.open(cert_dir .. meta.file, "w")
if not fd then
path = translate("Create upload file error.")
return
end
end
if chunk and fd then
fd:write(chunk)
end
if eof and fd then
fd:close()
fd = nil
path = '/etc/ssl/private/' .. meta.file .. ''
end
end
)
luci.http.setfilehandler(function(meta, chunk, eof)
if not fd then
if (not meta) or (not meta.name) or (not meta.file) then
return
end
fd = nixio.open(cert_dir .. meta.file, "w")
if not fd then
path = translate("Create upload file error.")
return
end
end
if chunk and fd then
fd:write(chunk)
end
if eof and fd then
fd:close()
fd = nil
path = '/etc/ssl/private/' .. meta.file .. ''
end
end)
if luci.http.formvalue("upload") then
local f = luci.http.formvalue("ulfile")
if #f <= 0 then
path = translate("No specify upload file.")
end
local f = luci.http.formvalue("ulfile")
if #f <= 0 then
path = translate("No specify upload file.")
end
end
o = s:option(Value, "certpath", translate("Current Certificate Path"))
@ -505,40 +541,40 @@ o.default = 1234
o.rmempty = false
if nixio.fs.access("/usr/bin/kcptun-client") then
kcp_enable = s:option(Flag, "kcp_enable", translate("KcpTun Enable"), translate("bin:/usr/bin/kcptun-client"))
kcp_enable.rmempty = true
kcp_enable.default = "0"
kcp_enable:depends("type", "ssr")
kcp_enable:depends("type", "ss")
kcp_enable = s:option(Flag, "kcp_enable", translate("KcpTun Enable"), translate("bin:/usr/bin/kcptun-client"))
kcp_enable.rmempty = true
kcp_enable.default = "0"
kcp_enable:depends("type", "ssr")
kcp_enable:depends("type", "ss")
o = s:option(Value, "kcp_port", translate("KcpTun Port"))
o.datatype = "port"
o.default = 4000
function o.validate(self, value, section)
local kcp_file="/usr/bin/kcptun-client"
local enable = kcp_enable:formvalue(section) or kcp_enable.disabled
if enable == kcp_enable.enabled then
if not nixio.fs.access(kcp_file) then
return nil, translate("Haven't a Kcptun executable file")
elseif not isKcptun(kcp_file) then
return nil, translate("Not a Kcptun executable file")
end
end
o = s:option(Value, "kcp_port", translate("KcpTun Port"))
o.datatype = "port"
o.default = 4000
function o.validate(self, value, section)
local kcp_file = "/usr/bin/kcptun-client"
local enable = kcp_enable:formvalue(section) or kcp_enable.disabled
if enable == kcp_enable.enabled then
if not nixio.fs.access(kcp_file) then
return nil, translate("Haven't a Kcptun executable file")
elseif not isKcptun(kcp_file) then
return nil, translate("Not a Kcptun executable file")
end
end
return value
end
o:depends("type", "ssr")
o:depends("type", "ss")
return value
end
o:depends("type", "ssr")
o:depends("type", "ss")
o = s:option(Value, "kcp_password", translate("KcpTun Password"))
o.password = true
o:depends("type", "ssr")
o:depends("type", "ss")
o = s:option(Value, "kcp_password", translate("KcpTun Password"))
o.password = true
o:depends("type", "ssr")
o:depends("type", "ss")
o = s:option(Value, "kcp_param", translate("KcpTun Param"))
o.default = "--nocomp"
o:depends("type", "ssr")
o:depends("type", "ss")
o = s:option(Value, "kcp_param", translate("KcpTun Param"))
o.default = "--nocomp"
o:depends("type", "ssr")
o:depends("type", "ss")
end
return m

View File

@ -1,27 +1,24 @@
-- Copyright (C) 2017 yushi studio <ywb94@qq.com> github.com/ywb94
-- Copyright (C) 2018 lean <coolsnowwolf@gmail.com> github.com/coolsnowwolf
-- Licensed to the public under the GNU General Public License v3.
local m, s, sec, o, kcp_enable
local shadowsocksr = "shadowsocksr"
local uci = luci.model.uci.cursor()
m = Map(shadowsocksr, translate("ShadowSocksR Plus+ Settings"),
translate("<h3>Support SS/SSR/V2RAY/TROJAN/NAIVEPROXY/SOCKS5/TUN etc.</h3>"))
m = Map("shadowsocksr", translate("ShadowSocksR Plus+ Settings"), translate("<h3>Support SS/SSR/V2RAY/TROJAN/NAIVEPROXY/SOCKS5/TUN etc.</h3>"))
m:section(SimpleSection).template = "shadowsocksr/status"
local server_table = {}
uci:foreach(shadowsocksr, "servers", function(s)
uci:foreach("shadowsocksr", "servers", function(s)
if s.alias then
server_table[s[".name"]] = "[%s]:%s" %{string.upper(s.type), s.alias}
server_table[s[".name"]] = "[%s]:%s" % {string.upper(s.type), s.alias}
elseif s.server and s.server_port then
server_table[s[".name"]] = "[%s]:%s:%s" %{string.upper(s.type), s.server, s.server_port}
server_table[s[".name"]] = "[%s]:%s:%s" % {string.upper(s.type), s.server, s.server_port}
end
end)
local key_table = {}
for key,_ in pairs(server_table) do
table.insert(key_table,key)
for key, _ in pairs(server_table) do
table.insert(key_table, key)
end
table.sort(key_table)
@ -32,26 +29,32 @@ s.anonymous = true
o = s:option(ListValue, "global_server", translate("Main Server"))
o:value("nil", translate("Disable"))
for _,key in pairs(key_table) do o:value(key,server_table[key]) end
for _, key in pairs(key_table) do
o:value(key, server_table[key])
end
o.default = "nil"
o.rmempty = false
o = s:option(ListValue, "udp_relay_server", translate("Game Mode UDP Server"))
o:value("", translate("Disable"))
o:value("same", translate("Same as Global Server"))
for _,key in pairs(key_table) do o:value(key,server_table[key]) end
for _, key in pairs(key_table) do
o:value(key, server_table[key])
end
o = s:option(ListValue, "netflix_server", translate("Netflix Node"))
o:value("nil", translate("Disable"))
o:value("same", translate("Same as Global Server"))
for _,key in pairs(key_table) do o:value(key,server_table[key]) end
for _, key in pairs(key_table) do
o:value(key, server_table[key])
end
o.default = "nil"
o.rmempty = false
o = s:option(Flag, "netflix_proxy", translate("External Proxy Mode"))
o.rmempty = false
o.description = translate("Forward Netflix Proxy through Main Proxy")
o.default="0"
o.default = "0"
o = s:option(ListValue, "threads", translate("Multi Threads Option"))
o:value("0", translate("Auto Threads"))

View File

@ -36,7 +36,7 @@ o.rmempty = false
o = s:taboption("lan_ac", DynamicList, "lan_ac_ips", translate("LAN Host List"))
o.datatype = "ipaddr"
luci.ip.neighbors({ family = 4 }, function(entry)
luci.ip.neighbors({family = 4}, function(entry)
if entry.reachable then
o:value(entry.dest:string())
end
@ -46,7 +46,7 @@ o:depends("lan_ac_mode", "b")
o = s:taboption("lan_ac", DynamicList, "lan_bp_ips", translate("LAN Bypassed Host List"))
o.datatype = "ipaddr"
luci.ip.neighbors({ family = 4 }, function(entry)
luci.ip.neighbors({family = 4}, function(entry)
if entry.reachable then
o:value(entry.dest:string())
end
@ -54,7 +54,7 @@ end)
o = s:taboption("lan_ac", DynamicList, "lan_fp_ips", translate("LAN Force Proxy Host List"))
o.datatype = "ipaddr"
luci.ip.neighbors({ family = 4 }, function(entry)
luci.ip.neighbors({family = 4}, function(entry)
if entry.reachable then
o:value(entry.dest:string())
end
@ -62,7 +62,7 @@ end)
o = s:taboption("lan_ac", DynamicList, "lan_gm_ips", translate("Game Mode Host List"))
o.datatype = "ipaddr"
luci.ip.neighbors({ family = 4 }, function(entry)
luci.ip.neighbors({family = 4}, function(entry)
if entry.reachable then
o:value(entry.dest:string())
end
@ -77,7 +77,7 @@ end)
-- o.rmempty = false
s:tab("esc", translate("Bypass Domain List"))
local escconf = "/etc/ssr/white.list"
local escconf = "/etc/ssrplus/white.list"
o = s:taboption("esc", TextValue, "escconf")
o.rows = 13
o.wrap = "off"
@ -93,7 +93,7 @@ o.remove = function(self, section, value)
end
s:tab("block", translate("Black Domain List"))
local blockconf = "/etc/ssr/black.list"
local blockconf = "/etc/ssrplus/black.list"
o = s:taboption("block", TextValue, "blockconf")
o.rows = 13
o.wrap = "off"
@ -109,7 +109,7 @@ o.remove = function(self, section, value)
end
s:tab("denydomain", translate("Deny Domain List"))
local denydomainconf = "/etc/ssr/deny.list"
local denydomainconf = "/etc/ssrplus/deny.list"
o = s:taboption("denydomain", TextValue, "denydomainconf")
o.rows = 13
o.wrap = "off"
@ -125,7 +125,7 @@ o.remove = function(self, section, value)
end
s:tab("netflix", translate("Netflix Domain List"))
local netflixconf = "/etc/ssr/netflix.list"
local netflixconf = "/etc/ssrplus/netflix.list"
o = s:taboption("netflix", TextValue, "netflixconf")
o.rows = 13
o.wrap = "off"

View File

@ -7,8 +7,8 @@ t = f:field(TextValue, "conf")
t.rmempty = true
t.rows = 20
function t.cfgvalue()
if nixio.fs.access("/tmp/ssrplus.log") then
local logs = luci.util.execi("cat /tmp/ssrplus.log")
if nixio.fs.access("/var/log/ssrplus.log") then
local logs = luci.util.execi("cat /var/log/ssrplus.log")
local s = ""
for line in logs do
s = line .. "\n" .. s
@ -16,5 +16,5 @@ function t.cfgvalue()
return s
end
end
t.readonly="readonly"
t.readonly = "readonly"
return f

View File

@ -5,48 +5,41 @@ require "luci.dispatcher"
require "nixio.fs"
local m, s, o
local shadowsocksr = "shadowsocksr"
local sid = arg[1]
local encrypt_methods = {
"rc4-md5",
"rc4-md5-6",
"rc4",
"table",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"bf-cfb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"cast5-cfb",
"des-cfb",
"idea-cfb",
"rc2-cfb",
"seed-cfb",
"salsa20",
"chacha20",
"chacha20-ietf",
"rc4-md5",
"rc4-md5-6",
"rc4",
"table",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"bf-cfb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"cast5-cfb",
"des-cfb",
"idea-cfb",
"rc2-cfb",
"seed-cfb",
"salsa20",
"chacha20",
"chacha20-ietf"
}
local protocol = {
"origin",
}
local protocol = {"origin"}
obfs = {
"plain",
"http_simple",
"http_post",
}
obfs = {"plain", "http_simple", "http_post"}
m = Map(shadowsocksr, translate("Edit ShadowSocksR Server"))
m = Map("shadowsocksr", translate("Edit ShadowSocksR Server"))
m.redirect = luci.dispatcher.build_url("admin/services/shadowsocksr/server")
if m.uci:get(shadowsocksr, sid) ~= "server_config" then
if m.uci:get("shadowsocksr", sid) ~= "server_config" then
luci.http.redirect(m.redirect)
return
end
@ -70,7 +63,7 @@ o.default = "socks5"
o = s:option(Value, "server_port", translate("Server Port"))
o.datatype = "port"
math.randomseed(tostring(os.time()):reverse():sub(1, 7))
o.default = math.random(10240,20480)
o.default = math.random(10240, 20480)
o.rmempty = false
o.description = translate("warning! Please do not reuse the port!")
@ -89,17 +82,23 @@ o.password = true
o.rmempty = false
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods) do o:value(v) end
for _, v in ipairs(encrypt_methods) do
o:value(v)
end
o.rmempty = false
o:depends("type", "ssr")
o = s:option(ListValue, "protocol", translate("Protocol"))
for _, v in ipairs(protocol) do o:value(v) end
for _, v in ipairs(protocol) do
o:value(v)
end
o.rmempty = false
o:depends("type", "ssr")
o = s:option(ListValue, "obfs", translate("Obfs"))
for _, v in ipairs(obfs) do o:value(v) end
for _, v in ipairs(obfs) do
o:value(v)
end
o.rmempty = false
o:depends("type", "ssr")

View File

@ -3,51 +3,50 @@
require "luci.http"
require "luci.dispatcher"
local m, sec, o
local shadowsocksr = "shadowsocksr"
local encrypt_methods = {
"table",
"rc4",
"rc4-md5",
"rc4-md5-6",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"bf-cfb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"cast5-cfb",
"des-cfb",
"idea-cfb",
"rc2-cfb",
"seed-cfb",
"salsa20",
"chacha20",
"chacha20-ietf",
"table",
"rc4",
"rc4-md5",
"rc4-md5-6",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"bf-cfb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"cast5-cfb",
"des-cfb",
"idea-cfb",
"rc2-cfb",
"seed-cfb",
"salsa20",
"chacha20",
"chacha20-ietf"
}
local protocol = {
"origin",
"verify_deflate",
"auth_sha1_v4",
"auth_aes128_sha1",
"auth_aes128_md5",
"auth_chain_a",
"origin",
"verify_deflate",
"auth_sha1_v4",
"auth_aes128_sha1",
"auth_aes128_md5",
"auth_chain_a"
}
obfs = {
"plain",
"http_simple",
"http_post",
"random_head",
"tls1.2_ticket_auth",
"tls1.2_ticket_fastauth",
"plain",
"http_simple",
"http_post",
"random_head",
"tls1.2_ticket_auth",
"tls1.2_ticket_fastauth"
}
m = Map(shadowsocksr)
m = Map("shadowsocksr")
-- [[ Global Setting ]]--
sec = m:section(TypedSection, "server_global", translate("Global Setting"))
sec.anonymous = true

View File

@ -3,17 +3,15 @@ require "luci.http"
require "luci.dispatcher"
require "luci.model.uci"
local m, s, o
local shadowsocksr = "shadowsocksr"
local uci = luci.model.uci.cursor()
local server_count = 0
uci:foreach("shadowsocksr", "servers", function(s)
server_count = server_count + 1
end)
m = Map(shadowsocksr, translate("Servers subscription and manage"))
m = Map("shadowsocksr", translate("Servers subscription and manage"))
-- Server Subscribe
s = m:section(TypedSection, "server_subscribe")
s.anonymous = true
@ -21,12 +19,11 @@ 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")
for t = 0, 23 do
o:value(t, t .. ":00")
end
o.default=2
o.default = 2
o.rmempty = false
o = s:option(DynamicList, "subscribe_url", translate("Subscribe URL"))
@ -36,28 +33,28 @@ o = s:option(Value, "filter_words", translate("Subscribe Filter Words"))
o.rmempty = true
o.description = translate("Filter Words splited by /")
o = s:option(Button,"update_Sub",translate("Update Subscribe List"))
o = s:option(Button, "update_Sub", translate("Update Subscribe List"))
o.inputstyle = "reload"
o.description = translate("Update subscribe url list first")
o.write = function()
uci:commit("shadowsocksr")
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr", "servers"))
end
o = s:option(Flag, "switch", translate("Subscribe Default Auto-Switch"))
o.rmempty = false
o.description = translate("Subscribe new add server default Auto-Switch on")
o.default="1"
o.default = "1"
o = s:option(Flag, "proxy", translate("Through proxy update"))
o.rmempty = false
o.description = translate("Through proxy update list, Not Recommended ")
o = s:option(Button,"subscribe", translate("Update All Subscribe Severs"))
o = s:option(Button, "subscribe", translate("Update All Subscribe Severs"))
o.rawhtml = true
o.template = "shadowsocksr/subscribe"
o = s:option(Button,"delete",translate("Delete All Subscribe Severs"))
o = s:option(Button, "delete", translate("Delete All Subscribe Severs"))
o.inputstyle = "reset"
o.description = string.format(translate("Server Count") .. ": %d", server_count)
o.write = function()
@ -69,9 +66,7 @@ o.write = function()
end
end)
uci:save("shadowsocksr")
uci:commit("shadowsocksr")
luci.sys.exec("/etc/init.d/shadowsocksr restart &")
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr", "servers"))
m.uci:commit("shadowsocksr")
return
end
@ -92,7 +87,7 @@ end
o = s:option(DummyValue, "type", translate("Type"))
function o.cfgvalue(...)
return (Value.cfgvalue(...) == "vless") and "VLESS" or Value.cfgvalue(...)
return Value.cfgvalue(...)
end
o = s:option(DummyValue, "alias", translate("Alias"))
@ -106,21 +101,19 @@ function o.cfgvalue(...)
end
o = s:option(DummyValue, "server_port", translate("Socket Connected"))
o.template="shadowsocksr/socket"
o.width="10%"
o.template = "shadowsocksr/socket"
o.width = "10%"
o = s:option(DummyValue, "server", translate("Ping Latency"))
o.template="shadowsocksr/ping"
o.width="10%"
o.template = "shadowsocksr/ping"
o.width = "10%"
node = s:option(Button,"apply_node",translate("Apply"))
node = s:option(Button, "apply_node", translate("Apply"))
node.inputstyle = "apply"
node.write = function(self, section)
uci:set("shadowsocksr", '@global[0]', 'global_server', section)
uci:save("shadowsocksr")
uci:commit("shadowsocksr")
luci.sys.exec("/etc/init.d/shadowsocksr restart &")
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr", "client"))
m.uci:commit("shadowsocksr")
end
o = s:option(Flag, "switch_enable", translate("Auto Switch"))

View File

@ -4,177 +4,184 @@ require "nixio.fs"
require "luci.sys"
require "luci.model.uci"
local m, s, o
local redir_run=0
local reudp_run=0
local sock5_run=0
local server_run=0
local kcptun_run=0
local tunnel_run=0
local gfw_count=0
local ad_count=0
local ip_count=0
local nfip_count=0
local redir_run = 0
local reudp_run = 0
local sock5_run = 0
local server_run = 0
local kcptun_run = 0
local tunnel_run = 0
local gfw_count = 0
local ad_count = 0
local ip_count = 0
local nfip_count = 0
local Process_list = luci.sys.exec("busybox ps -w")
local uci = luci.model.uci.cursor()
local shadowsocksr = "shadowsocksr"
-- html constants
font_blue = [[<font color="green">]]
font_off = [[</font>]]
bold_on = [[<strong>]]
bold_off = [[</strong>]]
local kcptun_version=translate("Unknown")
local kcp_file="/usr/bin/kcptun-client"
local kcptun_version = translate("Unknown")
local kcp_file = "/usr/bin/kcptun-client"
if not nixio.fs.access(kcp_file) then
kcptun_version=translate("Not exist")
kcptun_version = translate("Not exist")
else
if not nixio.fs.access(kcp_file, "rwx", "rx", "rx") then
nixio.fs.chmod(kcp_file, 755)
end
kcptun_version=luci.sys.exec(kcp_file .. " -v | awk '{printf $3}'")
kcptun_version = luci.sys.exec(kcp_file .. " -v | awk '{printf $3}'")
if not kcptun_version or kcptun_version == "" then
kcptun_version = translate("Unknown")
end
end
if nixio.fs.access("/etc/ssr/gfw_list.conf") then
gfw_count = tonumber(luci.sys.exec("cat /etc/ssr/gfw_list.conf | wc -l"))/2
if nixio.fs.access("/etc/ssrplus/gfw_list.conf") then
gfw_count = tonumber(luci.sys.exec("cat /etc/ssrplus/gfw_list.conf | wc -l")) / 2
end
if nixio.fs.access("/etc/ssr/ad.conf") then
ad_count = tonumber(luci.sys.exec("cat /etc/ssr/ad.conf | wc -l"))
if nixio.fs.access("/etc/ssrplus/ad.conf") then
ad_count = tonumber(luci.sys.exec("cat /etc/ssrplus/ad.conf | wc -l"))
end
if nixio.fs.access("/etc/ssr/china_ssr.txt") then
ip_count = tonumber(luci.sys.exec("cat /etc/ssr/china_ssr.txt | wc -l"))
if nixio.fs.access("/etc/ssrplus/china_ssr.txt") then
ip_count = tonumber(luci.sys.exec("cat /etc/ssrplus/china_ssr.txt | wc -l"))
end
if nixio.fs.access("/etc/ssr/netflixip.list") then
nfip_count = tonumber(luci.sys.exec("cat /etc/ssr/netflixip.list | wc -l"))
if nixio.fs.access("/etc/ssrplus/netflixip.list") then
nfip_count = tonumber(luci.sys.exec("cat /etc/ssrplus/netflixip.list | wc -l"))
end
local icount=luci.sys.exec("busybox ps -w | grep ssr-reudp |grep -v grep| wc -l")
if tonumber(icount)>0 then
reudp_run=1
else
icount=luci.sys.exec("busybox ps -w | grep ssr-retcp |grep \"\\-u\"|grep -v grep| wc -l")
if tonumber(icount)>0 then
reudp_run=1
end
if Process_list:find("udp.only.ssr.reudp") then
reudp_run = 1
end
if luci.sys.call("busybox ps -w | grep ssr-retcp | grep -v grep >/dev/null") == 0 then
redir_run=1
if Process_list:find("tcp.only.ssr.retcp") then
redir_run = 1
end
if luci.sys.call("busybox ps -w | grep ssr-local | grep -v ssr-socksdns |grep -v grep >/dev/null") == 0 then
sock5_run=1
if Process_list:find("tcp.udp.ssr.local") then
sock5_run = 1
end
if luci.sys.call("pidof kcptun-client >/dev/null") == 0 then
kcptun_run=1
if Process_list:find("tcp.udp.ssr.retcp") then
redir_run = 1
reudp_run = 1
end
if luci.sys.call("busybox ps -w | grep ssr-server | grep -v grep >/dev/null") == 0 then
server_run=1
if Process_list:find("local.ssr.retcp") then
redir_run = 1
sock5_run = 1
end
-- if luci.sys.call("busybox ps -w | grep ssr-tunnel |grep -v grep >/dev/null") == 0 then
-- tunnel_run=1
-- end
if luci.sys.call("pidof pdnsd >/dev/null") == 0 or (luci.sys.call("busybox ps -w | grep ssr-dns |grep -v grep >/dev/null") == 0 and luci.sys.call("pidof dns2socks >/dev/null") == 0)then
pdnsd_run=1
if Process_list:find("local.udp.ssr.retcp") then
reudp_run = 1
redir_run = 1
sock5_run = 1
end
if Process_list:find("kcptun.client") then
kcptun_run = 1
end
if Process_list:find("ssr.server") then
server_run = 1
end
if Process_list:find("ssrplus/bin/pdnsd") or (Process_list:find("ssrplus.dns") and Process_list:find("dns2socks 127.0.0.1:.*127.0.0.1:5335")) then
pdnsd_run = 1
end
m = SimpleForm("Version")
m.reset = false
m.submit = false
s=m:field(DummyValue,"redir_run",translate("Global Client"))
s = m:field(DummyValue, "redir_run", translate("Global Client"))
s.rawhtml = true
if redir_run == 1 then
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
s.value = font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
else
s.value = translate("Not Running")
end
s=m:field(DummyValue,"reudp_run",translate("Game Mode UDP Relay"))
s = m:field(DummyValue, "reudp_run", translate("Game Mode UDP Relay"))
s.rawhtml = true
if reudp_run == 1 then
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
s.value = font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
else
s.value = translate("Not Running")
end
if uci:get_first(shadowsocksr, 'global', 'pdnsd_enable', '0') ~= '0' then
s=m:field(DummyValue,"pdnsd_run",translate("DNS Anti-pollution"))
if uci:get_first("shadowsocksr", 'global', 'pdnsd_enable', '0') ~= '0' then
s = m:field(DummyValue, "pdnsd_run", translate("DNS Anti-pollution"))
s.rawhtml = true
if pdnsd_run == 1 then
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
s.value = font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
else
s.value = translate("Not Running")
end
end
s=m:field(DummyValue,"sock5_run",translate("Global SOCKS5 Proxy Server"))
s = m:field(DummyValue, "sock5_run", translate("Global SOCKS5 Proxy Server"))
s.rawhtml = true
if sock5_run == 1 then
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
s.value = font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
else
s.value = translate("Not Running")
end
s=m:field(DummyValue,"server_run",translate("Local Servers"))
s = m:field(DummyValue, "server_run", translate("Local Servers"))
s.rawhtml = true
if server_run == 1 then
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
s.value = font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
else
s.value = translate("Not Running")
end
if nixio.fs.access("/usr/bin/kcptun-client") then
s=m:field(DummyValue,"kcp_version",translate("KcpTun Version"))
s = m:field(DummyValue, "kcp_version", translate("KcpTun Version"))
s.rawhtml = true
s.value =kcptun_version
s=m:field(DummyValue,"kcptun_run",translate("KcpTun"))
s.value = kcptun_version
s = m:field(DummyValue, "kcptun_run", translate("KcpTun"))
s.rawhtml = true
if kcptun_run == 1 then
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
s.value = font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
else
s.value = translate("Not Running")
end
end
s=m:field(DummyValue,"google",translate("Google Connectivity"))
s = m:field(DummyValue, "google", translate("Google Connectivity"))
s.value = translate("No Check")
s.template = "shadowsocksr/check"
s=m:field(DummyValue,"baidu",translate("Baidu Connectivity"))
s = m:field(DummyValue, "baidu", translate("Baidu Connectivity"))
s.value = translate("No Check")
s.template = "shadowsocksr/check"
s=m:field(DummyValue,"gfw_data",translate("GFW List Data"))
s = m:field(DummyValue, "gfw_data", translate("GFW List Data"))
s.rawhtml = true
s.template = "shadowsocksr/refresh"
s.value = gfw_count .. " " .. translate("Records")
s=m:field(DummyValue,"ip_data",translate("China IP Data"))
s = m:field(DummyValue, "ip_data", translate("China IP Data"))
s.rawhtml = true
s.template = "shadowsocksr/refresh"
s.value = ip_count .. " " .. translate("Records")
s=m:field(DummyValue,"nfip_data",translate("Netflix IP Data"))
s = m:field(DummyValue, "nfip_data", translate("Netflix IP Data"))
s.rawhtml = true
s.template = "shadowsocksr/refresh"
s.value = nfip_count .. " " .. translate("Records")
if uci:get_first(shadowsocksr, 'global', 'adblock', '0') == '1' then
s=m:field(DummyValue,"ad_data",translate("Advertising Data"))
if uci:get_first("shadowsocksr", 'global', 'adblock', '0') == '1' then
s = m:field(DummyValue, "ad_data", translate("Advertising Data"))
s.rawhtml = true
s.template = "shadowsocksr/refresh"
s.value = ad_count .. " " .. translate("Records")
end
s=m:field(DummyValue,"check_port",translate("Check Server Port"))
s = m:field(DummyValue, "check_port", translate("Check Server Port"))
s.template = "shadowsocksr/checkport"
s.value =translate("No Check")
s.value = translate("No Check")
return m

View File

@ -26,5 +26,4 @@
//]]></script>
<input type="button" class="cbi-button cbi-button-apply" value="<%:Check Connect%>" onclick="return check_connect(this,'<%=self.option%>')" />
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
<%+cbi/valuefooter%>

View File

@ -1,7 +1,5 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
function check_port(btn)
{
btn.disabled = true;
@ -13,24 +11,15 @@
var s = document.getElementById('<%=self.option%>-status');
if (s)
{
s.innerHTML =rv.ret;
}
btn.disabled = false;
btn.value = '<%:Check Server%>';
}
);
return false;
}
//]]></script>
<input type="button" class="cbi-button cbi-button-apply" value="<%:Check Server%>" onclick="return check_port(this)" />
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
<%+cbi/valuefooter%>
<%+cbi/valuefooter%>

View File

@ -12,16 +12,18 @@
var s = document.getElementById(dataname+'-status');
if (s)
{
if (rv.ret=="0")
s.innerHTML ="<font color='green'>"+"<%:No new data!%> "+"</font>";
else if(rv.ret=="-1")
if(rv.ret=="-1")
{
s.innerHTML ="<font color='red'>"+"<%:Refresh Error!%> "+"</font>";
}
if (rv.ret=="0")
{
s.innerHTML ="<font color='green'>"+"<%:No new data!%> "+"</font>";
}
else
{
s.innerHTML ="<font color='green'>"+"<%:Refresh OK!%> "+"<%:Total Records:%>"+rv.ret+"</font>";
}
{
s.innerHTML ="<font color='green'>"+"<%:Refresh OK!%> "+"<%:Total Records:%>"+rv.ret+"</font>";
}
}
btn.disabled = false;
btn.value = '<%:Refresh Data %>';

View File

@ -0,0 +1,25 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
function subscribe(btn,dataname) {
var s = document.getElementById(dataname + '-status');
var reset = prompt('<%:Really reset all changes?%><%:Please fill in reset%>',"")
if (reset == null || reset == "") {
return false;
}
if (reset != "reset") {
s.innerHTML = "<font color='red'><%:The content entered is incorrect!%></font>";
return false;
}
btn.disabled = true;
btn.value = '<%:Perform reset%>';
murl=dataname;
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr","reset")%>', { set:murl }, function(x,rv) {
btn.value = '<%:Reset complete%>';
s.innerHTML = "<font color='green'><%:Reset complete%></font>";
});
return false;
}
//]]></script>
<input type="button" class="cbi-button cbi-button-reset" value="<%:Perform reset%> " onclick="return subscribe(this,'<%=self.option%>')" />
<span id="<%=self.option%>-status"></span>
<%+cbi/valuefooter%>

View File

@ -2,9 +2,6 @@
Copyright 2018-2019 Lienol <lawlienol@gmail.com>
Licensed to the public under the Apache License 2.0.
-%>
<%
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">
//<![CDATA[
const doms = document.getElementsByClassName('pingtime');
@ -15,8 +12,7 @@ local dsp = require "luci.dispatcher"
const port = ports[index];
if (!dom) res()
port.innerHTML = '<font color="#0072c3">connect</font>';
XHR.get('<%=dsp.build_url("admin/services/shadowsocksr/ping")%>', {
XHR.get('<%=luci.dispatcher.build_url("admin/services/shadowsocksr/ping")%>', {
index,
domain: dom.getAttribute("hint"),
port: port.getAttribute("hint")
@ -48,7 +44,6 @@ local dsp = require "luci.dispatcher"
for (let i = 0; i < 20; i++) {
thread()
}
function cbi_row_drop(fromId, toId, store, isToBottom) {
var fromNode = document.getElementById(fromId);
var toNode = document.getElementById(toId);
@ -65,7 +60,6 @@ local dsp = require "luci.dispatcher"
} else {
fromNode.parentNode.insertBefore(fromNode, toNode);
}
for (var idx = 2; idx < table.rows.length; idx++) {
table.rows[idx].className = table.rows[idx].className.replace(
/cbi-rowstyle-[12]/,
@ -75,53 +69,43 @@ local dsp = require "luci.dispatcher"
if (table.rows[idx].id && table.rows[idx].id.match(/-([^\-]+)$/))
ids.push(RegExp.$1);
}
var input = document.getElementById(store);
if (input) input.value = ids.join(" ");
return false;
}
// set tr draggable
function enableDragForTable(table_selecter, store) {
var trs = document.querySelectorAll(table_selecter + " tr");
if (!trs || trs.length.length < 3) {
return;
}
function ondragstart(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
}
function ondrop(ev) {
var from = ev.dataTransfer.getData("Text");
cbi_row_drop(from, this.id, store);
}
function ondragover(ev) {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move";
}
function moveToTop(id) {
var top = document.querySelectorAll(table_selecter + " tr")[2];
cbi_row_drop(id, top.id, store);
}
function moveToBottom(id) {
console.log('moveToBottom:', id);
var trList = document.querySelectorAll(table_selecter + " tr");
var bottom = trList[trList.length - 1];
cbi_row_drop(id, bottom.id, store, true);
}
for (let index = 2; index < trs.length; index++) {
const el = trs[index];
el.setAttribute("draggable", true);
el.ondragstart = ondragstart;
el.ondrop = ondrop;
el.ondragover = ondragover;
// reset the behaviors of the btns
var upBtns = el.querySelectorAll(".cbi-button.cbi-button-up");
if (upBtns && upBtns.length > 0) {
@ -131,7 +115,6 @@ local dsp = require "luci.dispatcher"
};
});
}
var downBtns = el.querySelectorAll(".cbi-button.cbi-button-down");
if (downBtns && downBtns.length > 0) {
downBtns.forEach(function (_el) {
@ -142,7 +125,6 @@ local dsp = require "luci.dispatcher"
}
}
}
// enable
enableDragForTable(
"#cbi-shadowsocksr-servers table",

View File

@ -80,7 +80,6 @@
}
return false;
}
function import_ssr_url(btn, urlname, sid) {
var s = document.getElementById(urlname + '-status');
if (!s)
@ -98,7 +97,6 @@
s.innerHTML = "<font color='red'>无效格式</font>";
return false;
}
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
if (ssu[0] == "ssr") {
@ -137,7 +135,6 @@
s.innerHTML = "<font color='green'>导入ShadowsocksR配置信息成功</font>";
return false;
} else if (ssu[0] == "ss") {
var url0, param = "";
var sipIndex = ssu[1].indexOf("@");
var ploc = ssu[1].indexOf("#");
@ -147,7 +144,6 @@
} else {
url0 = ssu[1];
}
if (sipIndex != -1) {
// SIP002
var userInfo = b64decsafe(url0.substr(0, sipIndex));
@ -163,7 +159,6 @@
plugin = pluginNameInfo.substr(pluginNameInfo.indexOf("=") + 1)
pluginOpts = pluginInfo.substr(pluginIndex + 1);
}
var userInfoSplitIndex = userInfo.indexOf(":");
if (userInfoSplitIndex != -1) {
method = userInfo.substr(0, userInfoSplitIndex);
@ -177,7 +172,6 @@
document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method_ss')[0].value = method || "";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.plugin')[0].value = plugin || "";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.plugin_opts')[0].value = pluginOpts || "";
if (param != undefined) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = decodeURI(param);
}
@ -212,7 +206,6 @@
url0 = ssu[1]
}
var sstr = url0;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "trojan";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
var team = sstr.split('@');
@ -229,7 +222,6 @@
queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || '');
}
}
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = serverPart[0];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = port;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = password;
@ -246,7 +238,7 @@
} else if (ssu[0] == "vmess") {
var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?");
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "v2ray";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "vmess";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {

View File

@ -690,3 +690,57 @@ msgstr "混淆密码(可选)"
msgid "Select the interface that needs to transmit data. If unchecked, all interfaces will pass data by default!"
msgstr "选择需要传递数据的接口。如果未选择,则默认情况下所有接口都将传递数据!"
msgid "Please fill in the Host, for example: www.baidu.com"
msgstr "请填写Host例如www.baidu.com"
msgid "Camouflage Type"
msgstr "伪装类型"
msgid "VideoCall (SRTP)"
msgstr "视频通话 (SRTP)"
msgid "BitTorrent (uTP)"
msgstr "BT下载 (uTP)"
msgid "WechatVideo"
msgstr "微信视频通话"
msgid "DTLS 1.2"
msgstr "DTLS 1.2 数据包"
msgid "WireGuard"
msgstr "WireGuard 数据包"
msgid "MTU"
msgstr "最大传输单元"
msgid "TTI"
msgstr "传输时间间隔"
msgid "Uplink Capacity"
msgstr "上行链路容量"
msgid "Downlink Capacity"
msgstr "下行链路容量"
msgid "Read Buffer Size"
msgstr "读取缓冲区大小"
msgid "Write Buffer Size"
msgstr "写入缓冲区大小"
msgid "Congestion"
msgstr "拥塞控制"
msgid "Network interface to use"
msgstr "使用的网络接口"
msgid "Please fill in reset"
msgstr "请填写 reset"
msgid "The content entered is incorrect!"
msgstr "输入的内容不正确!"
msgid "Reset complete"
msgstr "重置完成"

View File

@ -1,42 +0,0 @@
config global
option global_server 'nil'
option netflix_server 'nil'
option netflix_proxy '0'
option threads '0'
option run_mode 'router'
option dports '2'
option pdnsd_enable '1'
option tunnel_forward '8.8.4.4:53'
option monitor_enable '1'
option enable_switch '1'
option switch_time '667'
option switch_timeout '5'
option switch_try_count '3'
option gfwlist_url 'https://cdn.jsdelivr.net/gh/v2fly/domain-list-community@release/gfwlist.txt'
option chnroute_url 'https://ispip.clang.cn/all_cn.txt'
option nfip_url 'https://cdn.jsdelivr.net/gh/QiuSimons/Netflix_IP/getflix.txt'
option adblock_url 'https://anti-ad.net/anti-ad-for-dnsmasq.conf'
config access_control
option lan_ac_mode '0'
option router_proxy '1'
list wan_fw_ips '149.154.160.0/20'
list wan_fw_ips '67.198.55.0/24'
list wan_fw_ips '91.108.4.0/22'
list wan_fw_ips '91.108.56.0/22'
list wan_fw_ips '109.239.140.0/24'
list Interface 'lan'
config server_subscribe
option proxy '0'
option auto_update_time '2'
option auto_update '1'
option filter_words '过期时间/剩余流量/QQ群/官网/防失联地址/回国'
config socks5_proxy
option socks '0'
option local_port '1080'
config server_global
option enable_server '0'

File diff suppressed because it is too large Load Diff

View File

@ -4104,6 +4104,13 @@
103.158.224.0/23
103.159.80.0/23
103.159.122.0/23
103.159.124.0/23
103.159.134.0/23
103.159.142.0/23
103.160.32.0/23
103.160.34.0/23
103.160.112.0/23
103.160.114.0/23
103.192.0.0/22
103.192.4.0/22
103.192.8.0/22
@ -4335,7 +4342,6 @@
103.203.24.0/22
103.203.28.0/22
103.203.32.0/22
103.203.52.0/22
103.203.56.0/22
103.203.96.0/22
103.203.100.0/22

View File

@ -484,6 +484,8 @@ server=/airmax360.com/127.0.0.1#5335
ipset=/airmax360.com/gfwlist
server=/airmay.com/127.0.0.1#5335
ipset=/airmay.com/gfwlist
server=/airport-gov-cn.com/127.0.0.1#5335
ipset=/airport-gov-cn.com/gfwlist
server=/airport.brussels/127.0.0.1#5335
ipset=/airport.brussels/gfwlist
server=/airport.com/127.0.0.1#5335
@ -2032,6 +2034,8 @@ server=/bandwagonhost.com/127.0.0.1#5335
ipset=/bandwagonhost.com/gfwlist
server=/bangbros.com/127.0.0.1#5335
ipset=/bangbros.com/gfwlist
server=/banned.video/127.0.0.1#5335
ipset=/banned.video/gfwlist
server=/barefootnetworks.com/127.0.0.1#5335
ipset=/barefootnetworks.com/gfwlist
server=/barrons.com/127.0.0.1#5335
@ -2074,6 +2078,8 @@ server=/baxsound.com/127.0.0.1#5335
ipset=/baxsound.com/gfwlist
server=/bayareabmw.com/127.0.0.1#5335
ipset=/bayareabmw.com/gfwlist
server=/bayvoice.net/127.0.0.1#5335
ipset=/bayvoice.net/gfwlist
server=/bazel.build/127.0.0.1#5335
ipset=/bazel.build/gfwlist
server=/bbc.co.uk/127.0.0.1#5335
@ -4696,8 +4702,6 @@ server=/chimeforchange.org/127.0.0.1#5335
ipset=/chimeforchange.org/gfwlist
server=/china-facebook.com/127.0.0.1#5335
ipset=/china-facebook.com/gfwlist
server=/china-internet-exchange.com/127.0.0.1#5335
ipset=/china-internet-exchange.com/gfwlist
server=/chinaclothesstore.com/127.0.0.1#5335
ipset=/chinaclothesstore.com/gfwlist
server=/chinadecoding.com/127.0.0.1#5335
@ -4912,12 +4916,16 @@ server=/cmhalq.com/127.0.0.1#5335
ipset=/cmhalq.com/gfwlist
server=/cmpaas.com/127.0.0.1#5335
ipset=/cmpaas.com/gfwlist
server=/cmu.edu/127.0.0.1#5335
ipset=/cmu.edu/gfwlist
server=/cnbc.com/127.0.0.1#5335
ipset=/cnbc.com/gfwlist
server=/cnbcfm.com/127.0.0.1#5335
ipset=/cnbcfm.com/gfwlist
server=/cncrivals.com/127.0.0.1#5335
ipset=/cncrivals.com/gfwlist
server=/cnix-gov-cn.com/127.0.0.1#5335
ipset=/cnix-gov-cn.com/gfwlist
server=/cnn.com/127.0.0.1#5335
ipset=/cnn.com/gfwlist
server=/cnn.io/127.0.0.1#5335
@ -5208,8 +5216,6 @@ server=/cutt.ly/127.0.0.1#5335
ipset=/cutt.ly/gfwlist
server=/cvnad.com/127.0.0.1#5335
ipset=/cvnad.com/gfwlist
server=/cxkcloud.com/127.0.0.1#5335
ipset=/cxkcloud.com/gfwlist
server=/cyber-bay.info/127.0.0.1#5335
ipset=/cyber-bay.info/gfwlist
server=/cyber-bay.org/127.0.0.1#5335
@ -5510,6 +5516,8 @@ server=/digital-rb.com/127.0.0.1#5335
ipset=/digital-rb.com/gfwlist
server=/digitalassetlinks.org/127.0.0.1#5335
ipset=/digitalassetlinks.org/gfwlist
server=/digitalcertvalidation.com/127.0.0.1#5335
ipset=/digitalcertvalidation.com/gfwlist
server=/digitalhub.com/127.0.0.1#5335
ipset=/digitalhub.com/gfwlist
server=/digitalid.ch/127.0.0.1#5335
@ -5822,6 +5830,8 @@ server=/dleris.best/127.0.0.1#5335
ipset=/dleris.best/gfwlist
server=/dlfacebook.com/127.0.0.1#5335
ipset=/dlfacebook.com/gfwlist
server=/dlgarenanow-a.akamaihd.net/127.0.0.1#5335
ipset=/dlgarenanow-a.akamaihd.net/gfwlist
server=/dlmobilegarena-a.akamaihd.net/127.0.0.1#5335
ipset=/dlmobilegarena-a.akamaihd.net/gfwlist
server=/dmgmediaprivacy.co.uk/127.0.0.1#5335
@ -6672,6 +6682,8 @@ server=/edgefonts.net/127.0.0.1#5335
ipset=/edgefonts.net/gfwlist
server=/edisebay.com/127.0.0.1#5335
ipset=/edisebay.com/gfwlist
server=/edninfo.com/127.0.0.1#5335
ipset=/edninfo.com/gfwlist
server=/edu-research.org/127.0.0.1#5335
ipset=/edu-research.org/gfwlist
server=/edx-cdn.org/127.0.0.1#5335
@ -6818,12 +6830,28 @@ server=/epinions.com/127.0.0.1#5335
ipset=/epinions.com/gfwlist
server=/episodic.com/127.0.0.1#5335
ipset=/episodic.com/gfwlist
server=/epoch.cloud/127.0.0.1#5335
ipset=/epoch.cloud/gfwlist
server=/epoch.org.il/127.0.0.1#5335
ipset=/epoch.org.il/gfwlist
server=/epochbuy.com/127.0.0.1#5335
ipset=/epochbuy.com/gfwlist
server=/epochcar.com/127.0.0.1#5335
ipset=/epochcar.com/gfwlist
server=/epochhk.com/127.0.0.1#5335
ipset=/epochhk.com/gfwlist
server=/epochmall.com/127.0.0.1#5335
ipset=/epochmall.com/gfwlist
server=/epochmediagroup.com/127.0.0.1#5335
ipset=/epochmediagroup.com/gfwlist
server=/epochshop.com/127.0.0.1#5335
ipset=/epochshop.com/gfwlist
server=/epochstories.com/127.0.0.1#5335
ipset=/epochstories.com/gfwlist
server=/epochtime.com/127.0.0.1#5335
ipset=/epochtime.com/gfwlist
server=/epochtimes-bg.com/127.0.0.1#5335
ipset=/epochtimes-bg.com/gfwlist
server=/epochtimes-romania.com/127.0.0.1#5335
ipset=/epochtimes-romania.com/gfwlist
server=/epochtimes.co.il/127.0.0.1#5335
@ -6854,6 +6882,8 @@ server=/epochtimes.ru/127.0.0.1#5335
ipset=/epochtimes.ru/gfwlist
server=/epochtimes.se/127.0.0.1#5335
ipset=/epochtimes.se/gfwlist
server=/epochtimeshk.org/127.0.0.1#5335
ipset=/epochtimeshk.org/gfwlist
server=/epochtimestr.com/127.0.0.1#5335
ipset=/epochtimestr.com/gfwlist
server=/epochweek.com/127.0.0.1#5335
@ -6892,6 +6922,8 @@ server=/ethereum.foundation/127.0.0.1#5335
ipset=/ethereum.foundation/gfwlist
server=/ethereum.org/127.0.0.1#5335
ipset=/ethereum.org/gfwlist
server=/etviet.com/127.0.0.1#5335
ipset=/etviet.com/gfwlist
server=/etvonline.hk/127.0.0.1#5335
ipset=/etvonline.hk/gfwlist
server=/eu-consumer-empowerment.com/127.0.0.1#5335
@ -8692,6 +8724,8 @@ server=/goldnikeclub.com/127.0.0.1#5335
ipset=/goldnikeclub.com/gfwlist
server=/golos-ameriki.ru/127.0.0.1#5335
ipset=/golos-ameriki.ru/gfwlist
server=/golosameriki.com/127.0.0.1#5335
ipset=/golosameriki.com/gfwlist
server=/gonglchuangl.net/127.0.0.1#5335
ipset=/gonglchuangl.net/gfwlist
server=/gonike.com/127.0.0.1#5335
@ -9212,6 +9246,8 @@ server=/handbagsoutletebay.com/127.0.0.1#5335
ipset=/handbagsoutletebay.com/gfwlist
server=/hanime.tv/127.0.0.1#5335
ipset=/hanime.tv/gfwlist
server=/hanime1.me/127.0.0.1#5335
ipset=/hanime1.me/gfwlist
server=/happymeal.co.nz/127.0.0.1#5335
ipset=/happymeal.co.nz/gfwlist
server=/happymeal.com.au/127.0.0.1#5335
@ -10156,6 +10192,10 @@ server=/industrialtoys.com/127.0.0.1#5335
ipset=/industrialtoys.com/gfwlist
server=/informs.org/127.0.0.1#5335
ipset=/informs.org/gfwlist
server=/infowars.com/127.0.0.1#5335
ipset=/infowars.com/gfwlist
server=/infowarsmedia.com/127.0.0.1#5335
ipset=/infowarsmedia.com/gfwlist
server=/infrapedia.com/127.0.0.1#5335
ipset=/infrapedia.com/gfwlist
server=/ingads.com/127.0.0.1#5335
@ -11034,6 +11074,8 @@ server=/jfrog.org/127.0.0.1#5335
ipset=/jfrog.org/gfwlist
server=/jgg18.xyz/127.0.0.1#5335
ipset=/jgg18.xyz/gfwlist
server=/jiayoulu.com/127.0.0.1#5335
ipset=/jiayoulu.com/gfwlist
server=/jibemobile.com/127.0.0.1#5335
ipset=/jibemobile.com/gfwlist
server=/jijiji.ca/127.0.0.1#5335
@ -11126,6 +11168,8 @@ server=/keytransparency.foo/127.0.0.1#5335
ipset=/keytransparency.foo/gfwlist
server=/keytransparency.org/127.0.0.1#5335
ipset=/keytransparency.org/gfwlist
server=/kfs.io/127.0.0.1#5335
ipset=/kfs.io/gfwlist
server=/khanacademy.org/127.0.0.1#5335
ipset=/khanacademy.org/gfwlist
server=/kickshatchannel.com/127.0.0.1#5335
@ -11210,6 +11254,12 @@ server=/kirbysuperstarultra.com/127.0.0.1#5335
ipset=/kirbysuperstarultra.com/gfwlist
server=/kissjav.com/127.0.0.1#5335
ipset=/kissjav.com/gfwlist
server=/kkbox.com/127.0.0.1#5335
ipset=/kkbox.com/gfwlist
server=/kktix.com/127.0.0.1#5335
ipset=/kktix.com/gfwlist
server=/kktv.me/127.0.0.1#5335
ipset=/kktv.me/gfwlist
server=/klik.me/127.0.0.1#5335
ipset=/klik.me/gfwlist
server=/knovel.com/127.0.0.1#5335
@ -13218,12 +13268,12 @@ server=/mzed.com/127.0.0.1#5335
ipset=/mzed.com/gfwlist
server=/mzstatic.com/127.0.0.1#5335
ipset=/mzstatic.com/gfwlist
server=/n3ro.fun/127.0.0.1#5335
ipset=/n3ro.fun/gfwlist
server=/n3ro.live/127.0.0.1#5335
ipset=/n3ro.live/gfwlist
server=/n3ro.lol/127.0.0.1#5335
ipset=/n3ro.lol/gfwlist
server=/n3ro.net/127.0.0.1#5335
ipset=/n3ro.net/gfwlist
server=/n3ro.wtf/127.0.0.1#5335
ipset=/n3ro.wtf/gfwlist
server=/na-att-idns.net/127.0.0.1#5335
ipset=/na-att-idns.net/gfwlist
server=/nab.com.au/127.0.0.1#5335
@ -13878,6 +13928,10 @@ server=/ntc.party/127.0.0.1#5335
ipset=/ntc.party/gfwlist
server=/ntd.com/127.0.0.1#5335
ipset=/ntd.com/gfwlist
server=/ntdca.com/127.0.0.1#5335
ipset=/ntdca.com/gfwlist
server=/ntdimg.com/127.0.0.1#5335
ipset=/ntdimg.com/gfwlist
server=/ntdtv.ca/127.0.0.1#5335
ipset=/ntdtv.ca/gfwlist
server=/ntdtv.co.kr/127.0.0.1#5335
@ -14346,6 +14400,8 @@ server=/oxfordscholarship.com/127.0.0.1#5335
ipset=/oxfordscholarship.com/gfwlist
server=/oxfordwesternmusic.com/127.0.0.1#5335
ipset=/oxfordwesternmusic.com/gfwlist
server=/ozvoice.org/127.0.0.1#5335
ipset=/ozvoice.org/gfwlist
server=/p-events-delivery.akamaized.net/127.0.0.1#5335
ipset=/p-events-delivery.akamaized.net/gfwlist
server=/p16-tiktokcdn-com.akamaized.net/127.0.0.1#5335
@ -14780,6 +14836,8 @@ server=/perl.org/127.0.0.1#5335
ipset=/perl.org/gfwlist
server=/persagg.com/127.0.0.1#5335
ipset=/persagg.com/gfwlist
server=/persianepochtimes.com/127.0.0.1#5335
ipset=/persianepochtimes.com/gfwlist
server=/personaltrainermath.com/127.0.0.1#5335
ipset=/personaltrainermath.com/gfwlist
server=/personeelsland.com/127.0.0.1#5335
@ -15212,6 +15270,8 @@ server=/protonmail.com/127.0.0.1#5335
ipset=/protonmail.com/gfwlist
server=/protonstatus.com/127.0.0.1#5335
ipset=/protonstatus.com/gfwlist
server=/proxyrarbg.org/127.0.0.1#5335
ipset=/proxyrarbg.org/gfwlist
server=/pscdn.co/127.0.0.1#5335
ipset=/pscdn.co/gfwlist
server=/pscp.tv/127.0.0.1#5335
@ -16014,6 +16074,8 @@ server=/securepaypal.info/127.0.0.1#5335
ipset=/securepaypal.info/gfwlist
server=/sensorynetworks.com/127.0.0.1#5335
ipset=/sensorynetworks.com/gfwlist
server=/seqingx.com/127.0.0.1#5335
ipset=/seqingx.com/gfwlist
server=/sequence.com/127.0.0.1#5335
ipset=/sequence.com/gfwlist
server=/serialssolutions.com/127.0.0.1#5335
@ -16032,6 +16094,8 @@ server=/servicetalk.io/127.0.0.1#5335
ipset=/servicetalk.io/gfwlist
server=/seselah.com/127.0.0.1#5335
ipset=/seselah.com/gfwlist
server=/setapp.com/127.0.0.1#5335
ipset=/setapp.com/gfwlist
server=/sextop1.net/127.0.0.1#5335
ipset=/sextop1.net/gfwlist
server=/sexzy4.com/127.0.0.1#5335
@ -16332,6 +16396,10 @@ server=/softether-download.com/127.0.0.1#5335
ipset=/softether-download.com/gfwlist
server=/softether.org/127.0.0.1#5335
ipset=/softether.org/gfwlist
server=/sohcradio.com/127.0.0.1#5335
ipset=/sohcradio.com/gfwlist
server=/sohfrance.org/127.0.0.1#5335
ipset=/sohfrance.org/gfwlist
server=/soirt4.fun/127.0.0.1#5335
ipset=/soirt4.fun/gfwlist
server=/solarcity.com/127.0.0.1#5335
@ -16608,10 +16676,6 @@ server=/sslpaypal.org/127.0.0.1#5335
ipset=/sslpaypal.org/gfwlist
server=/ssplive.pw/127.0.0.1#5335
ipset=/ssplive.pw/gfwlist
server=/ssrcloud.com/127.0.0.1#5335
ipset=/ssrcloud.com/gfwlist
server=/ssrcloud.org/127.0.0.1#5335
ipset=/ssrcloud.org/gfwlist
server=/ssrpass.pw/127.0.0.1#5335
ipset=/ssrpass.pw/gfwlist
server=/sstatic.net/127.0.0.1#5335
@ -18814,6 +18878,8 @@ server=/walmart.pharmacy/127.0.0.1#5335
ipset=/walmart.pharmacy/gfwlist
server=/walmartimages.com/127.0.0.1#5335
ipset=/walmartimages.com/gfwlist
server=/wanokokorosoh.com/127.0.0.1#5335
ipset=/wanokokorosoh.com/gfwlist
server=/wariolandshakeit.com/127.0.0.1#5335
ipset=/wariolandshakeit.com/gfwlist
server=/wariowarediy.com/127.0.0.1#5335
@ -19370,6 +19436,8 @@ server=/xn--czrs0t4phtr3a.cn/127.0.0.1#5335
ipset=/xn--czrs0t4phtr3a.cn/gfwlist
server=/xn--d1acpjx3f.xn--p1ai/127.0.0.1#5335
ipset=/xn--d1acpjx3f.xn--p1ai/gfwlist
server=/xn--d4ty0ojsqzfd.com/127.0.0.1#5335
ipset=/xn--d4ty0ojsqzfd.com/gfwlist
server=/xn--fiqs8sxootzz.cn/127.0.0.1#5335
ipset=/xn--fiqs8sxootzz.cn/gfwlist
server=/xn--fiqs8sxootzz.xn--hxt814e/127.0.0.1#5335
@ -19450,6 +19518,8 @@ server=/xposed.info/127.0.0.1#5335
ipset=/xposed.info/gfwlist
server=/xscale.com/127.0.0.1#5335
ipset=/xscale.com/gfwlist
server=/xtube.com/127.0.0.1#5335
ipset=/xtube.com/gfwlist
server=/xvideos-cdn.com/127.0.0.1#5335
ipset=/xvideos-cdn.com/gfwlist
server=/xvideos.com/127.0.0.1#5335
@ -19756,6 +19826,8 @@ server=/youav.com/127.0.0.1#5335
ipset=/youav.com/gfwlist
server=/youjizz.com/127.0.0.1#5335
ipset=/youjizz.com/gfwlist
server=/youlucky.com/127.0.0.1#5335
ipset=/youlucky.com/gfwlist
server=/youporn.com/127.0.0.1#5335
ipset=/youporn.com/gfwlist
server=/yourfantasybeginsnow.com/127.0.0.1#5335

View File

@ -11,19 +11,19 @@ set firewall.shadowsocksr.path=/var/etc/shadowsocksr.include
set firewall.shadowsocksr.reload=1
commit firewall
EOF
rm -rf /etc/config/shadowsocksr-opkg /etc/ssr/*opkg
touch /etc/ssr/china_ssr.txt
touch /etc/ssr/deny.list
touch /etc/ssr/white.list
touch /etc/ssr/black.list
touch /etc/ssr/netflix.list
touch /etc/ssr/netflixip.list
touch /etc/ssr/gfw_base.conf
touch /etc/ssr/gfw_list.conf
touch /etc/ssr/oversea_list.conf
touch /etc/ssr/ad.conf
rm -rf /etc/config/shadowsocksr-opkg /etc/ssrplus/*opkg
touch /etc/ssrplus/china_ssr.txt
touch /etc/ssrplus/deny.list
touch /etc/ssrplus/white.list
touch /etc/ssrplus/black.list
touch /etc/ssrplus/netflix.list
touch /etc/ssrplus/netflixip.list
touch /etc/ssrplus/gfw_base.conf
touch /etc/ssrplus/gfw_list.conf
touch /etc/ssrplus/oversea_list.conf
touch /etc/ssrplus/ad.conf
touch /etc/config/shadowsocksr
if [ ! -s "/etc/config/shadowsocksr" ] ; then
if [ ! -s "/etc/config/shadowsocksr" ]; then
uci -q batch <<-EOF >/dev/null
add shadowsocksr global
set shadowsocksr.@global[0].global_server='nil'
@ -42,7 +42,7 @@ set shadowsocksr.@global[0].switch_try_count='3'
set shadowsocksr.@global[0].gfwlist_url='https://cdn.jsdelivr.net/gh/v2fly/domain-list-community@release/gfwlist.txt'
set shadowsocksr.@global[0].chnroute_url='https://ispip.clang.cn/all_cn.txt'
set shadowsocksr.@global[0].nfip_url='https://cdn.jsdelivr.net/gh/QiuSimons/Netflix_IP/getflix.txt'
set shadowsocksr.@global[0].adblock_url='https://anti-ad.net/anti-ad-for-dnsmasq.conf'
set shadowsocksr.@global[0].adblock_url='https://neodev.team/lite_host_dnsmasq.conf'
add shadowsocksr server_subscribe
set shadowsocksr.@server_subscribe[0].proxy='0'
set shadowsocksr.@server_subscribe[0].auto_update_time='2'

View File

@ -1,10 +0,0 @@
#!/bin/sh -e
if [ -f /tmp/ssr-update.$1 ]; then
if (grep -wq "address=" /tmp/ssr-update.$1); then
return $?
else
cp /tmp/ssr-update.$1 /tmp/adnew.conf
cat /tmp/adnew.conf | grep ^\|\|[^\*]*\^$ | sed -e 's:||:address\=\/:' -e 's:\^:/0\.0\.0\.0:' >/tmp/ssr-update.$1
rm -f /tmp/adnew.conf
fi
fi

View File

@ -1,23 +0,0 @@
#!/bin/sh -e
generate_china_banned() {
cat $1 | base64 -d >/tmp/gfwlist.txt
rm -f $1
sed -i '/^@@|/d' /tmp/gfwlist.txt
cat /tmp/gfwlist.txt | sort -u |
sed 's#!.\+##; s#|##g; s#@##g; s#http:\/\/##; s#https:\/\/##;' |
sed '/\*/d; /apple\.com/d; /sina\.cn/d; /sina\.com\.cn/d; /baidu\.com/d; /byr\.cn/d; /jlike\.com/d; /weibo\.com/d; /zhongsou\.com/d; /youdao\.com/d; /sogou\.com/d; /so\.com/d; /soso\.com/d; /aliyun\.com/d; /taobao\.com/d; /jd\.com/d; /qq\.com/d' |
sed '/^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/d' |
grep '^[0-9a-zA-Z\.-]\+$' | grep '\.' | sed 's#^\.\+##' | sort -u |
awk 'BEGIN { prev = "________"; } {
cur = $0;
if (index(cur, prev) == 1 && substr(cur, 1 + length(prev) ,1) == ".") {
} else {
print cur;
prev = cur;
}
}' | sort -u
}
generate_china_banned /tmp/ssr-update.$1 >/tmp/gfw.txt
rm -f /tmp/gfwlist.txt
sed '/.*/s/.*/server=\/&\/127.0.0.1#5335\nipset=\/&\/gfwlist/' /tmp/gfw.txt >/tmp/ssr-update.$1
rm -f /tmp/gfw.txt

View File

@ -6,66 +6,36 @@
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
. $IPKG_INSTROOT/etc/init.d/shadowsocksr
LOCK_FILE="/var/lock/ssr-monitor.lock"
[ -f "$LOCK_FILE" ] && exit 2
touch "$LOCK_FILE"
NAME=shadowsocksr
uci_get_by_name() {
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}
}
get_host_ip() {
local host=$1
local isip=""
local ip=$host
isip=$(echo $host | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}")
if [ -z "$isip" ]; then
if [ "$host" != "${host#*:[0-9a-fA-F]}" ]; then
ip=$host
else
local ip=$(resolveip -4 -t 3 $host | awk 'NR==1{print}')
# local hostip=$(ping $host -W 1 -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1)
[ -z "$ip" ] && ip=$(wget -q -O- http://119.29.29.29/d?dn=$1 | awk -F ';' '{print $1}')
fi
fi
echo ${ip:="ERROR"}
}
server_process_count=$1
redir_tcp_process=$2
redir_udp_process=$3
tunnel_process=$4
kcp_process=$5
local_process=$6
pdnsd_process=$7
kcp_process=$4
local_process=$5
pdnsd_process=$6
if [ -z "$pdnsd_process" ]; then
pdnsd_process=0
fi
i=0
GLOBAL_SERVER=$(uci_get_by_type global global_server)
server=$(get_host_ip $(uci_get_by_name $GLOBAL_SERVER server))
[ "$server" == "ERROR" ] && hostip=$(uci_get_by_name $GLOBAL_SERVER ip)
lkcp_port=$(uci_get_by_name $GLOBAL_SERVER kcp_port)
server=$(uci_get_by_name $GLOBAL_SERVER server)
kcp_port=$(uci_get_by_name $GLOBAL_SERVER kcp_port)
server_port=$(uci_get_by_name $GLOBAL_SERVER server_port)
password=$(uci_get_by_name $GLOBAL_SERVER kcp_password)
kcp_param=$(uci_get_by_name $GLOBAL_SERVER kcp_param)
[ "$password" != "" ] && password="--key "${password}
while [ "1" == "1" ]; do #死循环
sleep 30s
sleep 000030s
#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!"
echo "$(date "+%Y-%m-%d %H:%M:%S") ssr redir tcp error.restart!" >>/tmp/ssrplus.log
echolog "ssr redir tcp error.restart!"
/etc/init.d/shadowsocksr restart
exit 0
fi
@ -75,17 +45,7 @@ while [ "1" == "1" ]; do #死循环
icount=$(busybox ps -w | grep ssr-reudp | grep -v grep | wc -l)
if [ "$icount" == 0 ]; then
logger -t "$NAME" "ssr redir udp error.restart!"
echo "$(date "+%Y-%m-%d %H:%M:%S") ssr redir udp error.restart!" >>/tmp/ssrplus.log
/etc/init.d/shadowsocksr 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!"
echo "$(date "+%Y-%m-%d %H:%M:%S") ssr tunnel error.restart!" >>/tmp/ssrplus.log
echolog "ssr redir udp error.restart!"
/etc/init.d/shadowsocksr restart
exit 0
fi
@ -95,7 +55,7 @@ while [ "1" == "1" ]; do #死循环
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!"
echo "$(date "+%Y-%m-%d %H:%M:%S") ssr server error.restart!" >>/tmp/ssrplus.log
echolog "ssr server error.restart!"
kill -9 $(busybox ps -w | grep ssr-server | grep -v grep | awk '{print $1}') >/dev/null 2>&1
/etc/init.d/shadowsocksr restart
exit 0
@ -106,7 +66,7 @@ while [ "1" == "1" ]; do #死循环
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!"
echo "$(date "+%Y-%m-%d %H:%M:%S") ssr kcptun error.restart!" >>/tmp/ssrplus.log
echolog "ssr kcptun error.restart!"
killall -q -9 kcptun-client
(/usr/bin/kcptun-client -r $server:$kcp_port -l :$server_port $password $kcp_param &)
fi
@ -116,7 +76,7 @@ while [ "1" == "1" ]; do #死循环
icount=$(busybox ps -w | grep ssr-local | grep -v grep | wc -l)
if [ "$icount" -lt "$local_process" ]; then #如果进程挂掉就重启它
logger -t "$NAME" "global socks server error.restart!"
echo "$(date "+%Y-%m-%d %H:%M:%S") global socks server error.restart!" >>/tmp/ssrplus.log
echolog "global socks server error.restart!"
kill -9 $(busybox ps -w | grep ssr-local | grep -v grep | awk '{print $1}') >/dev/null 2>&1
/etc/init.d/shadowsocksr restart
exit 0
@ -124,31 +84,31 @@ while [ "1" == "1" ]; do #死循环
fi
#pdnsd
if [ "$pdnsd_process" -eq 1 ]; then
icount=$(busybox ps -w | grep pdnsd | grep -v grep | wc -l)
icount=$(busybox ps -w | grep $TMP_BIN_PATH/pdnsd | grep -v grep | wc -l)
if [ "$icount" -lt "$pdnsd_process" ]; then #如果进程挂掉就重启它
logger -t "$NAME" "pdnsd tunnel error.restart!"
echo "$(date "+%Y-%m-%d %H:%M:%S") pdnsd tunnel error.restart!" >>/tmp/ssrplus.log
echolog "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
kill -9 $(ps | grep $TMP_PATH/pdnsd.conf | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
(/usr/sbin/pdnsd -c /var/etc/pdnsd.conf >/dev/null 2>&1 &)
ln_start_bin $(first_type pdnsd) pdnsd -c $TMP_PATH/pdnsd.conf
fi
fi
#dns2socks
if [ "$pdnsd_process" -eq 2 ]; then
icount=$(busybox ps -w | grep -e ssr-dns -e dns2socks | grep -v grep | wc -l)
icount=$(busybox ps -w | grep -e ssrplus-dns -e "dns2socks 127.0.0.1 $tmp_dns_port" | grep -v grep | wc -l)
if [ "$icount" -lt 2 ]; then #如果进程挂掉就重启它
logger -t "$NAME" "dns2socks $dnsstr tunnel error.restart!"
echo "$(date "+%Y-%m-%d %H:%M:%S") dns2socks $dnsstr tunnel error.restart!" >>/tmp/ssrplus.log
echolog "dns2socks $dnsstr tunnel error.restart!"
dnsstr=$(uci_get_by_type global tunnel_forward 8.8.4.4:53)
dnsserver=$(echo "$dnsstr" | awk -F ':' '{print $1}')
dnsport=$(echo "$dnsstr" | awk -F ':' '{print $2}')
killall -q -9 dns2socks
kill -9 $(busybox ps -w | grep ssr-dns | grep -v grep | awk '{print $1}') >/dev/null 2>&1
microsocks -i 127.0.0.1 -p 10802 ssr-dns >/dev/null 2>&1 &
dns2socks 127.0.0.1:10802 $dnsserver:$dnsport 127.0.0.1:5335 -q >/dev/null 2>&1 &
kill -9 $(busybox ps -w | grep ssrplus-dns | grep -v grep | awk '{print $1}') >/dev/null 2>&1
kill -9 $(busybox ps -w | grep "dns2socks 127.0.0.1 $tmp_dns_port" | grep -v grep | awk '{print $1}') >/dev/null 2>&1
ln_start_bin $(first_type microsocks) microsocks -i 127.0.0.1 -p $tmp_dns_port ssrplus-dns
ln_start_bin $(first_type dns2socks) dns2socks 127.0.0.1:$tmp_dns_port $dnsserver:$dnsport 127.0.0.1:5335 -q
fi
fi
done

View File

@ -10,43 +10,43 @@ TAG="_SS_SPEC_RULE_" # comment tag
IPT="iptables -t nat" # alias of iptables
FWI=$(uci get firewall.shadowsocksr.path 2>/dev/null) # firewall include file
usage() {
cat <<-EOF
Usage: ssr-rules [options]
cat <<-EOF
Usage: ssr-rules [options]
Valid options are:
Valid options are:
-s <server_ip> ip address of shadowsocksr remote server
-l <local_port> port number of shadowsocksr local server
-S <server_ip> ip address of shadowsocksr remote UDP server
-L <local_port> port number of shadowsocksr local UDP server
-i <ip_list_file> a file content is bypassed ip list
-a <lan_ips> lan ip of access control, need a prefix to
define access control mode
-b <wan_ips> wan ip of will be bypassed
-w <wan_ips> wan ip of will be forwarded
-B <bp_lan_ips> lan ip of will be bypassed proxy
-p <fp_lan_ips> lan ip of will be global proxy
-G <gm_lan_ips> lan ip of will be game mode proxy
-D <proxy_ports> proxy ports
-F netflix mode
-N netflix server IP
-M netflix proxy mode
-m <Interface> Interface name
-I <ip_list_file> a file content is bypassed netflix ip list
-e <extra_options> extra options for iptables
-o apply the rules to the OUTPUT chain
-O apply the global rules to the OUTPUT chain
-u enable udprelay mode, TPROXY is required
-U enable udprelay mode, using different IP
and ports for TCP and UDP
-f flush the rules
-g gfwlist mode
-r router mode
-c oversea mode
-z all mode
-h show this help message and exit
EOF
exit $1
-s <server_ip> ip address of shadowsocksr remote server
-l <local_port> port number of shadowsocksr local server
-S <server_ip> ip address of shadowsocksr remote UDP server
-L <local_port> port number of shadowsocksr local UDP server
-i <ip_list_file> a file content is bypassed ip list
-a <lan_ips> lan ip of access control, need a prefix to
define access control mode
-b <wan_ips> wan ip of will be bypassed
-w <wan_ips> wan ip of will be forwarded
-B <bp_lan_ips> lan ip of will be bypassed proxy
-p <fp_lan_ips> lan ip of will be global proxy
-G <gm_lan_ips> lan ip of will be game mode proxy
-D <proxy_ports> proxy ports
-F shunt mode
-N shunt server IP
-M shunt proxy mode
-m <Interface> Interface name
-I <ip_list_file> a file content is bypassed shunt ip list
-e <extra_options> extra options for iptables
-o apply the rules to the OUTPUT chain
-O apply the global rules to the OUTPUT chain
-u enable udprelay mode, TPROXY is required
-U enable udprelay mode, using different IP
and ports for TCP and UDP
-f flush the rules
-g gfwlist mode
-r router mode
-c oversea mode
-z all mode
-h show this help message and exit
EOF
exit $1
}
loger() {
@ -94,15 +94,15 @@ ipset_r() {
$(gen_spec_iplist | sed -e "s/^/add ss_spec_wan_ac /")
EOF
$IPT -A SS_SPEC_WAN_AC -m set --match-set ss_spec_wan_ac dst -j RETURN
$IPT -A SS_SPEC_WAN_AC -m set --match-set gmlan src -m set ! --match-set china dst -j SS_SPEC_WAN_FW
$IPT -A SS_SPEC_WAN_AC -m set --match-set china dst -j RETURN
$IPT -A SS_SPEC_WAN_AC -m set --match-set gmlan src -m set ! --match-set china dst -j SS_SPEC_WAN_FW
$IPT -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW
;;
gfw)
ipset -N gfwlist hash:net 2>/dev/null
$IPT -A SS_SPEC_WAN_AC -m set --match-set china dst -j RETURN
$IPT -A SS_SPEC_WAN_AC -m set --match-set gfwlist dst -j SS_SPEC_WAN_FW
$IPT -A SS_SPEC_WAN_AC -m set --match-set gmlan src -m set ! --match-set china dst -j SS_SPEC_WAN_FW
$IPT -A SS_SPEC_WAN_AC -m set --match-set china dst -j RETURN
;;
oversea)
ipset -N oversea hash:net 2>/dev/null
@ -129,23 +129,24 @@ ipset_r() {
fi
for ip in $WAN_BP_IP; do ipset -! add whitelist $ip; done
for ip in $WAN_FW_IP; do ipset -! add blacklist $ip; done
if [ "$NETFLIX" != "0" ]; then
if [ "$SHUNT_PORT" != "0" ]; then
ipset -N netflix hash:net 2>/dev/null
for ip in $(cat ${NETFLIX_LIST:=/dev/null} 2>/dev/null); do ipset -! add netflix $ip; done
for ip in $(cat ${SHUNT_LIST:=/dev/null} 2>/dev/null); do ipset -! add netflix $ip; done
case "$SHUNT_PORT" in
0) ;;
1)
$IPT -I SS_SPEC_WAN_AC -p tcp -m set --match-set netflix dst -j REDIRECT --to-ports $local_port
;;
*)
$IPT -I SS_SPEC_WAN_AC -p tcp -m set --match-set netflix dst -j REDIRECT --to-ports $SHUNT_PORT
if [ "$SHUNT_PROXY" == "1" ]; then
$IPT -I SS_SPEC_WAN_AC -p tcp -d $SHUNT_IP -j REDIRECT --to-ports $local_port
else
ipset -! add whitelist $SHUNT_IP
fi
;;
esac
fi
case "$NETFLIX" in
1)
$IPT -I SS_SPEC_WAN_AC -p tcp -m set --match-set netflix dst -j REDIRECT --to-ports 4321
if [ "$NETFLIX_PROXY" == "1" ]; then
$IPT -I SS_SPEC_WAN_AC -p tcp -d $NETFLIX_IP -j REDIRECT --to-ports $local_port
else
ipset -! add whitelist $NETFLIX_IP
fi
;;
2)
$IPT -I SS_SPEC_WAN_AC -p tcp -m set --match-set netflix dst -j REDIRECT --to-ports $local_port
;;
esac
return $?
}
@ -159,8 +160,7 @@ fw_rule() {
$IPT -A SS_SPEC_WAN_FW -d 192.168.0.0/16 -j RETURN
$IPT -A SS_SPEC_WAN_FW -d 224.0.0.0/4 -j RETURN
$IPT -A SS_SPEC_WAN_FW -d 240.0.0.0/4 -j RETURN
$IPT -A SS_SPEC_WAN_FW -p tcp $PROXY_PORTS \
-j REDIRECT --to-ports $local_port 2>/dev/null || {
$IPT -A SS_SPEC_WAN_FW -p tcp $PROXY_PORTS -j REDIRECT --to-ports $local_port 2>/dev/null || {
loger 3 "Can't redirect, please check the iptables."
exit 1
}
@ -189,24 +189,23 @@ ac_rule() {
if [ -z "$Interface" ]; then
$IPT -I PREROUTING 1 -p tcp $EXT_ARGS $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_WAN_AC
else
for name in $Interface;do
local IFNAME=$(uci -P /var/state get network.$name.ifname 2>/dev/null)
[ -n "$IFNAME" ] && $IPT -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p tcp $EXT_ARGS $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_WAN_AC
for name in $Interface; do
local IFNAME=$(uci -P /var/state get network.$name.ifname 2>/dev/null)
[ -n "$IFNAME" ] && $IPT -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p tcp $EXT_ARGS $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_WAN_AC
done
fi
case "$OUTPUT" in
1)
$IPT -I OUTPUT 1 -p tcp $EXT_ARGS \
-m comment --comment "$TAG" -j SS_SPEC_WAN_AC
$IPT -I OUTPUT 1 -p tcp $EXT_ARGS -m comment --comment "$TAG" -j SS_SPEC_WAN_AC
;;
2)
ipset -! -R <<-EOF || return 1
create ssr_gen_router hash:net
$(gen_spec_iplist | sed -e "s/^/add ssr_gen_router /")
EOF
$IPT -N SS_SPEC_ROUTER && \
$IPT -A SS_SPEC_ROUTER -m set --match-set ssr_gen_router dst -j RETURN && \
$IPT -N SS_SPEC_ROUTER
$IPT -A SS_SPEC_ROUTER -m set --match-set ssr_gen_router dst -j RETURN
$IPT -A SS_SPEC_ROUTER -j SS_SPEC_WAN_FW
$IPT -I OUTPUT 1 -p tcp -m comment --comment "$TAG" -j SS_SPEC_ROUTER
;;
@ -234,25 +233,23 @@ tp_rule() {
$ipt -A SS_SPEC_TPROXY -p udp ! --dport 53 -d $SERVER -j RETURN
[ "$server" != "$SERVER" ] && ipset -! add whitelist $SERVER
$ipt -A SS_SPEC_TPROXY -p udp -m set --match-set bplan src -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set fplan src \
-j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set fplan src -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
case "$RUNMODE" in
router)
$ipt -A SS_SPEC_TPROXY -p udp -m set --match-set gmlan src -m set ! --match-set china dst \
-j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set ! --match-set ss_spec_wan_ac dst \
-j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
$IPT -A SS_SPEC_TPROXY -p udp -m set --match-set ss_spec_wan_ac dst -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -m set --match-set china dst -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -m set --match-set gmlan src -m set ! --match-set china dst -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set ! --match-set ss_spec_wan_ac dst -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
;;
gfw)
$ipt -A SS_SPEC_TPROXY -p udp -m set --match-set china dst -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -m set --match-set gmlan src -m set ! --match-set china dst \
-j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
$ipt -A SS_SPEC_TPROXY -p udp -m set $PROXY_PORTS --match-set gfwlist dst \
-j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set gfwlist dst -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
$ipt -A SS_SPEC_TPROXY -p udp -m set --match-set gmlan src -m set ! --match-set china dst -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
;;
oversea)
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set china dst \
-j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set oversea src -m dst -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
$ipt -A SS_SPEC_TPROXY -p udp -m set --match-set gmlan src -m set -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set china dst -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
;;
all)
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
@ -261,9 +258,9 @@ tp_rule() {
if [ -z "$Interface" ]; then
$ipt -I PREROUTING 1 -p udp $EXT_ARGS $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_TPROXY
else
for name in $Interface;do
local IFNAME=$(uci -P /var/state get network.$name.ifname 2>/dev/null)
[ -n "$IFNAME" ] && $ipt -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p udp $EXT_ARGS $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_TPROXY
for name in $Interface; do
local IFNAME=$(uci -P /var/state get network.$name.ifname 2>/dev/null)
[ -n "$IFNAME" ] && $ipt -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p udp $EXT_ARGS $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_TPROXY
done
fi
return $?
@ -303,8 +300,7 @@ gen_include() {
[ -n "$FWI" ] || return 0
extract_rules() {
echo "*$1"
iptables-save -t $1 | grep SS_SPEC_ | \
sed -e "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/"
iptables-save -t $1 | grep SS_SPEC_ | sed -e "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/"
echo 'COMMIT'
}
cat <<-EOF >>$FWI
@ -362,16 +358,16 @@ while getopts ":m:s:l:S:L:i:e:a:B:b:w:p:G:D:F:N:M:I:oOuUfgrczh" arg; do
PROXY_PORTS=$OPTARG
;;
F)
NETFLIX=$OPTARG
SHUNT_PORT=$OPTARG
;;
N)
NETFLIX_IP=$OPTARG
SHUNT_IP=$OPTARG
;;
M)
NETFLIX_PROXY=$OPTARG
SHUNT_PROXY=$OPTARG
;;
I)
NETFLIX_LIST=$OPTARG
SHUNT_LIST=$OPTARG
;;
o)
OUTPUT=1
@ -409,16 +405,16 @@ if [ -z "$server" -o -z "$local_port" ]; then
usage 2
fi
case "$TPROXY" in
1)
SERVER=$server
LOCAL_PORT=$local_port
;;
2)
: ${SERVER:?"You must assign an ip for the udp relay server."}
: ${LOCAL_PORT:?"You must assign a port for the udp relay server."}
case "$TPROXY" in
1)
SERVER=$server
LOCAL_PORT=$local_port
;;
esac
2)
: ${SERVER:?"You must assign an ip for the udp relay server."}
: ${LOCAL_PORT:?"You must assign a port for the udp relay server."}
;;
esac
flush_r && fw_rule && ipset_r && ac_rule && tp_rule && gen_include
RET=$?

View File

@ -7,51 +7,23 @@
# See /LICENSE for more information.
#
. $IPKG_INSTROOT/etc/init.d/shadowsocksr
LOCK_FILE="/var/lock/ssr-switch.lock"
[ -f "$LOCK_FILE" ] && exit 2
touch "$LOCK_FILE"
LOG_FILE=/var/log/ssrplus.log
cycle_time=60
switch_time=3
normal_flag=0
server_locate=0
server_count=0
NAME=shadowsocksr
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}
}
uci_get_by_type() {
local ret=$(uci get $NAME.@$1[0].$2 2>/dev/null)
echo ${ret:=$3}
}
DEFAULT_SERVER=$(uci_get_by_type global global_server)
CURRENT_SERVER=$DEFAULT_SERVER
#解析ip
get_host_ip() {
local host=$1
local isip=""
local ip=$host
isip=$(echo $host | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}")
if [ -z "$isip" ]; then
if [ "$host" != "${host#*:[0-9a-fA-F]}" ]; then
ip=$host
else
local ip=$(resolveip -4 -t 3 $host | awk 'NR==1{print}')
[ -z "$ip" ] && ip=$(wget -q -O- http://119.29.29.29/d?dn=$1 | awk -F ';' '{print $1}')
fi
fi
echo ${ip:="ERROR"}
}
#判断代理是否正常
check_proxy() {
local result=0
@ -59,11 +31,11 @@ check_proxy() {
for i in $(seq 1 $try_count); do
/usr/bin/ssr-check www.google.com 80 $switch_time 1
if [ "$?" == "0" ]; then
# echo "$(date "+%Y-%m-%d %H:%M:%S") Check Google Proxy Success, count=$i" >> /tmp/ssrplus.log
# echolog "Check Google Proxy Success, count=$i"
result=0
break
else
# echo "$(date "+%Y-%m-%d %H:%M:%S") Check Google Proxy Fail, count=$i" >> /tmp/ssrplus.log
# echolog "Check Google Proxy Fail, count=$i"
/usr/bin/ssr-check www.baidu.com 80 $switch_time 1
if [ "$?" == "0" ]; then
result=1
@ -77,19 +49,18 @@ check_proxy() {
}
test_proxy() {
local servername=$(get_host_ip $(uci_get_by_name $1 server))
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
ret1=$?
ipset add whitelist $servername 2>/dev/null
tcping -q -c 3 -i 1 -t 2 -p $serverport $servername
if [ "$?" -gt "0" ]; then
[ "$ret1" == "0" ] && ipset del ss_spec_wan_ac $servername 2>/dev/null
ipset del whitelist $servername 2>/dev/null
return 1
fi
/usr/bin/ssr-check $servername $serverport $switch_time
local ret2=$?
[ "$ret1" == "0" ] && ipset del ss_spec_wan_ac $servername 2>/dev/null
if [ "$ret2" == "0" ]; then
local ret=$?
ipset del whitelist $servername 2>/dev/null
if [ "$ret" == "0" ]; then
return 0
else
return 1
@ -102,14 +73,13 @@ search_proxy() {
[ "$(uci_get_by_name $1 switch_enable 0)" != "1" ] && return 1
[ $ENABLE_SERVER != nil ] && return 0
[ "$1" == "$CURRENT_SERVER" ] && return 0
local servername=$(get_host_ip $(uci_get_by_name $1 server))
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=$?
ipset add whitelist $servername 2>/dev/null
/usr/bin/ssr-check $servername $serverport $switch_time
local ret2=$?
[ "$ret" == "0" ] && ipset del ss_spec_wan_ac $servername 2>/dev/null
if [ "$ret2" == "0" ]; then
local ret=$?
ipset del whitelist $servername 2>/dev/null
if [ "$ret" == "0" ]; then
server_locate=$server_count
ENABLE_SERVER=$1
return 0
@ -137,49 +107,49 @@ start() {
#不支持kcptun启用时的切换
[ $(uci_get_by_name $DEFAULT_SERVER kcp_enable) = "1" ] && return 1
while [ "1" == "1" ]; do #死循环
sleep $cycle_time
sleep 0000$cycle_time
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") Current server is not default Main server, try to switch back." >>/tmp/ssrplus.log
echolog "Current server is not default Main server, try to switch back."
#检查缺省服务器是否正常
if test_proxy $DEFAULT_SERVER; then
#echo "switch to default proxy"
echo "$(date "+%Y-%m-%d %H:%M:%S") Main server is avilable." >>/tmp/ssrplus.log
echolog "Main server is avilable."
#缺省服务器正常,切换回来
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 alias)" proxy!" >>/tmp/ssrplus.log
echolog "switch to default "$(uci_get_by_name $CURRENT_SERVER alias)" proxy!"
else
echo "$(date "+%Y-%m-%d %H:%M:%S") Main server is NOT avilable.Continue using current server." >>/tmp/ssrplus.log
echolog "Main server is NOT avilable.Continue using current server."
fi
fi
#判断当前代理是否正常
#echo "$(date "+%Y-%m-%d %H:%M:%S") Start checking if the current server is available." >>/tmp/ssrplus.log
#echolog "Start checking if the current server is available."
check_proxy
current_ret=$?
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/ssrplus.log
echolog "Current server error, try to switch another server."
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/ssrplus.log
echolog "Another server is avilable, now switching server."
CURRENT_SERVER=$ENABLE_SERVER
switch_proxy $CURRENT_SERVER
normal_flag=1
echo "$(date "+%Y-%m-%d %H:%M:%S") Switch to "$(uci_get_by_name $CURRENT_SERVER alias)" proxy!" >>/tmp/ssrplus.log
echolog "Switch to "$(uci_get_by_name $CURRENT_SERVER alias)" proxy!"
else
switch_proxy $CURRENT_SERVER
normal_flag=1
echo "$(date "+%Y-%m-%d %H:%M:%S") Try restart current server." >>/tmp/ssrplus.log
echolog "Try restart current server."
fi
else
normal_flag=0
# echo "$(date "+%Y-%m-%d %H:%M:%S") ShadowsocksR No Problem." >>/tmp/ssrplus.log
# echolog "ShadowsocksR No Problem."
fi
done
}

View File

@ -3,5 +3,5 @@
ipset -! flush china 2>/dev/null
ipset -! -R <<-EOF || exit 1
create china hash:net
$(cat ${china_ip:=/etc/ssr/china_ssr.txt} | sed -e "s/^/add china /")
$(cat ${china_ip:=/etc/ssrplus/china_ssr.txt} | sed -e "s/^/add china /")
EOF

View File

@ -0,0 +1,171 @@
local ucursor = require"luci.model.uci".cursor()
local json = require "luci.jsonc"
local server_section = arg[1]
local proto = arg[2]
local local_port = arg[3] or "0"
local socks_port = arg[4] or "0"
local server = ucursor:get_all("shadowsocksr", server_section)
local Xray = {
log = {
-- error = "/var/ssrplus.log",
loglevel = "warning"
},
-- 传入连接
inbound = (local_port ~= "0") and {
port = tonumber(local_port),
protocol = "dokodemo-door",
settings = {network = proto, followRedirect = true},
sniffing = {enabled = true, destOverride = {"http", "tls"}}
} or nil,
-- 开启 socks 代理
inboundDetour = (proto == "tcp" and socks_port ~= "0") and {
{
protocol = "socks",
port = tonumber(socks_port),
settings = {auth = "noauth", udp = true}
}
} or nil,
-- 传出连接
outbound = {
protocol = server.type,
settings = {
vnext = {
{
address = server.server,
port = tonumber(server.server_port),
users = {
{
id = server.vmess_id,
alterId = (server.type == "vmess") and tonumber(server.alter_id) or nil,
security = (server.type == "vmess") and server.security or nil,
encryption = (server.type == "vless") and server.vless_encryption or nil,
flow = (server.xtls == '1') and (server.vless_flow and server.vless_flow or "xtls-rprx-splice") or nil
}
}
}
}
},
-- 底层传输配置
streamSettings = {
network = server.transport,
security = (server.xtls == '1') and "xtls" or (server.tls == '1') and "tls" or "none",
tlsSettings = (server.tls == '1' and (server.insecure == "1" or server.tls_host)) and {
allowInsecure = (server.insecure == "1") and true or nil,
serverName = server.tls_host
} or nil,
xtlsSettings = (server.xtls == '1' and (server.insecure == "1" or server.tls_host)) and {
allowInsecure = (server.insecure == "1") and true or nil,
serverName = server.tls_host
} or nil,
tcpSettings = (server.transport == "tcp" and server.tcp_guise == "http") and {
header = {
type = server.tcp_guise,
request = {
path = {server.http_path} or {"/"},
headers = {Host = {server.http_host} or {}}
}
}
} or nil,
kcpSettings = (server.transport == "kcp") and {
mtu = tonumber(server.mtu),
tti = tonumber(server.tti),
uplinkCapacity = tonumber(server.uplink_capacity),
downlinkCapacity = tonumber(server.downlink_capacity),
congestion = (server.congestion == "1") and true or false,
readBufferSize = tonumber(server.read_buffer_size),
writeBufferSize = tonumber(server.write_buffer_size),
header = {type = server.kcp_guise},
seed = server.seed or nil
} or nil,
wsSettings = (server.transport == "ws") and (server.ws_path or server.ws_host or server.tls_host) and {
path = server.ws_path,
headers = (server.ws_host or server.tls_host) and {
Host = server.ws_host or server.tls_host
} or nil
} or nil,
httpSettings = (server.transport == "h2") and {
path = server.h2_path or "",
host = {server.h2_host} or nil
} or nil,
quicSettings = (server.transport == "quic") and {
security = server.quic_security,
key = server.quic_key,
header = {type = server.quic_guise}
} or nil
},
mux = (server.mux == "1" and server.xtls ~= "1") and {
enabled = true,
concurrency = tonumber(server.concurrency)
} or nil
} or nil
}
local trojan = {
log_level = 3,
run_type = (proto == "nat" or proto == "tcp") and "nat" or "client",
local_addr = "0.0.0.0",
local_port = tonumber(local_port),
remote_addr = server.server,
remote_port = tonumber(server.server_port),
udp_timeout = 60,
-- 传入连接
password = {server.password},
-- 传出连接
ssl = {
verify = (server.insecure == "0") and true or false,
verify_hostname = (server.tls == "1") and true or false,
cert = "",
cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA",
cipher_tls13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384",
sni = server.tls_host,
alpn = {"h2", "http/1.1"},
curve = "",
reuse_session = true,
session_ticket = false
},
tcp = {
no_delay = true,
keep_alive = true,
reuse_port = true,
fast_open = (server.fast_open == "1") and true or false,
fast_open_qlen = 20
}
}
local naiveproxy = {
proxy = (server.username and server.password and server.server and server.server_port) and "https://" .. server.username .. ":" .. server.password .. "@" .. server.server .. ":" .. server.server_port,
listen = (proto == "redir") and "redir" .. "://0.0.0.0:" .. tonumber(local_port) or "socks" .. "://0.0.0.0:" .. tonumber(local_port),
concurrency = (socks_port ~= "0") and tonumber(socks_port) or "1"
}
local ss = {
server = (server.kcp_enable == "1") and "127.0.0.1" or server.server,
server_port = tonumber(server.server_port),
local_address = "0.0.0.0",
local_port = tonumber(local_port),
password = server.password,
method = server.encrypt_method,
timeout = tonumber(server.timeout) or 60,
fast_open = (server.fast_open == "1") and true or false,
reuse_port = true
}
if server.type == "ss" then
if server.plugin then
ss.plugin = server.plugin
ss.plugin_opts = (server.simple_obfs) and server.simple_obfs .. server.plugin_opts or (server.v2ray_plugin ~= "none") and server.v2ray_plugin .. server.plugin_opts or nil
end
print(json.stringify(ss, 1))
end
if server.type == "ssr" then
ss.protocol = server.protocol
ss.protocol_param = server.protocol_param
ss.obfs = server.obfs
ss.obfs_param = server.obfs_param
print(json.stringify(ss, 1))
end
if server.type == "vless" or server.type == "vmess" then
print(json.stringify(Xray, 1))
end
if server.type == "trojan" then
print(json.stringify(trojan, 1))
end
if server.type == "naiveproxy" then
print(json.stringify(naiveproxy, 1))
end

View File

@ -1,72 +1,95 @@
#!/bin/sh
cat <<-EOF >$1
base {
argv1=$1
argv2=$2
argv3=$3
argv4=$4
argv5=$5
argv6=$6
argv7=$7
argv8=$8
argv9=$9
cat <<-EOF >$argv1
base {
log_debug = off;
log_info = off;
log = stderr;
daemon = on;
redirector = iptables;
reuseport = on;
}
}
EOF
if [ "$2" == "socks5" ]; then
if [ "$3" == "tcp" ]; then
if [ "$7" == "0" ]; then
cat <<-EOF >>$1
redsocks {
bind = "0.0.0.0:$4";
relay = "$5:$6";
type = socks5;
autoproxy = 0;
timeout = 10;
tcp() {
if [ "$argv7" == "0" ]; then
cat <<-EOF >>$argv1
redsocks {
bind = "0.0.0.0:$argv4";
relay = "$argv5:$argv6";
type = socks5;
autoproxy = 0;
timeout = 10;
}
EOF
else
cat <<-EOF >>$argv1
redsocks {
bind = "0.0.0.0:$argv4";
relay = "$argv5:$argv6";
type = socks5;
autoproxy = 0;
timeout = 10;
login = "$argv8";
password = "$argv9";
}
EOF
fi
}
EOF
else
cat <<-EOF >>$1
redsocks {
bind = "0.0.0.0:$4";
relay = "$5:$6";
type = socks5;
autoproxy = 0;
timeout = 10;
login = "$8";
password = "$9";
udp() {
if [ "$argv7" == "0" ]; then
cat <<-EOF >>$argv1
redudp {
bind = "0.0.0.0:$argv4";
relay = "$argv5:$argv6";
type = socks5;
udp_timeout = 10;
}
EOF
else
cat <<-EOF >>$argv1
redudp {
bind = "0.0.0.0:$argv4";
relay = "$argv5:$argv6";
type = socks5;
udp_timeout = 10;
login = "$argv8";
password = "$argv9";
}
EOF
fi
}
EOF
fi
else
if [ "$7" == "0" ]; then
cat <<-EOF >>$1
redudp {
bind = "0.0.0.0:$4";
relay = "$5:$6";
type = socks5;
udp_timeout = 10;
}
EOF
else
cat <<-EOF >>$1
redudp {
bind = "0.0.0.0:$4";
relay = "$5:$6";
type = socks5;
udp_timeout = 10;
login = "$8";
password = "$9";
}
EOF
fi
fi
else
cat <<-EOF >>$1
redsocks {
bind = "0.0.0.0:$4";
type = direct;
interface = $3;
autoproxy = 0;
timeout = 10;
}
EOF
fi
case "$argv2" in
socks5)
case "$argv3" in
tcp)
tcp
;;
udp)
udp
;;
*)
tcp
udp
;;
esac
;;
*)
cat <<-EOF >>$argv1
redsocks {
bind = "0.0.0.0:$argv4";
type = direct;
interface = $argv3;
autoproxy = 0;
timeout = 10;
}
EOF
;;
esac

View File

@ -1,40 +0,0 @@
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("shadowsocksr", server_section)
local trojan = {
log_level = 3,
run_type = proto,
local_addr = "0.0.0.0",
local_port = tonumber(local_port),
remote_addr = server.server,
remote_port = tonumber(server.server_port),
udp_timeout = 60,
-- 传入连接
password = {server.password},
-- 传出连接
ssl = {
verify = (server.insecure == "0") and true or false,
verify_hostname = (server.tls == "1") and true or false,
cert = "",
cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA",
cipher_tls13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384",
sni = server.tls_host,
alpn = {"h2", "http/1.1"},
curve = "",
reuse_session = true,
session_ticket = false,
},
tcp = {
no_delay = true,
keep_alive = true,
reuse_port = true,
fast_open = (server.fast_open == "1") and true or false,
fast_open_qlen = 20
}
}
print(json.stringify(trojan, 1))

View File

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

View File

@ -1,61 +1,47 @@
#!/bin/sh
NAME=shadowsocksr
switch_server=$1
uci_get_by_type() {
local ret=$(uci get $NAME.@$1[0].$2 2>/dev/null)
echo ${ret:=$3}
. $IPKG_INSTROOT/etc/init.d/shadowsocksr
netflix() {
if [ -f "$TMP_DNSMASQ_PATH/gfw_list.conf" ]; then
for line in $(cat /etc/ssrplus/netflix.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/gfw_list.conf; done
for line in $(cat /etc/ssrplus/netflix.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/gfw_base.conf; done
fi
cat /etc/ssrplus/netflix.list | sed '/^$/d' | sed '/#/d' | sed "/.*/s/.*/server=\/&\/127.0.0.1#$1\nipset=\/&\/netflix/" >$TMP_DNSMASQ_PATH/netflix_forward.conf
}
if [ -z "$switch_server" ]; then
GLOBAL_SERVER=$(uci_get_by_type global global_server nil)
else
GLOBAL_SERVER=$switch_server
fi
mkdir -p /tmp/dnsmasq.ssr
mkdir -p $TMP_DNSMASQ_PATH
if [ "$(uci_get_by_type global run_mode router)" == "oversea" ]; then
cp -rf /etc/ssr/oversea_list.conf /tmp/dnsmasq.ssr/
cp -rf /etc/ssrplus/oversea_list.conf $TMP_DNSMASQ_PATH/
else
cp -rf /etc/ssr/gfw_list.conf /tmp/dnsmasq.ssr/
cp -rf /etc/ssr/gfw_base.conf /tmp/dnsmasq.ssr/
cp -rf /etc/ssrplus/gfw_list.conf $TMP_DNSMASQ_PATH/
cp -rf /etc/ssrplus/gfw_base.conf $TMP_DNSMASQ_PATH/
fi
NETFLIX_SERVER=$(uci_get_by_type global netflix_server nil)
[ "$NETFLIX_SERVER" == "same" ] && NETFLIX_SERVER=$GLOBAL_SERVER
if [ "$NETFLIX_SERVER" != "nil" ]; then
netflix() {
if [ -f "/tmp/dnsmasq.ssr/gfw_list.conf" ]; then
for line in $(cat /etc/ssr/netflix.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/gfw_list.conf; done
for line in $(cat /etc/ssr/netflix.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/gfw_base.conf; done
fi
awk '!/^$/&&!/^#/{printf("ipset=/%s/'"netflix"'\n",$0)}' /etc/ssr/netflix.list >/tmp/dnsmasq.ssr/netflix_forward.conf
awk '!/^$/&&!/^#/{printf("server=/%s/'"127.0.0.1#$1"'\n",$0)}' /etc/ssr/netflix.list >>/tmp/dnsmasq.ssr/netflix_forward.conf
}
if [ "$NETFLIX_SERVER" != "$GLOBAL_SERVER" ]; then
netflix 5555
else
netflix 5335
fi
else
rm -f /tmp/dnsmasq.ssr/netflix_forward.conf
fi
for line in $(cat /etc/ssr/black.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/gfw_list.conf; done
for line in $(cat /etc/ssr/black.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/gfw_base.conf; done
for line in $(cat /etc/ssr/white.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/gfw_list.conf; done
for line in $(cat /etc/ssr/white.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/gfw_base.conf; done
for line in $(cat /etc/ssr/deny.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/gfw_list.conf; done
for line in $(cat /etc/ssr/deny.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/gfw_base.conf; done
awk '!/^$/&&!/^#/{printf("ipset=/%s/'"blacklist"'\n",$0)}' /etc/ssr/black.list >/tmp/dnsmasq.ssr/blacklist_forward.conf
awk '!/^$/&&!/^#/{printf("server=/%s/'"127.0.0.1#5335"'\n",$0)}' /etc/ssr/black.list >>/tmp/dnsmasq.ssr/blacklist_forward.conf
awk '!/^$/&&!/^#/{printf("ipset=/%s/'"whitelist"'\n",$0)}' /etc/ssr/white.list >/tmp/dnsmasq.ssr/whitelist_forward.conf
awk '!/^$/&&!/^#/{printf("address=/%s/''\n",$0)}' /etc/ssr/deny.list >/tmp/dnsmasq.ssr/denylist.conf
case "$(uci_get_by_type global netflix_server nil)" in
nil)
rm -f $TMP_DNSMASQ_PATH/netflix_forward.conf
;;
same)
netflix 5335
;;
*)
netflix $tmp_shunt_dns_port
;;
esac
for line in $(cat /etc/ssrplus/black.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/gfw_list.conf; done
for line in $(cat /etc/ssrplus/black.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/gfw_base.conf; done
for line in $(cat /etc/ssrplus/white.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/gfw_list.conf; done
for line in $(cat /etc/ssrplus/white.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/gfw_base.conf; done
for line in $(cat /etc/ssrplus/deny.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/gfw_list.conf; done
for line in $(cat /etc/ssrplus/deny.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/gfw_base.conf; done
cat /etc/ssrplus/black.list | sed '/^$/d' | sed '/#/d' | sed "/.*/s/.*/server=\/&\/127.0.0.1#5335\nipset=\/&\/blacklist/" >$TMP_DNSMASQ_PATH/blacklist_forward.conf
cat /etc/ssrplus/white.list | sed '/^$/d' | sed '/#/d' | sed "/.*/s/.*/server=\/&\/127.0.0.1\nipset=\/&\/whitelist/" >$TMP_DNSMASQ_PATH/whitelist_forward.conf
cat /etc/ssrplus/deny.list | sed '/^$/d' | sed '/#/d' | sed "/.*/s/.*/address=\/&\//" >$TMP_DNSMASQ_PATH/denylist.conf
if [ "$(uci_get_by_type global adblock 0)" == "1" ]; then
[ -z "$switch_server" ] && cp -f /etc/ssr/ad.conf /tmp/dnsmasq.ssr/
if [ -f "/tmp/dnsmasq.ssr/ad.conf" ]; then
for line in $(cat /etc/ssr/black.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/ad.conf; done
for line in $(cat /etc/ssr/white.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/ad.conf; done
for line in $(cat /etc/ssr/deny.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/ad.conf; done
for line in $(cat /etc/ssr/netflix.list); do sed -i "/$line/d" /tmp/dnsmasq.ssr/ad.conf; done
cp -f /etc/ssrplus/ad.conf $TMP_DNSMASQ_PATH/
if [ -f "$TMP_DNSMASQ_PATH/ad.conf" ]; then
for line in $(cat /etc/ssrplus/black.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/ad.conf; done
for line in $(cat /etc/ssrplus/white.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/ad.conf; done
for line in $(cat /etc/ssrplus/deny.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/ad.conf; done
for line in $(cat /etc/ssrplus/netflix.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/ad.conf; done
fi
else
rm -f /tmp/dnsmasq.ssr/ad.conf
rm -f $TMP_DNSMASQ_PATH/ad.conf
fi

View File

@ -1,6 +1,6 @@
#!/bin/sh
/usr/bin/lua /usr/share/shadowsocksr/update.lua
sleep 2s
/usr/share/shadowsocksr/chinaipset.sh /tmp/etc/china_ssr.txt
/usr/share/shadowsocksr/chinaipset.sh /var/etc/ssrplus/china_ssr.txt
sleep 2s
/usr/bin/lua /usr/share/shadowsocksr/subscribe.lua

View File

@ -1,4 +1,5 @@
#!/usr/bin/lua
------------------------------------------------
-- This file is part of the luci-app-ssr-plus subscribe.lua
-- @author William Chan <root@williamchan.me>
@ -15,7 +16,7 @@ local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string.
local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify
local b64decode = nixio.bin.b64decode
local cache = {}
local nodeResult = setmetatable({}, { __index = cache }) -- update result
local nodeResult = setmetatable({}, {__index = cache}) -- update result
local name = 'shadowsocksr'
local uciType = 'servers'
local ucic = luci.model.uci.cursor()
@ -24,7 +25,7 @@ local switch = ucic:get_first(name, 'server_subscribe', 'switch', '1')
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url', {})
local filter_words = ucic:get_first(name, 'server_subscribe', 'filter_words', '过期时间/剩余流量')
local log = function(...)
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({ ... }, " "))
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({...}, " "))
end
-- 分割字符串
local function split(full, sep)
@ -79,7 +80,9 @@ end
-- base64
local function base64Decode(text)
local raw = text
if not text then return '' end
if not text then
return ''
end
text = text:gsub("%z", "")
text = text:gsub("_", "/")
text = text:gsub("-", "+")
@ -94,11 +97,7 @@ local function base64Decode(text)
end
-- 处理数据
local function processData(szType, content)
local result = {
type = szType,
local_port = 1234,
kcp_param = '--nocomp'
}
local result = {type = szType, local_port = 1234, kcp_param = '--nocomp'}
if szType == 'ssr' then
local dat = split(content, "/%?")
local hostInfo = split(dat[1], ':')
@ -122,7 +121,7 @@ local function processData(szType, content)
result.alias = result.alias .. base64Decode(params.remarks)
elseif szType == 'vmess' then
local info = jsonParse(content)
result.type = 'v2ray'
result.type = 'vmess'
result.server = info.add
result.server_port = info.port
result.transport = info.net
@ -278,7 +277,7 @@ local function processData(szType, content)
end
-- wget
local function wget(url)
local stdout = luci.sys.exec('wget-ssl -q --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36" --no-check-certificate -t 3 -T 10 -O- "' .. url .. '"')
local stdout = luci.sys.exec('wget -q --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36" --no-check-certificate -O- "' .. url .. '"')
return trim(stdout)
end
@ -287,7 +286,7 @@ local function check_filer(result)
local filter_word = split(filter_words, "/")
for i, v in pairs(filter_word) do
if result.alias:find(v) then
log('订阅节点关键字过滤:“' .. v ..'” ,该节点被丢弃')
-- log('订阅节点关键字过滤:“' .. v ..'” ,该节点被丢弃')
return true
end
end
@ -315,16 +314,11 @@ local execute = function()
local nEnd = select(2, raw:find('ssd://'))
nodes = base64Decode(raw:sub(nEnd + 1, #raw))
nodes = jsonParse(nodes)
local extra = {
airport = nodes.airport,
port = nodes.port,
encryption = nodes.encryption,
password = nodes.password
}
local extra = {airport = nodes.airport, port = nodes.port, encryption = nodes.encryption, password = nodes.password}
local servers = {}
-- SS里面包着 干脆直接这样
for _, server in ipairs(nodes.servers) do
tinsert(servers, setmetatable(server, { __index = extra }))
tinsert(servers, setmetatable(server, {__index = extra}))
end
nodes = servers
else
@ -355,16 +349,11 @@ local execute = function()
end
-- log(result)
if result then
if
not result.server or
not result.server_port or
result.alias == "NULL" or
check_filer(result) or
result.server:match("[^0-9a-zA-Z%-%.%s]") -- 中文做地址的 也没有人拿中文域名搞就算中文域也有Puny Code SB 机场
then
log('丢弃无效节点: ' .. result.type ..' 节点, ' .. result.alias)
-- 中文做地址的 也没有人拿中文域名搞就算中文域也有Puny Code SB 机场
if not result.server or not result.server_port or result.alias == "NULL" or check_filer(result) or result.server:match("[^0-9a-zA-Z%-%.%s]") then
log('丢弃无效节点: ' .. result.type .. ' 节点, ' .. result.alias)
else
log('成功解析: ' .. result.type ..' 节点, ' .. result.alias)
-- log('成功解析: ' .. result.type ..' 节点, ' .. result.alias)
result.grouphashkey = groupHash
tinsert(nodeResult[index], result)
cache[groupHash][result.hashkey] = nodeResult[index][#nodeResult[index]]
@ -372,7 +361,7 @@ local execute = function()
end
end
end
log('成功解析节点数量: ' ..#nodes)
log('成功解析节点数量: ' .. #nodes)
else
log(url .. ': 获取内容为空')
end
@ -398,7 +387,7 @@ local execute = function()
local dat = nodeResult[old.grouphashkey][old.hashkey]
ucic:tset(name, old['.name'], dat)
-- 标记一下
setmetatable(nodeResult[old.grouphashkey][old.hashkey], { __index = { _ignore = true } })
setmetatable(nodeResult[old.grouphashkey][old.hashkey], {__index = {_ignore = true}})
end
else
if not old.alias then
@ -432,14 +421,14 @@ local execute = function()
luci.sys.call("/etc/init.d/" .. name .. " start > /dev/null 2>&1 &")
else
log('维持当前主服务器节点。')
luci.sys.call("/etc/init.d/" .. name .." restart > /dev/null 2>&1 &")
luci.sys.call("/etc/init.d/" .. name .. " restart > /dev/null 2>&1 &")
end
else
log('没有服务器节点了,停止服务')
luci.sys.call("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &")
end
end
log('新增节点数量: ' ..add, '删除节点数量: ' .. del)
log('新增节点数量: ' .. add, '删除节点数量: ' .. del)
log('订阅更新成功')
end
end
@ -451,10 +440,10 @@ if subscribe_url and #subscribe_url > 0 then
log('发生错误, 正在恢复服务')
local firstServer = ucic:get_first(name, uciType)
if firstServer then
luci.sys.call("/etc/init.d/" .. name .." restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
luci.sys.call("/etc/init.d/" .. name .. " restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
log('重启服务成功')
else
luci.sys.call("/etc/init.d/" .. name .." stop > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
luci.sys.call("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
log('停止服务成功')
end
end)

View File

@ -1,4 +1,5 @@
#!/usr/bin/lua
------------------------------------------------
-- This file is part of the luci-app-ssr-plus update.lua
-- By Mattraks
@ -6,46 +7,192 @@
require "luci.sys"
require "luci.model.uci"
local icount = 0
local args = arg[1]
local uci = luci.model.uci.cursor()
local TMP_DNSMASQ_PATH = "/var/etc/dnsmasq-ssrplus.d"
local TMP_PATH = "/var/etc/ssrplus"
-- match comments/title/whitelist/ip address/excluded_domain
local comment_pattern = "^[!\\[@]+"
local ip_pattern = "^%d+%.%d+%.%d+%.%d+"
local domain_pattern = "([%w%-%_]+%.[%w%.%-%_]+)[%/%*]*"
local excluded_domain = {"apple.com", "sina.cn", "sina.com.cn", "baidu.com", "byr.cn", "jlike.com", "weibo.com", "zhongsou.com", "youdao.com", "sogou.com", "so.com", "soso.com", "aliyun.com", "taobao.com", "jd.com", "qq.com"}
-- gfwlist parameter
local mydnsip = '127.0.0.1'
local mydnsport = '5335'
local ipsetname = 'gfwlist'
local bc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
-- base64decoding
local function base64_dec(data)
data = string.gsub(data, '[^' .. bc .. '=]', '')
return (data:gsub('.', function(x)
if (x == '=') then
return ''
end
local r, f = '', (bc:find(x) - 1)
for i = 6, 1, -1 do
r = r .. (f % 2 ^ i - f % 2 ^ (i - 1) > 0 and '1' or '0')
end
return r;
end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
if (#x ~= 8) then
return ''
end
local c = 0
for i = 1, 8 do
c = c + (x:sub(i, i) == '1' and 2 ^ (8 - i) or 0)
end
return string.char(c)
end))
end
-- check excluded domain
local function check_excluded_domain(value)
for k, v in ipairs(excluded_domain) do
if value:find(v) then
return true
end
end
end
-- gfwlist转码至dnsmasq格式
local function generate_gfwlist(type)
local domains = {}
local out = io.open("/tmp/ssr-update." .. type, "w")
for line in io.lines("/tmp/ssr-update.tmp") do
if not (string.find(line, comment_pattern) or string.find(line, ip_pattern) or check_excluded_domain(line)) then
local start, finish, match = string.find(line, domain_pattern)
if (start) then
domains[match] = true
end
end
end
for k, v in pairs(domains) do
out:write(string.format("server=/%s/%s#%s\n", k, mydnsip, mydnsport))
out:write(string.format("ipset=/%s/%s\n", k, ipsetname))
end
out:close()
os.remove("/tmp/ssr-update.tmp")
end
-- adblock转码至dnsmasq格式
local function generate_adblock(type)
local domains = {}
local out = io.open("/tmp/ssr-update." .. type, "w")
for line in io.lines("/tmp/ssr-update.tmp") do
if not (string.find(line, comment_pattern)) then
local start, finish, match = string.find(line, domain_pattern)
if (start) then
domains[match] = true
end
end
end
for k, v in pairs(domains) do
out:write(string.format("address=/%s/\n", k))
end
out:close()
os.remove("/tmp/ssr-update.tmp")
end
local log = function(...)
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({ ... }, " "))
if args then
print(...)
else
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({...}, " "))
end
end
local function update(url, file, type, file2)
local Num = 1
refresh_cmd = "wget-ssl --no-check-certificate -t 3 -T 10 -O- " .. url .. " > /tmp/ssr-update." .. type
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
local refresh_cmd = "wget --no-check-certificate -q -O /tmp/ssr-update." .. type .. " " .. url
local sret = luci.sys.call(refresh_cmd)
if sret == 0 then
if type == "gfw_data" then
luci.sys.call("/usr/bin/ssr-gfw " .. type)
local gfwlist = io.open("/tmp/ssr-update." .. type, "r")
local decode = gfwlist:read("*a")
if not decode:find("google") then
decode = base64_dec(decode)
end
gfwlist:close()
-- 写回gfwlist
gfwlist = io.open("/tmp/ssr-update.tmp", "w")
gfwlist:write(decode)
gfwlist:close()
generate_gfwlist(type)
Num = 2
end
if type == "ad_data" then
luci.sys.call("/usr/bin/ssr-ad " .. type)
local adblock = io.open("/tmp/ssr-update." .. type, "r")
local decode = adblock:read("*a")
if decode:find("address=") then
adblock:close()
else
adblock:close()
-- 写回adblock
adblock = io.open("/tmp/ssr-update.tmp", "w")
adblock:write(decode)
adblock:close()
generate_adblock(type)
end
end
local new_md5 = luci.sys.exec("echo -n $([ -f '/tmp/ssr-update." .. type .. "' ] && md5sum /tmp/ssr-update." .. type .. " | awk '{print $1}')")
local old_md5 = luci.sys.exec("echo -n $([ -f '" .. file .. "' ] && md5sum " .. file .. " | awk '{print $1}')")
if new_md5 == old_md5 then
log("你已经是最新数据,无需更新!")
if args then
log("0")
else
log("你已经是最新数据,无需更新!")
end
else
icount = luci.sys.exec("cat /tmp/ssr-update." .. type .. " | wc -l")
luci.sys.exec("cp -f /tmp/ssr-update." .. type .. " " .. file)
if file2 then luci.sys.exec("cp -f /tmp/ssr-update." .. type .. " " .. file2) end
log("更新成功! 新的总纪录数:" .. tostring(tonumber(icount)/Num))
if file2 then
luci.sys.exec("cp -f /tmp/ssr-update." .. type .. " " .. file2)
end
if type == "gfw_data" or type == "ad_data" then
luci.sys.call("/usr/share/shadowsocksr/gfw2ipset.sh")
else
luci.sys.call("/usr/share/shadowsocksr/chinaipset.sh " .. TMP_PATH .. "/china_ssr.txt")
end
if args then
log(tonumber(icount) / Num)
else
log("更新成功! 新的总纪录数:" .. tostring(tonumber(icount) / Num))
end
end
else
log("更新失败!")
if args then
log("-1")
else
log("更新失败!")
end
end
luci.sys.exec("rm -f /tmp/ssr-update." .. type)
os.remove("/tmp/ssr-update." .. type)
end
log("正在更新【GFW列表】数据库")
update(uci:get_first("shadowsocksr", "global", "gfwlist_url", "https://cdn.jsdelivr.net/gh/v2fly/domain-list-community@release/gfwlist.txt"), "/etc/ssr/gfw_list.conf", "gfw_data", "/tmp/dnsmasq.ssr/gfw_list.conf")
log("正在更新【国内IP段】数据库")
update(uci:get_first("shadowsocksr", "global", "chnroute_url","https://ispip.clang.cn/all_cn.txt"), "/etc/ssr/china_ssr.txt", "cnip", "/tmp/etc/china_ssr.txt")
if uci:get_first("shadowsocksr", "global", "adblock","0") == "1" then
log("正在更新【广告屏蔽】数据库")
update(uci:get_first("shadowsocksr", "global", "adblock_url","https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt"), "/etc/ssr/ad.conf", "ad_data", "/tmp/dnsmasq.ssr/ad.conf")
if args then
if args == "gfw_data" then
update(uci:get_first("shadowsocksr", "global", "gfwlist_url"), "/etc/ssrplus/gfw_list.conf", args, TMP_DNSMASQ_PATH .. "/gfw_list.conf")
os.exit(0)
end
if args == "ip_data" then
update(uci:get_first("shadowsocksr", "global", "chnroute_url"), "/etc/ssrplus/china_ssr.txt", args, TMP_PATH .. "/china_ssr.txt")
os.exit(0)
end
if args == "ad_data" then
update(uci:get_first("shadowsocksr", "global", "adblock_url"), "/etc/ssrplus/ad.conf", args, TMP_DNSMASQ_PATH .. "/ad.conf")
os.exit(0)
end
if args == "nfip_data" then
update(uci:get_first("shadowsocksr", "global", "nfip_url"), "/etc/ssrplus/netflixip.list", args)
os.exit(0)
end
else
log("正在更新【GFW列表】数据库")
update(uci:get_first("shadowsocksr", "global", "gfwlist_url"), "/etc/ssrplus/gfw_list.conf", "gfw_data", TMP_DNSMASQ_PATH .. "/gfw_list.conf")
log("正在更新【国内IP段】数据库")
update(uci:get_first("shadowsocksr", "global", "chnroute_url"), "/etc/ssrplus/china_ssr.txt", "ip_data", TMP_PATH .. "/china_ssr.txt")
if uci:get_first("shadowsocksr", "global", "adblock", "0") == "1" then
log("正在更新【广告屏蔽】数据库")
update(uci:get_first("shadowsocksr", "global", "adblock_url"), "/etc/ssrplus/ad.conf", "ad_data", TMP_DNSMASQ_PATH .. "/ad.conf")
end
-- log("正在更新【Netflix IP段】数据库")
-- update(uci:get_first("shadowsocksr", "global", "nfip_url"), "/etc/ssrplus/netflixip.list", "nfip_data")
end
-- log("正在更新【Netflix IP段】数据库")
-- update(uci:get_first("shadowsocksr", "global", "nfip_url","https://raw.githubusercontent.com/QiuSimons/Netflix_IP/master/NF_only.txt"), "/etc/ssr/netflixip.list", "nfip_data")