瀏覽代碼

Preview in development

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

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

# Fixes
Fix the issue of starting twice after apply in the server node list
Fix the problem that dnsmasq fails to start when the access control list contains wrong entries
Mattraks 4 年之前
父節點
當前提交
703bcc9763
共有 48 個文件被更改,包括 1657 次插入1449 次删除
  1. 4 16
      luci-app-ssr-plus/Makefile
  2. 26 66
      luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua
  3. 17 11
      luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua
  4. 210 165
      luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua
  5. 16 13
      luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua
  6. 8 8
      luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/control.lua
  7. 3 3
      luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/log.lua
  8. 36 37
      luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua
  9. 35 36
      luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua
  10. 16 23
      luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua
  11. 75 68
      luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua
  12. 0 1
      luci-app-ssr-plus/luasrc/view/shadowsocksr/check.htm
  13. 1 12
      luci-app-ssr-plus/luasrc/view/shadowsocksr/checkport.htm
  14. 8 6
      luci-app-ssr-plus/luasrc/view/shadowsocksr/refresh.htm
  15. 25 0
      luci-app-ssr-plus/luasrc/view/shadowsocksr/reset.htm
  16. 1 19
      luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm
  17. 0 8
      luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm
  18. 54 0
      luci-app-ssr-plus/po/zh-cn/ssr-plus.po
  19. 0 42
      luci-app-ssr-plus/root/etc/config/shadowsocksr
  20. 486 376
      luci-app-ssr-plus/root/etc/init.d/shadowsocksr
  21. 0 0
      luci-app-ssr-plus/root/etc/ssrplus/ad.conf
  22. 0 0
      luci-app-ssr-plus/root/etc/ssrplus/black.list
  23. 2 0
      luci-app-ssr-plus/root/etc/ssrplus/china_ssr.txt
  24. 0 0
      luci-app-ssr-plus/root/etc/ssrplus/deny.list
  25. 0 0
      luci-app-ssr-plus/root/etc/ssrplus/gfw_base.conf
  26. 10 0
      luci-app-ssr-plus/root/etc/ssrplus/gfw_list.conf
  27. 0 0
      luci-app-ssr-plus/root/etc/ssrplus/netflix.list
  28. 0 0
      luci-app-ssr-plus/root/etc/ssrplus/netflixip.list
  29. 0 0
      luci-app-ssr-plus/root/etc/ssrplus/oversea_list.conf
  30. 0 0
      luci-app-ssr-plus/root/etc/ssrplus/white.list
  31. 13 14
      luci-app-ssr-plus/root/etc/uci-defaults/luci-ssr-plus
  32. 0 10
      luci-app-ssr-plus/root/usr/bin/ssr-ad
  33. 0 27
      luci-app-ssr-plus/root/usr/bin/ssr-gfw
  34. 21 61
      luci-app-ssr-plus/root/usr/bin/ssr-monitor
  35. 72 72
      luci-app-ssr-plus/root/usr/bin/ssr-rules
  36. 15 26
      luci-app-ssr-plus/root/usr/bin/ssr-switch
  37. 6 6
      luci-app-ssr-plus/root/usr/share/rpcd/acl.d/luci-app-ssr-plus.json
  38. 1 1
      luci-app-ssr-plus/root/usr/share/shadowsocksr/chinaipset.sh
  39. 171 0
      luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua
  40. 85 62
      luci-app-ssr-plus/root/usr/share/shadowsocksr/genred2config.sh
  41. 0 40
      luci-app-ssr-plus/root/usr/share/shadowsocksr/gentrojanconfig.lua
  42. 0 117
      luci-app-ssr-plus/root/usr/share/shadowsocksr/genv2config.lua
  43. 38 50
      luci-app-ssr-plus/root/usr/share/shadowsocksr/gfw2ipset.sh
  44. 1 1
      luci-app-ssr-plus/root/usr/share/shadowsocksr/ssrplusupdate.sh
  45. 19 30
      luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua
  46. 166 19
      luci-app-ssr-plus/root/usr/share/shadowsocksr/update.lua
  47. 3 3
      tcping/Makefile
  48. 13 0
      tcping/patches/0001-Remove-strip.patch

+ 4 - 16
luci-app-ssr-plus/Makefile

@@ -1,14 +1,12 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=luci-app-ssr-plus
-PKG_VERSION:=181
-PKG_RELEASE:=4
-
-include $(INCLUDE_DIR)/package.mk
+PKG_VERSION:=182
+PKG_RELEASE:=1
 
 define Package/$(PKG_NAME)/conffiles
 /etc/config/shadowsocksr
-/etc/ssr/
+/etc/ssrplus/
 endef
 
 define Package/$(PKG_NAME)/config
