remove obsolete package

This commit is contained in:
fw876@outlook.com 2020-04-16 12:27:11 +08:00
parent 6c8c96cedf
commit 988acf9daa
45 changed files with 0 additions and 24629 deletions

View File

@ -1,120 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-ssr-plus
PKG_VERSION:=176
PKG_RELEASE:=6
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)/config
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin
bool "Include Shadowsocks V2ray Plugin"
default y if i386||x86_64||arm||aarch64
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray
bool "Include V2ray"
default y if i386||x86_64||arm||aarch64
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan
bool "Include Trojan"
default y if i386||x86_64||arm||aarch64
config PACKAGE_$(PKG_NAME)_INCLUDE_Redsocks2
bool "Include Redsocks2"
default y if i386||x86_64||arm||aarch64
config PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun
bool "Include Kcptun"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server
bool "Include ShadowsocksR Server"
default y if i386||x86_64||arm||aarch64
endef
define Package/$(PKG_NAME)
SECTION:=luci
CATEGORY:=LuCI
SUBMENU:=3. Applications
TITLE:=SS/SSR/V2Ray/Trojan LuCI interface
PKGARCH:=all
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 +tcpping \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin:v2ray-plugin \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:ipt2socks \
+PACKAGE_$(PKG_NAME)_INCLUDE_Redsocks2:redsocks2 \
+PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun:kcptun-client \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-server
endef
define Build/Prepare
endef
define Build/Compile
endef
define Package/$(PKG_NAME)/conffiles
/etc/ssr_ip
/etc/china_ssr.txt
/etc/config/shadowsocksr
/etc/config/white.list
/etc/config/black.list
/etc/config/netflix.list
/etc/dnsmasq.ssr/ad.conf
/etc/dnsmasq.ssr/gfw_list.conf
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/etc
$(INSTALL_DATA) ./root/etc/china_ssr.txt $(1)/etc/china_ssr.txt
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./root/etc/config/shadowsocksr $(1)/etc/config/shadowsocksr
$(INSTALL_DATA) ./root/etc/config/*.list $(1)/etc/config/
$(INSTALL_DIR) $(1)/etc/dnsmasq.oversea
$(INSTALL_DATA) ./root/etc/dnsmasq.oversea/* $(1)/etc/dnsmasq.oversea/
$(INSTALL_DIR) $(1)/etc/dnsmasq.ssr
$(INSTALL_DATA) ./root/etc/dnsmasq.ssr/* $(1)/etc/dnsmasq.ssr/
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./root/etc/init.d/* $(1)/etc/init.d/
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./root/etc/uci-defaults/* $(1)/etc/uci-defaults/
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) ./root/usr/bin/* $(1)/usr/bin/
$(INSTALL_DIR) $(1)/usr/share/shadowsocksr
$(INSTALL_BIN) ./root/usr/share/shadowsocksr/*.sh $(1)/usr/share/shadowsocksr/
$(INSTALL_DATA) ./root/usr/share/shadowsocksr/*.lua $(1)/usr/share/shadowsocksr/
$(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d
$(INSTALL_DATA) ./root/usr/share/rpcd/acl.d/* $(1)/usr/share/rpcd/acl.d
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller
$(INSTALL_DATA) ./luasrc/controller/*.lua $(1)/usr/lib/lua/luci/controller/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/shadowsocksr
$(INSTALL_DATA) ./luasrc/model/cbi/shadowsocksr/*.lua $(1)/usr/lib/lua/luci/model/cbi/shadowsocksr/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/view/shadowsocksr
$(INSTALL_DATA) ./luasrc/view/shadowsocksr/* $(1)/usr/lib/lua/luci/view/shadowsocksr/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
po2lmo ./po/zh-cn/ssr-plus.po $(1)/usr/lib/lua/luci/i18n/ssr-plus.zh-cn.lmo
endef
define Package/$(PKG_NAME)/postrm
#!/bin/sh
rm -rf /etc/china_ssr.txt /etc/dnsmasq.ssr /etc/dnsmasq.oversea /etc/config/shadowsocksr /etc/config/black.list \
/etc/config/gfw.list /etc/config/white.list /etc/config/netflix.list /etc/config/netflixip.list 2>/dev/null
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -1,211 +0,0 @@
-- 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", "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", "ping"}, call("act_ping")).leaf = true
end
function subscribe()
luci.sys.call("/usr/bin/lua /usr/share/shadowsocksr/subscribe.lua >> /tmp/ssrplus.log 2>&1")
luci.http.prepare_content("application/json")
luci.http.write_json({ret = 1})
end
function act_status()
local e = {}
e.running = luci.sys.call("busybox ps -w | grep ssr-retcp | grep -v grep >/dev/null") == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function act_ping()
local e = {}
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 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 $(tcpping -c 1 -i 1 -p %s %s 2>&1 | grep -o 'ttl=[0-9]* time=[0-9]*.[0-9]' | awk -F '=' '{print$3}') 2>/dev/null",port, domain))
end
if (iret == 0) then
luci.sys.call(" ipset del ss_spec_wan_ac " .. domain)
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function check_status()
local set = "/usr/bin/ssr-check www." .. luci.http.formvalue("set") .. ".com 80 3 1"
sret = luci.sys.call(set)
if sret == 0 then
retstring = "0"
else
retstring = "1"
end
luci.http.prepare_content("application/json")
luci.http.write_json({ret = retstring})
end
function refresh_data()
local set = luci.http.formvalue("set")
local uci = luci.model.uci.cursor()
local icount = 0
if set == "gfw_data" then
refresh_cmd = "wget-ssl --no-check-certificate -O- " .. uci:get_first('shadowsocksr', 'global', 'gfwlist_url', 'https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt') .. ' > /tmp/gfw.b64'
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
if sret == 0 then
luci.sys.call("/usr/bin/ssr-gfw")
icount = luci.sys.exec("cat /tmp/gfwnew.txt | wc -l")
if tonumber(icount) > 1000 then
if nixio.fs.access("/etc/dnsmasq.ssr/gfw_list.conf") then
oldcount = luci.sys.exec("cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l")
else
oldcount = "0"
end
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec("cp -f /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf")
luci.sys.exec("cp -f /tmp/gfwnew.txt /tmp/dnsmasq.ssr/gfw_list.conf")
luci.sys.call("/etc/init.d/dnsmasq restart")
retstring = tostring(tonumber(icount)/2)
else
retstring = "0"
end
else
retstring = "-1"
end
luci.sys.exec("rm -f /tmp/gfwnew.txt")
else
retstring = "-1"
end
end
if set == "ip_data" then
refresh_cmd = "wget-ssl --no-check-certificate -O- " .. uci:get_first('shadowsocksr', 'global', 'chnroute_url', 'https://ispip.clang.cn/all_cn.txt') .. " > /tmp/china_ssr.txt"
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
icount = luci.sys.exec("cat /tmp/china_ssr.txt | wc -l")
if sret == 0 and tonumber(icount) > 1000 then
if nixio.fs.access("/etc/china_ssr.txt") then
oldcount = luci.sys.exec("cat /etc/china_ssr.txt | wc -l")
else
oldcount = "0"
end
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec("cp -f /tmp/china_ssr.txt /etc/china_ssr.txt")
luci.sys.exec("/etc/init.d/shadowsocksr restart &")
retstring = tostring(tonumber(icount))
else
retstring = "0"
end
else
retstring = "-1"
end
luci.sys.exec("rm -f /tmp/china_ssr.txt")
end
if set == "nfip_data" then
refresh_cmd = "wget-ssl --no-check-certificate -O- " .. uci:get_first('shadowsocksr', 'global', 'nfip_url','https://raw.githubusercontent.com/QiuSimons/Netflix_IP/master/NF_only.txt') .." > /tmp/netflixip.list"
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
icount = luci.sys.exec("cat /tmp/netflixip.list | wc -l")
if sret == 0 and tonumber(icount) > 5 then
if nixio.fs.access("/etc/config/netflixip.list") then
oldcount = luci.sys.exec("cat /etc/config/netflixip.list | wc -l")
else
oldcount = "0"
end
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec("cp -f /tmp/netflixip.list /etc/config/netflixip.list")
luci.sys.exec("/etc/init.d/shadowsocksr restart &")
retstring = tostring(tonumber(icount))
else
retstring = "0"
end
else
retstring = "-1"
end
luci.sys.exec("rm -f /tmp/netflixip.list")
end
if set == "ad_data" then
refresh_cmd = "wget-ssl --no-check-certificate -O- " .. uci:get_first('shadowsocksr', 'global', 'adblock_url','https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt') .." > /tmp/adnew.conf"
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
if sret == 0 then
luci.sys.call("/usr/bin/ssr-ad")
icount = luci.sys.exec("cat /tmp/ad.conf | wc -l")
if tonumber(icount) > 100 then
if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
oldcount = luci.sys.exec("cat /etc/dnsmasq.ssr/ad.conf | wc -l")
else
oldcount = "0"
end
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec("cp -f /tmp/ad.conf /etc/dnsmasq.ssr/ad.conf")
luci.sys.exec("cp -f /tmp/ad.conf /tmp/dnsmasq.ssr/ad.conf")
luci.sys.call("/etc/init.d/dnsmasq restart")
retstring = tostring(tonumber(icount))
else
retstring = "0"
end
else
retstring = "-1"
end
luci.sys.exec("rm -f /tmp/ad.conf")
else
retstring = "-1"
end
end
luci.http.prepare_content("application/json")
luci.http.write_json({ret = retstring,retcount = icount})
end
function check_port()
local set = ""
local retstring = "<br /><br />"
local s
local server_name = ""
local uci = luci.model.uci.cursor()
local iret = 1
uci:foreach("shadowsocksr", "servers", function(s)
if s.alias then
server_name = s.alias
elseif s.server and s.server_port then
server_name = "%s:%s" %{s.server, s.server_port}
end
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)
if tostring(ret) == "true" then
socket:close()
retstring = retstring .. "<font color = 'green'>[" .. server_name .. "] OK.</font><br />"
else
retstring = retstring .. "<font color = 'red'>[" .. server_name .. "] Error.</font><br />"
end
if iret == 0 then
luci.sys.call("ipset del ss_spec_wan_ac " .. s.server)
end
end)
luci.http.prepare_content("application/json")
luci.http.write_json({ret = retstring})
end

View File

@ -1,88 +0,0 @@
local shadowsocksr = "shadowsocksr"
local uci = luci.model.uci.cursor()
local server_table = {}
uci:foreach(shadowsocksr, "servers", function(s)
if s.alias then
server_table[s[".name"]] = "[%s]:%s" %{string.upper(s.type), s.alias}
elseif s.server and s.server_port then
server_table[s[".name"]] = "[%s]:%s:%s" %{string.upper(s.type), s.server, s.server_port}
end
end)
local key_table = {}
for key,_ in pairs(server_table) do
table.insert(key_table,key)
end
table.sort(key_table)
m = Map("shadowsocksr")
-- [[ global ]]--
s = m:section(TypedSection, "global", translate("Server failsafe auto swith and custom update settings"))
s.anonymous = true
-- o = s:option(Flag, "monitor_enable", translate("Enable Process Deamon"))
-- o.rmempty = false
-- o.default = "1"
o = s:option(Flag, "enable_switch", translate("Enable Auto Switch"))
o.rmempty = false
o.default = "1"
o = s:option(Value, "switch_time", translate("Switch check cycly(second)"))
o.datatype = "uinteger"
o:depends("enable_switch", "1")
o.default = 667
o = s:option(Value, "switch_timeout", translate("Check timout(second)"))
o.datatype = "uinteger"
o:depends("enable_switch", "1")
o.default = 5
o = s:option(Value, "switch_try_count", translate("Check Try Count"))
o.datatype = "uinteger"
o:depends("enable_switch", "1")
o.default = 3
o = s:option(Flag, "adblock", translate("Enable adblock"))
o.rmempty = false
o = s:option(Value, "adblock_url", translate("adblock_url"))
o:value("https://gitee.com/privacy-protection-tools/anti-ad/raw/master/anti-ad-for-dnsmasq.conf", translate("anti-AD"))
o.default = "https://gitee.com/privacy-protection-tools/anti-ad/raw/master/anti-ad-for-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/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/gfwlist/gfwlist/gfwlist.txt"
o = s:option(Value, "chnroute_url", translate("Chnroute Update url"))
o:value("https://ispip.clang.cn/all_cn.txt", translate("Clang.CN"))
o.default = "https://ispip.clang.cn/all_cn.txt"
o = s:option(Value, "nfip_url", translate("nfip_url"))
o:value("https://raw.githubusercontent.com/QiuSimons/Netflix_IP/master/NF_only.txt", translate("Netflix IP Only"))
o:value("https://raw.githubusercontent.com/QiuSimons/Netflix_IP/master/getflix.txt", translate("Netflix and AWS"))
o.default = "https://raw.githubusercontent.com/QiuSimons/Netflix_IP/master/NF_only.txt"
o.description = translate("Customize Netflix IP Url")
-- [[ SOCKS5 Proxy ]]--
s = m:section(TypedSection, "socks5_proxy", translate("Global SOCKS5 Proxy Server"))
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
o.default = "nil"
o.rmempty = false
o = s:option(Value, "local_port", translate("Local Port"))
o.datatype = "port"
o.default = 1080
o.rmempty = false
return m

View File

@ -1,500 +0,0 @@
-- Copyright (C) 2017 yushi studio <ywb94@qq.com> github.com/ywb94
-- Licensed to the public under the GNU General Public License v3.
local m, s, o,kcp_enable
local shadowsocksr = "shadowsocksr"
local uci = luci.model.uci.cursor()
local fs = require "nixio.fs"
local sys = require "luci.sys"
local sid = arg[1]
local uuid = luci.sys.exec("cat /proc/sys/kernel/random/uuid")
local http = require "luci.http"
local function isKcptun(file)
if not fs.access(file, "rwx", "rx", "rx") then
fs.chmod(file, 755)
end
local str = sys.exec(file .. " -v | awk '{printf $1}'")
return (str:lower() == "kcptun")
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",
}
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",
}
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",
}
obfs = {
"plain",
"http_simple",
"http_post",
"random_head",
"tls1.2_ticket_auth",
}
local securitys = {
"auto",
"none",
"aes-128-gcm",
"chacha20-poly1305"
}
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
end
-- [[ Servers Setting ]]--
s = m:section(NamedSection, sid, "servers")
s.anonymous = true
s.addremove = false
o = s:option(DummyValue,"ssr_url","SS/SSR/V2RAY/TROJAN URL")
o.rawhtml = true
o.template = "shadowsocksr/ssrurl"
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"))
end
if nixio.fs.access("/usr/bin/v2ray/v2ray") or nixio.fs.access("/usr/bin/v2ray") then
o:value("v2ray", translate("V2Ray"))
end
if nixio.fs.access("/usr/sbin/trojan") then
o:value("trojan", translate("Trojan"))
end
if nixio.fs.access("/usr/sbin/redsocks2") then
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")
o = s:option(Value, "alias", translate("Alias(optional)"))
o = s:option(ListValue, "iface", translate("Network interface to use"))
for _, e in ipairs(sys.net.devices()) do
if e ~= "lo" then o:value(e) end
end
o:depends("type", "tun")
o.description = translate("Redirect traffic to this network interface")
o = s:option(Value, "server", translate("Server Address"))
o.datatype = "host"
o.rmempty = false
o:depends("type", "ssr")
o:depends("type", "ss")
o:depends("type", "v2ray")
o:depends("type", "trojan")
o:depends("type", "socks5")
o = s:option(Value, "server_port", translate("Server Port"))
o.datatype = "port"
o.rmempty = false
o:depends("type", "ssr")
o:depends("type", "ss")
o:depends("type", "v2ray")
o:depends("type", "trojan")
o:depends("type", "socks5")
o = s:option(Flag, "auth_enable", translate("Enable Authentication"))
o.rmempty = false
o.default = "0"
o:depends("type", "socks5")
o = s:option(Value, "username", translate("Username"))
o.rmempty = true
o:depends("type", "socks5")
o = s:option(Value, "password", translate("Password"))
o.password = true
o.rmempty = true
o:depends("type", "ssr")
o:depends("type", "ss")
o:depends("type", "trojan")
o:depends("type", "socks5")
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods) do o:value(v) end
o.rmempty = true
o:depends("type", "ssr")
o = s:option(ListValue, "encrypt_method_ss", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods_ss) do o:value(v) end
o.rmempty = true
o:depends("type", "ss")
-- Shadowsocks Plugin
o = s:option(Value, "plugin", translate("Plugin"))
o.rmempty = true
o:depends("type", "ss")
o = s:option(Value, "plugin_opts", translate("Plugin Opts"))
o.rmempty = true
o:depends("type", "ss")
o = s:option(ListValue, "protocol", translate("Protocol"))
for _, v in ipairs(protocol) do o:value(v) end
o.rmempty = true
o:depends("type", "ssr")
o = s:option(Value, "protocol_param", translate("Protocol param(optional)"))
o:depends("type", "ssr")
o = s:option(ListValue, "obfs", translate("Obfs"))
for _, v in ipairs(obfs) do o:value(v) end
o.rmempty = true
o:depends("type", "ssr")
o = s:option(Value, "obfs_param", translate("Obfs param(optional)"))
o:depends("type", "ssr")
-- AlterId
o = s:option(Value, "alter_id", translate("AlterId"))
o.datatype = "port"
o.default = 16
o.rmempty = true
o:depends("type", "v2ray")
-- VmessId
o = s:option(Value, "vmess_id", translate("VmessId (UUID)"))
o.rmempty = true
o.default = uuid
o:depends("type", "v2ray")
-- 加密方式
o = s:option(ListValue, "security", translate("Encrypt Method"))
for _, v in ipairs(securitys) do o:value(v, v:upper()) end
o.rmempty = true
o:depends("type", "v2ray")
-- 传输协议
o = s:option(ListValue, "transport", translate("Transport"))
o:value("tcp", "TCP")
o:value("kcp", "mKCP")
o:value("ws", "WebSocket")
o:value("h2", "HTTP/2")
o:value("quic", "QUIC")
o.rmempty = true
o:depends("type", "v2ray")
-- [[ TCP部分 ]]--
-- TCP伪装
o = s:option(ListValue, "tcp_guise", translate("Camouflage Type"))
o:depends("transport", "tcp")
o:value("http", "HTTP")
o:value("none", translate("None"))
o.rmempty = true
-- HTTP域名
o = s:option(Value, "http_host", translate("HTTP Host"))
o:depends("tcp_guise", "http")
o.rmempty = true
-- HTTP路径
o = s:option(Value, "http_path", translate("HTTP Path"))
o:depends("tcp_guise", "http")
o.rmempty = true
-- [[ WS部分 ]]--
-- WS域名
o = s:option(Value, "ws_host", translate("WebSocket Host"))
o:depends("transport", "ws")
o.rmempty = true
-- WS路径
o = s:option(Value, "ws_path", translate("WebSocket Path"))
o:depends("transport", "ws")
o.rmempty = true
-- [[ H2部分 ]]--
-- H2域名
o = s:option(Value, "h2_host", translate("HTTP/2 Host"))
o:depends("transport", "h2")
o.rmempty = true
-- H2路径
o = s:option(Value, "h2_path", translate("HTTP/2 Path"))
o:depends("transport", "h2")
o.rmempty = true
-- [[ QUIC部分 ]]--
o = s:option(ListValue, "quic_security", translate("QUIC Security"))
o:depends("transport", "quic")
o.rmempty = true
o:value("none", translate("None"))
o:value("aes-128-gcm", translate("aes-128-gcm"))
o:value("chacha20-poly1305", translate("chacha20-poly1305"))
o = s:option(Value, "quic_key", translate("QUIC Key"))
o:depends("transport", "quic")
o.rmempty = true
o = s:option(ListValue, "quic_guise", translate("Header"))
o:depends("transport", "quic")
o.rmempty = true
o:value("none", translate("None"))
o:value("srtp", translate("VideoCall (SRTP)"))
o:value("utp", translate("BitTorrent (uTP)"))
o:value("wechat-video", translate("WechatVideo"))
o:value("dtls", "DTLS 1.2")
o:value("wireguard", "WireGuard")
-- [[ 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.rmempty = true
o = s:option(Value, "mtu", translate("MTU"))
o.datatype = "uinteger"
o:depends("transport", "kcp")
o.default = 1350
o.rmempty = true
o = s:option(Value, "tti", translate("TTI"))
o.datatype = "uinteger"
o:depends("transport", "kcp")
o.default = 50
o.rmempty = true
o = s:option(Value, "uplink_capacity", translate("Uplink Capacity"))
o.datatype = "uinteger"
o:depends("transport", "kcp")
o.default = 5
o.rmempty = true
o = s:option(Value, "downlink_capacity", translate("Downlink Capacity"))
o.datatype = "uinteger"
o:depends("transport", "kcp")
o.default = 20
o.rmempty = true
o = s:option(Value, "read_buffer_size", translate("Read Buffer Size"))
o.datatype = "uinteger"
o:depends("transport", "kcp")
o.default = 2
o.rmempty = true
o = s:option(Value, "write_buffer_size", translate("Write Buffer Size"))
o.datatype = "uinteger"
o:depends("transport", "kcp")
o.default = 2
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 = true
o:depends("type", "v2ray")
o:depends("type", "trojan")
o.default = "1"
-- [[ TLS ]]--
o = s:option(Flag, "tls", translate("TLS"))
o.rmempty = true
o.default = "0"
o:depends("type", "v2ray")
o:depends("type", "trojan")
o = s:option(Value, "tls_host", translate("TLS Host"))
--o:depends("type", "trojan")
o:depends("tls", "1")
o.rmempty = true
-- [[ Mux ]]--
o = s:option(Flag, "mux", translate("Mux"))
o.rmempty = true
o.default = "0"
o:depends("type", "v2ray")
o = s:option(Value, "concurrency", translate("Concurrency"))
o.datatype = "uinteger"
o.rmempty = true
o.default = "8"
o:depends("mux", "1")
-- [[ Cert ]]--
o = s:option(Flag, "certificate", translate("Self-signed Certificate"))
o.rmempty = true
o.default = "0"
o:depends("type", "trojan")
o:depends("type", "v2ray")
o.description = translate("If you have a self-signed certificate,please check the box")
o = s:option(DummyValue, "upload", translate("Upload"))
o.template = "shadowsocksr/certupload"
o:depends("certificate", 1)
cert_dir = "/etc/ssl/private/"
local path
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
end
o = s:option(Value, "certpath", translate("Current Certificate Path"))
o:depends("certificate", 1)
o:value("/etc/ssl/private/")
o.description = translate("Please confirm the current certificate path")
o.default = "/etc/ssl/private/"
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
o.rmempty = true
o.default = "0"
o:depends("type", "ssr")
o:depends("type", "ss")
o:depends("type", "trojan")
o = s:option(Flag, "switch_enable", translate("Enable Auto Switch"))
o.rmempty = false
o.default = "1"
o = s:option(Value, "local_port", translate("Local Port"))
o.datatype = "port"
o.default = 1234
o.rmempty = false
if nixio.fs.access("/usr/bin/kcptun-client") then
kcp_enable = s:option(Flag, "kcp_enable", translate("KcpTun Enable"), translate("bin:/usr/bin/kcptun-client"))
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 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")
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")
end
return m

View File

@ -1,109 +0,0 @@
-- 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()
local sys = require "luci.sys"
m = Map(shadowsocksr, translate("ShadowSocksR Plus+ Settings"))
m:section(SimpleSection).template = "shadowsocksr/status"
local server_table = {}
uci:foreach(shadowsocksr, "servers", function(s)
if s.alias then
server_table[s[".name"]] = "[%s]:%s" %{string.upper(s.type), s.alias}
elseif s.server and s.server_port then
server_table[s[".name"]] = "[%s]:%s:%s" %{string.upper(s.type), s.server, s.server_port}
end
end)
local key_table = {}
for key,_ in pairs(server_table) do
table.insert(key_table,key)
end
table.sort(key_table)
-- [[ Global Setting ]]--
s = m:section(TypedSection, "global")
s.anonymous = true
o = s:option(ListValue, "global_server", translate("Main Server"))
o:value("nil", translate("Disable"))
for _,key in pairs(key_table) do o:value(key,server_table[key]) end
o.default = "nil"
o.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
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
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 = s:option(ListValue, "threads", translate("Multi Threads Option"))
o:value("0", translate("Auto Threads"))
o:value("1", translate("1 Thread"))
o:value("2", translate("2 Threads"))
o:value("4", translate("4 Threads"))
o:value("8", translate("8 Threads"))
o:value("16", translate("16 Threads"))
o:value("32", translate("32 Threads"))
o:value("64", translate("64 Threads"))
o:value("128", translate("128 Threads"))
o.default = "0"
o.rmempty = false
o = s:option(ListValue, "run_mode", translate("Running Mode"))
o:value("gfw", translate("GFW List Mode"))
o:value("router", translate("IP Route Mode"))
o:value("all", translate("Global Mode"))
o:value("oversea", translate("Oversea Mode"))
o.default = gfw
o = s:option(ListValue, "dports", translate("Proxy Ports"))
o:value("1", translate("All Ports"))
o:value("2", translate("Only Common Ports"))
o.default = 1
o = s:option(ListValue, "pdnsd_enable", translate("Resolve Dns Mode"))
o:value("1", translate("Use Pdnsd tcp query and cache"))
o:value("2", translate("Use DNS2SOCKS query and cache"))
o:value("0", translate("Use Local DNS Service listen port 5335"))
o.default = 1
o = s:option(Value, "tunnel_forward", translate("Anti-pollution DNS Server"))
o:value("8.8.4.4:53", translate("Google Public DNS (8.8.4.4)"))
o:value("8.8.8.8:53", translate("Google Public DNS (8.8.8.8)"))
o:value("208.67.222.222:53", translate("OpenDNS (208.67.222.222)"))
o:value("208.67.220.220:53", translate("OpenDNS (208.67.220.220)"))
o:value("209.244.0.3:53", translate("Level 3 Public DNS (209.244.0.3)"))
o:value("209.244.0.4:53", translate("Level 3 Public DNS (209.244.0.4)"))
o:value("4.2.2.1:53", translate("Level 3 Public DNS (4.2.2.1)"))
o:value("4.2.2.2:53", translate("Level 3 Public DNS (4.2.2.2)"))
o:value("4.2.2.3:53", translate("Level 3 Public DNS (4.2.2.3)"))
o:value("4.2.2.4:53", translate("Level 3 Public DNS (4.2.2.4)"))
o:value("1.1.1.1:53", translate("Cloudflare DNS (1.1.1.1)"))
o:value("114.114.114.114:53", translate("Oversea Mode DNS-1 (114.114.114.114)"))
o:value("114.114.115.115:53", translate("Oversea Mode DNS-2 (114.114.115.115)"))
o:depends("pdnsd_enable", "1")
o:depends("pdnsd_enable", "2")
o.description = translate("Custom DNS Server format as IP:PORT (default: 8.8.4.4:53)")
return m

View File

@ -1,138 +0,0 @@
local m, s, o
local NXFS = require "nixio.fs"
m = Map("shadowsocksr", translate("IP black-and-white list"))
s = m:section(TypedSection, "access_control")
s.anonymous = true
-- Part of WAN
s:tab("wan_ac", translate("WAN IP AC"))
o = s:taboption("wan_ac", DynamicList, "wan_bp_ips", translate("WAN White List IP"))
o.datatype = "ip4addr"
o = s:taboption("wan_ac", DynamicList, "wan_fw_ips", translate("WAN Force Proxy IP"))
o.datatype = "ip4addr"
-- Part of LAN
s:tab("lan_ac", translate("LAN IP AC"))
o = s:taboption("lan_ac", ListValue, "lan_ac_mode", translate("LAN Access Control"))
o:value("0", translate("Disable"))
o:value("w", translate("Allow listed only"))
o:value("b", translate("Allow all except listed"))
o.rmempty = false
o = s:taboption("lan_ac", DynamicList, "lan_ac_ips", translate("LAN Host List"))
o.datatype = "ipaddr"
luci.ip.neighbors({ family = 4 }, function(entry)
if entry.reachable then
o:value(entry.dest:string())
end
end)
o:depends("lan_ac_mode", "w")
o:depends("lan_ac_mode", "b")
o = s:taboption("lan_ac", DynamicList, "lan_bp_ips", translate("LAN Bypassed Host List"))
o.datatype = "ipaddr"
luci.ip.neighbors({ family = 4 }, function(entry)
if entry.reachable then
o:value(entry.dest:string())
end
end)
o = s:taboption("lan_ac", DynamicList, "lan_fp_ips", translate("LAN Force Proxy Host List"))
o.datatype = "ipaddr"
luci.ip.neighbors({ family = 4 }, function(entry)
if entry.reachable then
o:value(entry.dest:string())
end
end)
o = s:taboption("lan_ac", DynamicList, "lan_gm_ips", translate("Game Mode Host List"))
o.datatype = "ipaddr"
luci.ip.neighbors({ family = 4 }, function(entry)
if entry.reachable then
o:value(entry.dest:string())
end
end)
-- Part of Self
-- s:tab("self_ac", translate("Router Self AC"))
-- o = s:taboption("self_ac",ListValue, "router_proxy", translate("Router Self Proxy"))
-- o:value("1", translatef("Normal Proxy"))
-- o:value("0", translatef("Bypassed Proxy"))
-- o:value("2", translatef("Forwarded Proxy"))
-- o.rmempty = false
s:tab("esc", translate("Bypass Domain List"))
local escconf = "/etc/config/white.list"
o = s:taboption("esc", TextValue, "escconf")
o.rows = 13
o.wrap = "off"
o.rmempty = true
o.cfgvalue = function(self, section)
return NXFS.readfile(escconf) or ""
end
o.write = function(self, section, value)
NXFS.writefile(escconf, value:gsub("\r\n", "\n"))
end
o.remove = function(self, section, value)
NXFS.writefile(escconf, "")
end
s:tab("block", translate("Black Domain List"))
local blockconf = "/etc/config/black.list"
o = s:taboption("block", TextValue, "blockconf")
o.rows = 13
o.wrap = "off"
o.rmempty = true
o.cfgvalue = function(self, section)
return NXFS.readfile(blockconf) or " "
end
o.write = function(self, section, value)
NXFS.writefile(blockconf, value:gsub("\r\n", "\n"))
end
o.remove = function(self, section, value)
NXFS.writefile(blockconf, "")
end
s:tab("netflix", translate("Netflix Domain List"))
local netflixconf = "/etc/config/netflix.list"
o = s:taboption("netflix", TextValue, "netflixconf")
o.rows = 13
o.wrap = "off"
o.rmempty = true
o.cfgvalue = function(self, section)
return NXFS.readfile(netflixconf) or " "
end
o.write = function(self, section, value)
NXFS.writefile(netflixconf, value:gsub("\r\n", "\n"))
end
o.remove = function(self, section, value)
NXFS.writefile(netflixconf, "")
end
s:tab("netflixip", translate("Netflix IP List"))
local netflixipconf = "/etc/config/netflixip.list"
o = s:taboption("netflixip", TextValue, "netflixipconf")
o.rows = 13
o.wrap = "off"
o.rmempty = true
o.cfgvalue = function(self, section)
return NXFS.readfile(netflixipconf) or " "
end
o.write = function(self, section, value)
NXFS.writefile(netflixipconf, value:gsub("\r\n", "\n"))
end
o.remove = function(self, section, value)
NXFS.writefile(netflixipconf, "")
end
return m

View File

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

View File

@ -1,115 +0,0 @@
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
-- Licensed to the public under the GNU General Public License v3.
require "luci.http"
require "luci.dispatcher"
require "nixio.fs"
local m, s, o
local 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",
}
local protocol = {
"origin",
}
obfs = {
"plain",
"http_simple",
"http_post",
}
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
luci.http.redirect(m.redirect)
return
end
-- [[ Server Setting ]]--
s = m:section(NamedSection, sid, "server_config")
s.anonymous = true
s.addremove = false
o = s:option(Flag, "enable", translate("Enable"))
o.default = 1
o.rmempty = false
o = s:option(ListValue, "type", translate("Server Type"))
o:value("socks5", translate("Socks5"))
if nixio.fs.access("/usr/bin/ss-server") then
o:value("ssr", translate("ShadowsocksR"))
end
o.default = "socks5"
o = s:option(Value, "server_port", translate("Server Port"))
o.datatype = "port"
o.default = 8388
o.rmempty = false
o = s:option(Value, "timeout", translate("Connection Timeout"))
o.datatype = "uinteger"
o.default = 60
o.rmempty = false
o:depends("type", "ssr")
o = s:option(Value, "username", translate("Username"))
o.rmempty = false
o:depends("type", "socks5")
o = s:option(Value, "password", translate("Password"))
o.password = true
o.rmempty = false
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods) do o:value(v) end
o.rmempty = false
o:depends("type", "ssr")
o = s:option(ListValue, "protocol", translate("Protocol"))
for _, v in ipairs(protocol) do o:value(v) end
o.rmempty = false
o:depends("type", "ssr")
o = s:option(ListValue, "obfs", translate("Obfs"))
for _, v in ipairs(obfs) do o:value(v) end
o.rmempty = false
o:depends("type", "ssr")
o = s:option(Value, "obfs_param", translate("Obfs param(optional)"))
o:depends("type", "ssr")
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
o.rmempty = false
o:depends("type", "ssr")
return m

View File

@ -1,112 +0,0 @@
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
-- Licensed to the public under the GNU General Public License v3.
local m, sec, o
local shadowsocksr = "shadowsocksr"
local uci = luci.model.uci.cursor()
m = Map(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",
}
local protocol = {
"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",
}
-- [[ Global Setting ]]--
sec = m:section(TypedSection, "server_global", translate("Global Setting"))
sec.anonymous = true
o = sec:option(Flag, "enable_server", translate("Enable Server"))
o.rmempty = false
-- [[ Server Setting ]]--
sec = m:section(TypedSection, "server_config", translate("Server Setting"))
sec.anonymous = true
sec.addremove = true
sec.template = "cbi/tblsection"
sec.extedit = luci.dispatcher.build_url("admin/services/shadowsocksr/server/%s")
function sec.create(...)
local sid = TypedSection.create(...)
if sid then
luci.http.redirect(sec.extedit % sid)
return
end
end
o = sec:option(Flag, "enable", translate("Enable"))
function o.cfgvalue(...)
return Value.cfgvalue(...) or translate("0")
end
o.rmempty = false
o = sec:option(DummyValue, "type", translate("Server Type"))
function o.cfgvalue(...)
return Value.cfgvalue(...) or "ssr"
end
o = sec:option(DummyValue, "server_port", translate("Server Port"))
function o.cfgvalue(...)
return Value.cfgvalue(...) or "-"
end
o = sec:option(DummyValue, "username", translate("Username"))
function o.cfgvalue(...)
return Value.cfgvalue(...) or "-"
end
o = sec:option(DummyValue, "encrypt_method", translate("Encrypt Method"))
function o.cfgvalue(...)
local v = Value.cfgvalue(...)
return v and v:upper() or "-"
end
o = sec:option(DummyValue, "protocol", translate("Protocol"))
function o.cfgvalue(...)
return Value.cfgvalue(...) or "-"
end
o = sec:option(DummyValue, "obfs", translate("Obfs"))
function o.cfgvalue(...)
return Value.cfgvalue(...) or "-"
end
return m

View File

@ -1,139 +0,0 @@
-- Licensed to the public under the GNU General Public License v3.
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)
local fs = require "nixio.fs"
local sys = require "luci.sys"
local ucic = luci.model.uci.cursor()
m = Map(shadowsocksr, translate("Servers subscription and manage"))
-- Server Subscribe
s = m:section(TypedSection, "server_subscribe")
s.anonymous = true
o = s:option(Flag, "auto_update", translate("Auto Update"))
o.rmempty = false
o.description = translate("Auto Update Server subscription, GFW list and CHN route")
o = s:option(ListValue, "auto_update_time", translate("Update time (every day)"))
for t = 0,23 do
o:value(t, t..":00")
end
o.default=2
o.rmempty = false
o = s:option(DynamicList, "subscribe_url", translate("Subscribe URL"))
o.rmempty = true
o = s:option(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.inputstyle = "reload"
o.description = translate("Update subscribe url list first")
o.write = function()
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 = 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.rawhtml = true
o.template = "shadowsocksr/subscribe"
o = s:option(Button,"delete",translate("Delete All Subscribe Severs"))
o.inputstyle = "reset"
o.description = string.format(translate("Server Count") .. ": %d", server_count)
o.write = function()
uci:delete_all("shadowsocksr", "servers", function(s)
if s.hashkey or s.isSubscribe then
return true
else
return false
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"))
return
end
-- [[ Servers Manage ]]--
s = m:section(TypedSection, "servers")
s.anonymous = true
s.addremove = true
s.template = "cbi/tblsection"
s.sortable = true
s.extedit = luci.dispatcher.build_url("admin/services/shadowsocksr/servers/%s")
function s.create(...)
local sid = TypedSection.create(...)
if sid then
luci.http.redirect(s.extedit % sid)
return
end
end
o = s:option(DummyValue, "type", translate("Type"))
function o.cfgvalue(...)
return Value.cfgvalue(...) or ""
end
o = s:option(DummyValue, "alias", translate("Alias"))
function o.cfgvalue(...)
return Value.cfgvalue(...) or translate("None")
end
o = s:option(DummyValue, "server_port", translate("Server Port"))
function o.cfgvalue(...)
return Value.cfgvalue(...) or "N/A"
end
o = s:option(DummyValue, "server_port", translate("Socket Connected"))
o.template="shadowsocksr/socket"
o.width="10%"
o = s:option(DummyValue, "server", translate("Ping Latency"))
o.template="shadowsocksr/ping"
o.width="10%"
node = s:option(Button,"apply_node",translate("Apply"))
node.inputstyle = "apply"
node.write = function(self, section)
ucic:set("shadowsocksr", '@global[0]', 'global_server', section)
ucic:save("shadowsocksr")
ucic:commit("shadowsocksr")
luci.sys.exec("/etc/init.d/shadowsocksr restart")
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr", "client"))
end
o = s:option(Flag, "switch_enable", translate("Auto Switch"))
o.rmempty = false
function o.cfgvalue(...)
return Value.cfgvalue(...) or 1
end
m:append(Template("shadowsocksr/server_list"))
return m

View File

@ -1,183 +0,0 @@
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
-- Licensed to the public under the GNU General Public License v3.
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 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 fs = require "nixio.fs"
local sys = require "luci.sys"
local kcptun_version=translate("Unknown")
local kcp_file="/usr/bin/kcptun-client"
if not fs.access(kcp_file) then
kcptun_version=translate("Not exist")
else
if not fs.access(kcp_file, "rwx", "rx", "rx") then
fs.chmod(kcp_file, 755)
end
kcptun_version=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/dnsmasq.ssr/gfw_list.conf") then
gfw_count = tonumber(sys.exec("cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l"))/2
end
if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
ad_count = tonumber(sys.exec("cat /etc/dnsmasq.ssr/ad.conf | wc -l"))
end
if nixio.fs.access("/etc/china_ssr.txt") then
ip_count = tonumber(sys.exec("cat /etc/china_ssr.txt | wc -l"))
end
if nixio.fs.access("/etc/config/netflixip.list") then
nfip_count = tonumber(sys.exec("cat /etc/config/netflixip.list | wc -l"))
end
local icount=sys.exec("busybox ps -w | grep ssr-reudp |grep -v grep| wc -l")
if tonumber(icount)>0 then
reudp_run=1
else
icount=sys.exec("busybox ps -w | grep ssr-retcp |grep \"\\-u\"|grep -v grep| wc -l")
if tonumber(icount)>0 then
reudp_run=1
end
end
if luci.sys.call("busybox ps -w | grep ssr-retcp | grep -v grep >/dev/null") == 0 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
end
if luci.sys.call("pidof kcptun-client >/dev/null") == 0 then
kcptun_run=1
end
if luci.sys.call("busybox ps -w | grep ssr-server | grep -v grep >/dev/null") == 0 then
server_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
end
m = SimpleForm("Version")
m.reset = false
m.submit = false
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
else
s.value = translate("Not Running")
end
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
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"))
s.rawhtml = true
if pdnsd_run == 1 then
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.rawhtml = true
if sock5_run == 1 then
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.rawhtml = true
if server_run == 1 then
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.rawhtml = true
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
else
s.value = translate("Not Running")
end
end
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.value = translate("No Check")
s.template = "shadowsocksr/check"
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.rawhtml = true
s.template = "shadowsocksr/refresh"
s.value = ip_count .. " " .. translate("Records")
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"))
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.template = "shadowsocksr/checkport"
s.value =translate("No Check")
return m

View File

@ -1,4 +0,0 @@
<%+cbi/valueheader%>
<input class="cbi-input-file" style="width: 400px" type="file" id="ulfile" name="ulfile" />
<input type="submit" class="cbi-button cbi-input-apply" name="upload" value="<%:Upload%>" />
<%+cbi/valuefooter%>

View File

@ -1,30 +0,0 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
function check_connect(btn,urlname)
{
btn.disabled = true;
btn.value = '<%:Check...%>';
murl=urlname;
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr","check")%>',
{ set:murl },
function(x,rv)
{
var s = document.getElementById(urlname+'-status');
if (s)
{
if (rv.ret=="0")
s.innerHTML ="<font color='green'>"+"<%:Connect OK%>"+"</font>";
else
s.innerHTML ="<font color='red'>"+"<%:Connect Error%>"+"</font>";
}
btn.disabled = false;
btn.value = '<%:Check Connect%>';
}
);
return false;
}
//]]></script>
<input type="button" class="cbi-button cbi-button-apply" value="<%:Check Connect%>" onclick="return check_connect(this,'<%=self.option%>')" />
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
<%+cbi/valuefooter%>

View File

@ -1,36 +0,0 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
function check_port(btn)
{
btn.disabled = true;
btn.value = '<%:Check...%>';
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr","checkport")%>',
null,
function(x,rv)
{
var s = document.getElementById('<%=self.option%>-status');
if (s)
{
s.innerHTML =rv.ret;
}
btn.disabled = false;
btn.value = '<%:Check Server%>';
}
);
return false;
}
//]]></script>
<input type="button" class="cbi-button cbi-button-apply" value="<%:Check Server%>" onclick="return check_port(this)" />
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
<%+cbi/valuefooter%>

View File

@ -1,3 +0,0 @@
<%+cbi/valueheader%>
<span class="pingtime" hint="<%=self:cfgvalue(section)%>">-- ms</span>
<%+cbi/valuefooter%>

View File

@ -1,35 +0,0 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
function refresh_data(btn,dataname)
{
btn.disabled = true;
btn.value = '<%:Refresh...%> ';
murl=dataname;
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr","refresh")%>',
{ set:murl },
function(x,rv)
{
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")
{
s.innerHTML ="<font color='red'>"+"<%:Refresh Error!%> "+"</font>";
}
else
{
s.innerHTML ="<font color='green'>"+"<%:Refresh OK!%> "+"<%:Total Records:%>"+rv.ret+"</font>";
}
}
btn.disabled = false;
btn.value = '<%:Refresh Data %>';
}
);
return false;
}
//]]></script>
<input type="button" class="cbi-button cbi-input-reload" value="<%:Refresh Data%> " onclick="return refresh_data(this,'<%=self.option%>')" />
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
<%+cbi/valuefooter%>

View File

@ -1,151 +0,0 @@
<%#
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');
const ports = document.getElementsByClassName("socket-connected")
const xhr = (index) => {
return new Promise((res) => {
const dom = doms[index];
const port = ports[index];
if (!dom) res()
port.innerHTML = '<font color="#0072c3">connect</font>';
XHR.get('<%=dsp.build_url("admin/services/shadowsocksr/ping")%>', {
index,
domain: dom.getAttribute("hint"),
port: port.getAttribute("hint")
},
(x, result) => {
let col = '#ff0000';
if (result.ping) {
if (result.ping < 300) col = '#ff3300';
if (result.ping < 200) col = '#ff7700';
if (result.ping < 100) col = '#249400';
}
dom.innerHTML = `<font color="${col}">${(result.ping ? result.ping : "--") + " ms"}</font>`
if (result.socket) {
port.innerHTML = '<font color="#249400">ok</font>';
} else {
port.innerHTML = '<font color="#ff0000">fail</font>';
}
res();
});
})
}
let task = -1;
const thread = () => {
task = task + 1
if (doms[task]) {
xhr(task).then(thread);
}
}
for (let i = 0; i < 20; i++) {
thread()
}
function cbi_row_drop(fromId, toId, store, isToBottom) {
var fromNode = document.getElementById(fromId);
var toNode = document.getElementById(toId);
if (!fromNode || !toNode) return false;
var table = fromNode.parentNode;
while (table && table.nodeName.toLowerCase() != "table")
table = table.parentNode;
if (!table) return false;
var ids = [];
if (isToBottom) {
toNode.parentNode.appendChild(fromNode);
} else {
fromNode.parentNode.insertBefore(fromNode, toNode);
}
for (var idx = 2; idx < table.rows.length; idx++) {
table.rows[idx].className = table.rows[idx].className.replace(
/cbi-rowstyle-[12]/,
"cbi-rowstyle-" + (1 + (idx % 2))
);
if (table.rows[idx].id && table.rows[idx].id.match(/-([^\-]+)$/))
ids.push(RegExp.$1);
}
var input = document.getElementById(store);
if (input) input.value = ids.join(" ");
return false;
}
// set tr draggable
function enableDragForTable(table_selecter, store) {
var trs = document.querySelectorAll(table_selecter + " tr");
if (!trs || trs.length.length < 3) {
return;
}
function ondragstart(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
}
function ondrop(ev) {
var from = ev.dataTransfer.getData("Text");
cbi_row_drop(from, this.id, store);
}
function ondragover(ev) {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move";
}
function moveToTop(id) {
var top = document.querySelectorAll(table_selecter + " tr")[2];
cbi_row_drop(id, top.id, store);
}
function moveToBottom(id) {
console.log('moveToBottom:', id);
var trList = document.querySelectorAll(table_selecter + " tr");
var bottom = trList[trList.length - 1];
cbi_row_drop(id, bottom.id, store, true);
}
for (let index = 2; index < trs.length; index++) {
const el = trs[index];
el.setAttribute("draggable", true);
el.ondragstart = ondragstart;
el.ondrop = ondrop;
el.ondragover = ondragover;
// reset the behaviors of the btns
var upBtns = el.querySelectorAll(".cbi-button.cbi-button-up");
if (upBtns && upBtns.length > 0) {
upBtns.forEach(function (_el) {
_el.onclick = function () {
moveToTop(el.id);
};
});
}
var downBtns = el.querySelectorAll(".cbi-button.cbi-button-down");
if (downBtns && downBtns.length > 0) {
downBtns.forEach(function (_el) {
_el.onclick = function () {
moveToBottom(el.id);
};
});
}
}
}
// enable
enableDragForTable(
"#cbi-shadowsocksr-servers table",
"cbi.sts.shadowsocksr.servers"
);
</script>

View File

@ -1,3 +0,0 @@
<%+cbi/valueheader%>
<span class="socket-connected" hint="<%=self:cfgvalue(section)%>">wait</span>
<%+cbi/valuefooter%>

View File

@ -1,297 +0,0 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
function padright(str, cnt, pad) {
return str + Array(cnt + 1).join(pad);
}
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
function b64encutf8safe(str) {
return b64EncodeUnicode(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '');
}
function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
function b64decutf8safe(str) {
var l;
str = str.replace(/-/g, "+").replace(/_/g, "/");
l = str.length;
l = (4 - l % 4) % 4;
if (l)
str = padright(str, l, "=");
return b64DecodeUnicode(str);
}
function b64encsafe(str) {
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '')
}
function b64decsafe(str) {
var l;
str = str.replace(/-/g, "+").replace(/_/g, "/");
l = str.length;
l = (4 - l % 4) % 4;
if (l)
str = padright(str, l, "=");
return atob(str);
}
function dictvalue(d, key) {
var v = d[key];
if (typeof (v) == 'undefined' || v == '')
return '';
return b64decsafe(v);
}
function export_ssr_url(btn, urlname, sid) {
var s = document.getElementById(urlname + '-status');
if (!s)
return false;
var v_server = document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0];
var v_port = document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0];
var v_protocol = document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol')[0];
var v_method = document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method')[0];
var v_obfs = document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs')[0];
var v_password = document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0];
var v_obfs_param = document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs_param')[0];
var v_protocol_param = document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol_param')[0];
var v_alias = document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0];
var ssr_str = v_server.value + ":" +
v_port.value + ":" +
v_protocol.value + ":" +
v_method.value + ":" +
v_obfs.value + ":" +
b64encsafe(v_password.value) +
"/?obfsparam=" + b64encsafe(v_obfs_param.value) +
"&protoparam=" + b64encsafe(v_protocol_param.value) +
"&remarks=" + b64encutf8safe(v_alias.value);
var textarea = document.createElement("textarea");
textarea.textContent = "ssr://" + b64encsafe(ssr_str);
textarea.style.position = "fixed";
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand("copy"); // Security exception may be thrown by some browsers.
s.innerHTML = "<font color='green'><%:Copy SSR to clipboard successfully.%></font>";
} catch (ex) {
s.innerHTML = "<font color='red'><%:Unable to copy SSR to clipboard.%></font>";
} finally {
document.body.removeChild(textarea);
}
return false;
}
function import_ssr_url(btn, urlname, sid) {
var s = document.getElementById(urlname + '-status');
if (!s)
return false;
var ssrurl = prompt("在这里黏贴配置链接 ssr:// | ss:// | vmess:// | trojan://", "");
if (ssrurl == null || ssrurl == "") {
s.innerHTML = "<font color='red'>用户取消</font>";
return false;
}
s.innerHTML = "";
//var ssu = ssrurl.match(/ssr:\/\/([A-Za-z0-9_-]+)/i);
var ssu = ssrurl.split('://');
console.log(ssu.length);
if ((ssu[0] != "ssr" && ssu[0] != "ss" && ssu[0] != "vmess" && ssu[0] != "trojan") || ssu[1] == "") {
s.innerHTML = "<font color='red'>无效格式</font>";
return false;
}
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
if (ssu[0] == "ssr") {
var sstr = b64decsafe(ssu[1]);
var ploc = sstr.indexOf("/?");
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "ssr";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
}
var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
if (!ssm || ssm.length < 7)
return false;
var pdict = {};
if (param.length > 2)
{
var a = param.split('&');
for (var i = 0; i < a.length; i++) {
var b = a[i].split('=');
pdict[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
}
}
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = ssm[1];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = ssm[2];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol')[0].value = ssm[3];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method')[0].value = ssm[4];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs')[0].value = ssm[5];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = b64decsafe(ssm[6]);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.obfs_param')[0].value = dictvalue(pdict, 'obfsparam');
document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol_param')[0].value = dictvalue(pdict, 'protoparam');
var rem = pdict['remarks'];
if (typeof (rem) != 'undefined' && rem != '' && rem.length > 0)
document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = b64decutf8safe(rem);
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("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = ssu[1].substr(ploc + 1);
} else {
url0 = ssu[1];
}
if (sipIndex != -1) {
// SIP002
var userInfo = b64decsafe(url0.substr(0, sipIndex));
var temp = url0.substr(sipIndex + 1).split("/?");
var serverInfo = temp[0].split(":");
var server = serverInfo[0];
var port = serverInfo[1];
var method, password, plugin, pluginOpts;
if (temp[1]) {
var pluginInfo = decodeURIComponent(temp[1]);
var pluginIndex = pluginInfo.indexOf(";");
var pluginNameInfo = pluginInfo.substr(0, pluginIndex);
plugin = pluginNameInfo.substr(pluginNameInfo.indexOf("=") + 1)
pluginOpts = pluginInfo.substr(pluginIndex + 1);
}
var userInfoSplitIndex = userInfo.indexOf(":");
if (userInfoSplitIndex != -1) {
method = userInfo.substr(0, userInfoSplitIndex);
password = userInfo.substr(userInfoSplitIndex + 1);
}
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "ss";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = server;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = port;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = password || "";
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);
}
s.innerHTML = "<font color='green'>导入Shadowsocks配置信息成功</font>";
} else {
var sstr = b64decsafe(url0);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "ss";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
var team = sstr.split('@');
console.log(param);
var part1 = team[0].split(':');
var part2 = team[1].split(':');
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = part2[0];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = part2[1];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = part1[1];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.encrypt_method_ss')[0].value = part1[0];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.plugin')[0].value = "";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.plugin_opts')[0].value = "";
if (param != undefined) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = decodeURI(param);
}
s.innerHTML = "<font color='green'>导入Shadowsocks配置信息成功</font>";
}
return false;
} else if (ssu[0] == "trojan") {
var url0, param = "";
var ploc = ssu[1].indexOf("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = ssu[1].substr(ploc + 1);
} else {
url0 = ssu[1]
}
var sstr = url0;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "trojan";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
var team = sstr.split('@');
var password = team[0]
var serverPart = team[1].split(':');
var others = serverPart[1].split('?');
var port = others[0]
var queryParam = {}
if(others.length > 1) {
var queryParams = others[1]
var queryArray = queryParams.split('&')
for (i = 0; i < queryArray.length; i++) {
var params = queryArray[i].split('=');
queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || '');
}
}
document.getElementsByName('cbid.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;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = queryParam.peer || '';
document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].checked = queryParam.allowInsecure === '1';
if (param != undefined) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = decodeURI(param);
}
s.innerHTML = "<font color='green'>导入Trojan配置信息成功</font>";
return false;
} else if (ssu[0] == "vmess") {
var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?");
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "v2ray";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
}
var ssm = JSON.parse(sstr);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = ssm.ps;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = ssm.add;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = ssm.port;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.alter_id')[0].value = ssm.aid;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.vmess_id')[0].value = ssm.id;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].value = ssm.net;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].dispatchEvent(event);
if (ssm.net == "tcp") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_host')[0].value = ssm.host;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.http_path')[0].value = ssm.path;
}
if (ssm.net == "ws") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.ws_host')[0].value = ssm.host;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.ws_path')[0].value = ssm.path;
}
if (ssm.net == "h2") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_host')[0].value = ssm.host;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.h2_path')[0].value = ssm.path;
}
if (ssm.net == "quic") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_security')[0].value = ssm.securty;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.quic_key')[0].value = ssm.key;
}
if (ssm.net == "kcp") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.kcp_guise')[0].value = ssm.type;
}
if (ssm.tls == "tls") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = ssm.host;
}
document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].dispatchEvent(event);
s.innerHTML = "<font color='green'>导入V2ray配置信息成功</font>";
return false;
}
}
//]]></script>
<input type="button" class="cbi-button cbi-button-apply" value="导入配置信息" onclick="return import_ssr_url(this, '<%=self.option%>', '<%=self.value%>')" />
<span id="<%=self.option%>-status"></span>
<%+cbi/valuefooter%>

View File

@ -1,22 +0,0 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(3, '<%=url([[admin]], [[services]], [[shadowsocksr]], [[run]])%>', null,
function(x, data) {
var tb = document.getElementById('shadowsocksr_status');
if (data && tb) {
if (data.running) {
var links = '<em><b><font color=green>ShadowsocksR Plus+ <%:RUNNING%></font></b></em>';
tb.innerHTML = links;
} else {
tb.innerHTML = '<em><b><font color=red>ShadowsocksR Plus+ <%:NOT RUNNING%></font></b></em>';
}
}
}
);
//]]>
</script>
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
<fieldset class="cbi-section">
<p id="shadowsocksr_status">
<em><%:Collecting data...%></em>
</p>
</fieldset>

View File

@ -1,18 +0,0 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
function subscribe(btn,dataname) {
btn.disabled = true;
btn.value = '<%:Refresh...%> ';
murl=dataname;
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr","subscribe")%>', { set:murl }, function(x,rv) {
// 先简单刷新后期如果重构会考虑下如何组织lua shell JavaScript之间的代码逻辑和各自的调用逻辑
window.location.reload()
// btn.disabled = false;
// btn.value = '<%:Refresh Data %>';
});
return false;
}
//]]></script>
<input type="button" class="cbi-button cbi-input-apply" value="<%:Update All Subscribe Severs%> " onclick="return subscribe(this,'<%=self.option%>')" />
<!-- <span id="<%=self.option%>-status"><em><%=self.value%></em></span> -->
<%+cbi/valuefooter%>

View File

@ -1,659 +0,0 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\n"
msgid "ShadowSocksR Client"
msgstr "ShadowSocksR 客户端"
msgid "Enable"
msgstr "启用"
msgid "Disable"
msgstr "停用"
msgid "Log"
msgstr "日志"
msgid "ShadowSocksR is running"
msgstr "ShadowSocksR 客户端运行中"
msgid "ShadowSocksR is not running"
msgstr "ShadowSocksR 客户端未运行"
msgid "Global Setting"
msgstr "全局设置"
msgid "Global Server"
msgstr "全局服务器"
msgid "ShadowSocksR SOCK5 Proxy is running"
msgstr "ShadowSocksR SOCK5代理运行中"
msgid "UDP Relay Server"
msgstr "UDP中继服务器"
msgid "Same as Global Server"
msgstr "与全局服务器相同"
msgid "Servers Setting"
msgstr "服务器配置"
msgid "Alias(optional)"
msgstr "别名(可选)"
msgid "Onetime Authentication"
msgstr "一次验证"
msgid "Server Address"
msgstr "服务器地址"
msgid "Server Port"
msgstr "端口"
msgid "Local Port"
msgstr "本地端口"
msgid "Connection Timeout"
msgstr "连接超时"
msgid "Password"
msgstr "密码"
msgid "Encrypt Method"
msgstr "加密方式"
msgid "Protocol"
msgstr "传输协议"
msgid "Protocol param(optional)"
msgstr "传输协议参数(可选)"
msgid "Obfs"
msgstr "混淆插件"
msgid "Obfs param(optional)"
msgstr "混淆参数(可选)"
msgid "Enable Tunnel(DNS)"
msgstr "启用隧道DNS转发"
msgid "Tunnel Port"
msgstr "隧道DNS本地端口"
msgid "Forwarding Tunnel"
msgstr "隧道DNS转发地址"
msgid "Access Control"
msgstr "访问控制"
msgid "Interfaces - WAN"
msgstr "接口 - WAN"
msgid "Bypassed IP List"
msgstr "被忽略IP列表"
msgid "NULL - As Global Proxy"
msgstr "留空 - 作为全局代理"
msgid "Bypassed IP"
msgstr "额外被忽略IP"
msgid "Forwarded IP"
msgstr "强制走代理IP"
msgid "Interfaces - LAN"
msgstr "接口 - LAN"
msgid "LAN Access Control"
msgstr "内网客户端分流代理控制"
msgid "Allow listed only"
msgstr "仅允许列表内主机"
msgid "Allow all except listed"
msgstr "除列表外主机皆允许"
msgid "LAN Host List"
msgstr "内网主机列表"
msgid "SSR Client"
msgstr "客户端"
msgid "SSR Server"
msgstr "服务端"
msgid "ShadowSocksR Server"
msgstr "ShadowSocksR 服务端"
msgid "ShadowSocksR Server is running"
msgstr "ShadowSocksR 服务端运行中"
msgid "ShadowSocksR Server is not running"
msgstr "ShadowSocksR 服务端未运行"
msgid "Enable Server"
msgstr "启动服务端"
msgid "Server Setting"
msgstr "服务端配置"
msgid "KcpTun Enable"
msgstr "KcpTun 启用"
msgid "bin:/usr/bin/kcptun-client"
msgstr "二进制文件:/usr/bin/kcptun-client"
msgid "KcpTun Port"
msgstr "KcpTun 端口"
msgid "KcpTun Param"
msgstr "KcpTun 参数"
msgid "KcpTun Password"
msgstr "KcpTun 密码"
msgid "Haven't a Kcptun executable file"
msgstr "不存在Kcptun可执行文件请下载Kcptun可执行文件并改名放入/usr/bin/kcptun-client"
msgid "Not a Kcptun executable file"
msgstr "Kcptun可执行文件格式不正确请确认是否正确下载了路由器对应的可执行文件"
msgid "Enable Process Monitor"
msgstr "启用进程监控"
msgid "Edit ShadowSocksR Server"
msgstr "编辑服务器配置"
msgid "Alias"
msgstr "别名"
msgid "Server"
msgstr "服务器"
msgid "TCP Fast Open"
msgstr "TCP快速打开"
msgid "Status"
msgstr "状态"
msgid "Unknown"
msgstr "未知"
msgid "Running Status"
msgstr "运行状态"
msgid "Global Client"
msgstr "TCP透明代理"
msgid "Global SSR Server"
msgstr "SSR服务端"
msgid "DNS Tunnel"
msgstr "DNS 隧道"
msgid "IPK Version"
msgstr "IPK 版本号"
msgid "KcpTun Version"
msgstr "KcpTun 版本号"
msgid "Not exist"
msgstr "未安装可执行文件"
msgid "IPK Installation Time"
msgstr "IPK 安装时间"
msgid "Project"
msgstr "项目地址"
msgid "Not Running"
msgstr "未运行"
msgid "Running"
msgstr "运行中"
msgid "Enable GFW mode"
msgstr "启用 GFW 模式"
msgid "Running Mode"
msgstr "运行模式"
msgid "IP Route Mode"
msgstr "绕过中国大陆IP模式"
msgid "GFW List Mode"
msgstr "GFW列表模式"
msgid "Global Mode"
msgstr "全局模式"
msgid "Oversea Mode"
msgstr "海外用户回国模式"
msgid "Router Proxy"
msgstr "路由器访问控制"
msgid "Normal Proxy"
msgstr "正常代理"
msgid "Bypassed Proxy"
msgstr "不走代理"
msgid "Forwarded Proxy"
msgstr "强制走代理"
msgid "UDP Relay"
msgstr "UDP中继"
msgid "Google Connectivity"
msgstr "【谷歌】连通性检查"
msgid "Baidu Connectivity"
msgstr "【百度】连通性检查"
msgid "No Check"
msgstr "未检查"
msgid "Check"
msgstr "检查"
msgid "Connect OK"
msgstr "连接正常"
msgid "Connect Error"
msgstr "连接错误"
msgid "Check..."
msgstr "正在检查.."
msgid "Proxy Check"
msgstr "代理检查"
msgid "GFW List Data"
msgstr "【GFW列表】数据库"
msgid "China IP Data"
msgstr "【国内IP段】数据库"
msgid "Netflix IP Data"
msgstr "【Netflix IP段】数据库"
msgid "Advertising Data"
msgstr "【广告屏蔽】数据库"
msgid "Records"
msgstr "条记录"
msgid "Refresh Data"
msgstr "更新数据库"
msgid "Refresh..."
msgstr "正在更新,请稍候.."
msgid "Refresh OK!"
msgstr "更新成功!"
msgid "Refresh Error!"
msgstr "更新失败!"
msgid "No new data!"
msgstr "你已经是最新数据,无需更新!"
msgid "Total Records:"
msgstr "新的总纪录数:"
msgid "Check Server Port"
msgstr "【服务器端口】检查"
msgid "Check Connect"
msgstr "检查连通性"
msgid "Check Server"
msgstr "检查服务器"
msgid "Auto Switch"
msgstr "自动切换"
msgid "Enable Auto Switch"
msgstr "启用自动切换"
msgid "Switch check cycly(second)"
msgstr "自动切换检查周期(秒)"
msgid "Check timout(second)"
msgstr "切换检查超时时间(秒)"
msgid "Check Try Count"
msgstr "切换检查重试次数"
msgid "Enable adblock"
msgstr "启用广告屏蔽"
msgid "adblock_url"
msgstr "广告屏蔽更新URL"
msgid "gfwlist Update url"
msgstr "GFWList更新URL"
msgid "Chnroute Update url"
msgstr "国内IP段更新URL"
msgid "nfip_url"
msgstr "Netflix IP段更新URL"
msgid "Customize Netflix IP Url"
msgstr "自定义Netflix IP更新URL默认项目地址https://github.com/QiuSimons/Netflix_IP"
msgid "Enable Process Deamon"
msgstr "启用进程自动守护"
msgid "DNS Server IP and Port"
msgstr "DNS服务器地址和端口"
msgid "Resolve Dns Mode"
msgstr "DNS解析方式"
msgid "Use SSR DNS Tunnel"
msgstr "使用SSR-DNS隧道"
msgid "Use Pdnsd"
msgstr "使用Pdnsd"
msgid "DNS Anti-pollution"
msgstr "DNS 防污染服务"
msgid "Use Other DNS Tunnel(Need to install)"
msgstr "使用其他DNS转发(需要自己安装)"
msgid "Import SSR"
msgstr "导入ssr配置信息"
msgid "Export SSR"
msgstr "导出ssr配置信息"
msgid "Import SSR successfully."
msgstr "成功导入SSR。"
msgid "Invalid SSR format."
msgstr "无效的SSR格式。"
msgid "User cancelled."
msgstr "用户已取消。"
msgid "Paste ssr url here"
msgstr "在此处粘贴ssr://网址"
msgid "Unable to copy SSR to clipboard."
msgstr "无法复制SSR网址到剪贴板。"
msgid "Copy SSR to clipboard successfully."
msgstr "成功复制SSR网址到剪贴板。"
msgid "Servers Manage"
msgstr "服务器管理"
msgid "Auto Update"
msgstr "自动更新"
msgid "Through proxy update"
msgstr "通过代理更新"
msgid "GFW List"
msgstr "GFW列表"
msgid "ShadowSocksR Plus+ Settings"
msgstr "ShadowSocksR Plus+ 设置支持SS/SSR/V2RAY/TROJAN/SOCKS5/TUN"
msgid "Main Server"
msgstr "主服务器"
msgid "Anti-pollution DNS Server"
msgstr "访问国外域名DNS服务器"
msgid "Custom DNS Server format as IP:PORT (default: 8.8.4.4:53)"
msgstr "格式为 IP:PORT (默认: 8.8.4.4:53)"
msgid "Use Pdnsd tcp query and cache"
msgstr "使用PDNSD TCP查询并缓存"
msgid "Use DNS2SOCKS query and cache"
msgstr "使用 DNS2SOCKS 查询并缓存"
msgid "DNS Server IP:Port"
msgstr "DNS服务器 IP:Port"
msgid "Update time (every day)"
msgstr "更新时间 (每天)"
msgid "Auto Update Server subscription, GFW list and CHN route"
msgstr "自动更新服务器订阅、GFW列表和 CHN路由表"
msgid "Subscribe URL"
msgstr "SS/SSR/V2/TROJAN订阅URL"
msgid "Subscribe Filter Words"
msgstr "订阅节点关键字过滤"
msgid "Filter Words splited by /"
msgstr "命中关键字的节点将被丢弃。多个关键字用 / 分隔"
msgid "Update"
msgstr "更新"
msgid "Server Count"
msgstr "服务器节点数量"
msgid "IP black-and-white list"
msgstr "黑白名单"
msgid "WAN IP AC"
msgstr "WAN IP访问控制"
msgid "WAN White List IP"
msgstr "不走代理的WAN IP"
msgid "WAN Force Proxy IP"
msgstr "强制走代理的WAN IP"
msgid "LAN Bypassed Host List"
msgstr "不走代理的局域网LAN IP"
msgid "LAN Force Proxy Host List"
msgstr "全局代理的LAN IP"
msgid "Router Self AC"
msgstr "路由器自身代理设置"
msgid "Router Self Proxy"
msgstr "路由器自身代理方式"
msgid "Normal Proxy"
msgstr "跟随全局设置"
msgid "Bypassed Proxy"
msgstr "不走代理"
msgid "Forwarded Proxy"
msgstr "全局代理"
msgid "GFW Custom List"
msgstr "GFW 用户自定义列表"
msgid "Please refer to the following writing"
msgstr "每行一个域名,无需写前面的 HTTP(S):// ,提交后即时生效"
msgid "Servers subscription and manage"
msgstr "服务器节点订阅与管理"
msgid "Through proxy update list, Not Recommended"
msgstr "通过路由器自身代理更新订阅"
msgid "LAN IP AC"
msgstr "LAN IP访问控制"
msgid "Game Mode UDP Server"
msgstr "游戏模式UDP中继服务器"
msgid "Game Mode UDP Relay"
msgstr "游戏模式UDP中继"
msgid "Server failsafe auto swith and custom update settings"
msgstr "服务器节点故障自动切换/广告屏蔽/国内IP段数据库更新设置"
msgid "Support AdGuardHome and DNSMASQ format list"
msgstr "同时支持 AdGuard Home 和 DNSMASQ 格式的过滤列表"
msgid "Delete All Subscribe Severs"
msgstr "删除所有订阅服务器节点"
msgid "Severs Nodes"
msgstr "服务器节点"
msgid "Use Local DNS Service listen port 5335"
msgstr "使用本机端口为5335的DNS服务"
msgid "Server Node Type"
msgstr "服务器节点类型"
msgid "Using incorrect encryption mothod may causes service fail to start"
msgstr "输入不正确的参数组合可能会导致服务无法启动"
msgid "Game Mode Host List"
msgstr "增强游戏模式客户端LAN IP"
msgid "Multi Threads Option"
msgstr "多线程并发转发"
msgid "Auto Threads"
msgstr "自动CPU线程数"
msgid "1 Thread"
msgstr "单线程"
msgid "2 Threads"
msgstr "2 线程"
msgid "4 Threads"
msgstr "4 线程"
msgid "8 Threads"
msgstr "8 线程"
msgid "16 Threads"
msgstr "16 线程"
msgid "32 Threads"
msgstr "32 线程"
msgid "64 Threads"
msgstr "64 线程"
msgid "128 Threads"
msgstr "128 线程"
msgid "Proxy Ports"
msgstr "需要代理的端口"
msgid "All Ports"
msgstr "所有端口(默认)"
msgid "Only Common Ports"
msgstr "仅常用端口不走P2P流量到代理"
msgid "Socket Connected"
msgstr "连接测试"
msgid "Ping Latency"
msgstr "Ping延迟"
msgid "Bypass Domain List"
msgstr "不走代理的域名"
msgid "Black Domain List"
msgstr "强制走代理的域名"
msgid "Update Subscribe List"
msgstr "更新订阅URL列表"
msgid "Update subscribe url list first"
msgstr "修改订阅URL和节点关键字后请先点击更新"
msgid "Update All Subscribe Severs"
msgstr "更新所有订阅服务器节点"
msgid "Plugin"
msgstr "插件"
msgid "Plugin Opts"
msgstr "插件参数"
msgid "Self-signed Certificate"
msgstr "自签证书"
msgid "If you have a self-signed certificate,please check the box"
msgstr "如果你使用自签证书,请选择"
msgid "upload"
msgstr "上传"
msgid "Upload"
msgstr "上传"
msgid "No specify upload file."
msgstr "没有上传证书"
msgid "Current Certificate Path"
msgstr "当前证书路径"
msgid "Please confirm the current certificate path"
msgstr "请选择确认所传证书,证书不正确将无法运行"
msgid "Subscribe Default Auto-Switch"
msgstr "订阅新节点自动切换设置"
msgid "Subscribe new add server default Auto-Switch on"
msgstr "订阅加入的新节点默认开启自动切换"
msgid "SOCKS5 Proxy Server Settings"
msgstr "SOCKS5 代理服务端设置"
msgid "SOCKS5 Proxy Server"
msgstr "SOCKS5 代理服务端"
msgid "Enable SOCKS5 Proxy Server"
msgstr "启用 SOCKS5 代理服务"
msgid "Enable Authentication"
msgstr "启用用户名/密码认证"
msgid "Enable SOCKS5 Proxy Server"
msgstr "启用 SOCKS5 代理服务"
msgid "Enable WAN Access"
msgstr "允许从 WAN 访问"
msgid "Redirect traffic to this network interface"
msgstr "分流到这个网络接口"
msgid "Netflix Node"
msgstr "Netflix 分流服务器"
msgid "Netflix Domain List"
msgstr "Netflix 分流域名列表"
msgid "Netflix IP List"
msgstr "Netflix 分流IP列表"
msgid "External Proxy Mode"
msgstr "分流服务器(前置)代理"
msgid "Forward Netflix Proxy through Main Proxy"
msgstr "分流服务器流量通过主服务节点中转代理转发"
msgid "Server Type"
msgstr "服务端类型"
msgid "Local Servers"
msgstr "本机服务端"
msgid "Global SOCKS5 Proxy Server"
msgstr "SOCKS5 代理服务端(全局)"

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
amazonaws.com
aws.amazon.com
awsstatic.com
fast.com
netflix.com
netflix.net
nflxext.com
nflximg.net
nflxso.net
nflxvideo.net
netflixdnstest0.com
netflixdnstest1.com
netflixdnstest2.com
netflixdnstest3.com
netflixdnstest4.com
netflixdnstest5.com
netflixdnstest6.com
netflixdnstest7.com
netflixdnstest8.com
netflixdnstest9.com
hulu.com
huluim.com
hbonow.com
hbogo.com
hbo.com

View File

@ -1,15 +0,0 @@
8.41.4.0/24
23.246.0.0/18
37.77.184.0/21
45.57.0.0/17
64.120.128.0/17
66.197.128.0/17
69.53.224.0/19
108.175.32.0/20
185.2.220.0/22
185.9.188.0/22
192.173.64.0/18
198.38.96.0/19
198.45.48.0/20
207.45.72.0/22
208.75.76.0/22

View File

@ -1,43 +0,0 @@
config global
option tunnel_forward '8.8.4.4:53'
option tunnel_address '0.0.0.0'
option run_mode 'router'
option dports '2'
option pdnsd_enable '1'
option monitor_enable '1'
option global_server 'nil'
option enable_switch '1'
option switch_timeout '5'
option switch_time '667'
option switch_try_count '3'
option gfwlist_url 'https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt'
option chnroute_url 'https://ispip.clang.cn/all_cn.txt'
option nfip_url 'https://raw.githubusercontent.com/QiuSimons/Netflix_IP/master/NF_only.txt'
option adblock_url 'https://gitee.com/privacy-protection-tools/anti-ad/raw/master/anti-ad-for-dnsmasq.conf'
option netflix_server 'same'
option threads '0'
config socks5_proxy
option socks '0'
option local_port '1080'
option local_address '0.0.0.0'
config access_control
option wan_bp_list '/etc/china_ssr.txt'
option lan_ac_mode 'b'
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'
config server_global
option enable_server '0'
config server_subscribe
option proxy '0'
option auto_update_time '2'
option auto_update '1'
option filter_words '过期时间/剩余流量/QQ群/官网/防失联地址/回国'

View File

@ -1,192 +0,0 @@
server=/v.youku.com/127.0.0.1#5335
server=/api.youku.com/127.0.0.1#5335
server=/v2.tudou.com/127.0.0.1#5335
server=/www.tudou.com/127.0.0.1#5335
server=/s.plcloud.music.qq.com/127.0.0.1#5335
server=/i.y.qq.com/127.0.0.1#5335
server=/hot.vrs.sohu.com/127.0.0.1#5335
server=/live.tv.sohu.com/127.0.0.1#5335
server=/pad.tv.sohu.com/127.0.0.1#5335
server=/my.tv.sohu.com/127.0.0.1#5335
server=/hot.vrs.letv.com/127.0.0.1#5335
server=/data.video.qiyi.com/127.0.0.1#5335
server=/cache.video.qiyi.com/127.0.0.1#5335
server=/cache.vip.qiyi.com/127.0.0.1#5335
server=/vv.video.qq.com/127.0.0.1#5335
server=/tt.video.qq.com/127.0.0.1#5335
server=/ice.video.qq.com/127.0.0.1#5335
server=/tjsa.video.qq.com/127.0.0.1#5335
server=/a10.video.qq.com/127.0.0.1#5335
server=/xyy.video.qq.com/127.0.0.1#5335
server=/vcq.video.qq.com/127.0.0.1#5335
server=/vsh.video.qq.com/127.0.0.1#5335
server=/vbj.video.qq.com/127.0.0.1#5335
server=/bobo.video.qq.com/127.0.0.1#5335
server=/flvs.video.qq.com/127.0.0.1#5335
server=/bkvv.video.qq.com/127.0.0.1#5335
server=/info.zb.qq.com/127.0.0.1#5335
server=/geo.js.kankan.xunlei.com/127.0.0.1#5335
server=/web-play.pptv.com/127.0.0.1#5335
server=/web-play.pplive.cn/127.0.0.1#5335
server=/dyn.ugc.pps.tv/127.0.0.1#5335
server=/v.pps.tv/127.0.0.1#5335
server=/inner.kandian.com/127.0.0.1#5335
server=/ipservice.163.com/127.0.0.1#5335
server=/so.open.163.com/127.0.0.1#5335
server=/zb.s.qq.com/127.0.0.1#5335
server=/ip.kankan.xunlei.com/127.0.0.1#5335
server=/vxml.56.com/127.0.0.1#5335
server=/music.sina.com.cn/127.0.0.1#5335
server=/play.baidu.com/127.0.0.1#5335
server=/v.iask.com/127.0.0.1#5335
server=/tv.weibo.com/127.0.0.1#5335
server=/wtv.v.iask.com/127.0.0.1#5335
server=/video.sina.com.cn/127.0.0.1#5335
server=/www.yinyuetai.com/127.0.0.1#5335
server=/api.letv.com/127.0.0.1#5335
server=/live.gslb.letv.com/127.0.0.1#5335
server=/static.itv.letv.com/127.0.0.1#5335
server=/ip.apps.cntv.cn/127.0.0.1#5335
server=/vdn.apps.cntv.cn/127.0.0.1#5335
server=/vdn.live.cntv.cn/127.0.0.1#5335
server=/vip.sports.cntv.cn/127.0.0.1#5335
server=/a.play.api.3g.youku.com/127.0.0.1#5335
server=/i.play.api.3g.youku.com/127.0.0.1#5335
server=/api.3g.youku.com/127.0.0.1#5335
server=/tv.api.3g.youku.com/127.0.0.1#5335
server=/play.api.3g.youku.com/127.0.0.1#5335
server=/play.api.3g.tudou.com/127.0.0.1#5335
server=/tv.api.3g.tudou.com/127.0.0.1#5335
server=/api.3g.tudou.com/127.0.0.1#5335
server=/api.tv.sohu.com/127.0.0.1#5335
server=/access.tv.sohu.com/127.0.0.1#5335
server=/iface.iqiyi.com/127.0.0.1#5335
server=/iface2.iqiyi.com/127.0.0.1#5335
server=/cache.m.iqiyi.com/127.0.0.1#5335
server=/dynamic.app.m.letv.com/127.0.0.1#5335
server=/dynamic.meizi.app.m.letv.com/127.0.0.1#5335
server=/dynamic.search.app.m.letv.com/127.0.0.1#5335
server=/dynamic.live.app.m.letv.com/127.0.0.1#5335
server=/listso.m.areainfo.ppstream.com/127.0.0.1#5335
server=/epg.api.pptv.com/127.0.0.1#5335
server=/play.api.pptv.com/127.0.0.1#5335
server=/m.letv.com/127.0.0.1#5335
server=/interface.bilibili.com/127.0.0.1#5335
server=/3g.music.qq.com/127.0.0.1#5335
server=/mqqplayer.3g.qq.com/127.0.0.1#5335
server=/proxy.music.qq.com/127.0.0.1#5335
server=/proxymc.qq.com/127.0.0.1#5335
server=/ip2.kugou.com/127.0.0.1#5335
server=/ip.kugou.com/127.0.0.1#5335
server=/client.api.ttpod.com/127.0.0.1#5335
server=/mobi.kuwo.cn/127.0.0.1#5335
server=/mobilefeedback.kugou.com/127.0.0.1#5335
server=/tingapi.ting.baidu.com/127.0.0.1#5335
server=/music.baidu.com/127.0.0.1#5335
server=/serviceinfo.sdk.duomi.com/127.0.0.1#5335
server=/music.163.com/127.0.0.1#5335
server=/www.xiami.com/127.0.0.1#5335
server=/spark.api.xiami.com/127.0.0.1#5335
server=/iplocation.geo.qiyi.com/127.0.0.1#5335
server=/sns.video.qq.com/127.0.0.1#5335
server=/v5.pc.duomi.com/127.0.0.1#5335
server=/tms.is.ysten.com/127.0.0.1#5335
server=/internal.check.duokanbox.com/127.0.0.1#5335
server=/openapi.youku.com/127.0.0.1#5335
server=/y.qq.com/127.0.0.1#5335
ipset=/v.youku.com/oversea
ipset=/api.youku.com/oversea
ipset=/v2.tudou.com/oversea
ipset=/www.tudou.com/oversea
ipset=/s.plcloud.music.qq.com/oversea
ipset=/i.y.qq.com/oversea
ipset=/hot.vrs.sohu.com/oversea
ipset=/live.tv.sohu.com/oversea
ipset=/pad.tv.sohu.com/oversea
ipset=/my.tv.sohu.com/oversea
ipset=/hot.vrs.letv.com/oversea
ipset=/data.video.qiyi.com/oversea
ipset=/cache.video.qiyi.com/oversea
ipset=/cache.vip.qiyi.com/oversea
ipset=/vv.video.qq.com/oversea
ipset=/tt.video.qq.com/oversea
ipset=/ice.video.qq.com/oversea
ipset=/tjsa.video.qq.com/oversea
ipset=/a10.video.qq.com/oversea
ipset=/xyy.video.qq.com/oversea
ipset=/vcq.video.qq.com/oversea
ipset=/vsh.video.qq.com/oversea
ipset=/vbj.video.qq.com/oversea
ipset=/bobo.video.qq.com/oversea
ipset=/flvs.video.qq.com/oversea
ipset=/bkvv.video.qq.com/oversea
ipset=/info.zb.qq.com/oversea
ipset=/geo.js.kankan.xunlei.com/oversea
ipset=/web-play.pptv.com/oversea
ipset=/web-play.pplive.cn/oversea
ipset=/dyn.ugc.pps.tv/oversea
ipset=/v.pps.tv/oversea
ipset=/inner.kandian.com/oversea
ipset=/ipservice.163.com/oversea
ipset=/so.open.163.com/oversea
ipset=/zb.s.qq.com/oversea
ipset=/ip.kankan.xunlei.com/oversea
ipset=/vxml.56.com/oversea
ipset=/music.sina.com.cn/oversea
ipset=/play.baidu.com/oversea
ipset=/v.iask.com/oversea
ipset=/tv.weibo.com/oversea
ipset=/wtv.v.iask.com/oversea
ipset=/video.sina.com.cn/oversea
ipset=/www.yinyuetai.com/oversea
ipset=/api.letv.com/oversea
ipset=/live.gslb.letv.com/oversea
ipset=/static.itv.letv.com/oversea
ipset=/ip.apps.cntv.cn/oversea
ipset=/vdn.apps.cntv.cn/oversea
ipset=/vdn.live.cntv.cn/oversea
ipset=/vip.sports.cntv.cn/oversea
ipset=/a.play.api.3g.youku.com/oversea
ipset=/i.play.api.3g.youku.com/oversea
ipset=/api.3g.youku.com/oversea
ipset=/tv.api.3g.youku.com/oversea
ipset=/play.api.3g.youku.com/oversea
ipset=/play.api.3g.tudou.com/oversea
ipset=/tv.api.3g.tudou.com/oversea
ipset=/api.3g.tudou.com/oversea
ipset=/api.tv.sohu.com/oversea
ipset=/access.tv.sohu.com/oversea
ipset=/iface.iqiyi.com/oversea
ipset=/iface2.iqiyi.com/oversea
ipset=/cache.m.iqiyi.com/oversea
ipset=/dynamic.app.m.letv.com/oversea
ipset=/dynamic.meizi.app.m.letv.com/oversea
ipset=/dynamic.search.app.m.letv.com/oversea
ipset=/dynamic.live.app.m.letv.com/oversea
ipset=/listso.m.areainfo.ppstream.com/oversea
ipset=/epg.api.pptv.com/oversea
ipset=/play.api.pptv.com/oversea
ipset=/m.letv.com/oversea
ipset=/interface.bilibili.com/oversea
ipset=/3g.music.qq.com/oversea
ipset=/mqqplayer.3g.qq.com/oversea
ipset=/proxy.music.qq.com/oversea
ipset=/proxymc.qq.com/oversea
ipset=/ip2.kugou.com/oversea
ipset=/ip.kugou.com/oversea
ipset=/client.api.ttpod.com/oversea
ipset=/mobi.kuwo.cn/oversea
ipset=/mobilefeedback.kugou.com/oversea
ipset=/tingapi.ting.baidu.com/oversea
ipset=/music.baidu.com/oversea
ipset=/serviceinfo.sdk.duomi.com/oversea
ipset=/music.163.com/oversea
ipset=/www.xiami.com/oversea
ipset=/spark.api.xiami.com/oversea
ipset=/iplocation.geo.qiyi.com/oversea
ipset=/sns.video.qq.com/oversea
ipset=/v5.pc.duomi.com/oversea
ipset=/tms.is.ysten.com/oversea
ipset=/internal.check.duokanbox.com/oversea
ipset=/openapi.youku.com/oversea
ipset=/y.qq.com/oversea

View File

@ -1,108 +0,0 @@
ipset=/.91smartyun.pt/gfwlist
ipset=/.adobe.com/gfwlist
ipset=/.amazonaws.com/gfwlist
ipset=/.ampproject.org/gfwlist
ipset=/.apple.news/gfwlist
ipset=/.aws.amazon.com/gfwlist
ipset=/.azureedge.net/gfwlist
ipset=/.backpackers.com.tw/gfwlist
ipset=/.bitfinex.com/gfwlist
ipset=/.buzzfeed.com/gfwlist
ipset=/.clockwise.ee/gfwlist
ipset=/.cloudfront.net/gfwlist
ipset=/.coindesk.com/gfwlist
ipset=/.coinsquare.io/gfwlist
ipset=/.cryptocompare.com/gfwlist
ipset=/.dropboxstatic.com/gfwlist
ipset=/.eurecom.fr/gfwlist
ipset=/.gdax.com/gfwlist
ipset=/.github.com/gfwlist
ipset=/.kknews.cc/gfwlist
ipset=/.nutaq.com/gfwlist
ipset=/.openairinterface.org/gfwlist
ipset=/.skype.com/gfwlist
ipset=/.sublimetext.com/gfwlist
ipset=/.textnow.com/gfwlist
ipset=/.textnow.me/gfwlist
ipset=/.trouter.io/gfwlist
ipset=/.t66y.com/gfwlist
ipset=/.uploaded.net/gfwlist
ipset=/.whatsapp.com/gfwlist
ipset=/.whatsapp.net/gfwlist
ipset=/.wsj.net/gfwlist
ipset=/.google.com/gfwlist
ipset=/.google.com.hk/gfwlist
ipset=/.gstatic.com/gfwlist
ipset=/.googleusercontent.com/gfwlist
ipset=/.googlepages.com/gfwlist
ipset=/.googlevideo.com/gfwlist
ipset=/.googlecode.com/gfwlist
ipset=/.googleapis.com/gfwlist
ipset=/.googlesource.com/gfwlist
ipset=/.googledrive.com/gfwlist
ipset=/.ggpht.com/gfwlist
ipset=/.youtube.com/gfwlist
ipset=/.youtu.be/gfwlist
ipset=/.ytimg.com/gfwlist
ipset=/.twitter.com/gfwlist
ipset=/.facebook.com/gfwlist
ipset=/.fastly.net/gfwlist
ipset=/.akamai.net/gfwlist
ipset=/.akamaiedge.net/gfwlist
ipset=/.akamaihd.net/gfwlist
ipset=/.edgesuite.net/gfwlist
ipset=/.edgekey.net/gfwlist
server=/.91smartyun.pt/127.0.0.1#5335
server=/.adobe.com/127.0.0.1#5335
server=/.amazonaws.com/127.0.0.1#5335
server=/.ampproject.org/127.0.0.1#5335
server=/.apple.news/127.0.0.1#5335
server=/.aws.amazon.com/127.0.0.1#5335
server=/.azureedge.net/127.0.0.1#5335
server=/.backpackers.com.tw/127.0.0.1#5335
server=/.bitfinex.com/127.0.0.1#5335
server=/.buzzfeed.com/127.0.0.1#5335
server=/.clockwise.ee/127.0.0.1#5335
server=/.cloudfront.net/127.0.0.1#5335
server=/.coindesk.com/127.0.0.1#5335
server=/.coinsquare.io/127.0.0.1#5335
server=/.cryptocompare.com/127.0.0.1#5335
server=/.dropboxstatic.com/127.0.0.1#5335
server=/.eurecom.fr/127.0.0.1#5335
server=/.gdax.com/127.0.0.1#5335
server=/.github.com/127.0.0.1#5335
server=/.kknews.cc/127.0.0.1#5335
server=/.nutaq.com/127.0.0.1#5335
server=/.openairinterface.org/127.0.0.1#5335
server=/.skype.com/127.0.0.1#5335
server=/.sublimetext.com/127.0.0.1#5335
server=/.textnow.com/127.0.0.1#5335
server=/.textnow.me/127.0.0.1#5335
server=/.trouter.io/127.0.0.1#5335
server=/.t66y.com/127.0.0.1#5335
server=/.uploaded.net/127.0.0.1#5335
server=/.whatsapp.com/127.0.0.1#5335
server=/.whatsapp.net/127.0.0.1#5335
server=/.wsj.net/127.0.0.1#5335
server=/.google.com/127.0.0.1#5335
server=/.google.com.hk/127.0.0.1#5335
server=/.gstatic.com/127.0.0.1#5335
server=/.googleusercontent.com/127.0.0.1#5335
server=/.googlepages.com/127.0.0.1#5335
server=/.googlevideo.com/127.0.0.1#5335
server=/.googlecode.com/127.0.0.1#5335
server=/.googleapis.com/127.0.0.1#5335
server=/.googlesource.com/127.0.0.1#5335
server=/.googledrive.com/127.0.0.1#5335
server=/.ggpht.com/127.0.0.1#5335
server=/.youtube.com/127.0.0.1#5335
server=/.youtu.be/127.0.0.1#5335
server=/.ytimg.com/127.0.0.1#5335
server=/.twitter.com/127.0.0.1#5335
server=/.facebook.com/127.0.0.1#5335
server=/.fastly.net/127.0.0.1#5335
server=/.akamai.net/127.0.0.1#5335
server=/.akamaiedge.net/127.0.0.1#5335
server=/.akamaihd.net/127.0.0.1#5335
server=/.edgesuite.net/127.0.0.1#5335
server=/.edgekey.net/127.0.0.1#5335

View File

@ -1,754 +0,0 @@
#!/bin/sh /etc/rc.common
#
# Copyright (C) 2017 openwrt-ssr
# Copyright (C) 2017 yushi studio <ywb94@qq.com>
# Copyright (C) 2018 lean <coolsnowwolf@gmail.com>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
START=95
STOP=15
SERVICE_DAEMONIZE=1
NAME=shadowsocksr
EXTRA_COMMANDS=rules
CONFIG_FILE=/var/etc/${NAME}.json
CONFIG_UDP_FILE=/var/etc/${NAME}_u.json
CONFIG_SOCK5_FILE=/var/etc/${NAME}_s.json
CONFIG_NETFLIX_FILE=/var/etc/${NAME}_n.json
server_count=0
redir_tcp=0
redir_udp=0
tunnel_enable=0
local_enable=0
kcp_enable_flag=0
kcp_flag=0
pdnsd_enable_flag=0
switch_enable=0
switch_server=$1
MAXFD=32768
CRON_FILE=/etc/crontabs/root
threads=1
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}
}
uci_get_by_cfgid() {
local ret=$(uci show $NAME.@$1[0].$2 | awk -F '.' '{print $2}' 2>/dev/null)
echo ${ret:=$3}
}
check_host() {
local host=$1
if echo $host | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
hostip=$host
elif [ "$host" != "${host#*:[0-9a-fA-F]}" ]; then
hostip=$host
else
hostip=$(ping $host -W 1 -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1)
if echo $hostip | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
hostip=$hostip
else
hostip="127.0.0.1"
fi
fi
echo -e $hostip
}
add_cron() {
sed -i '/shadowsocksr/d' $CRON_FILE
sed -i '/ssrplus.log/d' $CRON_FILE && echo '0 1 * * * echo "" > /tmp/ssrplus.log' >>$CRON_FILE
[ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/share/shadowsocksr/ssrplusupdate.sh >> /tmp/ssrplus.log 2>&1" >>$CRON_FILE
crontab $CRON_FILE
}
del_cron() {
sed -i '/shadowsocksr/d' $CRON_FILE
sed -i '/ssrplus.log/d' $CRON_FILE
/etc/init.d/cron restart
}
run_mode=$(uci_get_by_type global run_mode)
gen_config_file() {
local host=$(uci_get_by_name $1 server)
if echo $host | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
hostip=$host
elif [ "$host" != "${host#*:[0-9a-fA-F]}" ]; then
hostip=$host
else
hostip=$(ping $host -W 1 -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1)
if echo $hostip | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
hostip=$hostip
else
hostip=$(cat /etc/ssr_ip)
fi
fi
[ "$2" == "0" -a "$kcp_flag" == "1" ] && hostip="127.0.0.1"
if [ "$2" == "0" ]; then
config_file=$CONFIG_FILE
elif [ "$2" == "1" ]; then
config_file=$CONFIG_UDP_FILE
elif [ "$2" == "2" ]; then
config_file=$CONFIG_NETFLIX_FILE
else
config_file=$CONFIG_SOCK5_FILE
fi
if [ $(uci_get_by_name $1 fast_open 0) == "1" ]; then
fastopen="true"
else
fastopen="false"
fi
local stype=$(uci_get_by_name $1 type)
if [ "$stype" == "ss" ]; then
cat <<-EOF >$config_file
{
"server": "$hostip",
"server_port": $(uci_get_by_name $1 server_port),
"local_address": "0.0.0.0",
"local_port": $3,
"password": "$(uci_get_by_name $1 password)",
"timeout": $(uci_get_by_name $1 timeout 60),
"method": "$(uci_get_by_name $1 encrypt_method_ss)",
"reuse_port": true,
"fast_open": $fastopen
}
EOF
local plugin=$(uci_get_by_name $1 plugin)
if [ -n "$plugin" ]; then
if [ "$plugin" == "simple-obfs" ]; then
plugin="obfs-local"
fi
if [ -x "/usr/bin/$plugin" ]; then
sed -i "s@$hostip\",@$hostip\",\n\"plugin\": \"$plugin\",\n\"plugin_opts\": \"$(uci_get_by_name $1 plugin_opts)\",@" $config_file
else
echo "$(date "+%Y-%m-%d %H:%M:%S") Warning!!! SIP003 plugin $plugin not found!!!" >>/tmp/ssrplus.log
fi
fi
elif [ "$stype" == "ssr" ]; then
cat <<-EOF >$config_file
{
"server": "$hostip",
"server_port": $(uci_get_by_name $1 server_port),
"local_address": "0.0.0.0",
"local_port": $3,
"password": "$(uci_get_by_name $1 password)",
"timeout": $(uci_get_by_name $1 timeout 60),
"method": "$(uci_get_by_name $1 encrypt_method)",
"protocol": "$(uci_get_by_name $1 protocol)",
"protocol_param": "$(uci_get_by_name $1 protocol_param)",
"obfs": "$(uci_get_by_name $1 obfs)",
"obfs_param": "$(uci_get_by_name $1 obfs_param)",
"reuse_port": true,
"fast_open": $fastopen
}
EOF
elif [ "$stype" == "v2ray" ]; then
lua /usr/share/shadowsocksr/genv2config.lua $GLOBAL_SERVER tcp $(uci_get_by_name $1 local_port) >/var/etc/v2-ssr-retcp.json
sed -i 's/\\//g' /var/etc/v2-ssr-retcp.json
elif [ "$stype" == "trojan" ]; then
lua /usr/share/shadowsocksr/gentrojanconfig.lua $GLOBAL_SERVER nat $(uci_get_by_name $1 local_port) >/var/etc/trojan-ssr-retcp.json
sed -i 's/\\//g' /var/etc/trojan-ssr-retcp.json
fi
}
get_arg_out() {
case "$(uci_get_by_type access_control router_proxy 1)" in
1) echo "-o" ;;
2) echo "-O" ;;
esac
}
start_rules() {
local server=$(uci_get_by_name $GLOBAL_SERVER server)
#resolve name
if echo $server | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
server=$server
elif [ "$server" != "${server#*:[0-9a-fA-F]}" ]; then
server=$server
else
server=$(ping $server -W 1 -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1)
if echo $server | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
echo $server >/etc/ssr_ip
else
server=$(cat /etc/ssr_ip)
fi
fi
kcp_server=$server
local kcp_enable=$(uci_get_by_name $GLOBAL_SERVER kcp_enable 0)
if [ $kcp_enable == "1" ]; then
kcp_flag=1
fi
local local_port=$(uci_get_by_name $GLOBAL_SERVER local_port)
local lan_ac_ips=$(uci_get_by_type access_control lan_ac_ips)
local lan_ac_mode=$(uci_get_by_type access_control lan_ac_mode)
local router_proxy=$(uci_get_by_type access_control router_proxy)
if [ "$GLOBAL_SERVER" == "$UDP_RELAY_SERVER" -a "$kcp_flag" == "0" ]; then
ARG_UDP="-u"
elif [ -n "$UDP_RELAY_SERVER" ]; then
ARG_UDP="-U"
local udp_server=$(uci_get_by_name $UDP_RELAY_SERVER server)
local udp_local_port=$(uci_get_by_name $UDP_RELAY_SERVER local_port)
fi
if [ -n "$lan_ac_ips" ]; then
case "$lan_ac_mode" in
w | W | b | B) local ac_ips="$lan_ac_mode$lan_ac_ips" ;;
esac
fi
#deal gfw firewall rule
local gfwmode=""
if [ "$run_mode" == "gfw" ]; then
gfwmode="-g"
elif [ "$run_mode" == "router" ]; then
gfwmode="-r"
elif [ "$run_mode" == "oversea" ]; then
gfwmode="-c"
elif [ "$run_mode" == "all" ]; then
gfwmode="-z"
fi
local dports=$(uci_get_by_type global dports 1)
if [ $dports == "1" ]; then
proxyport=" "
else
proxyport="-m multiport --dports 22,53,587,465,995,993,143,80,443"
fi
if [ "$NETFLIX_SERVER" != "nil" ]; then
if [ "$NETFLIX_SERVER" != "$GLOBAL_SERVER" ]; then
netflix="1"
else
netflix="2"
fi
else
netflix="0"
fi
netflix_ip=$(check_host $(uci_get_by_name $NETFLIX_SERVER server 127.0.0.1))
/usr/bin/ssr-rules \
-s "$server" \
-l "$local_port" \
-S "$udp_server" \
-L "$udp_local_port" \
-a "$ac_ips" \
-i "$(uci_get_by_type access_control wan_bp_list)" \
-b "$(uci_get_by_type access_control wan_bp_ips)" \
-w "$(uci_get_by_type access_control wan_fw_ips)" \
-B "$(uci_get_by_type access_control lan_bp_ips)" \
-p "$(uci_get_by_type access_control lan_fp_ips)" \
-G "$(uci_get_by_type access_control lan_gm_ips)" \
-D "$proxyport" \
-F "$netflix" \
-N "$netflix_ip" \
-M "$(uci_get_by_type global netflix_proxy 0)" \
$(get_arg_out) $gfwmode $ARG_UDP
return $?
}
start_pdnsd() {
local usr_dns="$1"
local usr_port="$2"
local tcp_dns_list="208.67.222.222, 208.67.220.220"
[ -z "$usr_dns" ] && usr_dns="8.8.8.8"
[ -z "$usr_port" ] && usr_port="53"
[ -d /var/etc ] || mkdir -p /var/etc
if [ ! -d /var/pdnsd ]; then
mkdir -p /var/pdnsd
echo -ne "pd13\000\000\000\000" >/var/pdnsd/pdnsd.cache
chown -R nobody:nogroup /var/pdnsd
fi
cat <<-EOF >/var/etc/pdnsd.conf
global{
perm_cache=1024;
cache_dir="/var/pdnsd";
pid_file="/var/run/pdnsd.pid";
run_as="nobody";
server_ip=127.0.0.1;
server_port=5335;
status_ctl=on;
query_method=tcp_only;
min_ttl=1h;
max_ttl=1w;
timeout=10;
neg_domain_pol=on;
proc_limit=2;
procq_limit=8;
par_queries=1;
}
server{
label="ssr-usrdns";
ip=$usr_dns;
port=$usr_port;
timeout=6;
uptest=none;
interval=10m;
purge_cache=off;
}
EOF
/usr/sbin/pdnsd -c /var/etc/pdnsd.conf &
}
start_redir() {
case "$(uci_get_by_name $GLOBAL_SERVER auth_enable)" in
1 | on | true | yes | enabled) ARG_OTA="-A" ;;
*) ARG_OTA="" ;;
esac
#deal kcp
local kcp_enable=$(uci_get_by_name $GLOBAL_SERVER kcp_enable 0)
if [ "$kcp_enable" == "1" ]; then
[ ! -f "/usr/bin/kcptun-client" ] && return 1
local kcp_str=$(/usr/bin/kcptun-client -v | grep kcptun | wc -l)
[ "0" == "$kcp_str" ] && return 1
local kcp_port=$(uci_get_by_name $GLOBAL_SERVER kcp_port)
local server_port=$(uci_get_by_name $GLOBAL_SERVER server_port)
local password=$(uci_get_by_name $GLOBAL_SERVER kcp_password)
local kcp_param=$(uci_get_by_name $GLOBAL_SERVER kcp_param)
[ "$password" != "" ] && password="--key "$password
service_start /usr/bin/kcptun-client \
-r $kcp_server:$kcp_port \
-l :$server_port $password $kcp_param
kcp_enable_flag=1
fi
gen_config_file $GLOBAL_SERVER 0 $(uci_get_by_name $GLOBAL_SERVER local_port 1234)
local stype=$(uci_get_by_name $GLOBAL_SERVER type)
if [ "$stype" == "ss" ]; then
sscmd="/usr/bin/ss-redir"
elif [ "$stype" == "ssr" ]; then
sscmd="/usr/bin/ssr-redir"
elif [ "$stype" == "v2ray" ]; then
sscmd="/usr/bin/v2ray/v2ray"
[ ! -f "$sscmd" ] && sscmd="/usr/bin/v2ray"
elif [ "$stype" == "trojan" ]; then
sscmd="/usr/sbin/trojan"
elif [ "$stype" == "socks5" ]; then
sscmd="/usr/sbin/redsocks2"
elif [ "$stype" == "tun" ]; then
sscmd="/usr/sbin/redsocks2"
fi
local ntype=$(uci_get_by_name $NETFLIX_SERVER type)
if [ "$ntype" == "ss" ]; then
ncmd="/usr/bin/ss-redir"
sssock="/usr/bin/ss-local"
elif [ "$ntype" == "ssr" ]; then
ncmd="/usr/bin/ssr-redir"
sssock="/usr/bin/ssr-local"
elif [ "$ntype" == "v2ray" ]; then
ncmd="/usr/bin/v2ray/v2ray"
[ ! -f "$ncmd" ] && ncmd="/usr/bin/v2ray"
elif [ "$ntype" == "trojan" ]; then
ncmd="/usr/sbin/trojan"
elif [ "$ntype" == "socks5" ]; then
ncmd="/usr/sbin/redsocks2"
elif [ "$ntype" == "tun" ]; then
ncmd="/usr/sbin/redsocks2"
fi
local utype=$(uci_get_by_name $UDP_RELAY_SERVER type)
if [ "$utype" == "ss" ]; then
ucmd="/usr/bin/ss-redir"
elif [ "$utype" == "ssr" ]; then
ucmd="/usr/bin/ssr-redir"
elif [ "$utype" == "v2ray" ]; then
ucmd="/usr/bin/v2ray/v2ray"
[ ! -f "$ucmd" ] && ucmd="/usr/bin/v2ray"
elif [ "$utype" == "trojan" ]; then
ucmd="/usr/sbin/trojan"
elif [ "$stype" == "socks5" ]; then
ucmd="/usr/sbin/redsocks2"
elif [ "$stype" == "tun" ]; then
ucmd="/usr/sbin/redsocks2"
fi
if [ "$(uci_get_by_type global threads 0)" == "0" ]; then
threads=$(cat /proc/cpuinfo | grep 'processor' | wc -l)
else
threads=$(uci_get_by_type global threads)
fi
if [ "$stype" == "ss" -o "$stype" == "ssr" ]; then
local last_config_file=$CONFIG_FILE
local pid_file="/var/run/ssr-retcp.pid"
for i in $(seq 1 $threads); do
$sscmd -c $CONFIG_FILE $ARG_OTA -f /var/run/ssr-retcp_$i.pid >/dev/null 2>&1
done
echo "$(date "+%Y-%m-%d %H:%M:%S") Shadowsocks/ShadowsocksR $threads Threads Started!" >>/tmp/ssrplus.log
elif [ "$stype" == "v2ray" ]; then
$sscmd -config /var/etc/v2-ssr-retcp.json >/dev/null 2>&1 &
echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd -version | head -1) Started!" >>/tmp/ssrplus.log
elif [ "$stype" == "trojan" ]; then
for i in $(seq 1 $threads); do
$sscmd --config /var/etc/trojan-ssr-retcp.json >/dev/null 2>&1 &
done
echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd --version 2>&1 | head -1) , $threads Threads Started!" >>/tmp/ssrplus.log
elif [ "$stype" == "socks5" ]; then
/usr/share/shadowsocksr/genred2config.sh "/var/etc/redsocks-ssr-retcp.conf" socks5 tcp $(uci_get_by_name $GLOBAL_SERVER local_port) \
$(check_host $(uci_get_by_name $GLOBAL_SERVER server)) $(uci_get_by_name $GLOBAL_SERVER server_port) \
$(uci_get_by_name $GLOBAL_SERVER auth_enable 0) $(uci_get_by_name $GLOBAL_SERVER username) $(uci_get_by_name $GLOBAL_SERVER password)
for i in $(seq 1 $threads); do
$sscmd -c /var/etc/redsocks-ssr-retcp.conf >/dev/null 2>&1
done
echo "$(date "+%Y-%m-%d %H:%M:%S") Socks5 REDIRECT/TPROXY $threads Threads Started!" >>/tmp/ssrplus.log
elif [ "$stype" == "tun" ]; then
/usr/share/shadowsocksr/genred2config.sh "/var/etc/redsocks-ssr-retcp.conf" vpn $(uci_get_by_name $GLOBAL_SERVER iface "br-lan") $(uci_get_by_name $GLOBAL_SERVER local_port)
for i in $(seq 1 $threads); do
$sscmd -c /var/etc/redsocks-ssr-retcp.conf >/dev/null 2>&1
done
echo "$(date "+%Y-%m-%d %H:%M:%S") Network Tunnel REDIRECT $threads Threads Started!" >>/tmp/ssrplus.log
fi
if [ "$NETFLIX_SERVER" != "nil" ] && [ "$NETFLIX_SERVER" != "$GLOBAL_SERVER" ]; then
if [ "$ntype" == "ss" -o "$ntype" == "ssr" ]; then
gen_config_file $NETFLIX_SERVER 2 4321
gen_config_file $NETFLIX_SERVER 3 1088
$sssock -c /var/etc/shadowsocksr_s.json $ARG_OTA -f /var/run/ssr-socksdns.pid >/dev/null 2>&1
dns2socks 127.0.0.1:1088 8.8.8.8:53 127.0.0.1:5555 -q >/dev/null 2>&1 &
$ncmd -c /var/etc/shadowsocksr_n.json $ARG_OTA -f /var/run/ssr-netflix.pid >/dev/null 2>&1
elif [ "$ntype" == "v2ray" ]; then
lua /usr/share/shadowsocksr/genv2config.lua $NETFLIX_SERVER tcp 4321 1088 >/var/etc/v2-ssr-netflix.json
$ncmd -config /var/etc/v2-ssr-netflix.json >/dev/null 2>&1 &
dns2socks 127.0.0.1:1088 8.8.8.8:53 127.0.0.1:5555 -q >/dev/null 2>&1 &
elif [ "$ntype" == "trojan" ]; then
lua /usr/share/shadowsocksr/gentrojanconfig.lua $NETFLIX_SERVER nat 4321 >/var/etc/trojan-ssr-netflix.json
sed -i 's/\\//g' /var/etc/trojan-ssr-netflix.json
$ncmd --config /var/etc/trojan-ssr-netflix.json >/dev/null 2>&1 &
lua /usr/share/shadowsocksr/gentrojanconfig.lua $NETFLIX_SERVER client 1088 >/var/etc/trojan-ssr-socksdns.json
sed -i 's/\\//g' /var/etc/trojan-ssr-socksdns.json
$ncmd --config /var/etc/trojan-ssr-socksdns.json >/dev/null 2>&1 &
dns2socks 127.0.0.1:1088 8.8.8.8:53 127.0.0.1:5555 -q >/dev/null 2>&1 &
elif [ "$ntype" == "socks5" ]; then
/usr/share/shadowsocksr/genred2config.sh "/var/etc/redsocks-ssr-netflix.conf" socks5 tcp 4321 \
$(check_host $(uci_get_by_name $NETFLIX_SERVER server)) $(uci_get_by_name $NETFLIX_SERVER server_port) \
$(uci_get_by_name $NETFLIX_SERVER auth_enable 0) $(uci_get_by_name $NETFLIX_SERVER username) $(uci_get_by_name $NETFLIX_SERVER password)
$ncmd -c /var/etc/redsocks-ssr-netflix.conf >/dev/null 2>&1
microsocks -i 127.0.0.1 -p 1088 ssr-socksdns >/dev/null 2>&1 &
dns2socks 127.0.0.1:1088 8.8.8.8:53 127.0.0.1:5555 -q >/dev/null 2>&1 &
elif [ "$ntype" == "tun" ]; then
/usr/share/shadowsocksr/genred2config.sh "/var/etc/redsocks-ssr-netflix.conf" vpn $(uci_get_by_name $NETFLIX_SERVER iface "br-lan") 4321
$ncmd -c /var/etc/redsocks-ssr-netflix.conf >/dev/null 2>&1
microsocks -i 127.0.0.1 -p 1088 ssr-socksdns >/dev/null 2>&1 &
dns2socks 127.0.0.1:1088 8.8.8.8:53 127.0.0.1:5555 -q >/dev/null 2>&1 &
fi
fi
if [ -n "$UDP_RELAY_SERVER" ]; then
if [ "$utype" == "ss" -o "$utype" == "ssr" ]; then
case "$(uci_get_by_name $UDP_RELAY_SERVER auth_enable)" in
1 | on | true | yes | enabled) ARG_OTA="-A" ;;
*) ARG_OTA="" ;;
esac
gen_config_file $UDP_RELAY_SERVER 1 $(uci_get_by_name $UDP_RELAY_SERVER local_port 1234)
last_config_file=$CONFIG_UDP_FILE
pid_file="/var/run/ssr-reudp.pid"
$ucmd -c $last_config_file $ARG_OTA -U -f /var/run/ssr-reudp.pid >/dev/null 2>&1
elif [ "$utype" == "v2ray" ]; then
lua /usr/share/shadowsocksr/genv2config.lua $UDP_RELAY_SERVER udp $(uci_get_by_name $UDP_RELAY_SERVER local_port) >/var/etc/v2-ssr-reudp.json
sed -i 's/\\//g' /var/etc/v2-ssr-reudp.json
$ucmd -config /var/etc/v2-ssr-reudp.json >/dev/null 2>&1 &
elif [ "$stype" == "trojan" ]; then
lua /usr/share/shadowsocksr/gentrojanconfig.lua $GLOBAL_SERVER client 10801 >/var/etc/trojan-ssr-reudp.json
sed -i 's/\\//g' /var/etc/trojan-ssr-reudp.json
$ucmd --config /var/etc/trojan-ssr-reudp.json >/dev/null 2>&1 &
ipt2socks -U -b 0.0.0.0 -4 -s 127.0.0.1 -p 10801 -l $(uci_get_by_name $UDP_RELAY_SERVER local_port) >/dev/null 2>&1 &
elif [ "$utype" == "socks5" ]; then
/usr/share/shadowsocksr/genred2config.sh "/var/etc/redsocks-ssr-reudp.conf" socks5 udp $(uci_get_by_name $UDP_RELAY_SERVER local_port) \
$(check_host $(uci_get_by_name $UDP_RELAY_SERVER server)) $(uci_get_by_name $UDP_RELAY_SERVER server_port) \
$(uci_get_by_name $UDP_RELAY_SERVER auth_enable 0) $(uci_get_by_name $UDP_RELAY_SERVER username) $(uci_get_by_name $UDP_RELAY_SERVER password)
$ucmd -c /var/etc/redsocks-ssr-reudp.conf >/dev/null 2>&1
elif [ "$stype" == "tun" ]; then
redir_udp=0
echo "$(date "+%Y-%m-%d %H:%M:%S") Network Tunnel UDP TPROXY Relay not supported!" >>/tmp/ssrplus.log
fi
fi
#deal with dns
local ssr_dns="$(uci_get_by_type global pdnsd_enable 0)"
local dnsstr="$(uci_get_by_type global tunnel_forward 8.8.4.4:53)"
local dnsserver=$(echo "$dnsstr" | awk -F ':' '{print $1}')
local dnsport=$(echo "$dnsstr" | awk -F ':' '{print $2}')
if [ "$ssr_dns" != "0" ]; then # not use custom dns service
if [ "$run_mode" == "gfw" ]; then
ipset add gfwlist $dnsserver 2>/dev/null
elif [ "$run_mode" == "oversea" ]; then
ipset add oversea $dnsserver 2>/dev/null
else
ipset add ss_spec_wan_ac $dnsserver nomatch 2>/dev/null
fi
fi
if [ "$ssr_dns" == "1" ]; then
start_pdnsd $dnsserver $dnsport
pdnsd_enable_flag=1
elif [ "$ssr_dns" == "2" ]; then
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 &
pdnsd_enable_flag=2
fi
if [ "$(uci_get_by_type global enable_switch)" == "1" ]; then
if [ "$(uci_get_by_name $GLOBAL_SERVER switch_enable 1)" == "1" ]; then
if [ -z "$switch_server" ]; then
local switch_time=$(uci_get_by_type global switch_time)
local switch_timeout=$(uci_get_by_type global switch_timeout)
service_start /usr/bin/ssr-switch start $switch_time $switch_timeout
switch_enable=1
fi
fi
fi
add_cron
return $?
}
gen_service_file() {
if [ $(uci_get_by_name $1 fast_open) == "1" ]; then
fastopen="true"
else
fastopen="false"
fi
cat <<-EOF >$2
{
"server": "0.0.0.0",
"server_port": $(uci_get_by_name $1 server_port),
"password": "$(uci_get_by_name $1 password)",
"timeout": $(uci_get_by_name $1 timeout 60),
"method": "$(uci_get_by_name $1 encrypt_method)",
"protocol": "$(uci_get_by_name $1 protocol)",
"protocol_param": "$(uci_get_by_name $1 protocol_param)",
"obfs": "$(uci_get_by_name $1 obfs)",
"obfs_param": "$(uci_get_by_name $1 obfs_param)",
"fast_open": $fastopen
}
EOF
}
start_service() {
[ $(uci_get_by_name $1 enable 0) == "0" ] && return 1
let server_count=server_count+1
if [ "$server_count" == "1" ]; then
if ! (iptables-save -t filter | grep SSR-SERVER-RULE >/dev/null); then
iptables -N SSR-SERVER-RULE && \
iptables -t filter -I INPUT -j SSR-SERVER-RULE
fi
fi
if [ "$(uci_get_by_name $1 type ssr)" == "ssr" ]; then
gen_service_file $1 /var/etc/${NAME}_$server_count.json
/usr/bin/ssr-server -c /var/etc/${NAME}_$server_count.json -u -f /var/run/ssr-server$server_count.pid >/dev/null 2>&1
else
microsocks -i :: -p $(uci_get_by_name $1 server_port) -1 -u $(uci_get_by_name $1 username) -P $(uci_get_by_name $1 password) ssr-server$server_count >/dev/null 2>&1 &
fi
iptables -t filter -A SSR-SERVER-RULE -p tcp --dport $(uci_get_by_name $1 server_port) -j ACCEPT
iptables -t filter -A SSR-SERVER-RULE -p udp --dport $(uci_get_by_name $1 server_port) -j ACCEPT
return 0
}
gen_serv_include() {
FWI=$(uci get firewall.shadowsocksr.path 2>/dev/null)
[ -n "$FWI" ] || return 0
if [ ! -f $FWI ]; then
echo '#!/bin/sh' >$FWI
fi
extract_rules() {
echo "*filter"
iptables-save -t filter | grep SSR-SERVER-RULE | sed -e "s/^-A INPUT/-I INPUT/"
echo 'COMMIT'
}
cat <<-EOF >>$FWI
iptables-save -c | grep -v "SSR-SERVER" | iptables-restore -c
iptables-restore -n <<-EOT
$(extract_rules)
EOT
EOF
}
start_server() {
SERVER_ENABLE=$(uci_get_by_type server_global enable_server 0)
[ "$SERVER_ENABLE" == "0" ] && return 0
mkdir -p /var/run /var/etc
config_load $NAME
config_foreach start_service server_config
gen_serv_include
return 0
}
start_local() {
local local_server=$(uci_get_by_type socks5_proxy server nil)
[ "$local_server" == "same" ] && local_server=$GLOBAL_SERVER
[ "$local_server" == "nil" ] && return 1
local local_type=$(uci_get_by_name $local_server type)
mkdir -p /var/run /var/etc
if [ "$local_type" == "ssr" ]; then
gen_config_file $local_server 3 $(uci_get_by_type socks5_proxy local_port 1080)
/usr/bin/ssr-local -c $CONFIG_SOCK5_FILE -u -f /var/run/ssr-local.pid >/dev/null 2>&1
elif [ "$local_type" == "ss" ]; then
gen_config_file $local_server 3 $(uci_get_by_type socks5_proxy local_port 1080)
/usr/bin/ss-local -c $CONFIG_SOCK5_FILE -u -f /var/run/ssr-local.pid >/dev/null 2>&1
elif [ "$local_type" == "v2ray" ]; then
lua /usr/share/shadowsocksr/genv2config.lua $local_server tcp 0 $(uci_get_by_type socks5_proxy local_port 1080) >/var/etc/v2-ssr-local.json
sed -i 's/\\//g' /var/etc/v2-ssr-local.json
/usr/bin/v2ray/v2ray -config /var/etc/v2-ssr-local.json >/dev/null 2>&1 &
elif [ "$local_type" == "trojan" ]; then
lua /usr/share/shadowsocksr/gentrojanconfig.lua $local_server client $(uci_get_by_type socks5_proxy local_port 1080) >/var/etc/trojan-ssr-local.json
sed -i 's/\\//g' /var/etc/trojan-ssr-local.json
/usr/sbin/trojan --config /var/etc/trojan-ssr-local.json >/dev/null 2>&1 &
else
microsocks -i :: -p $(uci_get_by_type socks5_proxy local_port 1080) ssr-local >/dev/null 2>&1 &
fi
local_enable=1
}
rules() {
if [ "$GLOBAL_SERVER" == "nil" ]; then
return 1
else
redir_tcp=1
fi
mkdir -p /var/run /var/etc
UDP_RELAY_SERVER=$(uci_get_by_type global udp_relay_server)
[ "$UDP_RELAY_SERVER" == "same" ] && UDP_RELAY_SERVER=$GLOBAL_SERVER
[ -n "$UDP_RELAY_SERVER" ] && redir_udp=1
if start_rules; then
return 0
else
return 1
fi
}
start() {
if [ -z "$switch_server" ]; then
GLOBAL_SERVER=$(uci_get_by_type global global_server)
else
GLOBAL_SERVER=$switch_server
switch_enable=1
fi
NETFLIX_SERVER=$(uci_get_by_type global netflix_server nil)
if [ "$NETFLIX_SERVER" == "same" ]; then
NETFLIX_SERVER=$GLOBAL_SERVER
fi
if rules; then
start_redir
mkdir -p /tmp/dnsmasq.d && cp -a /etc/dnsmasq.ssr /tmp/ && cp -a /etc/dnsmasq.oversea /tmp/
if ! [ "$run_mode" == "oversea" ]; then
cat <<-EOF >/tmp/dnsmasq.d/dnsmasq-ssr.conf
conf-dir=/tmp/dnsmasq.ssr
EOF
else
cat <<-EOF >/tmp/dnsmasq.d/dnsmasq-ssr.conf
conf-dir=/tmp/dnsmasq.oversea
EOF
fi
if [ $(uci_get_by_type global adblock 0) == "0" ]; then
rm -f /tmp/dnsmasq.ssr/ad.conf
fi
/usr/share/shadowsocksr/gfw2ipset.sh
if [ "$NETFLIX_SERVER" != "nil" ]; then
if [ "$NETFLIX_SERVER" != "$GLOBAL_SERVER" ]; then
cat /etc/config/netflix.list | while read line || [ -n "$line" ]; do
sed -i "/$line/d" /tmp/dnsmasq.ssr/gfw_list.conf
done
awk '!/^$/&&!/^#/{printf("ipset=/.%s/'"netflix"'\n",$0)}' /etc/config/netflix.list >/tmp/dnsmasq.ssr/netflix_forward.conf
awk '!/^$/&&!/^#/{printf("server=/.%s/'"127.0.0.1#5555"'\n",$0)}' /etc/config/netflix.list >>/tmp/dnsmasq.ssr/netflix_forward.conf
ipset -N netflix hash:net 2>/dev/null
cat /etc/config/netflixip.list | while read nip || [ -n "$nip" ]; do
ipset add netflix $nip 2>/dev/null
done
else
cat /etc/config/netflix.list | while read line || [ -n "$line" ]; do
sed -i "/$line/d" /tmp/dnsmasq.ssr/gfw_list.conf
done
awk '!/^$/&&!/^#/{printf("ipset=/.%s/'"netflix"'\n",$0)}' /etc/config/netflix.list >/tmp/dnsmasq.ssr/netflix_forward.conf
awk '!/^$/&&!/^#/{printf("server=/.%s/'"127.0.0.1#5335"'\n",$0)}' /etc/config/netflix.list >>/tmp/dnsmasq.ssr/netflix_forward.conf
ipset -N netflix hash:net 2>/dev/null
cat /etc/config/netflixip.list | while read nip || [ -n "$nip" ]; do
ipset add netflix $nip 2>/dev/null
done
fi
else
rm -f /tmp/dnsmasq.ssr/netflix_forward.conf
fi
/etc/init.d/dnsmasq restart >/dev/null 2>&1
fi
start_server
start_local
if [ $(uci_get_by_type global monitor_enable 1) == "1" ]; then
let total_count=server_count+redir_tcp+redir_udp+tunnel_enable+kcp_enable_flag+local_enable+pdnsd_enable_flag+switch_enable
if [ $total_count -gt 0 ]; then
#param:server(count) redir_tcp(0:no,1:yes) redir_udp tunnel kcp local gfw
service_start /usr/bin/ssr-monitor $server_count $redir_tcp $redir_udp $tunnel_enable $kcp_enable_flag $local_enable $pdnsd_enable_flag $switch_enable
fi
fi
ENABLE_SERVER=$(uci_get_by_type global global_server nil)
if [ "$ENABLE_SERVER" == "nil" ]; then
return 1
else
STYPE=$(uci_get_by_name $ENABLE_SERVER type nil)
if [ "$STYPE" == "nil" ]; then
CFGID=$(uci_get_by_cfgid servers type nil)
if [ "$CFGID" == "nil" ]; then
uci set shadowsocksr.@global[0].global_server='nil'
else
uci set shadowsocksr.@global[0].global_server=$CFGID
fi
uci commit shadowsocksr
/etc/init.d/shadowsocksr restart
fi
fi
}
boot() {
(/usr/share/shadowsocksr/chinaipset.sh && sleep 3 && start >/dev/null 2>&1) &
}
stop() {
/usr/bin/ssr-rules -f
srulecount=$(iptables -L | grep SSR-SERVER-RULE | wc -l)
if [ $srulecount -gt 0 ]; then
iptables -F SSR-SERVER-RULE
iptables -t filter -D INPUT -j SSR-SERVER-RULE
iptables -X SSR-SERVER-RULE 2>/dev/null
fi
if [ -z "$switch_server" ]; then
kill -9 $(busybox ps -w | grep ssr-switch | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
if [ $(uci_get_by_type global monitor_enable 0) == "1" ]; then
kill -9 $(busybox ps -w | grep ssr-monitor | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
killall -q -9 ssr-monitor
killall -q -9 ss-redir
killall -q -9 obfs-local
killall -q -9 v2ray-plugin
killall -q -9 ssr-redir
killall -q -9 v2ray
killall -q -9 trojan
killall -q -9 ipt2socks
kill -9 $(busybox ps -w | grep ssr-server | grep -v grep | awk '{print $1}') >/dev/null 2>&1
kill -9 $(busybox ps -w | grep ssr-local | grep -v grep | awk '{print $1}') >/dev/null 2>&1
killall -q -9 ssr-local
killall -q -9 ss-local
killall -q -9 kcptun-client
killall -q -9 dns2socks
killall -q -9 microsocks
killall -q -9 redsocks2
if [ -f /var/run/pdnsd.pid ]; then
kill $(cat /var/run/pdnsd.pid) >/dev/null 2>&1
else
kill -9 $(busybox ps -w | grep pdnsd | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
if [ -f "/tmp/dnsmasq.d/dnsmasq-ssr.conf" ]; then
rm -f /tmp/dnsmasq.d/dnsmasq-ssr.conf /tmp/dnsmasq.ssr/* /tmp/dnsmasq.oversea/*
/etc/init.d/dnsmasq restart >/dev/null 2>&1
fi
del_cron
}

View File

@ -1,26 +0,0 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@shadowsocksr[-1]
add ucitrack shadowsocksr
set ucitrack.@shadowsocksr[-1].init=shadowsocksr
commit ucitrack
delete firewall.shadowsocksr
set firewall.shadowsocksr=include
set firewall.shadowsocksr.type=script
set firewall.shadowsocksr.path=/var/etc/shadowsocksr.include
set firewall.shadowsocksr.reload=1
commit firewall
EOF
touch /etc/china_ssr.txt
touch /etc/config/white.list
touch /etc/config/black.list
touch /etc/config/netflix.list
touch /etc/config/netflixip.list
touch /etc/dnsmasq.ssr/ad.conf
touch /etc/dnsmasq.ssr/gfw_list.conf
rm -rf /tmp/luci-modulecache/*
rm -f /tmp/luci-indexcache
exit 0

View File

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

View File

@ -1,25 +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/gfw.b64 >/tmp/gfw.txt
rm -f /tmp/gfwlist.txt
sed '/.*/s/.*/server=\/\.&\/127.0.0.1#5335\nipset=\/\.&\/gfwlist/' /tmp/gfw.txt >/tmp/gfwnew.txt
rm -f /tmp/gfw.txt