@@ -46,17 +44,7 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server
 	default y if i386||x86_64||arm||aarch64
 endef
 
-PKG_CONFIG_DEPENDS:= \
-	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin \
-	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray \
-	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray \
-	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan \
-	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \
-	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Redsocks2 \
-	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun \
-	CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server
-
-LUCI_TITLE:=SS/SSR/V2Ray/Xray/Trojan/NaiveProxy/Socks5/Tun LuCI interface
+LUCI_TITLE:=SS/SSR/V2Ray/Trojan/NaiveProxy/Socks5/Tun LuCI interface
 LUCI_PKGARCH:=all
 LUCI_DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +pdnsd-alt +wget +lua +libuci-lua \
 	+microsocks +dns2socks +shadowsocks-libev-ss-local +shadowsocksr-libev-ssr-local +shadowsocks-libev-ss-redir +simple-obfs +tcping +resolveip\

+ 26 - 66
luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua

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

+ 17 - 11
luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua

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

+ 210 - 165
luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua

@@ -1,118 +1,121 @@
 -- Copyright (C) 2017 yushi studio <[email protected]> github.com/ywb94
 -- Licensed to the public under the GNU General Public License v3.
-
 require "nixio.fs"
 require "luci.sys"
 require "luci.http"
 local m, s, o, kcp_enable
-local shadowsocksr = "shadowsocksr"
 local sid = arg[1]
 local uuid = luci.sys.exec("cat /proc/sys/kernel/random/uuid")
 
 local function isKcptun(file)
-if not nixio.fs.access(file, "rwx", "rx", "rx") then
-nixio.fs.chmod(file, 755)
-end
-local str = luci.sys.exec(file .. " -v | awk '{printf $1}'")
-return (str:lower() == "kcptun")
+	if not nixio.fs.access(file, "rwx", "rx", "rx") then
+		nixio.fs.chmod(file, 755)
+	end
+	local str = luci.sys.exec(file .. " -v | awk '{printf $1}'")
+	return (str:lower() == "kcptun")
 end
 
 local server_table = {}
 local encrypt_methods = {
-"none",
-"table",
-"rc4",
-"rc4-md5-6",
-"rc4-md5",
-"aes-128-cfb",
-"aes-192-cfb",
-"aes-256-cfb",
-"aes-128-ctr",
-"aes-192-ctr",
-"aes-256-ctr",
-"bf-cfb",
-"camellia-128-cfb",
-"camellia-192-cfb",
-"camellia-256-cfb",
-"cast5-cfb",
-"des-cfb",
-"idea-cfb",
-"rc2-cfb",
-"seed-cfb",
-"salsa20",
-"chacha20",
-"chacha20-ietf",
+	-- ssr
+	"none",
+	"table",
+	"rc4",
+	"rc4-md5-6",
+	"rc4-md5",
+	"aes-128-cfb",
+	"aes-192-cfb",
+	"aes-256-cfb",
+	"aes-128-ctr",
+	"aes-192-ctr",
+	"aes-256-ctr",
+	"bf-cfb",
+	"camellia-128-cfb",
+	"camellia-192-cfb",
+	"camellia-256-cfb",
+	"cast5-cfb",
+	"des-cfb",
+	"idea-cfb",
+	"rc2-cfb",
+	"seed-cfb",
+	"salsa20",
+	"chacha20",
+	"chacha20-ietf"
 }
 
 local encrypt_methods_ss = {
--- aead
-"aes-128-gcm",
-"aes-192-gcm",
-"aes-256-gcm",
-"chacha20-ietf-poly1305",
-"xchacha20-ietf-poly1305",
--- stream
-"table",
-"rc4",
-"rc4-md5",
-"aes-128-cfb",
-"aes-192-cfb",
-"aes-256-cfb",
-"aes-128-ctr",
-"aes-192-ctr",
-"aes-256-ctr",
-"bf-cfb",
-"camellia-128-cfb",
-"camellia-192-cfb",
-"camellia-256-cfb",
-"salsa20",
-"chacha20",
-"chacha20-ietf",
+	-- aead
+	"aes-128-gcm",
+	"aes-192-gcm",
+	"aes-256-gcm",
+	"chacha20-ietf-poly1305",
+	"xchacha20-ietf-poly1305",
+	-- stream
+	"table",
+	"rc4",
+	"rc4-md5",
+	"aes-128-cfb",
+	"aes-192-cfb",
+	"aes-256-cfb",
+	"aes-128-ctr",
+	"aes-192-ctr",
+	"aes-256-ctr",
+	"bf-cfb",
+	"camellia-128-cfb",
+	"camellia-192-cfb",
+	"camellia-256-cfb",
+	"salsa20",
+	"chacha20",
+	"chacha20-ietf"
 }
 
 local protocol = {
-"origin",
-"verify_deflate",
-"auth_sha1_v4",
-"auth_aes128_sha1",
-"auth_aes128_md5",
-"auth_chain_a",
-"auth_chain_b",
-"auth_chain_c",
-"auth_chain_d",
-"auth_chain_e",
-"auth_chain_f",
+	-- ssr
+	"origin",
+	"verify_deflate",
+	"auth_sha1_v4",
+	"auth_aes128_sha1",
+	"auth_aes128_md5",
+	"auth_chain_a",
+	"auth_chain_b",
+	"auth_chain_c",
+	"auth_chain_d",
+	"auth_chain_e",
+	"auth_chain_f"
 }
 
 obfs = {
-"plain",
-"http_simple",
-"http_post",
-"random_head",
-"tls1.2_ticket_auth",
+	-- ssr
+	"plain",
+	"http_simple",
+	"http_post",
+	"random_head",
+	"tls1.2_ticket_auth"
 }
 
 local securitys = {
-"auto",
-"none",
-"aes-128-gcm",
-"chacha20-poly1305"
+	-- vmess
+	"auto",
+	"none",
+	"aes-128-gcm",
+	"chacha20-poly1305"
 }
 
 local flows = {
-"xtls-rprx-origin",
-"xtls-rprx-origin-udp443",
-"xtls-rprx-direct",
-"xtls-rprx-direct-udp443",
-"xtls-rprx-splice",
-"xtls-rprx-splice-udp443"
+	-- xlts
+	"xtls-rprx-origin",
+	"xtls-rprx-origin-udp443",
+	"xtls-rprx-direct",
+	"xtls-rprx-direct-udp443",
+	"xtls-rprx-splice",
+	"xtls-rprx-splice-udp443"
 }
 
-m = Map(shadowsocksr, translate("Edit ShadowSocksR Server"))
+m = Map("shadowsocksr", translate("Edit ShadowSocksR Server"))
 m.redirect = luci.dispatcher.build_url("admin/services/shadowsocksr/servers")
-if m.uci:get(shadowsocksr, sid) ~= "servers" then
-luci.http.redirect(m.redirect)
-return
+if m.uci:get("shadowsocksr", sid) ~= "servers" then
+	luci.http.redirect(m.redirect)
+	return
 end
 
 -- [[ Servers Setting ]]--
@@ -126,30 +129,36 @@ 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/ssr-redir") then
+	o:value("ssr", translate("ShadowsocksR"))
+end
 if nixio.fs.access("/usr/bin/ss-redir") then
-o:value("ss", translate("Shadowsocks New Version"))
+	o:value("ss", translate("Shadowsocks New Version"))
 end
-if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/bin/xray/xray") or nixio.fs.access("/usr/bin/v2ray/v2ray") or nixio.fs.access("/usr/bin/v2ray") then
-o:value("vmess", translate("Vmess"))
-o:value("vless", translate("VLESS"))
+if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/bin/v2ray") then
+	o:value("vmess", translate("Vmess"))
+	o:value("vless", translate("VLESS"))
 end
 if nixio.fs.access("/usr/sbin/trojan") then
-o:value("trojan", translate("Trojan"))
+	o:value("trojan", translate("Trojan"))
 end
 if nixio.fs.access("/usr/bin/naive") then
-o:value("naiveproxy", translate("NaiveProxy"))
+	o:value("naiveproxy", translate("NaiveProxy"))
 end
 if nixio.fs.access("/usr/sbin/redsocks2") then
-o:value("socks5", translate("Socks5"))
-o:value("tun", translate("Network Tunnel"))
+	o:value("socks5", translate("Socks5"))
+	o:value("tun", translate("Network Tunnel"))
 end
 o.description = translate("Using incorrect encryption mothod may causes service fail to start")
 
 o = s:option(Value, "alias", translate("Alias(optional)"))
 
 o = s:option(ListValue, "iface", translate("Network interface to use"))