View File

@ -1,132 +0,0 @@
#!/bin/sh
#
# Copyright (C) 2017 openwrt-ssr
# Copyright (C) 2017 yushi studio <ywb94@qq.com>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
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}
}
server_process_count=$1
redir_tcp_process=$2
redir_udp_process=$3
tunnel_process=$4
kcp_process=$5
local_process=$6
pdnsd_process=$7
if [ -z "$pdnsd_process" ]; then
pdnsd_process=0
fi
i=0
GLOBAL_SERVER=$(uci_get_by_type global global_server)
server=$(uci_get_by_name $GLOBAL_SERVER server)
lkcp_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}
if echo "$server" | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then
server=${server}
else
server=$(cat /etc/ssr_ip)
fi
while [ "1" == "1" ]; do #死循环
sleep 30
#redir tcp
if [ "$redir_tcp_process" -gt 0 ]; then
icount=$(busybox ps -w | grep ssr-retcp | grep -v grep | wc -l)
if [ "$icount" == 0 ]; then
logger -t "$NAME" "ssr redir tcp error.restart!"
/etc/init.d/shadowsocksr restart
exit 0
fi
fi
#redir udp
if [ "$redir_udp_process" -gt 0 ]; then
icount=$(busybox ps -w | grep ssr-reudp | grep -v grep | wc -l)
if [ "$icount" == 0 ]; then
logger -t "$NAME" "ssr redir udp error.restart!"
/etc/init.d/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!"
/etc/init.d/shadowsocksr restart
exit 0
fi
fi
#server
if [ "$server_process_count" -gt 0 ]; then
icount=$(busybox ps -w | grep ssr-server | grep -v grep | wc -l)
if [ "$icount" -lt "$server_process_count" ]; then #如果进程挂掉就重启它
logger -t "$NAME" "ssr server error.restart!"
kill -9 $(busybox ps -w | grep ssr-server | grep -v grep | awk '{print $1}') >/dev/null 2>&1
/etc/init.d/shadowsocksr restart
fi
fi
#kcptun
if [ "$kcp_process" -gt 0 ]; then
icount=$(busybox ps -w | grep kcptun-client | grep -v grep | wc -l)
if [ "$icount" -lt "$kcp_process" ]; then #如果进程挂掉就重启它
logger -t "$NAME" "ssr kcptun error.restart!"
killall -q -9 kcptun-client
(/usr/bin/kcptun-client -r $server:$kcp_port -l :$server_port $password $kcp_param &)
fi
fi
#localsocks
if [ "$local_process" -gt 0 ]; then
icount=$(busybox ps -w | grep ssr-local | grep -v grep | wc -l)
if [ "$icount" -lt "$local_process" ]; then #如果进程挂掉就重启它
logger -t "$NAME" "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
fi
fi
#pdnsd
if [ "$pdnsd_process" -eq 1 ]; then
icount=$(busybox ps -w | grep pdnsd | grep -v grep | wc -l)
if [ "$icount" -lt "$pdnsd_process" ]; then #如果进程挂掉就重启它
logger -t "$NAME" "pdnsd tunnel error.restart!"
if [ -f /var/run/pdnsd.pid ]; then
kill $(cat /var/run/pdnsd.pid) >/dev/null 2>&1
else
kill -9 $(ps | grep pdnsd | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
(/usr/sbin/pdnsd -c /var/etc/pdnsd.conf -d &)
fi
fi
#dns2socks
if [ "$pdnsd_process" -eq 2 ]; then
icount=$(busybox ps -w | grep -e ssr-dns -e dns2socks | grep -v grep | wc -l)
if [ "$icount" -lt 2 ]; then #如果进程挂掉就重启它
logger -t "$NAME" "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 &
fi
fi
done

View File

@ -1,406 +0,0 @@
#!/bin/sh
#
# Copyright (C) 2017 openwrt-ssr
# Copyright (C) 2017 yushi studio <ywb94@qq.com>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
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]
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
-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 gfw list mode
-r return china mode
-h show this help message and exit
EOF
exit $1
}
loger() {
# 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug
logger -st ssr-rules[$$] -p$1 $2
}
flush_r() {
flush_iptables() {
local ipt="iptables -t $1"
local DAT=$(iptables-save -t $1)
eval $(echo "$DAT" | grep "$TAG" | sed -e 's/^-A/$ipt -D/' -e 's/$/;/')
for chain in $(echo "$DAT" | awk '/^:SS_SPEC/{print $1}'); do
$ipt -F ${chain:1} 2>/dev/null && $ipt -X ${chain:1}
done
}
flush_iptables nat
flush_iptables mangle
ip rule del fwmark 0x01/0x01 table 100 2>/dev/null
ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null
ipset -X ss_spec_lan_ac 2>/dev/null
ipset -X ss_spec_wan_ac 2>/dev/null
ipset -X ssr_gen_router 2>/dev/null
ipset -X fplan 2>/dev/null
ipset -X bplan 2>/dev/null
ipset -X gmlan 2>/dev/null
ipset -X oversea 2>/dev/null
ipset -X whitelist 2>/dev/null
ipset -X blacklist 2>/dev/null
ipset -X netflix 2>/dev/null
[ -n "$FWI" ] && echo '#!/bin/sh' >$FWI
return 0
}
ipset_r() {
ipset -N gmlan hash:net 2>/dev/null
for ip in $LAN_GM_IP; do ipset -! add gmlan $ip; done
if [ "$RUNMODE" == "router" ]; then
ipset -! -R <<-EOF || return 1
create ss_spec_wan_ac hash:net
$(gen_iplist | sed -e "s/^/add ss_spec_wan_ac /")
EOF
ipset -N gfwlist hash:net 2>/dev/null
$IPT -N SS_SPEC_WAN_AC
$IPT -I SS_SPEC_WAN_AC -p tcp ! --dport 53 -d $server -j RETURN
$IPT -A SS_SPEC_WAN_AC -m set --match-set ss_spec_wan_ac dst -j RETURN
$IPT -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW
elif [ "$RUNMODE" == "gfw" ]; then
ipset -N gfwlist hash:net 2>/dev/null
$IPT -N SS_SPEC_WAN_AC
$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
$IPT -I SS_SPEC_WAN_AC -p tcp ! --dport 53 -d $server -j RETURN
elif [ "$RUNMODE" == "oversea" ]; then
ipset -N oversea hash:net 2>/dev/null
$IPT -N SS_SPEC_WAN_AC
ipset -N gmlan hash:net 2>/dev/null
for ip in $LAN_GM_IP; do ipset -! add gmlan $ip; done
$IPT -A SS_SPEC_WAN_AC -m set --match-set china dst -j SS_SPEC_WAN_FW
$IPT -I SS_SPEC_WAN_AC -p tcp ! --dport 53 -d $server -j RETURN
elif [ "$RUNMODE" == "all" ]; then
$IPT -N SS_SPEC_WAN_AC
$IPT -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW
$IPT -I SS_SPEC_WAN_AC -p tcp ! --dport 53 -d $server -j RETURN
fi
ipset -N fplan hash:net 2>/dev/null
for ip in $LAN_FP_IP; do ipset -! add fplan $ip; done
$IPT -I SS_SPEC_WAN_AC -m set --match-set fplan src -j SS_SPEC_WAN_FW
ipset -N bplan hash:net 2>/dev/null
for ip in $LAN_BP_IP; do ipset -! add bplan $ip; done
$IPT -I SS_SPEC_WAN_AC -m set --match-set bplan src -j RETURN
ipset -N whitelist hash:net 2>/dev/null
ipset -N blacklist hash:net 2>/dev/null
$IPT -I SS_SPEC_WAN_AC -m set --match-set blacklist dst -j SS_SPEC_WAN_FW
$IPT -I SS_SPEC_WAN_AC -m set --match-set whitelist dst -j RETURN
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" == "1" ]; then
$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
elif [ "$NETFLIX" == "2" ]; then
$IPT -I SS_SPEC_WAN_AC -p tcp -m set --match-set netflix dst -j REDIRECT --to-ports $local_port
fi
return $?
}
fw_rule() {
ipset -N netflix hash:net 2>/dev/null
$IPT -N SS_SPEC_WAN_FW
$IPT -A SS_SPEC_WAN_FW -d 0.0.0.0/8 -j RETURN
$IPT -A SS_SPEC_WAN_FW -d 10.0.0.0/8 -j RETURN
$IPT -A SS_SPEC_WAN_FW -d 127.0.0.0/8 -j RETURN
$IPT -A SS_SPEC_WAN_FW -d 169.254.0.0/16 -j RETURN
$IPT -A SS_SPEC_WAN_FW -d 172.16.0.0/12 -j RETURN
$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 || {
loger 3 "Can't redirect, please check the iptables."
exit 1
}
return $?
}
ac_rule() {
if [ -n "$LAN_AC_IP" ]; then
case "${LAN_AC_IP:0:1}" in
w | W)
MATCH_SET="-m set --match-set ss_spec_lan_ac src"
;;
b | B)
MATCH_SET="-m set ! --match-set ss_spec_lan_ac src"
;;
*)
loger 3 "Bad argument \`-a $LAN_AC_IP\`."
return 2
;;
esac
fi
IFNAME=$(uci get -P/var/state network.lan.ifname 2>/dev/null)
ipset -! -R <<-EOF || return 1
create ss_spec_lan_ac hash:net
$(for ip in ${LAN_AC_IP:1}; do echo "add ss_spec_lan_ac $ip"; done)
EOF
$IPT -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p tcp $EXT_ARGS $MATCH_SET \
-m comment --comment "$TAG" -j SS_SPEC_WAN_AC
if [ "$OUTPUT" = 1 ]; then
$IPT -I OUTPUT 1 -p tcp $EXT_ARGS \
-m comment --comment "$TAG" -j SS_SPEC_WAN_AC
elif [ "$OUTPUT" = 2 ]; then
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 -A SS_SPEC_ROUTER -j SS_SPEC_WAN_FW
$IPT -I OUTPUT 1 -p tcp -m comment --comment "$TAG" -j SS_SPEC_ROUTER
fi
return $?
}
tp_rule() {
[ -n "$TPROXY" ] || return 0
ip rule add fwmark 0x01/0x01 table 100
ip route add local 0.0.0.0/0 dev lo table 100
local ipt="iptables -t mangle"
$ipt -N SS_SPEC_TPROXY
$ipt -A SS_SPEC_TPROXY -p udp --dport 443 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp --dport 80 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp --dport 53 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -d 0.0.0.0/8 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -d 10.0.0.0/8 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -d 127.0.0.0/8 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -d 169.254.0.0/16 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -d 172.16.0.0/12 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -d 192.168.0.0/16 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -d 224.0.0.0/4 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -d 240.0.0.0/4 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp ! --dport 53 -d $server -j RETURN
$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
if [ "$RUNMODE" == "router" ]; then
$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
elif [ "$RUNMODE" == "gfw" ]; then
$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
elif [ "$RUNMODE" == "oversea" ]; then
$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
elif [ "$RUNMODE" == "all" ]; then
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
fi
$ipt -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p udp $EXT_ARGS $MATCH_SET \
-m comment --comment "$TAG" -j SS_SPEC_TPROXY
return $?
}
get_wan_ip() {
cat <<-EOF | grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}"
$server
$SERVER
$WAN_BP_IP
EOF
}
gen_iplist() {
cat <<-EOF
0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
172.16.0.0/12
192.0.0.0/24
192.0.2.0/24
192.88.99.0/24
192.168.0.0/16
198.18.0.0/15
198.51.100.0/24
203.0.113.0/24
224.0.0.0/4
240.0.0.0/4
255.255.255.255
$(get_wan_ip)
$(cat ${IGNORE_LIST:=/dev/null} 2>/dev/null)
EOF
}
gen_spec_iplist() {
cat <<-EOF
0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
172.16.0.0/12
192.0.0.0/24
192.0.2.0/24
192.88.99.0/24
192.168.0.0/16
198.18.0.0/15
198.51.100.0/24
203.0.113.0/24
224.0.0.0/4
240.0.0.0/4
255.255.255.255
$(get_wan_ip)
EOF
}
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/"
echo 'COMMIT'
}
cat <<-EOF >>$FWI
iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c
iptables-restore -n <<-EOT
$(extract_rules nat)
$(extract_rules mangle)
EOT
EOF
return 0
}
while getopts ":s:l:S:L:i:e:a:B:b:w:p:G:D:F:N:M:oOuUfgrczh" arg; do
case "$arg" in
s)
server=$OPTARG
;;
l)
local_port=$OPTARG
;;
S)
SERVER=$OPTARG
;;
L)
LOCAL_PORT=$OPTARG
;;
i)
IGNORE_LIST=$OPTARG
;;
e)
EXT_ARGS=$OPTARG
;;
a)
LAN_AC_IP=$OPTARG
;;
B)
LAN_BP_IP=$OPTARG
;;
b)
WAN_BP_IP=$(for ip in $OPTARG; do echo $ip; done)
;;
w)
WAN_FW_IP=$OPTARG
;;
p)
LAN_FP_IP=$OPTARG
;;
G)
LAN_GM_IP=$OPTARG
;;
D)
PROXY_PORTS=$OPTARG
;;
F)
NETFLIX=$OPTARG
;;
N)
NETFLIX_IP=$OPTARG
;;
M)
NETFLIX_PROXY=$OPTARG
;;
o)
OUTPUT=1
;;
O)
OUTPUT=2
;;
u)
TPROXY=1
;;
U)
TPROXY=2
;;
g)
RUNMODE=gfw
;;
r)
RUNMODE=router
;;
c)
RUNMODE=oversea
;;
z)
RUNMODE=all
;;
f)
flush_r
exit 0
;;
h) usage 0 ;;
esac
done
if [ -z "$server" -o -z "$local_port" ]; then
usage 2
fi
if [ "$TPROXY" == 1 ]; then
SERVER=$server
LOCAL_PORT=$local_port
elif [ "$TPROXY" == 2 ]; then
: ${SERVER:?"You must assign an ip for the udp relay server."}
: ${LOCAL_PORT:?"You must assign a port for the udp relay server."}
fi
flush_r && fw_rule && ipset_r && ac_rule && tp_rule && gen_include
[ "$?" == 0 ] || loger 3 "Start failed!"
exit $?