-for _, e in ipairs(luci.sys.net.devices()) do if e ~= "lo" then o:value(e) end end
+for _, e in ipairs(luci.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")
 
@@ -195,26 +204,54 @@ o:depends("type", "naiveproxy")
 o:depends({type = "socks5", auth_enable = true})
 
 o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
-for _, v in ipairs(encrypt_methods) do o:value(v) end
+for _, v in ipairs(encrypt_methods) do
+	o:value(v)
+end
 o.rmempty = true
 o:depends("type", "ssr")
 
 o = s:option(ListValue, "encrypt_method_ss", translate("Encrypt Method"))
-for _, v in ipairs(encrypt_methods_ss) do o:value(v) end
+for _, v in ipairs(encrypt_methods_ss) do
+	o:value(v)
+end
 o.rmempty = true
 o:depends("type", "ss")
 
 -- Shadowsocks Plugin
-o = s:option(Value, "plugin", translate("Plugin"))
+o = s:option(ListValue, "plugin", translate("Obfs"))
+o:value("", translate("None"))
+if nixio.fs.access("/usr/bin/obfs-local") then
+	o:value("obfs-local", translate("simple-obfs"))
+end
+if nixio.fs.access("/usr/bin/v2ray-plugin") then
+	o:value("v2ray-plugin", translate("v2ray-plugin"))
+end
 o.rmempty = true
 o:depends("type", "ss")
 
-o = s:option(Value, "plugin_opts", translate("Plugin Opts"))
+o = s:option(ListValue, "simple_obfs", translate("Plugin Opts"))
+o:value("obfs=tls;obfs-host=", translate("TLS"))
+o:value("obfs=http;obfs-host=", translate("HTTP"))
+o:depends("plugin", "obfs-local")
+o.rmempty = true
+
+o = s:option(ListValue, "v2ray_plugin", translate("Plugin Opts"))
+o:value("tls;host=", translate("TLS"))
+o:value("mode=quic;host=", translate("QUIC"))
+o:value("none", translate("HTTP"))
+o:depends("plugin", "v2ray-plugin")
 o.rmempty = true
-o:depends("type", "ss")
+
+o = s:option(Value, "plugin_opts", translate("Plugin Opts"), translate("Please fill in the Host, for example: www.baidu.com"))
+o.rmempty = true
+o:depends({type = "ss", plugin = "obfs-local"})
+o:depends({type = "ss", v2ray_plugin = "tls;host="})
+o:depends({type = "ss", v2ray_plugin = "mode=quic;host="})
 
 o = s:option(ListValue, "protocol", translate("Protocol"))
-for _, v in ipairs(protocol) do o:value(v) end
+for _, v in ipairs(protocol) do
+	o:value(v)
+end
 o.rmempty = true
 o:depends("type", "ssr")
 
@@ -222,7 +259,9 @@ o = s:option(Value, "protocol_param", translate("Protocol param(optional)"))
 o:depends("type", "ssr")
 
 o = s:option(ListValue, "obfs", translate("Obfs"))
-for _, v in ipairs(obfs) do o:value(v) end
+for _, v in ipairs(obfs) do
+	o:value(v)
+end
 o.rmempty = true
 o:depends("type", "ssr")
 
@@ -251,7 +290,9 @@ o:depends("type", "vless")
 
 -- 加密方式
 o = s:option(ListValue, "security", translate("Encrypt Method"))
-for _, v in ipairs(securitys) do o:value(v, v:upper()) end
+for _, v in ipairs(securitys) do
+	o:value(v, v:upper())
+end
 o.rmempty = true
 o:depends("type", "vmess")
 
@@ -267,7 +308,6 @@ o:depends("type", "vmess")
 o:depends("type", "vless")
 
 -- [[ TCP部分 ]]--
-
 -- TCP伪装
 o = s:option(ListValue, "tcp_guise", translate("Camouflage Type"))
 o:depends("transport", "tcp")
@@ -286,7 +326,6 @@ o:depends("tcp_guise", "http")
 o.rmempty = true
 
 -- [[ WS部分 ]]--
-
 -- WS域名
 o = s:option(Value, "ws_host", translate("WebSocket Host"))
 o:depends({transport = "ws", tls = false})
@@ -310,7 +349,6 @@ o:depends("transport", "h2")
 o.rmempty = true
 
 -- [[ QUIC部分 ]]--
-
 o = s:option(ListValue, "quic_security", translate("QUIC Security"))
 o:depends("transport", "quic")
 o:value("none", translate("None"))
@@ -329,19 +367,18 @@ o:value("none", translate("None"))
 o:value("srtp", translate("VideoCall (SRTP)"))
 o:value("utp", translate("BitTorrent (uTP)"))
 o:value("wechat-video", translate("WechatVideo"))
-o:value("dtls", "DTLS 1.2")
-o:value("wireguard", "WireGuard")
+o:value("dtls", translate("DTLS 1.2"))
+o:value("wireguard", translate("WireGuard"))
 
 -- [[ mKCP部分 ]]--
-
 o = s:option(ListValue, "kcp_guise", translate("Camouflage Type"))
 o:depends("transport", "kcp")
 o:value("none", translate("None"))
 o:value("srtp", translate("VideoCall (SRTP)"))
 o:value("utp", translate("BitTorrent (uTP)"))
 o:value("wechat-video", translate("WechatVideo"))
-o:value("dtls", "DTLS 1.2")
-o:value("wireguard", "WireGuard")
+o:value("dtls", translate("DTLS 1.2"))
+o:value("wireguard", translate("WireGuard"))
 o.rmempty = true
 
 o = s:option(Value, "mtu", translate("MTU"))
@@ -397,16 +434,18 @@ o:depends({type = "vless", xtls = false})
 o:depends("type", "trojan")
 
 -- XTLS
-if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/bin/xray/xray") then
-o = s:option(Flag, "xtls", translate("XTLS"))
-o.rmempty = true
-o.default = "0"
-o:depends({type = "vless", transport = "tcp", tls = false})
+if nixio.fs.access("/usr/bin/xray") then
+	o = s:option(Flag, "xtls", translate("XTLS"))
+	o.rmempty = true
+	o.default = "0"
+	o:depends({type = "vless", transport = "tcp", tls = false})
 end
 
 -- Flow
 o = s:option(Value, "vless_flow", translate("Flow"))
-for _, v in ipairs(flows) do o:value(v, v) end
+for _, v in ipairs(flows) do
+	o:value(v, v)
+end
 o.rmempty = true
 o.default = "xtls-rprx-splice"
 o:depends("xtls", true)
@@ -453,24 +492,30 @@ cert_dir = "/etc/ssl/private/"
 local path
 
 luci.http.setfilehandler(function(meta, chunk, eof)
-if not fd then
-if (not meta) or (not meta.name) or (not meta.file) then return end
-fd = nixio.open(cert_dir .. meta.file, "w")
-if not fd then
-path = translate("Create upload file error.")
-return
-end
-end
-if chunk and fd then fd:write(chunk) end
-if eof and fd then
-fd:close()
-fd = nil
-path = '/etc/ssl/private/' .. meta.file .. ''
-end
+	if not fd then
+		if (not meta) or (not meta.name) or (not meta.file) then
+			return
+		end
+		fd = nixio.open(cert_dir .. meta.file, "w")
+		if not fd then
+			path = translate("Create upload file error.")
+			return
+		end
+	end
+	if chunk and fd then
+		fd:write(chunk)
+	end
+	if eof and fd then
+		fd:close()
+		fd = nil
+		path = '/etc/ssl/private/' .. meta.file .. ''
+	end
 end)
 if luci.http.formvalue("upload") then
-local f = luci.http.formvalue("ulfile")
-if #f <= 0 then path = translate("No specify upload file.") end
+	local f = luci.http.formvalue("ulfile")
+	if #f <= 0 then
+		path = translate("No specify upload file.")
+	end
 end
 
 o = s:option(Value, "certpath", translate("Current Certificate Path"))
@@ -496,40 +541,40 @@ o.default = 1234
 o.rmempty = false
 
 if nixio.fs.access("/usr/bin/kcptun-client") then
-kcp_enable = s:option(Flag, "kcp_enable", translate("KcpTun Enable"), translate("bin:/usr/bin/kcptun-client"))
-kcp_enable.rmempty = true
-kcp_enable.default = "0"
-kcp_enable:depends("type", "ssr")
-kcp_enable:depends("type", "ss")
-
-o = s:option(Value, "kcp_port", translate("KcpTun Port"))
-o.datatype = "port"
-o.default = 4000
-function o.validate(self, value, section)
-local kcp_file = "/usr/bin/kcptun-client"
-local enable = kcp_enable:formvalue(section) or kcp_enable.disabled
-if enable == kcp_enable.enabled then
-if not nixio.fs.access(kcp_file) then
-return nil, translate("Haven't a Kcptun executable file")
-elseif not isKcptun(kcp_file) then
-return nil, translate("Not a Kcptun executable file")
-end
-end
-
-return value
-end
-o:depends("type", "ssr")
-o:depends("type", "ss")
-
-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")
+	kcp_enable = s:option(Flag, "kcp_enable", translate("KcpTun Enable"), translate("bin:/usr/bin/kcptun-client"))
+	kcp_enable.rmempty = true
+	kcp_enable.default = "0"
+	kcp_enable:depends("type", "ssr")
+	kcp_enable:depends("type", "ss")
+
+	o = s:option(Value, "kcp_port", translate("KcpTun Port"))
+	o.datatype = "port"
+	o.default = 4000
+	function o.validate(self, value, section)
+		local kcp_file = "/usr/bin/kcptun-client"
+		local enable = kcp_enable:formvalue(section) or kcp_enable.disabled
+		if enable == kcp_enable.enabled then
+			if not nixio.fs.access(kcp_file) then
+				return nil, translate("Haven't a Kcptun executable file")
+			elseif not isKcptun(kcp_file) then
+				return nil, translate("Not a Kcptun executable file")
+			end
+		end
+
+		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

+ 16 - 13
luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua

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

+ 8 - 8
luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/control.lua

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

+ 3 - 3
luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/log.lua

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

+ 36 - 37
luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua

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

+ 35 - 36
luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua

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

+ 16 - 23
luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua

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

+ 75 - 68
luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua

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

+ 0 - 1
luci-app-ssr-plus/luasrc/view/shadowsocksr/check.htm

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

+ 1 - 12
luci-app-ssr-plus/luasrc/view/shadowsocksr/checkport.htm

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

+ 8 - 6
luci-app-ssr-plus/luasrc/view/shadowsocksr/refresh.htm

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

+ 25 - 0
luci-app-ssr-plus/luasrc/view/shadowsocksr/reset.htm

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

+ 1 - 19
luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm

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

+ 0 - 8
luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm

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

+ 54 - 0
luci-app-ssr-plus/po/zh-cn/ssr-plus.po

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

+ 0 - 42
luci-app-ssr-plus/root/etc/config/shadowsocksr

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

文件差異過大導致無法顯示
+ 486 - 376
luci-app-ssr-plus/root/etc/init.d/shadowsocksr


+ 0 - 0
luci-app-ssr-plus/root/etc/ssr/ad.conf → luci-app-ssr-plus/root/etc/ssrplus/ad.conf


+ 0 - 0
luci-app-ssr-plus/root/etc/ssr/black.list → luci-app-ssr-plus/root/etc/ssrplus/black.list


+ 2 - 0
luci-app-ssr-plus/root/etc/ssr/china_ssr.txt → luci-app-ssr-plus/root/etc/ssrplus/china_ssr.txt

@@ -4109,6 +4109,8 @@
 103.159.142.0/23
 103.160.32.0/23
 103.160.34.0/23
+103.160.112.0/23
+103.160.114.0/23
 103.192.0.0/22
 103.192.4.0/22
 103.192.8.0/22

+ 0 - 0
luci-app-ssr-plus/root/etc/ssr/deny.list → luci-app-ssr-plus/root/etc/ssrplus/deny.list


+ 0 - 0
luci-app-ssr-plus/root/etc/ssr/gfw_base.conf → luci-app-ssr-plus/root/etc/ssrplus/gfw_base.conf


+ 10 - 0
luci-app-ssr-plus/root/etc/ssr/gfw_list.conf → luci-app-ssr-plus/root/etc/ssrplus/gfw_list.conf

@@ -4916,6 +4916,8 @@ server=/cmhalq.com/127.0.0.1#5335
 ipset=/cmhalq.com/gfwlist
 server=/cmpaas.com/127.0.0.1#5335
 ipset=/cmpaas.com/gfwlist
+server=/cmu.edu/127.0.0.1#5335
+ipset=/cmu.edu/gfwlist
 server=/cnbc.com/127.0.0.1#5335
 ipset=/cnbc.com/gfwlist
 server=/cnbcfm.com/127.0.0.1#5335
@@ -11166,6 +11168,8 @@ server=/keytransparency.foo/127.0.0.1#5335
 ipset=/keytransparency.foo/gfwlist
 server=/keytransparency.org/127.0.0.1#5335
 ipset=/keytransparency.org/gfwlist
+server=/kfs.io/127.0.0.1#5335
+ipset=/kfs.io/gfwlist
 server=/khanacademy.org/127.0.0.1#5335
 ipset=/khanacademy.org/gfwlist
 server=/kickshatchannel.com/127.0.0.1#5335
@@ -11250,6 +11254,12 @@ server=/kirbysuperstarultra.com/127.0.0.1#5335
 ipset=/kirbysuperstarultra.com/gfwlist
 server=/kissjav.com/127.0.0.1#5335
 ipset=/kissjav.com/gfwlist
+server=/kkbox.com/127.0.0.1#5335
+ipset=/kkbox.com/gfwlist
+server=/kktix.com/127.0.0.1#5335
+ipset=/kktix.com/gfwlist
+server=/kktv.me/127.0.0.1#5335
+ipset=/kktv.me/gfwlist
 server=/klik.me/127.0.0.1#5335
 ipset=/klik.me/gfwlist
 server=/knovel.com/127.0.0.1#5335

+ 0 - 0
luci-app-ssr-plus/root/etc/ssr/netflix.list → luci-app-ssr-plus/root/etc/ssrplus/netflix.list


+ 0 - 0
luci-app-ssr-plus/root/etc/ssr/netflixip.list → luci-app-ssr-plus/root/etc/ssrplus/netflixip.list


+ 0 - 0
luci-app-ssr-plus/root/etc/ssr/oversea_list.conf → luci-app-ssr-plus/root/etc/ssrplus/oversea_list.conf


+ 0 - 0
luci-app-ssr-plus/root/etc/ssr/white.list → luci-app-ssr-plus/root/etc/ssrplus/white.list


+ 13 - 14
luci-app-ssr-plus/root/etc/uci-defaults/luci-ssr-plus

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

+ 0 - 10
luci-app-ssr-plus/root/usr/bin/ssr-ad

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

+ 0 - 27
luci-app-ssr-plus/root/usr/bin/ssr-gfw

@@ -1,27 +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
-rm -f /tmp/gfwlist.txt
-}
-if (grep -w 'google' /tmp/ssr-update.$1 >/dev/null) ;then
-cp -rf /tmp/ssr-update.$1 /tmp/gfw.txt
-else
-generate_china_banned /tmp/ssr-update.$1 >/tmp/gfw.txt
-fi
-sed '/.*/s/.*/server=\/&\/127.0.0.1#5335\nipset=\/&\/gfwlist/' /tmp/gfw.txt >/tmp/ssr-update.$1
-rm -f /tmp/gfw.txt

+ 21 - 61
luci-app-ssr-plus/root/usr/bin/ssr-monitor

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

+ 72 - 72
luci-app-ssr-plus/root/usr/bin/ssr-rules

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

+ 15 - 26
luci-app-ssr-plus/root/usr/bin/ssr-switch

@@ -7,31 +7,20 @@
 # See /LICENSE for more information.
 #
 
+. $IPKG_INSTROOT/etc/init.d/shadowsocksr
 LOCK_FILE="/var/lock/ssr-switch.lock"
 [ -f "$LOCK_FILE" ] && exit 2
 touch "$LOCK_FILE"
+LOG_FILE=/var/log/ssrplus.log
+
 cycle_time=60
 switch_time=3
 normal_flag=0
 server_locate=0
 server_count=0
-NAME=shadowsocksr
 ENABLE_SERVER=nil
-CONFIG_SWTICH_FILE=/var/etc/${NAME}_t.json
-
 [ -n "$1" ] && cycle_time=$1
 [ -n "$2" ] && switch_time=$2
-
-uci_get_by_name() {
-	local ret=$(uci get $NAME.$1.$2 2>/dev/null)
-	echo ${ret:=$3}
-}
-
-uci_get_by_type() {
-	local ret=$(uci get $NAME.@$1[0].$2 2>/dev/null)
-	echo ${ret:=$3}
-}
-
 DEFAULT_SERVER=$(uci_get_by_type global global_server)
 CURRENT_SERVER=$DEFAULT_SERVER
 