View File

@ -1,168 +0,0 @@
#!/bin/sh /etc/rc.common
#
# Copyright (C) 2017 openwrt-ssr
# Copyright (C) 2017 yushi studio <ywb94@qq.com>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
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
#判断代理是否正常
check_proxy() {
local result=0
local try_count=$(uci_get_by_type global switch_try_count 3)
for i in $(seq 1 $try_count); do
/usr/bin/ssr-check www.google.com 80 $switch_time 1
if [ "$?" == "0" ]; then
# echo "$(date "+%Y-%m-%d %H:%M:%S") Check Google Proxy Success, count=$i" >> /tmp/ssrplus.log
result=0
break
else
# echo "$(date "+%Y-%m-%d %H:%M:%S") Check Google Proxy Fail, count=$i" >> /tmp/ssrplus.log
/usr/bin/ssr-check www.baidu.com 80 $switch_time 1
if [ "$?" == "0" ]; then
result=1
else
result=2
fi
fi
sleep 1
done
return $result
}
test_proxy() {
local servername=$(uci_get_by_name $1 server)
local serverport=$(uci_get_by_name $1 server_port)
ret=$(ping -c 3 $servername | grep 'loss' | awk -F ',' '{ print $3 }' | awk -F "%" '{ print $1 }')
[ -z "$ret" ] && return 1
[ "$ret" -gt "50" ] && return 1
ipset add ss_spec_wan_ac $servername 2>/dev/null
ret=$?
/usr/bin/ssr-check $servername $serverport $switch_time
local ret2=$?
if [ "$ret" == "0" ]; then
ipset del ss_spec_wan_ac $servername 2>/dev/null
fi
if [ "$ret2" == "0" ]; then
return 0
else
return 1
fi
}
search_proxy() {
let server_count=server_count+1
[ "$normal_flag" == "1" -a "$server_count" -le "$server_locate" ] && return 0
[ "$(uci_get_by_name $1 switch_enable)" != "1" ] && return 1
[ $ENABLE_SERVER != nil ] && return 0
[ "$1" == "$CURRENT_SERVER" ] && return 0
local servername=$(uci_get_by_name $1 server)
local serverport=$(uci_get_by_name $1 server_port)
ipset add ss_spec_wan_ac $servername 2>/dev/null
ret=$?
/usr/bin/ssr-check $servername $serverport $switch_time
local ret2=$?
if [ "$ret" == "0" ]; then
ipset del ss_spec_wan_ac $servername 2>/dev/null
fi
if [ "$ret2" == "0" ]; then
server_locate=$server_count
ENABLE_SERVER=$1
return 0
else
return 1
fi
}
#选择可用的代理
select_proxy() {
config_load $NAME
ENABLE_SERVER=nil
mkdir -p /var/run /var/etc
server_count=0
config_foreach search_proxy servers
}
#切换代理
switch_proxy() {
/etc/init.d/shadowsocksr restart $1
return 0
}
start() {
#不支持kcptun启用时的切换
[ $(uci_get_by_name $DEFAULT_SERVER kcp_enable) = "1" ] && return 1
while [ "1" == "1" ]; do #死循环
sleep $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
#检查缺省服务器是否正常
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
#缺省服务器正常,切换回来
CURRENT_SERVER=$DEFAULT_SERVER
switch_proxy $CURRENT_SERVER
echo "$(date "+%Y-%m-%d %H:%M:%S") switch to default ["$(uci_get_by_name $CURRENT_SERVER server)"] proxy!" >>/tmp/ssrplus.log
else
echo "$(date "+%Y-%m-%d %H:%M:%S") Main server is NOT avilable.Continue using current server." >>/tmp/ssrplus.log
fi
fi
#判断当前代理是否正常
#echo "$(date "+%Y-%m-%d %H:%M:%S") Start checking if the current server is available." >>/tmp/ssrplus.log
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
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
CURRENT_SERVER=$ENABLE_SERVER
switch_proxy $CURRENT_SERVER
normal_flag=1
echo "$(date "+%Y-%m-%d %H:%M:%S") ShadowsocksR server switch OK" >>/tmp/ssrplus.log
else
switch_proxy $CURRENT_SERVER
normal_flag=1
echo "$(date "+%Y-%m-%d %H:%M:%S") Try restart current server." >>/tmp/ssrplus.log
fi
else
normal_flag=0
echo "$(date "+%Y-%m-%d %H:%M:%S") ShadowsocksR No Problem." >>/tmp/ssrplus.log
fi
done
}

View File

@ -1,11 +0,0 @@
{
"luci-app-ssr-plus": {
"description": "Grant UCI access for luci-app-ssr-plus",
"read": {
"uci": [ "shadowsocksr" ]
},
"write": {
"uci": [ "shadowsocksr" ]
}
}
}

View File

@ -1,5 +0,0 @@
echo "create china hash:net family inet hashsize 1024 maxelem 65536" > /tmp/china.ipset
awk '!/^$/&&!/^#/{printf("add china %s'" "'\n",$0)}' /etc/china_ssr.txt >> /tmp/china.ipset
ipset -! flush china
ipset -! restore < /tmp/china.ipset 2>/dev/null
rm -f /tmp/china.ipset

View File

@ -1,72 +0,0 @@
#!/bin/sh
cat <<-EOF >$1
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;
}
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";
}
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

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,107 +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 v2ray = {
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 = "vmess",
settings = {
vnext = {
{
address = server.server,
port = tonumber(server.server_port),
users = {
{
id = server.vmess_id,
alterId = tonumber(server.alter_id),
security = server.security
}
}
}
}
},
-- 底层传输配置
streamSettings = {
network = server.transport,
security = (server.tls == '1') and "tls" or "none",
tlsSettings = {allowInsecure = (server.insecure ~= "0") and true or false,serverName=server.tls_host,},
kcpSettings = (server.transport == "kcp") and {
mtu = tonumber(server.mtu),
tti = tonumber(server.tti),
uplinkCapacity = tonumber(server.uplink_capacity),
downlinkCapacity = tonumber(server.downlink_capacity),
congestion = (server.congestion == "1") and true or false,
readBufferSize = tonumber(server.read_buffer_size),
writeBufferSize = tonumber(server.write_buffer_size),
header = {
type = server.kcp_guise
}
} or nil,
wsSettings = (server.transport == "ws") and (server.ws_path ~= nil or server.ws_host ~= nil) and {
path = server.ws_path,
headers = (server.ws_host ~= nil) and {
Host = server.ws_host
} or nil,
} or nil,
httpSettings = (server.transport == "h2") and {
path = server.h2_path,
host = server.h2_host,
} or nil,
quicSettings = (server.transport == "quic") and {
security = server.quic_security,
key = server.quic_key,
header = {
type = server.quic_guise
}
} or nil
},
mux = {
enabled = (server.mux == "1") and true or false,
concurrency = tonumber(server.concurrency)
}
},
-- 额外传出连接
outboundDetour = {
{
protocol = "freedom",
tag = "direct",
settings = { keep = "" }
}
}
}
print(json.stringify(v2ray, 1))