@@ -42,11 +31,11 @@ check_proxy() {
 	for i in $(seq 1 $try_count); do
 		/usr/bin/ssr-check www.google.com 80 $switch_time 1
 		if [ "$?" == "0" ]; then
-			# echo "$(date "+%Y-%m-%d %H:%M:%S") Check Google Proxy Success, count=$i" >> /tmp/ssrplus.log
+			# echolog "Check Google Proxy Success, count=$i"
 			result=0
 			break
 		else
-			# echo "$(date "+%Y-%m-%d %H:%M:%S") Check Google Proxy Fail, count=$i" >> /tmp/ssrplus.log
+			# echolog "Check Google Proxy Fail, count=$i"
 			/usr/bin/ssr-check www.baidu.com 80 $switch_time 1
 			if [ "$?" == "0" ]; then
 				result=1
@@ -123,44 +112,44 @@ start() {
 		#判断当前代理是否为缺省服务器
 		if [ "$CURRENT_SERVER" != "$DEFAULT_SERVER" ]; then
 			#echo "not default proxy"
-			echo "$(date "+%Y-%m-%d %H:%M:%S") Current server is not default Main server, try to switch back." >>/tmp/ssrplus.log
+			echolog "Current server is not default Main server, try to switch back."
 			#检查缺省服务器是否正常
 			if test_proxy $DEFAULT_SERVER; then
 				#echo "switch to default proxy"
-				echo "$(date "+%Y-%m-%d %H:%M:%S") Main server is avilable." >>/tmp/ssrplus.log
+				echolog "Main server is avilable."
 				#缺省服务器正常,切换回来
 				CURRENT_SERVER=$DEFAULT_SERVER
 				switch_proxy $CURRENT_SERVER
-				echo "$(date "+%Y-%m-%d %H:%M:%S") switch to default "$(uci_get_by_name $CURRENT_SERVER alias)" proxy!" >>/tmp/ssrplus.log
+				echolog "switch to default "$(uci_get_by_name $CURRENT_SERVER alias)" proxy!"
 			else
-				echo "$(date "+%Y-%m-%d %H:%M:%S") Main server is NOT avilable.Continue using current server." >>/tmp/ssrplus.log
+				echolog "Main server is NOT avilable.Continue using current server."
 			fi
 		fi
 		#判断当前代理是否正常
-		#echo "$(date "+%Y-%m-%d %H:%M:%S") Start checking if the current server is available." >>/tmp/ssrplus.log
+		#echolog "Start checking if the current server is available."
 		check_proxy
 		current_ret=$?
 		if [ "$current_ret" == "1" ]; then
 			#当前代理错误,判断有无可用的服务器
 			#echo "current error"
-			echo "$(date "+%Y-%m-%d %H:%M:%S") Current server error, try to switch another server." >>/tmp/ssrplus.log
+			echolog "Current server error, try to switch another server."
 			select_proxy
 			if [ "$ENABLE_SERVER" != nil ]; then
 				#有其他服务器可用,进行切换
 				#echo $(uci_get_by_name $new_proxy server)
-				echo "$(date "+%Y-%m-%d %H:%M:%S") Another server is avilable, now switching server." >>/tmp/ssrplus.log
+				echolog "Another server is avilable, now switching server."
 				CURRENT_SERVER=$ENABLE_SERVER
 				switch_proxy $CURRENT_SERVER
 				normal_flag=1
-				echo "$(date "+%Y-%m-%d %H:%M:%S") Switch to "$(uci_get_by_name $CURRENT_SERVER alias)" proxy!" >>/tmp/ssrplus.log
+				echolog "Switch to "$(uci_get_by_name $CURRENT_SERVER alias)" proxy!"
 			else
 				switch_proxy $CURRENT_SERVER
 				normal_flag=1
-				echo "$(date "+%Y-%m-%d %H:%M:%S") Try restart current server." >>/tmp/ssrplus.log
+				echolog "Try restart current server."
 			fi
 		else
 			normal_flag=0
-			# echo "$(date "+%Y-%m-%d %H:%M:%S") ShadowsocksR No Problem." >>/tmp/ssrplus.log
+			# echolog "ShadowsocksR No Problem."
 		fi
 	done
 }

+ 6 - 6
luci-app-ssr-plus/root/usr/share/rpcd/acl.d/luci-app-ssr-plus.json

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

+ 1 - 1
luci-app-ssr-plus/root/usr/share/shadowsocksr/chinaipset.sh

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

+ 171 - 0
luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua

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

+ 85 - 62
luci-app-ssr-plus/root/usr/share/shadowsocksr/genred2config.sh

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

+ 0 - 40
luci-app-ssr-plus/root/usr/share/shadowsocksr/gentrojanconfig.lua

@@ -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))