View File

@ -1,5 +0,0 @@
#!/bin/sh
mkdir -p /tmp/dnsmasq.ssr
awk '!/^$/&&!/^#/{printf("ipset=/.%s/'"blacklist"'\n",$0)}' /etc/config/black.list > /tmp/dnsmasq.ssr/blacklist_forward.conf
awk '!/^$/&&!/^#/{printf("server=/.%s/'"127.0.0.1#5335"'\n",$0)}' /etc/config/black.list >> /tmp/dnsmasq.ssr/blacklist_forward.conf
awk '!/^$/&&!/^#/{printf("ipset=/.%s/'"whitelist"'\n",$0)}' /etc/config/white.list > /tmp/dnsmasq.ssr/whitelist_forward.conf

View File

@ -1,6 +0,0 @@
#!/bin/sh
/usr/bin/lua /usr/share/shadowsocksr/update.lua
/usr/bin/lua /usr/share/shadowsocksr/subscribe.lua
sleep 10
/etc/init.d/shadowsocksr restart

View File

@ -1,447 +0,0 @@
#!/usr/bin/lua
------------------------------------------------
-- This file is part of the luci-app-ssr-plus subscribe.lua
-- @author William Chan <root@williamchan.me>
------------------------------------------------
require 'nixio'
require 'luci.util'
require 'luci.jsonc'
require 'luci.sys'
require 'uci'
-- these global functions are accessed all the time by the event handler
-- so caching them is worth the effort
local luci = luci
local tinsert = table.insert
local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string.char, string.byte, string.format, string.gsub
local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify
local b64decode = nixio.bin.b64decode
local cache = {}
local nodeResult = setmetatable({}, { __index = cache }) -- update result
local name = 'shadowsocksr'
local uciType = 'servers'
local ucic = luci.model.uci.cursor()
local proxy = ucic:get_first(name, 'server_subscribe', 'proxy', '0')
local switch = ucic:get_first(name, 'server_subscribe', 'switch', '1')
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url', {})
local filter_words = ucic:get_first(name, 'server_subscribe', 'filter_words', 'QQ群')
local log = function(...)
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({ ... }, " "))
end
-- 分割字符串
local function split(full, sep)
full = full:gsub("%z", "") -- 这里不是很清楚 有时候结尾带个\0
local off, result = 1, {}
while true do
local nStart, nEnd = full:find(sep, off)
if not nEnd then
local res = ssub(full, off, slen(full))
if #res > 0 then -- 过滤掉 \0
tinsert(result, res)
end
break
else
tinsert(result, ssub(full, off, nStart - 1))
off = nEnd + 1
end
end
return result
end
-- urlencode
local function get_urlencode(c)
return sformat("%%%02X", sbyte(c))
end
local function urlEncode(szText)
local str = szText:gsub("([^0-9a-zA-Z ])", get_urlencode)
str = str:gsub(" ", "+")
return str
end
local function get_urldecode(h)
return schar(tonumber(h, 16))
end
local function UrlDecode(szText)
return szText:gsub("+", " "):gsub("%%(%x%x)", get_urldecode)
end
-- trim
local function trim(text)
if not text or text == "" then
return ""
end
return (sgsub(text, "^%s*(.-)%s*$", "%1"))
end
-- md5
local function md5(content)
local stdout = luci.sys.exec('echo \"' .. urlEncode(content) .. '\" | md5sum | cut -d \" \" -f1')
-- assert(nixio.errno() == 0)
return trim(stdout)
end
-- base64
local function base64Decode(text)
local raw = text
if not text then return '' end
text = text:gsub("%z", "")
text = text:gsub("_", "/")
text = text:gsub("-", "+")
local mod4 = #text % 4
text = text .. string.sub('====', mod4 + 1)
local result = b64decode(text)
if result then
return result:gsub("%z", "")
else
return raw
end
end
-- 处理数据
local function processData(szType, content)
local result = {
type = szType,
local_port = 1234,
kcp_param = '--nocomp'
}
if szType == 'ssr' then
local dat = split(content, "/%?")
local hostInfo = split(dat[1], ':')
result.server = hostInfo[1]
result.server_port = hostInfo[2]
result.protocol = hostInfo[3]
result.encrypt_method = hostInfo[4]
result.obfs = hostInfo[5]
result.password = base64Decode(hostInfo[6])
local params = {}
for _, v in pairs(split(dat[2], '&')) do
local t = split(v, '=')
params[t[1]] = t[2]
end
result.obfs_param = base64Decode(params.obfsparam)
result.protocol_param = base64Decode(params.protoparam)
local group = base64Decode(params.group)
if group then
result.alias = "[" .. group .. "] "
end
result.alias = result.alias .. base64Decode(params.remarks)
elseif szType == 'vmess' then
local info = jsonParse(content)
result.type = 'v2ray'
result.server = info.add
result.server_port = info.port
result.transport = info.net
result.alter_id = info.aid
result.vmess_id = info.id
result.alias = info.ps
result.insecure = 1
-- result.mux = 1
-- result.concurrency = 8
if info.net == 'ws' then
result.ws_host = info.host
result.ws_path = info.path
end
if info.net == 'h2' then
result.h2_host = info.host
result.h2_path = info.path
end
if info.net == 'tcp' then
result.tcp_guise = info.type
result.http_host = info.host
result.http_path = info.path
end
if info.net == 'kcp' then
result.kcp_guise = info.type
result.mtu = 1350
result.tti = 50
result.uplink_capacity = 5
result.downlink_capacity = 20
result.read_buffer_size = 2
result.write_buffer_size = 2
end
if info.net == 'quic' then
result.quic_guise = info.type
result.quic_key = info.key
result.quic_security = info.securty
end
if info.security then
result.security = info.security
end
if info.tls == "tls" or info.tls == "1" then
result.tls = "1"
result.tls_host = info.host
else
result.tls = "0"
end
elseif szType == "ss" then
local idx_sp = 0
local alias = ""
if content:find("#") then
idx_sp = content:find("#")
alias = content:sub(idx_sp + 1, -1)
end
local info = content:sub(1, idx_sp - 1)
local hostInfo = split(base64Decode(info), "@")
local host = split(hostInfo[2], ":")
local userinfo = base64Decode(hostInfo[1])
local method = userinfo:sub(1, userinfo:find(":") - 1)
local password = userinfo:sub(userinfo:find(":") + 1, #userinfo)
result.alias = UrlDecode(alias)
result.type = "ss"
result.server = host[1]
if host[2]:find("/%?") then
local query = split(host[2], "/%?")
result.server_port = query[1]
local params = {}
for _, v in pairs(split(query[2], '&')) do
local t = split(v, '=')
params[t[1]] = t[2]
end
if params.plugin then
local plugin_info = UrlDecode(params.plugin)
local idx_pn = plugin_info:find(";")
if idx_pn then
result.plugin = plugin_info:sub(1, idx_pn - 1)
result.plugin_opts = plugin_info:sub(idx_pn + 1, #plugin_info)
else
result.plugin = plugin_info
end
end
else
result.server_port = host[2]
end
result.encrypt_method_ss = method
result.password = password
elseif szType == "ssd" then
result.type = "ss"
result.server = content.server
result.server_port = content.port
result.password = content.password
result.encrypt_method_ss = content.encryption
result.plugin = content.plugin
result.plugin_opts = content.plugin_options
result.alias = "[" .. content.airport .. "] " .. content.remarks
elseif szType == "trojan" then
local idx_sp = 0
local alias = ""
if content:find("#") then
idx_sp = content:find("#")
alias = content:sub(idx_sp + 1, -1)
end
local info = content:sub(1, idx_sp - 1)
local hostInfo = split(info, "@")
local host = split(hostInfo[2], ":")
local userinfo = hostInfo[1]
local password = userinfo
result.alias = UrlDecode(alias)
result.type = "trojan"
result.server = host[1]
-- 按照官方的建议 默认验证ssl证书
result.insecure = "0"
result.tls = "1"
if host[2]:find("?") then
local query = split(host[2], "?")
result.server_port = query[1]
local params = {}
for _, v in pairs(split(query[2], '&')) do
local t = split(v, '=')
params[t[1]] = t[2]
end
if params.peer then
-- 未指定peersni默认使用remote addr
result.tls_host = params.peer
end
if params.allowInsecure == "1" then
result.insecure = "1"
else
result.insecure = "0"
end
else
result.server_port = host[2]
end
result.password = password
end
if not result.alias then
result.alias = result.server .. ':' .. result.server_port
end
-- alias 不参与 hashkey 计算
local alias = result.alias
result.alias = nil
local switch_enable = result.switch_enable
result.switch_enable = nil
result.hashkey = md5(jsonStringify(result))
result.alias = alias
result.switch_enable = switch_enable
return result
end
-- 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 .. '"')
return trim(stdout)
end
local function check_filer(result)
do
local filter_word = split(filter_words, "/")
for i, v in pairs(filter_word) do
if result.alias:find(v) then
log('订阅节点关键字过滤:“' .. v ..'” ,该节点被丢弃')
return true
end
end
end
end
local execute = function()
-- exec
do
if proxy == '0' then -- 不使用代理更新的话先暂停
log('服务正在暂停')
luci.sys.init.stop(name)
end
for k, url in ipairs(subscribe_url) do
local raw = wget(url)
if #raw > 0 then
local nodes, szType
local groupHash = md5(url)
cache[groupHash] = {}
tinsert(nodeResult, {})
local index = #nodeResult
-- SSD 似乎是这种格式 ssd:// 开头的
if raw:find('ssd://') then
szType = 'ssd'
local nEnd = select(2, raw:find('ssd://'))
nodes = base64Decode(raw:sub(nEnd + 1, #raw))
nodes = jsonParse(nodes)
local extra = {
airport = nodes.airport,
port = nodes.port,
encryption = nodes.encryption,
password = nodes.password
}
local servers = {}
-- SS里面包着 干脆直接这样
for _, server in ipairs(nodes.servers) do
tinsert(servers, setmetatable(server, { __index = extra }))
end
nodes = servers
else
-- ssd 外的格式
nodes = split(base64Decode(raw):gsub(" ", "\n"), "\n")
end
for _, v in ipairs(nodes) do
if v then
local result
if szType == 'ssd' then
result = processData(szType, v)
elseif not szType then
local node = trim(v)
local dat = split(node, "://")
if dat and dat[1] and dat[2] then
if dat[1] == 'ss' or dat[1] == 'trojan' then
result = processData(dat[1], dat[2])
else
result = processData(dat[1], base64Decode(dat[2]))
end
end
else
log('跳过未知类型: ' .. szType)
end
-- log(result)
if result then
if
not result.server or
check_filer(result) or
result.server:match("[^0-9a-zA-Z%-%.%s]") -- 中文做地址的 也没有人拿中文域名搞就算中文域也有Puny Code SB 机场
then
log('丢弃无效节点: ' .. result.type ..' 节点, ' .. result.alias)
else
log('成功解析: ' .. result.type ..' 节点, ' .. result.alias)
result.grouphashkey = groupHash
tinsert(nodeResult[index], result)
cache[groupHash][result.hashkey] = nodeResult[index][#nodeResult[index]]
end
end
end
end
log('成功解析节点数量: ' ..#nodes)
else
log(url .. ': 获取内容为空')
end
end
end
-- diff
do
if next(nodeResult) == nil then
log("更新失败,没有可用的节点信息")
return
end
local add, del = 0, 0
ucic:foreach(name, uciType, function(old)
if old.grouphashkey or old.hashkey then -- 没有 hash 的不参与删除
if not nodeResult[old.grouphashkey] or not nodeResult[old.grouphashkey][old.hashkey] then
ucic:delete(name, old['.name'])
del = del + 1
else
local dat = nodeResult[old.grouphashkey][old.hashkey]
ucic:tset(name, old['.name'], dat)
-- 标记一下
setmetatable(nodeResult[old.grouphashkey][old.hashkey], { __index = { _ignore = true } })
end
else
if not old.alias then
old.alias = old.server .. ':' .. old.server_port
end
log('忽略手动添加的节点: ' .. old.alias)
end
end)
for k, v in ipairs(nodeResult) do
for kk, vv in ipairs(v) do
if not vv._ignore then
local section = ucic:add(name, uciType)
ucic:tset(name, section, vv)
ucic:set(name, section, "switch_enable", switch)
add = add + 1
end
end
end
ucic:commit(name)
-- 如果原有服务器节点已经不见了就尝试换为第一个节点
local globalServer = ucic:get_first(name, 'global', 'global_server', '')
local firstServer = ucic:get_first(name, uciType)
if firstServer then
if not ucic:get(name, globalServer) then
luci.sys.call("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &")
ucic:commit(name)
ucic:set(name, ucic:get_first(name, 'global'), 'global_server', ucic:get_first(name, uciType))
ucic:commit(name)
log('当前主服务器节点已被删除,正在自动更换为第一个节点。')
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 &")
end
else
log('没有服务器节点了,停止服务')
luci.sys.call("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &")
end
log('新增节点数量: ' ..add, '删除节点数量: ' .. del)
log('订阅更新成功')
end
end
if subscribe_url and #subscribe_url > 0 then
xpcall(execute, function(e)
log(e)
log(debug.traceback())
log('发生错误, 正在恢复服务')
local firstServer = ucic:get_first(name, uciType)
if firstServer then
luci.sys.call("/etc/init.d/" .. name .." restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
log('重启服务成功')
else
luci.sys.call("/etc/init.d/" .. name .." stop > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
log('停止服务成功')
end
end)
end

View File

@ -1,125 +0,0 @@
#!/usr/bin/lua
------------------------------------------------
-- This file is part of the luci-app-ssr-plus update.lua
-- By Mattraks
------------------------------------------------
require 'nixio'
require 'luci.util'
require 'luci.jsonc'
require 'luci.sys'
local icount = 0
local uci = luci.model.uci.cursor()
local log = function(...)
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({ ... }, " "))
end
log('正在更新【GFW列表】数据库')
refresh_cmd = "wget-ssl --no-check-certificate -O- " .. uci:get_first('shadowsocksr', 'global', 'gfwlist_url', 'https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt') .. " > /tmp/gfw.b64"
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
if sret == 0 then
luci.sys.call("/usr/bin/ssr-gfw")
icount = luci.sys.exec("cat /tmp/gfwnew.txt | wc -l")
if tonumber(icount) > 1000 then
if nixio.fs.access("/etc/dnsmasq.ssr/gfw_list.conf") then
oldcount = luci.sys.exec("cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l")
else
oldcount = "0"
end
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec("cp -f /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf")
luci.sys.exec("cp -f /tmp/gfwnew.txt /tmp/dnsmasq.ssr/gfw_list.conf")
log('更新成功! 新的总纪录数:' .. tostring(tonumber(icount)/2))
else
log('你已经是最新数据,无需更新!')
end
else
log('更新失败!')
end
luci.sys.exec("rm -f /tmp/gfwnew.txt")
else
log('更新失败!')
end
log('正在更新【国内IP段】数据库')
refresh_cmd = "wget-ssl --no-check-certificate -O- " .. uci:get_first('shadowsocksr', 'global', 'chnroute_url','https://ispip.clang.cn/all_cn.txt') .. " > /tmp/china_ssr.txt"
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
icount = luci.sys.exec("cat /tmp/china_ssr.txt | wc -l")
if sret == 0 then
icount = luci.sys.exec("cat /tmp/china_ssr.txt | wc -l")
if tonumber(icount) > 1000 then
if nixio.fs.access("/etc/china_ssr.txt") then
oldcount = luci.sys.exec("cat /etc/china_ssr.txt | wc -l")
else
oldcount = "0"
end
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec("cp -f /tmp/china_ssr.txt /etc/china_ssr.txt")
log('更新成功! 新的总纪录数:' .. tostring(tonumber(icount)))
else
log('你已经是最新数据,无需更新!')
end
else
log('更新失败!')
end
luci.sys.exec("rm -f /tmp/china_ssr.txt")
else
log('更新失败!')
end
if uci:get_first('shadowsocksr', 'global', 'adblock','0') == "1" then
log('正在更新【广告屏蔽】数据库')
refresh_cmd = "wget-ssl --no-check-certificate -O- " .. uci:get_first('shadowsocksr', 'global', 'adblock_url','https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt') .. " > /tmp/adnew.conf"
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
if sret == 0 then
luci.sys.call("/usr/bin/ssr-ad")
icount = luci.sys.exec("cat /tmp/ad.conf | wc -l")
if tonumber(icount) > 100 then
if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
oldcount = luci.sys.exec("cat /etc/dnsmasq.ssr/ad.conf | wc -l")
else
oldcount = "0"
end
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec("cp -f /tmp/ad.conf /etc/dnsmasq.ssr/ad.conf")
luci.sys.exec("cp -f /tmp/ad.conf /tmp/dnsmasq.ssr/ad.conf")
log('更新成功! 新的总纪录数:' .. tostring(tonumber(icount)))
else
log('你已经是最新数据,无需更新!')
end
else
log('更新失败!')
end
luci.sys.exec("rm -f /tmp/ad.conf")
else
log('更新失败!')
end
end
--[[
log('正在更新【Netflix IP段】数据库')
refresh_cmd = "wget-ssl --no-check-certificate -O- " .. uci:get_first('shadowsocksr', 'global', 'nfip_url','https://raw.githubusercontent.com/QiuSimons/Netflix_IP/master/NF_only.txt') .. " > /tmp/netflixip.list"
sret = luci.sys.call(refresh_cmd .. " 2>/dev/null")
if sret == 0 then
luci.sys.call("/usr/bin/ssr-gfw")
icount = luci.sys.exec("cat /tmp/netflixip.list | wc -l")
if tonumber(icount) > 5 then
if nixio.fs.access("/etc/config/netflixip.list") then
oldcount = luci.sys.exec("cat /etc/config/netflixip.list | wc -l")
else
oldcount = "0"
end
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec("cp -f /tmp/netflixip.list /etc/config/netflixip.list")
log('更新成功! 新的总纪录数:' .. tostring(tonumber(icount)))
else
log('你已经是最新数据,无需更新!')
end
else
log('更新失败!')
end
luci.sys.exec("rm -f /tmp/netflixip.list")
else
log('更新失败!')
end
--]]