+ 0 - 117
luci-app-ssr-plus/root/usr/share/shadowsocksr/genv2config.lua

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

+ 38 - 50
luci-app-ssr-plus/root/usr/share/shadowsocksr/gfw2ipset.sh

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

+ 1 - 1
luci-app-ssr-plus/root/usr/share/shadowsocksr/ssrplusupdate.sh

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

+ 19 - 30
luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua

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

+ 166 - 19
luci-app-ssr-plus/root/usr/share/shadowsocksr/update.lua

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

+ 3 - 3
tcping/Makefile

@@ -12,9 +12,9 @@ PKG_VERSION:=0.3
 PKG_RELEASE:=1
 
 PKG_SOURCE_PROTO:=git
-PKG_SOURCE_URL:=https://github.com/Lienol/tcping
+PKG_SOURCE_URL:=https://github.com/Mattraks/tcping
 PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
-PKG_SOURCE_VERSION:=db9101834732dac9aaa59dbb7fb9c74612dbf723
+PKG_SOURCE_VERSION:=de2b709f8c386507678041d11102c671d470fea7
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
 
@@ -24,7 +24,7 @@ define Package/tcping
 	SECTION:=net
 	CATEGORY:=Network
 	TITLE:=tcping measures the latency of a tcp-connection
-	URL:=https://github.com/Lienol/tcping
+	URL:=https://github.com/Mattraks/tcping
 endef
 
 define Package/tcping/description

+ 13 - 0
tcping/patches/0001-Remove-strip.patch

@@ -0,0 +1,13 @@
+diff --git a/Makefile b/Makefile
+index 1778ebf..e44119e 100644
+--- a/Makefile
++++ b/Makefile
+@@ -9,7 +9,7 @@ all: tcping
+ 
+ tcping: $(OBJS)
+ 	$(CC) $(OBJS) $(LDFLAGS) -o tcping
+-	strip tcping
++
+ 
+ install: tcping
+ 	cp tcping $(DESTDIR)/usr/bin

部分文件因文件數量過多而無法顯示