mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-19 14:13:30 +00:00
add NEW openwrt ssr luci to support multi-server subscription and switch (Alpha)
This commit is contained in:
parent
7cedf8f3de
commit
a180d3fb62
238
package/lean/openwrt-ssr/Makefile
Normal file
238
package/lean/openwrt-ssr/Makefile
Normal file
@ -0,0 +1,238 @@
|
||||
#
|
||||
# Copyright (C) 2017 OpenWrt-ssr
|
||||
# Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=openwrt-ssr
|
||||
PKG_VERSION:=3.1.1
|
||||
# PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/shadowsocksrr/shadowsocksr-libev
|
||||
PKG_SOURCE_VERSION:=d4904568c0bd7e0861c0cbfeaa43740f404db214
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
PKG_LICENSE:=GPLv3
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_MAINTAINER:=Akkariiin
|
||||
|
||||
#PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
PKG_INSTALL:=1
|
||||
PKG_FIXUP:=autoreconf
|
||||
PKG_USE_MIPS16:=0
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/openwrt-ssr/Default
|
||||
SECTION:=luci
|
||||
CATEGORY:=LuCI
|
||||
SUBMENU:=3. Applications
|
||||
TITLE:=shadowsocksR-libev LuCI interface
|
||||
URL:=https://github.com/MrTheUniverse/openwrt-ssr
|
||||
VARIANT:=$(1)
|
||||
DEPENDS:=$(3)
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
|
||||
Package/luci-app-shadowsocksR = $(call Package/openwrt-ssr/Default,openssl,(OpenSSL),+libopenssl +libpthread +ipset +ip-full +iptables-mod-tproxy +libpcre +zlib)
|
||||
Package/luci-app-shadowsocksR-Client = $(call Package/openwrt-ssr/Default,openssl,(OpenSSL),+libopenssl +libpthread +ipset +ip-full +iptables-mod-tproxy +libpcre +zlib)
|
||||
Package/luci-app-shadowsocksR-Server = $(call Package/openwrt-ssr/Default,openssl,(OpenSSL),+libopenssl +libpthread +ipset +ip-full +iptables-mod-tproxy +libpcre +zlib)
|
||||
Package/luci-app-shadowsocksR-GFW = $(call Package/openwrt-ssr/Default,openssl,(OpenSSL),+libopenssl +libpthread +ipset +ip-full +iptables-mod-tproxy +libpcre +zlib +dnsmasq-full +coreutils +coreutils-base64 +curl +bash +bind-dig +pdnsd-alt)
|
||||
|
||||
define Package/openwrt-ssr/description
|
||||
LuCI Support for $(1).
|
||||
endef
|
||||
|
||||
Package/luci-app-shadowsocksR/description = $(call Package/openwrt-ssr/description,shadowsocksr-libev Client and Server)
|
||||
Package/luci-app-shadowsocksR-Client/description = $(call Package/openwrt-ssr/description,shadowsocksr-libev Client)
|
||||
Package/luci-app-shadowsocksR-Server/description = $(call Package/openwrt-ssr/description,shadowsocksr-libev Server)
|
||||
Package/luci-app-shadowsocksR-GFW/description = $(call Package/openwrt-ssr/description,shadowsocksr-libev GFW)
|
||||
|
||||
define Package/openwrt-ssr/prerm
|
||||
#!/bin/sh
|
||||
# check if we are on real system
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
echo "Removing rc.d symlink for shadowsocksr"
|
||||
/etc/init.d/shadowsocksr disable
|
||||
/etc/init.d/shadowsocksr stop
|
||||
echo "Removing firewall rule for shadowsocksr"
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete firewall.shadowsocksr
|
||||
commit firewall
|
||||
EOF
|
||||
if [ "$(1)" = "GFW" ] ;then
|
||||
sed -i '/conf-dir/d' /etc/dnsmasq.conf
|
||||
/etc/init.d/dnsmasq restart
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
endef
|
||||
|
||||
Package/luci-app-shadowsocksR/prerm = $(call Package/openwrt-ssr/prerm,shadowsocksr)
|
||||
Package/luci-app-shadowsocksR-Client/prerm = $(call Package/openwrt-ssr/prerm,shadowsocksr)
|
||||
Package/luci-app-shadowsocksR-GFW/prerm = $(call Package/openwrt-ssr/prerm,GFW)
|
||||
|
||||
define Package/luci-app-shadowsocksR-Server/prerm
|
||||
#!/bin/sh
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
/etc/init.d/shadowsocksr disable
|
||||
/etc/init.d/shadowsocksr stop
|
||||
fi
|
||||
exit 0
|
||||
|
||||
endef
|
||||
|
||||
|
||||
define Package/openwrt-ssr/postinst
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete firewall.shadowsocksr
|
||||
set firewall.shadowsocksr=include
|
||||
set firewall.shadowsocksr.type=script
|
||||
set firewall.shadowsocksr.path=/var/etc/shadowsocksr.include
|
||||
set firewall.shadowsocksr.reload=1
|
||||
commit firewall
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
( . /etc/uci-defaults/luci-shadowsocksr ) && rm -f /etc/uci-defaults/luci-shadowsocksr
|
||||
chmod 755 /etc/init.d/shadowsocksr >/dev/null 2>&1
|
||||
/etc/init.d/shadowsocksr enable >/dev/null 2>&1
|
||||
if [ "$(1)" = "GFW" ] ;then
|
||||
if [ -f "/etc/dnsmasq.conf" ]; then
|
||||
str=`cat /etc/dnsmasq.conf|grep conf-dir`
|
||||
if [ -z "$str" ]; then
|
||||
echo "conf-dir=/etc/dnsmasq.ssr" >> /etc/dnsmasq.conf
|
||||
else
|
||||
sed -i '/conf-dir/d' /etc/dnsmasq.conf
|
||||
echo "conf-dir=/etc/dnsmasq.ssr" >> /etc/dnsmasq.conf
|
||||
fi
|
||||
else
|
||||
echo "conf-dir=/etc/dnsmasq.ssr" > /etc/dnsmasq.conf
|
||||
fi
|
||||
/etc/init.d/dnsmasq restart
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
endef
|
||||
|
||||
|
||||
Package/luci-app-shadowsocksR/postinst = $(call Package/openwrt-ssr/postinst,shadowsocksr)
|
||||
Package/luci-app-shadowsocksR-Client/postinst = $(call Package/openwrt-ssr/postinst,shadowsocksr)
|
||||
Package/luci-app-shadowsocksR-GFW/postinst = $(call Package/openwrt-ssr/postinst,GFW)
|
||||
|
||||
define Package/luci-app-shadowsocksR-Server/postinst
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
( . /etc/uci-defaults/luci-shadowsocksr ) && rm -f /etc/uci-defaults/luci-shadowsocksr
|
||||
chmod 755 /etc/init.d/shadowsocksr >/dev/null 2>&1
|
||||
/etc/init.d/shadowsocksr enable >/dev/null 2>&1
|
||||
fi
|
||||
exit 0
|
||||
endef
|
||||
|
||||
|
||||
|
||||
CONFIGURE_ARGS += --disable-documentation --disable-ssp
|
||||
|
||||
define Install/common
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller
|
||||
$(INSTALL_DATA) ./files/luci/controller/shadowsocksr.lua $(1)/usr/lib/lua/luci/controller/shadowsocksr.lua
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
|
||||
$(INSTALL_DATA) ./files/luci/i18n/shadowsocksr.*.lmo $(1)/usr/lib/lua/luci/i18n
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/shadowsocksr
|
||||
$(INSTALL_DATA) ./files/luci/model/cbi/shadowsocksr/*.lua $(1)/usr/lib/lua/luci/model/cbi/shadowsocksr/
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/view/shadowsocksr
|
||||
$(INSTALL_DATA) ./files/luci/view/shadowsocksr/*.htm $(1)/usr/lib/lua/luci/view/shadowsocksr/
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/root/etc/uci-defaults/luci-shadowsocksr $(1)/etc/uci-defaults/luci-shadowsocksr
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_DATA) ./files/shadowsocksr.config $(1)/etc/config/shadowsocksr
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.init $(1)/etc/init.d/shadowsocksr
|
||||
endef
|
||||
|
||||
define Package/openwrt-ssr/install
|
||||
$(call Install/common,$(1))
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-redir $(1)/usr/bin/ssr-redir
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-local $(1)/usr/bin/ssr-local
|
||||
$(LN) /usr/bin/ssr-local $(1)/usr/bin/ssr-tunnel
|
||||
#$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-server $(1)/usr/bin/ssr-server
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-check $(1)/usr/bin/ssr-check
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.rule $(1)/usr/bin/ssr-rules
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.monitor $(1)/usr/bin/ssr-monitor
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.switch $(1)/usr/bin/ssr-switch
|
||||
$(INSTALL_DIR) $(1)/etc
|
||||
$(INSTALL_DATA) ./files/china_ssr.txt $(1)/etc/china_ssr.txt
|
||||
$(INSTALL_DIR) $(1)/usr/share/shadowsocksr
|
||||
$(INSTALL_DATA) ./files/root/usr/share/shadowsocksr/*.sh $(1)/usr/share/shadowsocksr/
|
||||
endef
|
||||
|
||||
Package/luci-app-shadowsocksR/install = $(call Package/openwrt-ssr/install,$(1),shadowsocksr)
|
||||
|
||||
define Package/luci-app-shadowsocksR-Client/install
|
||||
$(call Install/common,$(1))
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-redir $(1)/usr/bin/ssr-redir
|
||||
#$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-tunnel $(1)/usr/bin/ssr-tunnel
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-local $(1)/usr/bin/ssr-local
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-check $(1)/usr/bin/ssr-check
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.rule $(1)/usr/bin/ssr-rules
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.monitor $(1)/usr/bin/ssr-monitor
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.switch $(1)/usr/bin/ssr-switch
|
||||
$(INSTALL_DIR) $(1)/etc
|
||||
$(INSTALL_DATA) ./files/china_ssr.txt $(1)/etc/china_ssr.txt
|
||||
endef
|
||||
|
||||
define Package/luci-app-shadowsocksR-Server/install
|
||||
$(call Install/common,$(1))
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-server $(1)/usr/bin/ssr-server
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.rule $(1)/usr/bin/ssr-rules
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.monitor $(1)/usr/bin/ssr-monitor
|
||||
endef
|
||||
|
||||
define Package/luci-app-shadowsocksR-GFW/install
|
||||
$(call Install/common,$(1))
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-redir $(1)/usr/bin/ssr-redir
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-local $(1)/usr/bin/ssr-local
|
||||
$(LN) /usr/bin/ssr-local $(1)/usr/bin/ssr-tunnel
|
||||
#$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-server $(1)/usr/bin/ssr-server
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-check $(1)/usr/bin/ssr-check
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.rule $(1)/usr/bin/ssr-rules
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.monitor $(1)/usr/bin/ssr-monitor
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.gfw $(1)/usr/bin/ssr-gfw
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.ad $(1)/usr/bin/ssr-ad
|
||||
$(INSTALL_BIN) ./files/shadowsocksr.switch $(1)/usr/bin/ssr-switch
|
||||
$(INSTALL_DIR) $(1)/etc/dnsmasq.ssr
|
||||
$(INSTALL_DATA) ./files/gfw_list.conf $(1)/etc/dnsmasq.ssr/gfw_list.conf
|
||||
$(INSTALL_DATA) ./files/custom_forward.conf $(1)/etc/dnsmasq.ssr/custom_forward.conf
|
||||
$(INSTALL_DATA) ./files/ad.conf $(1)/etc/dnsmasq.ssr/ad.conf
|
||||
$(INSTALL_DIR) $(1)/etc
|
||||
$(INSTALL_DATA) ./files/china_ssr.txt $(1)/etc/china_ssr.txt
|
||||
$(INSTALL_DIR) $(1)/usr/share/shadowsocksr
|
||||
$(INSTALL_DATA) ./files/root/usr/share/shadowsocksr/*.sh $(1)/usr/share/shadowsocksr/
|
||||
endef
|
||||
|
||||
#$(eval $(call BuildPackage,luci-app-shadowsocksR))
|
||||
#$(eval $(call BuildPackage,luci-app-shadowsocksR-Client))
|
||||
#$(eval $(call BuildPackage,luci-app-shadowsocksR-Server))
|
||||
$(eval $(call BuildPackage,luci-app-shadowsocksR-GFW))
|
3365
package/lean/openwrt-ssr/files/ad.conf
Executable file
3365
package/lean/openwrt-ssr/files/ad.conf
Executable file
File diff suppressed because it is too large
Load Diff
7689
package/lean/openwrt-ssr/files/china_ssr.txt
Normal file
7689
package/lean/openwrt-ssr/files/china_ssr.txt
Normal file
File diff suppressed because it is too large
Load Diff
68
package/lean/openwrt-ssr/files/custom_forward.conf
Executable file
68
package/lean/openwrt-ssr/files/custom_forward.conf
Executable file
@ -0,0 +1,68 @@
|
||||
server=/.skype.com/127.0.0.1#5353
|
||||
ipset=/.skype.com/gfwlist
|
||||
server=/.buzzfeed.com/127.0.0.1#5353
|
||||
ipset=/.buzzfeed.com/gfwlist
|
||||
server=/.openairinterface.org/127.0.0.1#5353
|
||||
ipset=/.openairinterface.org/gfwlist
|
||||
server=/.apple.news/127.0.0.1#5353
|
||||
ipset=/.apple.news/gfwlist
|
||||
server=/.dropboxstatic.com/127.0.0.1#5353
|
||||
ipset=/.dropboxstatic.com/gfwlist
|
||||
server=/.github.com/127.0.0.1#5353
|
||||
ipset=/.github.com/gfwlist
|
||||
server=/.amazonaws.com/127.0.0.1#5353
|
||||
ipset=/.amazonaws.com/gfwlist
|
||||
server=/.aws.amazon.com/127.0.0.1#5353
|
||||
ipset=/.aws.amazon.com/gfwlist
|
||||
server=/.sublimetext.com/127.0.0.1#5353
|
||||
ipset=/.sublimetext.com/gfwlist
|
||||
server=/.clockwise.ee/127.0.0.1#5353
|
||||
ipset=/.clockwise.ee/gfwlist
|
||||
server=/.adobe.com/127.0.0.1#5353
|
||||
ipset=/.adobe.com/gfwlist
|
||||
server=/.nutaq.com/127.0.0.1#5353
|
||||
ipset=/.nutaq.com/gfwlist
|
||||
server=/.uploaded.net/127.0.0.1#5353
|
||||
ipset=/.uploaded.net/gfwlist
|
||||
server=/.whatsapp.com/127.0.0.1#5353
|
||||
ipset=/.whatsapp.com/gfwlist
|
||||
server=/.whatsapp.net/127.0.0.1#5353
|
||||
ipset=/.whatsapp.net/gfwlist
|
||||
server=/.backpackers.com.tw/127.0.0.1#5353
|
||||
ipset=/.backpackers.com.tw/gfwlst
|
||||
server=/.kknews.cc/127.0.0.1#5353
|
||||
ipset=/.kknews.cc/gfwlist
|
||||
server=/.eurecom.fr/127.0.0.1#5353
|
||||
ipset=/.eurecom.fr/gfwlist
|
||||
server=/.91smartyun.pt/127.0.0.1#5353
|
||||
ipset=/.91smartyun.pt/gfwlist
|
||||
server=/.gdax.com/127.0.0.1#5353
|
||||
ipset=/.gdax.com/gfwlist
|
||||
server=/.coinsquare.io/127.0.0.1#5353
|
||||
ipset=/.coinsquare.io/gfwlist
|
||||
server=/.coindesk.com/127.0.0.1#5353
|
||||
ipset=/.coindesk.com/gfwlist
|
||||
server=/.trouter.io/127.0.0.1#5353
|
||||
ipset=/.trouter.io/gfwlist
|
||||
server=/.cryptocompare.com/127.0.0.1#5353
|
||||
ipset=/.cryptocompare.com/gfwlist
|
||||
server=/.github.com/127.0.0.1#5353
|
||||
ipset=/.github.com/gfwlist
|
||||
server=/.azureedge.net/127.0.0.1#5353
|
||||
ipset=/.azureedge.net/gfwlist
|
||||
server=/.wsj.net/127.0.0.1#5353
|
||||
ipset=/.wsj.net/gfwlist
|
||||
server=/.bitfinex.com/127.0.0.1#5353
|
||||
ipset=/.bitfinex.com/gfwlist
|
||||
server=/.textnow.me/127.0.0.1#5353
|
||||
ipset=/.textnow.me/gfwlist
|
||||
server=/.textnow.com/127.0.0.1#5353
|
||||
ipset=/.textnow.com/gfwlist
|
||||
server=/.isnssdk.com/127.0.0.1#5353
|
||||
ipset=/.isnssdk.com/gfwlist
|
||||
server=/.snssdk.com/127.0.0.1#5353
|
||||
ipset=/.snssdk.com/gfwlist
|
||||
server=/.ampproject.org/127.0.0.1#5353
|
||||
ipset=/.ampproject.org/gfwlist
|
||||
server=/.cloudfront.net/127.0.0.1#5353
|
||||
ipset=/.cloudfront.net/gfwlist
|
38
package/lean/openwrt-ssr/files/dnsmasq.conf
Normal file
38
package/lean/openwrt-ssr/files/dnsmasq.conf
Normal file
@ -0,0 +1,38 @@
|
||||
# Change the following lines if you want dnsmasq to serve SRV
|
||||
# records.
|
||||
# You may add multiple srv-host lines.
|
||||
# The fields are <name>,<target>,<port>,<priority>,<weight>
|
||||
|
||||
# A SRV record sending LDAP for the example.com domain to
|
||||
# ldapserver.example.com port 289
|
||||
#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389
|
||||
|
||||
# Two SRV records for LDAP, each with different priorities
|
||||
#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,1
|
||||
#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,2
|
||||
|
||||
# A SRV record indicating that there is no LDAP server for the domain
|
||||
# example.com
|
||||
#srv-host=_ldap._tcp.example.com
|
||||
|
||||
# The following line shows how to make dnsmasq serve an arbitrary PTR
|
||||
# record. This is useful for DNS-SD.
|
||||
# The fields are <name>,<target>
|
||||
#ptr-record=_http._tcp.dns-sd-services,"New Employee Page._http._tcp.dns-sd-services"
|
||||
|
||||
# Change the following lines to enable dnsmasq to serve TXT records.
|
||||
# These are used for things like SPF and zeroconf.
|
||||
# The fields are <name>,<text>,<text>...
|
||||
|
||||
#Example SPF.
|
||||
#txt-record=example.com,"v=spf1 a -all"
|
||||
|
||||
#Example zeroconf
|
||||
#txt-record=_http._tcp.example.com,name=value,paper=A4
|
||||
|
||||
# Provide an alias for a "local" DNS name. Note that this _only_ works
|
||||
# for targets which are names from DHCP or /etc/hosts. Give host
|
||||
# "bert" another name, bertrand
|
||||
# The fields are <cname>,<target>
|
||||
#cname=bertand,bert
|
||||
conf-dir=/etc/dnsmasq.ssr
|
10193
package/lean/openwrt-ssr/files/gfw_list.conf
Executable file
10193
package/lean/openwrt-ssr/files/gfw_list.conf
Executable file
File diff suppressed because it is too large
Load Diff
166
package/lean/openwrt-ssr/files/luci/controller/shadowsocksr.lua
Normal file
166
package/lean/openwrt-ssr/files/luci/controller/shadowsocksr.lua
Normal file
@ -0,0 +1,166 @@
|
||||
-- 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
|
||||
|
||||
if nixio.fs.access("/usr/bin/ssr-redir")
|
||||
then
|
||||
entry({"admin", "services", "shadowsocksr"},alias("admin", "services", "shadowsocksr", "client"),_("ShadowSocksR"), 10).dependent = true
|
||||
entry({"admin", "services", "shadowsocksr", "client"},arcombine(cbi("shadowsocksr/client"), cbi("shadowsocksr/client-config")),_("SSR Client"), 10).leaf = true
|
||||
elseif nixio.fs.access("/usr/bin/ssr-server")
|
||||
then
|
||||
entry({"admin", "services", "shadowsocksr"},alias("admin", "services", "shadowsocksr", "server"),_("ShadowSocksR"), 10).dependent = true
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "servers"},cbi("shadowsocksr/servers"),_("Subscription"), 20).leaf = true
|
||||
|
||||
entry({"admin", "services", "shadowsocksr", "status"},cbi("shadowsocksr/status"),_("Status"), 30).leaf = true
|
||||
entry({"admin", "services", "shadowsocksr", "check"}, call("check_status"))
|
||||
entry({"admin", "services", "shadowsocksr", "refresh"}, call("refresh_data"))
|
||||
entry({"admin", "services", "shadowsocksr", "checkport"}, call("check_port"))
|
||||
|
||||
end
|
||||
|
||||
function check_status()
|
||||
local set ="/usr/bin/ssr-check www." .. luci.http.formvalue("set") .. ".com 80 3 1"
|
||||
sret=luci.sys.call(set)
|
||||
if sret== 0 then
|
||||
retstring ="0"
|
||||
else
|
||||
retstring ="1"
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ ret=retstring })
|
||||
end
|
||||
|
||||
function refresh_data()
|
||||
local set =luci.http.formvalue("set")
|
||||
local icount =0
|
||||
|
||||
if set == "gfw_data" then
|
||||
if nixio.fs.access("/usr/bin/wget-ssl") then
|
||||
refresh_cmd="wget-ssl --no-check-certificate https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt -O /tmp/gfw.b64"
|
||||
else
|
||||
refresh_cmd="wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64"
|
||||
end
|
||||
sret=luci.sys.call(refresh_cmd .. " 2>/dev/null")
|
||||
if sret== 0 then
|
||||
luci.sys.call("/usr/bin/ssr-gfw")
|
||||
icount = luci.sys.exec("cat /tmp/gfwnew.txt | wc -l")
|
||||
if tonumber(icount)>1000 then
|
||||
oldcount=luci.sys.exec("cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l")
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf")
|
||||
retstring=tostring(math.ceil(tonumber(icount)/2))
|
||||
else
|
||||
retstring ="0"
|
||||
end
|
||||
else
|
||||
retstring ="-1"
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/gfwnew.txt ")
|
||||
else
|
||||
retstring ="-1"
|
||||
end
|
||||
elseif set == "ip_data" then
|
||||
refresh_cmd="wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' 2>/dev/null| awk -F\\| '/CN\\|ipv4/ { printf(\"%s/%d\\n\", $4, 32-log($5)/log(2)) }' > /tmp/china_ssr.txt"
|
||||
sret=luci.sys.call(refresh_cmd)
|
||||
icount = luci.sys.exec("cat /tmp/china_ssr.txt | wc -l")
|
||||
if sret== 0 and tonumber(icount)>1000 then
|
||||
oldcount=luci.sys.exec("cat /etc/china_ssr.txt | wc -l")
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/china_ssr.txt /etc/china_ssr.txt")
|
||||
retstring=tostring(tonumber(icount))
|
||||
else
|
||||
retstring ="0"
|
||||
end
|
||||
|
||||
else
|
||||
retstring ="-1"
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/china_ssr.txt ")
|
||||
else
|
||||
local need_process = 0
|
||||
if nixio.fs.access("/usr/bin/wget-ssl") then
|
||||
refresh_cmd="wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf"
|
||||
need_process = 1
|
||||
else
|
||||
refresh_cmd="wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf"
|
||||
end
|
||||
sret=luci.sys.call(refresh_cmd .. " 2>/dev/null")
|
||||
if sret== 0 then
|
||||
if need_process == 1 then
|
||||
luci.sys.call("/usr/bin/ssr-ad")
|
||||
end
|
||||
icount = luci.sys.exec("cat /tmp/ad.conf | wc -l")
|
||||
if tonumber(icount)>1000 then
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
|
||||
oldcount=luci.sys.exec("cat /etc/dnsmasq.ssr/ad.conf | wc -l")
|
||||
else
|
||||
oldcount=0
|
||||
end
|
||||
|
||||
if tonumber(icount) ~= tonumber(oldcount) then
|
||||
luci.sys.exec("cp -f /tmp/ad.conf /etc/dnsmasq.ssr/ad.conf")
|
||||
retstring=tostring(math.ceil(tonumber(icount)))
|
||||
if oldcount==0 then
|
||||
luci.sys.call("/etc/init.d/dnsmasq restart")
|
||||
end
|
||||
else
|
||||
retstring ="0"
|
||||
end
|
||||
else
|
||||
retstring ="-1"
|
||||
end
|
||||
luci.sys.exec("rm -f /tmp/ad.conf ")
|
||||
else
|
||||
retstring ="-1"
|
||||
end
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ ret=retstring ,retcount=icount})
|
||||
end
|
||||
|
||||
|
||||
function check_port()
|
||||
local set=""
|
||||
local retstring="<br /><br />"
|
||||
local s
|
||||
local server_name = ""
|
||||
local shadowsocksr = "shadowsocksr"
|
||||
local uci = luci.model.uci.cursor()
|
||||
local iret=1
|
||||
|
||||
uci:foreach(shadowsocksr, "servers", function(s)
|
||||
|
||||
if s.alias then
|
||||
server_name=s.alias
|
||||
elseif s.server and s.server_port then
|
||||
server_name= "%s:%s" %{s.server, s.server_port}
|
||||
end
|
||||
iret=luci.sys.call(" ipset add ss_spec_wan_ac " .. s.server .. " 2>/dev/null")
|
||||
socket = nixio.socket("inet", "stream")
|
||||
socket:setopt("socket", "rcvtimeo", 3)
|
||||
socket:setopt("socket", "sndtimeo", 3)
|
||||
ret=socket:connect(s.server,s.server_port)
|
||||
if tostring(ret) == "true" then
|
||||
socket:close()
|
||||
retstring =retstring .. "<font color='green'>[" .. server_name .. "] OK.</font><br />"
|
||||
else
|
||||
retstring =retstring .. "<font color='red'>[" .. server_name .. "] Error.</font><br />"
|
||||
end
|
||||
if iret== 0 then
|
||||
luci.sys.call(" ipset del ss_spec_wan_ac " .. s.server)
|
||||
end
|
||||
end)
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ ret=retstring })
|
||||
end
|
BIN
package/lean/openwrt-ssr/files/luci/i18n/shadowsocksr.zh-cn.lmo
Normal file
BIN
package/lean/openwrt-ssr/files/luci/i18n/shadowsocksr.zh-cn.lmo
Normal file
Binary file not shown.
374
package/lean/openwrt-ssr/files/luci/i18n/shadowsocksr.zh-cn.po
Normal file
374
package/lean/openwrt-ssr/files/luci/i18n/shadowsocksr.zh-cn.po
Normal file
@ -0,0 +1,374 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
||||
msgid "ShadowSocksR Client"
|
||||
msgstr "ShadowSocksR 客户端"
|
||||
|
||||
msgid "Enable"
|
||||
msgstr "启用"
|
||||
|
||||
msgid "Disable"
|
||||
msgstr "停用"
|
||||
|
||||
msgid "ShadowSocksR is running"
|
||||
msgstr "ShadowSocksR 客户端运行中"
|
||||
|
||||
msgid "ShadowSocksR is not running"
|
||||
msgstr "ShadowSocksR 客户端未运行"
|
||||
|
||||
msgid "Global Setting"
|
||||
msgstr "全局设置"
|
||||
|
||||
msgid "Global Server"
|
||||
msgstr "全局服务器"
|
||||
|
||||
msgid "ShadowSocksR SOCK5 Proxy is running"
|
||||
msgstr "ShadowSocksR SOCK5代理运行中"
|
||||
|
||||
msgid "UDP Relay Server"
|
||||
msgstr "UDP中继服务器"
|
||||
|
||||
msgid "Same as Global Server"
|
||||
msgstr "与全局服务器相同"
|
||||
|
||||
msgid "Servers Setting"
|
||||
msgstr "服务器配置"
|
||||
|
||||
msgid "Alias(optional)"
|
||||
msgstr "别名(可选)"
|
||||
|
||||
msgid "Onetime Authentication"
|
||||
msgstr "一次验证"
|
||||
|
||||
msgid "Server Address"
|
||||
msgstr "服务器地址"
|
||||
|
||||
msgid "Server Port"
|
||||
msgstr "服务器端口"
|
||||
|
||||
msgid "Local Port"
|
||||
msgstr "本地端口"
|
||||
|
||||
msgid "Connection Timeout"
|
||||
msgstr "连接超时"
|
||||
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
|
||||
msgid "Encrypt Method"
|
||||
msgstr "加密方式"
|
||||
|
||||
msgid "Protocol"
|
||||
msgstr "传输协议"
|
||||
|
||||
msgid "Protocol param(optional)"
|
||||
msgstr "传输协议参数(可选)"
|
||||
|
||||
msgid "Obfs"
|
||||
msgstr "混淆插件"
|
||||
|
||||
msgid "Obfs param(optional)"
|
||||
msgstr "混淆参数(可选)"
|
||||
|
||||
msgid "Enable Tunnel(DNS)"
|
||||
msgstr "启用隧道(DNS)转发"
|
||||
|
||||
msgid "Tunnel Port"
|
||||
msgstr "隧道(DNS)本地端口"
|
||||
|
||||
msgid "Forwarding Tunnel"
|
||||
msgstr "隧道(DNS)转发地址"
|
||||
|
||||
msgid "Access Control"
|
||||
msgstr "访问控制"
|
||||
|
||||
msgid "Interfaces - WAN"
|
||||
msgstr "接口 - WAN"
|
||||
|
||||
msgid "Bypassed IP List"
|
||||
msgstr "被忽略IP列表"
|
||||
|
||||
msgid "NULL - As Global Proxy"
|
||||
msgstr "留空 - 作为全局代理"
|
||||
|
||||
msgid "Bypassed IP"
|
||||
msgstr "额外被忽略IP"
|
||||
|
||||
msgid "Forwarded IP"
|
||||
msgstr "强制走代理IP"
|
||||
|
||||
msgid "Interfaces - LAN"
|
||||
msgstr "接口 - LAN"
|
||||
|
||||
msgid "LAN Access Control"
|
||||
msgstr "内网访问控制"
|
||||
|
||||
msgid "Allow listed only"
|
||||
msgstr "仅允许列表内"
|
||||
|
||||
msgid "Allow all except listed"
|
||||
msgstr "仅允许列表外"
|
||||
|
||||
msgid "LAN Host List"
|
||||
msgstr "内网主机列表"
|
||||
|
||||
msgid "SSR Client"
|
||||
msgstr "客户端"
|
||||
|
||||
msgid "SSR Server"
|
||||
msgstr "服务端"
|
||||
|
||||
msgid "ShadowSocksR Server"
|
||||
msgstr "ShadowSocksR 服务端"
|
||||
|
||||
msgid "ShadowSocksR Server is running"
|
||||
msgstr "ShadowSocksR 服务端运行中"
|
||||
|
||||
msgid "ShadowSocksR Server is not running"
|
||||
msgstr "ShadowSocksR 服务端未运行"
|
||||
|
||||
msgid "Enable Server"
|
||||
msgstr "启动服务端"
|
||||
|
||||
msgid "Server Setting"
|
||||
msgstr "服务端配置"
|
||||
|
||||
msgid "KcpTun Enable"
|
||||
msgstr "KcpTun 启用"
|
||||
|
||||
msgid "bin:/usr/bin/ssr-kcptun"
|
||||
msgstr "二进制文件:/usr/bin/ssr-kcptun"
|
||||
|
||||
msgid "KcpTun Port"
|
||||
msgstr "KcpTun 端口"
|
||||
|
||||
msgid "KcpTun Param"
|
||||
msgstr "KcpTun 参数"
|
||||
|
||||
msgid "KcpTun Password"
|
||||
msgstr "KcpTun 密码"
|
||||
|
||||
msgid "Haven't a Kcptun executable file"
|
||||
msgstr "不存在Kcptun可执行文件,请下载Kcptun可执行文件并改名放入/usr/bin/ssr-kcptun"
|
||||
|
||||
msgid "Not a Kcptun executable file"
|
||||
msgstr "Kcptun可执行文件格式不正确,请确认是否正确下载了路由器对应的可执行文件"
|
||||
|
||||
msgid "Enable Process Monitor"
|
||||
msgstr "启用进程监控"
|
||||
|
||||
msgid "Edit ShadowSocksR Server"
|
||||
msgstr "编辑服务器配置"
|
||||
|
||||
msgid "Alias"
|
||||
msgstr "别名"
|
||||
|
||||
msgid "SOCKS5 Proxy"
|
||||
msgstr "SOCKS5代理"
|
||||
|
||||
msgid "Server"
|
||||
msgstr "服务器"
|
||||
|
||||
msgid "TCP Fast Open"
|
||||
msgstr "TCP快速打开"
|
||||
|
||||
msgid "Status"
|
||||
msgstr "状态"
|
||||
|
||||
msgid "Unknown"
|
||||
msgstr "未知"
|
||||
|
||||
msgid "Running Status"
|
||||
msgstr "运行状态"
|
||||
|
||||
msgid "Global Client"
|
||||
msgstr "全局客户端"
|
||||
|
||||
msgid "Global SSR Server"
|
||||
msgstr "SSR服务端"
|
||||
|
||||
msgid "DNS Tunnel"
|
||||
msgstr "DNS 隧道"
|
||||
|
||||
msgid "IPK Version"
|
||||
msgstr "IPK 版本号"
|
||||
|
||||
msgid "KcpTun Version"
|
||||
msgstr "KcpTun 版本号"
|
||||
|
||||
msgid "Not exist"
|
||||
msgstr "未安装可执行文件"
|
||||
|
||||
msgid "IPK Installation Time"
|
||||
msgstr "IPK 安装时间"
|
||||
|
||||
msgid "Project"
|
||||
msgstr "项目地址"
|
||||
|
||||
msgid "Not Running"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "Running"
|
||||
msgstr "运行中"
|
||||
|
||||
msgid "Enable GFW mode"
|
||||
msgstr "启用 GFW 模式"
|
||||
|
||||
msgid "Running Mode"
|
||||
msgstr "运行模式"
|
||||
|
||||
msgid "IP Route Mode"
|
||||
msgstr "IP路由模式"
|
||||
|
||||
msgid "GFW List Mode"
|
||||
msgstr "GFW列表模式"
|
||||
|
||||
msgid "Router Proxy"
|
||||
msgstr "路由器访问控制"
|
||||
|
||||
msgid "Normal Proxy"
|
||||
msgstr "正常代理"
|
||||
|
||||
msgid "Bypassed Proxy"
|
||||
msgstr "不走代理"
|
||||
|
||||
msgid "Forwarded Proxy"
|
||||
msgstr "强制走代理"
|
||||
|
||||
msgid "UDP Relay"
|
||||
msgstr "UDP中继"
|
||||
|
||||
msgid "Google Connectivity"
|
||||
msgstr "【谷歌】连通性检查"
|
||||
|
||||
msgid "Baidu Connectivity"
|
||||
msgstr "【百度】连通性检查"
|
||||
|
||||
msgid "No Check"
|
||||
msgstr "未检查"
|
||||
|
||||
msgid "Check"
|
||||
msgstr "检查"
|
||||
|
||||
msgid "Connect OK"
|
||||
msgstr "连接正常"
|
||||
|
||||
msgid "Connect Error"
|
||||
msgstr "连接错误"
|
||||
|
||||
msgid "Check..."
|
||||
msgstr "正在检查.."
|
||||
|
||||
msgid "Proxy Check"
|
||||
msgstr "代理检查"
|
||||
|
||||
|
||||
msgid "GFW List Data"
|
||||
msgstr "【GFW列表】数据库"
|
||||
|
||||
msgid "China IP Data"
|
||||
msgstr "【国内IP段】数据库"
|
||||
|
||||
msgid "Records"
|
||||
msgstr "条记录"
|
||||
|
||||
msgid "Refresh Data"
|
||||
msgstr "更新数据库"
|
||||
|
||||
msgid "Refresh..."
|
||||
msgstr "正在更新,请稍候.."
|
||||
|
||||
msgid "Refresh OK!"
|
||||
msgstr "更新成功!"
|
||||
|
||||
msgid "Refresh Error!"
|
||||
msgstr "更新失败!"
|
||||
|
||||
msgid "No new data!"
|
||||
msgstr "你已经是最新数据,无需更新!"
|
||||
|
||||
msgid "Total Records:"
|
||||
msgstr "新的总纪录数:"
|
||||
|
||||
msgid "Check Server Port"
|
||||
msgstr "【服务器端口】检查"
|
||||
|
||||
msgid "Check Connect"
|
||||
msgstr "检查连通性"
|
||||
|
||||
msgid "Check Server"
|
||||
msgstr "检查服务器"
|
||||
|
||||
msgid "Auto Switch"
|
||||
msgstr "自动切换"
|
||||
|
||||
msgid "Enable Auto Switch"
|
||||
msgstr "启用自动切换"
|
||||
|
||||
msgid "Switch check cycly(second)"
|
||||
msgstr "自动切换检查周期(秒)"
|
||||
|
||||
msgid "Check timout(second)"
|
||||
msgstr "切换检查超时时间(秒)"
|
||||
|
||||
msgid "Advertising Data"
|
||||
msgstr "【广告屏蔽】数据库"
|
||||
|
||||
msgid "DNS Server IP and Port"
|
||||
msgstr "DNS服务器地址和端口"
|
||||
|
||||
msgid "Resolve Dns Mode"
|
||||
msgstr "DNS解析方式"
|
||||
|
||||
msgid "Use SSR DNS Tunnel"
|
||||
msgstr "使用SSR-DNS隧道"
|
||||
|
||||
msgid "Use Pdnsd"
|
||||
msgstr "使用Pdnsd"
|
||||
|
||||
msgid "Use Other DNS Tunnel(Need to install)"
|
||||
msgstr "使用其他DNS转发(需要自己安装)"
|
||||
|
||||
msgid "Import SSR"
|
||||
msgstr "导入ssr配置信息"
|
||||
|
||||
msgid "Export SSR"
|
||||
msgstr "导出ssr配置信息"
|
||||
|
||||
msgid "Import SSR successfully."
|
||||
msgstr "成功导入SSR。"
|
||||
|
||||
msgid "Invalid SSR format."
|
||||
msgstr "无效的SSR格式。"
|
||||
|
||||
msgid "User cancelled."
|
||||
msgstr "用户已取消。"
|
||||
|
||||
msgid "Paste ssr url here"
|
||||
msgstr "在此处粘贴ssr://网址"
|
||||
|
||||
msgid "Unable to copy SSR to clipboard."
|
||||
msgstr "无法复制SSR网址到剪贴板。"
|
||||
|
||||
msgid "Copy SSR to clipboard successfully."
|
||||
msgstr "成功复制SSR网址到剪贴板。"
|
||||
|
||||
msgid "Subscription"
|
||||
msgstr "订阅"
|
||||
|
||||
msgid "Auto Update"
|
||||
msgstr "自动更新"
|
||||
|
||||
msgid "Through proxy update"
|
||||
msgstr "通过代理更新"
|
||||
|
||||
msgid "Update time (every day)"
|
||||
msgstr "更新时间 (每天)"
|
||||
|
||||
msgid "Subscribe URL"
|
||||
msgstr "订阅链接"
|
||||
|
||||
msgid "Update"
|
||||
msgstr "更新"
|
||||
|
||||
|
@ -0,0 +1,165 @@
|
||||
-- Copyright (C) 2017 yushi studio <ywb94@qq.com> github.com/ywb94
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, s, o,kcp_enable
|
||||
local shadowsocksr = "shadowsocksr"
|
||||
local uci = luci.model.uci.cursor()
|
||||
local ipkg = require("luci.model.ipkg")
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
local sid = arg[1]
|
||||
|
||||
local function isKcptun(file)
|
||||
if not fs.access(file, "rwx", "rx", "rx") then
|
||||
fs.chmod(file, 755)
|
||||
end
|
||||
|
||||
local str = sys.exec(file .. " -v | awk '{printf $1}'")
|
||||
return (str:lower() == "kcptun")
|
||||
end
|
||||
|
||||
|
||||
local server_table = {}
|
||||
local encrypt_methods = {
|
||||
"none",
|
||||
"table",
|
||||
"rc4",
|
||||
"rc4-md5-6",
|
||||
"rc4-md5",
|
||||
"aes-128-cfb",
|
||||
"aes-192-cfb",
|
||||
"aes-256-cfb",
|
||||
"aes-128-ctr",
|
||||
"aes-192-ctr",
|
||||
"aes-256-ctr",
|
||||
"bf-cfb",
|
||||
"camellia-128-cfb",
|
||||
"camellia-192-cfb",
|
||||
"camellia-256-cfb",
|
||||
"cast5-cfb",
|
||||
"des-cfb",
|
||||
"idea-cfb",
|
||||
"rc2-cfb",
|
||||
"seed-cfb",
|
||||
"salsa20",
|
||||
"chacha20",
|
||||
"chacha20-ietf",
|
||||
}
|
||||
|
||||
local protocol = {
|
||||
"origin",
|
||||
"verify_deflate",
|
||||
"auth_sha1_v4",
|
||||
"auth_aes128_sha1",
|
||||
"auth_aes128_md5",
|
||||
"auth_chain_a",
|
||||
"auth_chain_b",
|
||||
"auth_chain_c",
|
||||
"auth_chain_d",
|
||||
"auth_chain_e",
|
||||
"auth_chain_f",
|
||||
}
|
||||
|
||||
obfs = {
|
||||
"plain",
|
||||
"http_simple",
|
||||
"http_post",
|
||||
"random_head",
|
||||
"tls1.2_ticket_auth",
|
||||
}
|
||||
|
||||
m = Map(shadowsocksr, translate("Edit ShadowSocksR Server"))
|
||||
m.redirect = luci.dispatcher.build_url("admin/services/shadowsocksr/client")
|
||||
if m.uci:get(shadowsocksr, sid) ~= "servers" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
-- [[ Servers Setting ]]--
|
||||
s = m:section(NamedSection, sid, "servers")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(Value, "alias", translate("Alias(optional)"))
|
||||
|
||||
o = s:option(Flag, "auth_enable", translate("Onetime Authentication"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "switch_enable", translate("Auto Switch"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server", translate("Server Address"))
|
||||
o.datatype = "host"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server_port", translate("Server Port"))
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "local_port", translate("Local Port"))
|
||||
o.datatype = "port"
|
||||
o.default = 1234
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "timeout", translate("Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 60
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "password", translate("Password"))
|
||||
o.password = true
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
|
||||
for _, v in ipairs(encrypt_methods) do o:value(v) end
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "protocol", translate("Protocol"))
|
||||
for _, v in ipairs(protocol) do o:value(v) end
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "protocol_param", translate("Protocol param(optional)"))
|
||||
|
||||
o = s:option(ListValue, "obfs", translate("Obfs"))
|
||||
for _, v in ipairs(obfs) do o:value(v) end
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "obfs_param", translate("Obfs param(optional)"))
|
||||
|
||||
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
|
||||
o.rmempty = false
|
||||
|
||||
kcp_enable = s:option(Flag, "kcp_enable", translate("KcpTun Enable"), translate("bin:/usr/bin/ssr-kcptun"))
|
||||
kcp_enable.rmempty = false
|
||||
|
||||
|
||||
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/ssr-kcptun"
|
||||
local enable = kcp_enable:formvalue(section) or kcp_enable.disabled
|
||||
if enable == kcp_enable.enabled then
|
||||
if not fs.access(kcp_file) then
|
||||
return nil, translate("Haven't a Kcptun executable file")
|
||||
elseif not isKcptun(kcp_file) then
|
||||
return nil, translate("Not a Kcptun executable file")
|
||||
end
|
||||
end
|
||||
|
||||
return value
|
||||
end
|
||||
|
||||
o = s:option(Value, "kcp_password", translate("KcpTun Password"))
|
||||
o.password = true
|
||||
|
||||
o = s:option(Value, "kcp_param", translate("KcpTun Param"))
|
||||
o.default = "--nocomp"
|
||||
|
||||
|
||||
o = s:option(DummyValue,"ssr_url","SSR URL")
|
||||
o.rawhtml = true
|
||||
o.template = "shadowsocksr/ssrurl"
|
||||
o.value =sid
|
||||
|
||||
return m
|
@ -0,0 +1,376 @@
|
||||
-- Copyright (C) 2017 yushi studio <ywb94@qq.com> github.com/ywb94
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, s, sec, o, kcp_enable
|
||||
local shadowsocksr = "shadowsocksr"
|
||||
local uci = luci.model.uci.cursor()
|
||||
local ipkg = require("luci.model.ipkg")
|
||||
|
||||
local sys = require "luci.sys"
|
||||
|
||||
m = Map(shadowsocksr, translate("ShadowSocksR Client"))
|
||||
|
||||
local server_table = {}
|
||||
local encrypt_methods = {
|
||||
"none",
|
||||
"table",
|
||||
"rc4",
|
||||
"rc4-md5-6",
|
||||
"rc4-md5",
|
||||
"aes-128-cfb",
|
||||
"aes-192-cfb",
|
||||
"aes-256-cfb",
|
||||
"aes-128-ctr",
|
||||
"aes-192-ctr",
|
||||
"aes-256-ctr",
|
||||
"bf-cfb",
|
||||
"camellia-128-cfb",
|
||||
"camellia-192-cfb",
|
||||
"camellia-256-cfb",
|
||||
"cast5-cfb",
|
||||
"des-cfb",
|
||||
"idea-cfb",
|
||||
"rc2-cfb",
|
||||
"seed-cfb",
|
||||
"salsa20",
|
||||
"chacha20",
|
||||
"chacha20-ietf",
|
||||
}
|
||||
|
||||
local protocol = {
|
||||
"origin",
|
||||
"verify_deflate",
|
||||
"auth_sha1_v4",
|
||||
"auth_aes128_sha1",
|
||||
"auth_aes128_md5",
|
||||
"auth_chain_a",
|
||||
"auth_chain_b",
|
||||
"auth_chain_c",
|
||||
"auth_chain_d",
|
||||
"auth_chain_e",
|
||||
"auth_chain_f",
|
||||
}
|
||||
|
||||
obfs = {
|
||||
"plain",
|
||||
"http_simple",
|
||||
"http_post",
|
||||
"random_head",
|
||||
"tls1.2_ticket_auth",
|
||||
}
|
||||
|
||||
local raw_mode = {
|
||||
"faketcp",
|
||||
"udp",
|
||||
"icmp",
|
||||
}
|
||||
|
||||
local seq_mode = {
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
}
|
||||
|
||||
local cipher_mode = {
|
||||
"none",
|
||||
"xor",
|
||||
"aes128cbc",
|
||||
}
|
||||
|
||||
local auth_mode = {
|
||||
"none",
|
||||
"simple",
|
||||
"md5",
|
||||
"crc32",
|
||||
}
|
||||
|
||||
local speeder_mode = {
|
||||
"0",
|
||||
"1",
|
||||
}
|
||||
|
||||
uci:foreach(shadowsocksr, "servers", function(s)
|
||||
if s.alias then
|
||||
server_table[s[".name"]] = s.alias
|
||||
elseif s.server and s.server_port then
|
||||
server_table[s[".name"]] = "%s:%s" %{s.server, s.server_port}
|
||||
end
|
||||
end)
|
||||
|
||||
-- [[ Servers Setting ]]--
|
||||
sec = m:section(TypedSection, "servers", translate("Servers Setting"))
|
||||
sec.anonymous = true
|
||||
sec.addremove = true
|
||||
sec.sortable = true
|
||||
sec.template = "cbi/tblsection"
|
||||
sec.extedit = luci.dispatcher.build_url("admin/services/shadowsocksr/client/%s")
|
||||
function sec.create(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
luci.http.redirect(sec.extedit % sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "alias", translate("Alias"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or translate("None")
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "server", translate("Server Address"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "server_port", translate("Server Port"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "encrypt_method", translate("Encrypt Method"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "protocol", translate("Protocol"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "obfs", translate("Obfs"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "kcp_enable", translate("KcpTun"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "switch_enable", translate("Auto Switch"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "0"
|
||||
end
|
||||
|
||||
-- [[ Global Setting ]]--
|
||||
s = m:section(TypedSection, "global", translate("Global Setting"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(ListValue, "global_server", translate("Global Server"))
|
||||
o:value("nil", translate("Disable"))
|
||||
for k, v in pairs(server_table) do o:value(k, v) end
|
||||
o.default = "nil"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "udp_relay_server", translate("UDP Relay Server"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("same", translate("Same as Global Server"))
|
||||
for k, v in pairs(server_table) do o:value(k, v) end
|
||||
|
||||
o = s:option(Flag, "monitor_enable", translate("Enable Process Monitor"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "enable_switch", translate("Enable Auto Switch"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "switch_time", translate("Switch check cycly(second)"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("enable_switch", "1")
|
||||
o.default = 600
|
||||
|
||||
o = s:option(Value, "switch_timeout", translate("Check timout(second)"))
|
||||
o.datatype = "uinteger"
|
||||
o:depends("enable_switch", "1")
|
||||
o.default = 3
|
||||
|
||||
if nixio.fs.access("/usr/bin/ssr-gfw") then
|
||||
o = s:option(ListValue, "run_mode", translate("Running Mode"))
|
||||
o:value("router", translate("IP Route Mode"))
|
||||
o:value("gfw", translate("GFW List Mode"))
|
||||
|
||||
o = s:option(ListValue, "pdnsd_enable", translate("Resolve Dns Mode"))
|
||||
o:depends("run_mode", "gfw")
|
||||
o:value("0", translate("Use SSR DNS Tunnel"))
|
||||
o:value("1", translate("Use Pdnsd(Need to install)"))
|
||||
o:value("2", translate("Use Other DNS Tunnel(Need to install)"))
|
||||
|
||||
o = s:option(Flag, "tunnel_enable", translate("Enable Tunnel(DNS)"))
|
||||
o:depends("run_mode", "router")
|
||||
o.default = 0
|
||||
|
||||
o = s:option(Value, "tunnel_port", translate("Tunnel Port"))
|
||||
o:depends("run_mode", "router")
|
||||
o.datatype = "port"
|
||||
o.default = 5300
|
||||
else
|
||||
o = s:option(Flag, "tunnel_enable", translate("Enable Tunnel(DNS)"))
|
||||
o.default = 0
|
||||
|
||||
o = s:option(Value, "tunnel_port", translate("Tunnel Port"))
|
||||
o.datatype = "port"
|
||||
o.default = 5300
|
||||
end
|
||||
|
||||
o = s:option(Value, "tunnel_forward", translate("DNS Server IP and Port"))
|
||||
o.default = "8.8.4.4:53"
|
||||
o.rmempty = false
|
||||
|
||||
-- [[ SOCKS5 Proxy ]]--
|
||||
s = m:section(TypedSection, "socks5_proxy", translate("SOCKS5 Proxy"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(ListValue, "server", translate("Server"))
|
||||
o:value("nil", translate("Disable"))
|
||||
for k, v in pairs(server_table) do o:value(k, v) end
|
||||
o.default = "nil"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "local_port", translate("Local Port"))
|
||||
o.datatype = "port"
|
||||
o.default = 1234
|
||||
o.rmempty = false
|
||||
|
||||
-- [[ udp2raw ]]--
|
||||
if nixio.fs.access("/usr/bin/udp2raw") then
|
||||
|
||||
s = m:section(TypedSection, "udp2raw", translate("udp2raw tunnel"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "udp2raw_enable", translate("Enable udp2raw"))
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server", translate("Server Address"))
|
||||
o.datatype = "host"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server_port", translate("Server Port"))
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "local_port", translate("Local Port"))
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "key", translate("Password"))
|
||||
o.password = true
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "raw_mode", translate("Raw Mode"))
|
||||
for _, v in ipairs(raw_mode) do o:value(v) end
|
||||
o.default = "faketcp"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "seq_mode", translate("Seq Mode"))
|
||||
for _, v in ipairs(seq_mode) do o:value(v) end
|
||||
o.default = "3"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "cipher_mode", translate("Cipher Mode"))
|
||||
for _, v in ipairs(cipher_mode) do o:value(v) end
|
||||
o.default = "xor"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "auth_mode", translate("Auth Mode"))
|
||||
for _, v in ipairs(auth_mode) do o:value(v) end
|
||||
o.default = "simple"
|
||||
o.rmempty = false
|
||||
|
||||
end
|
||||
|
||||
-- [[ udpspeeder ]]--
|
||||
if nixio.fs.access("/usr/bin/udpspeeder") then
|
||||
|
||||
s = m:section(TypedSection, "udpspeeder", translate("UDPspeeder"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "udpspeeder_enable", translate("Enable UDPspeeder"))
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server", translate("Server Address"))
|
||||
o.datatype = "host"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server_port", translate("Server Port"))
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "local_port", translate("Local Port"))
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "key", translate("Password"))
|
||||
o.password = true
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "speeder_mode", translate("Speeder Mode"))
|
||||
for _, v in ipairs(speeder_mode) do o:value(v) end
|
||||
o.default = "0"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "fec", translate("Fec"))
|
||||
o.default = "20:10"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "mtu", translate("Mtu"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 1250
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "queue_len", translate("Queue Len"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 200
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "timeout", translate("Fec Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 8
|
||||
o.rmempty = false
|
||||
|
||||
end
|
||||
|
||||
-- [[ Access Control ]]--
|
||||
s = m:section(TypedSection, "access_control", translate("Access Control"))
|
||||
s.anonymous = true
|
||||
|
||||
-- Part of WAN
|
||||
s:tab("wan_ac", translate("Interfaces - WAN"))
|
||||
|
||||
o = s:taboption("wan_ac", Value, "wan_bp_list", translate("Bypassed IP List"))
|
||||
o:value("/dev/null", translate("NULL - As Global Proxy"))
|
||||
|
||||
o.default = "/dev/null"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:taboption("wan_ac", DynamicList, "wan_bp_ips", translate("Bypassed IP"))
|
||||
o.datatype = "ip4addr"
|
||||
|
||||
o = s:taboption("wan_ac", DynamicList, "wan_fw_ips", translate("Forwarded IP"))
|
||||
o.datatype = "ip4addr"
|
||||
|
||||
-- Part of LAN
|
||||
s:tab("lan_ac", translate("Interfaces - LAN"))
|
||||
|
||||
o = s:taboption("lan_ac",ListValue, "router_proxy", translate("Router Proxy"))
|
||||
o:value("1", translatef("Normal Proxy"))
|
||||
o:value("0", translatef("Bypassed Proxy"))
|
||||
o:value("2", translatef("Forwarded Proxy"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:taboption("lan_ac", ListValue, "lan_ac_mode", translate("LAN Access Control"))
|
||||
o:value("0", translate("Disable"))
|
||||
o:value("w", translate("Allow listed only"))
|
||||
o:value("b", translate("Allow all except listed"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:taboption("lan_ac", DynamicList, "lan_ac_ips", translate("LAN Host List"))
|
||||
o.datatype = "ipaddr"
|
||||
luci.ip.neighbors({ family = 4 }, function(entry)
|
||||
if entry.reachable then
|
||||
o:value(entry.dest:string())
|
||||
end
|
||||
end)
|
||||
return m
|
@ -0,0 +1,108 @@
|
||||
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, s, o
|
||||
local shadowsocksr = "shadowsocksr"
|
||||
local sid = arg[1]
|
||||
|
||||
local encrypt_methods = {
|
||||
"table",
|
||||
"rc4",
|
||||
"rc4-md5",
|
||||
"rc4-md5-6",
|
||||
"aes-128-cfb",
|
||||
"aes-192-cfb",
|
||||
"aes-256-cfb",
|
||||
"aes-128-ctr",
|
||||
"aes-192-ctr",
|
||||
"aes-256-ctr",
|
||||
"bf-cfb",
|
||||
"camellia-128-cfb",
|
||||
"camellia-192-cfb",
|
||||
"camellia-256-cfb",
|
||||
"cast5-cfb",
|
||||
"des-cfb",
|
||||
"idea-cfb",
|
||||
"rc2-cfb",
|
||||
"seed-cfb",
|
||||
"salsa20",
|
||||
"chacha20",
|
||||
"chacha20-ietf",
|
||||
}
|
||||
|
||||
local protocol = {
|
||||
"origin",
|
||||
"verify_deflate",
|
||||
"auth_sha1_v4",
|
||||
"auth_aes128_sha1",
|
||||
"auth_aes128_md5",
|
||||
"auth_chain_a",
|
||||
}
|
||||
|
||||
obfs = {
|
||||
"plain",
|
||||
"http_simple",
|
||||
"http_post",
|
||||
"random_head",
|
||||
"tls1.2_ticket_auth",
|
||||
"tls1.2_ticket_fastauth",
|
||||
}
|
||||
|
||||
m = Map(shadowsocksr, translate("Edit ShadowSocksR Server"))
|
||||
|
||||
m.redirect = luci.dispatcher.build_url("admin/services/shadowsocksr/server")
|
||||
if m.uci:get(shadowsocksr, sid) ~= "server_config" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
-- [[ Server Setting ]]--
|
||||
s = m:section(NamedSection, sid, "server_config")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(Flag, "enable", translate("Enable"))
|
||||
o.default = 1
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server", translate("Server Address"))
|
||||
o.datatype = "ipaddr"
|
||||
o.default = "0.0.0.0"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server_port", translate("Server Port"))
|
||||
o.datatype = "port"
|
||||
o.default = 8388
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "timeout", translate("Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 60
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "password", translate("Password"))
|
||||
o.password = true
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
|
||||
for _, v in ipairs(encrypt_methods) do o:value(v) end
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "protocol", translate("Protocol"))
|
||||
for _, v in ipairs(protocol) do o:value(v) end
|
||||
o.rmempty = false
|
||||
|
||||
|
||||
o = s:option(ListValue, "obfs", translate("Obfs"))
|
||||
for _, v in ipairs(obfs) do o:value(v) end
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "obfs_param", translate("Obfs param(optional)"))
|
||||
|
||||
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
|
||||
o.rmempty = false
|
||||
|
||||
return m
|
@ -0,0 +1,122 @@
|
||||
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, sec, o
|
||||
local shadowsocksr = "shadowsocksr"
|
||||
local uci = luci.model.uci.cursor()
|
||||
local ipkg = require("luci.model.ipkg")
|
||||
|
||||
|
||||
m = Map(shadowsocksr, translate("ShadowSocksR Server"))
|
||||
|
||||
local encrypt_methods = {
|
||||
"table",
|
||||
"rc4",
|
||||
"rc4-md5",
|
||||
"rc4-md5-6",
|
||||
"aes-128-cfb",
|
||||
"aes-192-cfb",
|
||||
"aes-256-cfb",
|
||||
"aes-128-ctr",
|
||||
"aes-192-ctr",
|
||||
"aes-256-ctr",
|
||||
"bf-cfb",
|
||||
"camellia-128-cfb",
|
||||
"camellia-192-cfb",
|
||||
"camellia-256-cfb",
|
||||
"cast5-cfb",
|
||||
"des-cfb",
|
||||
"idea-cfb",
|
||||
"rc2-cfb",
|
||||
"seed-cfb",
|
||||
"salsa20",
|
||||
"chacha20",
|
||||
"chacha20-ietf",
|
||||
}
|
||||
|
||||
local protocol = {
|
||||
"origin",
|
||||
"verify_deflate",
|
||||
"auth_sha1_v4",
|
||||
"auth_aes128_sha1",
|
||||
"auth_aes128_md5",
|
||||
"auth_chain_a",
|
||||
}
|
||||
|
||||
obfs = {
|
||||
"plain",
|
||||
"http_simple",
|
||||
"http_post",
|
||||
"random_head",
|
||||
"tls1.2_ticket_auth",
|
||||
"tls1.2_ticket_fastauth",
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- [[ Global Setting ]]--
|
||||
sec = m:section(TypedSection, "server_global", translate("Global Setting"))
|
||||
sec.anonymous = true
|
||||
|
||||
|
||||
|
||||
o = sec:option(Flag, "enable_server", translate("Enable Server"))
|
||||
o.rmempty = false
|
||||
|
||||
-- [[ Server Setting ]]--
|
||||
sec = m:section(TypedSection, "server_config", translate("Server Setting"))
|
||||
sec.anonymous = true
|
||||
sec.addremove = true
|
||||
sec.sortable = true
|
||||
sec.template = "cbi/tblsection"
|
||||
sec.extedit = luci.dispatcher.build_url("admin/services/shadowsocksr/server/%s")
|
||||
function sec.create(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
luci.http.redirect(sec.extedit % sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
o = sec:option(Flag, "enable", translate("Enable"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or translate("0")
|
||||
end
|
||||
o.rmempty = false
|
||||
|
||||
o = sec:option(DummyValue, "server", translate("Server Address"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "server_port", translate("Server Port"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
|
||||
o = sec:option(DummyValue, "encrypt_method", translate("Encrypt Method"))
|
||||
function o.cfgvalue(...)
|
||||
local v = Value.cfgvalue(...)
|
||||
return v and v:upper() or "?"
|
||||
end
|
||||
|
||||
o = sec:option(DummyValue, "protocol", translate("Protocol"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
|
||||
|
||||
o = sec:option(DummyValue, "obfs", translate("Obfs"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return m
|
@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
local m, s, o
|
||||
local shadowsocksr = "shadowsocksr"
|
||||
|
||||
local function has_bin(name)
|
||||
return luci.sys.call("command -v %s >/dev/null" %{name}) == 0
|
||||
end
|
||||
|
||||
m = Map(shadowsocksr, "%s - %s" %{translate("ShadowSocksR"), translate("Servers Manage")})
|
||||
|
||||
-- Server Subscribe
|
||||
if nixio.fs.access("/usr/share/shadowsocksr/subscribe.sh") and has_bin("base64") and has_bin("curl") and has_bin("bash") and has_bin("dig") then
|
||||
s = m:section(TypedSection, "server_subscribe", translate("Server subscription"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "auto_update", translate("Auto Update"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "proxy", translate("Through proxy update"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "auto_update_time", translate("Update time (every day)"))
|
||||
for t = 0,23 do
|
||||
o:value(t, t..":00")
|
||||
end
|
||||
o.default=2
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(DynamicList, "subscribe_url", translate("Subscribe URL"))
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Button,"update",translate("Update"))
|
||||
o.write = function()
|
||||
luci.sys.call("/usr/share/shadowsocksr/subscribe.sh >/dev/null 2>&1")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr", "servers"))
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
@ -0,0 +1,258 @@
|
||||
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local IPK_Version="3.1.0"
|
||||
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 udp2raw_run=0
|
||||
local udpspeeder_run=0
|
||||
local gfw_count=0
|
||||
local ad_count=0
|
||||
local ip_count=0
|
||||
local gfwmode=0
|
||||
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/gfw_list.conf") then
|
||||
gfwmode=1
|
||||
end
|
||||
|
||||
local shadowsocksr = "shadowsocksr"
|
||||
-- html constants
|
||||
font_blue = [[<font color="blue">]]
|
||||
font_off = [[</font>]]
|
||||
bold_on = [[<strong>]]
|
||||
bold_off = [[</strong>]]
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
local kcptun_version=translate("Unknown")
|
||||
local kcp_file="/usr/bin/ssr-kcptun"
|
||||
if not fs.access(kcp_file) then
|
||||
kcptun_version=translate("Not exist")
|
||||
else
|
||||
if not fs.access(kcp_file, "rwx", "rx", "rx") then
|
||||
fs.chmod(kcp_file, 755)
|
||||
end
|
||||
kcptun_version=sys.exec(kcp_file .. " -v | awk '{printf $3}'")
|
||||
if not kcptun_version or kcptun_version == "" then
|
||||
kcptun_version = translate("Unknown")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local udp2raw_version=translate("Unknown")
|
||||
local udp2raw_file="/usr/bin/udp2raw"
|
||||
if not fs.access(udp2raw_file) then
|
||||
udp2raw_version=translate("Not exist")
|
||||
else
|
||||
if not fs.access(udp2raw_file, "rwx", "rx", "rx") then
|
||||
fs.chmod(udp2raw_file, 755)
|
||||
end
|
||||
udp2raw_version=sys.exec(udp2raw_file .. " -h |grep 'git version' |awk -F ':' '{print $2}'|awk '{print $1}'")
|
||||
if not udp2raw_version or udp2raw_version == "" then
|
||||
udp2raw_version = translate("Unknown")
|
||||
end
|
||||
end
|
||||
|
||||
local udpspeeder_version=translate("Unknown")
|
||||
local udpspeeder_file="/usr/bin/udpspeeder"
|
||||
if not fs.access(udpspeeder_file) then
|
||||
udpspeeder_version=translate("Not exist")
|
||||
else
|
||||
if not fs.access(udpspeeder_file, "rwx", "rx", "rx") then
|
||||
fs.chmod(udpspeeder_file, 755)
|
||||
end
|
||||
udpspeeder_version=sys.exec(udpspeeder_file .. " -h |grep 'git version' |awk -F ':' '{print $2}'|awk '{print $1}'")
|
||||
if not udpspeeder_version or udpspeeder_version == "" then
|
||||
udpspeeder_version = translate("Unknown")
|
||||
end
|
||||
end
|
||||
|
||||
if gfwmode==1 then
|
||||
gfw_count = tonumber(sys.exec("cat /etc/dnsmasq.ssr/gfw_list.conf | wc -l"))/2
|
||||
if nixio.fs.access("/etc/dnsmasq.ssr/ad.conf") then
|
||||
ad_count=tonumber(sys.exec("cat /etc/dnsmasq.ssr/ad.conf | wc -l"))
|
||||
end
|
||||
end
|
||||
|
||||
if nixio.fs.access("/etc/china_ssr.txt") then
|
||||
ip_count = sys.exec("cat /etc/china_ssr.txt | wc -l")
|
||||
end
|
||||
|
||||
local icount=sys.exec("ps -w | grep ssr-reudp |grep -v grep| wc -l")
|
||||
if tonumber(icount)>0 then
|
||||
reudp_run=1
|
||||
else
|
||||
icount=sys.exec("ps -w | grep ssr-retcp |grep \"\\-u\"|grep -v grep| wc -l")
|
||||
if tonumber(icount)>0 then
|
||||
reudp_run=1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if luci.sys.call("pidof ssr-redir >/dev/null") == 0 then
|
||||
redir_run=1
|
||||
end
|
||||
|
||||
if luci.sys.call("ps -w | grep ssr-local |grep -v grep >/dev/null") == 0 then
|
||||
sock5_run=1
|
||||
end
|
||||
|
||||
if luci.sys.call("pidof ssr-kcptun >/dev/null") == 0 then
|
||||
kcptun_run=1
|
||||
end
|
||||
|
||||
-- if luci.sys.call("pidof ssr-server >/dev/null") == 0 then
|
||||
-- server_run=1
|
||||
-- end
|
||||
|
||||
if luci.sys.call("ps -w | grep ssr-tunnel |grep -v grep >/dev/null") == 0 then
|
||||
tunnel_run=1
|
||||
end
|
||||
|
||||
if luci.sys.call("pidof udp2raw >/dev/null") == 0 then
|
||||
udp2raw_run=1
|
||||
end
|
||||
|
||||
if luci.sys.call("pidof udpspeeder >/dev/null") == 0 then
|
||||
udpspeeder_run=1
|
||||
end
|
||||
|
||||
m = SimpleForm("Version", translate("Running Status"))
|
||||
m.reset = false
|
||||
m.submit = false
|
||||
|
||||
s=m:field(DummyValue,"redir_run",translate("Global Client"))
|
||||
s.rawhtml = true
|
||||
if redir_run == 1 then
|
||||
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
|
||||
else
|
||||
s.value = translate("Not Running")
|
||||
end
|
||||
|
||||
-- s=m:field(DummyValue,"server_run",translate("Global SSR Server"))
|
||||
-- s.rawhtml = true
|
||||
-- if server_run == 1 then
|
||||
-- s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
|
||||
-- else
|
||||
-- s.value = translate("Not Running")
|
||||
-- end
|
||||
|
||||
s=m:field(DummyValue,"reudp_run",translate("UDP Relay"))
|
||||
s.rawhtml = true
|
||||
if reudp_run == 1 then
|
||||
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
|
||||
else
|
||||
s.value = translate("Not Running")
|
||||
end
|
||||
|
||||
s=m:field(DummyValue,"sock5_run",translate("SOCKS5 Proxy"))
|
||||
s.rawhtml = true
|
||||
if sock5_run == 1 then
|
||||
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
|
||||
else
|
||||
s.value = translate("Not Running")
|
||||
end
|
||||
|
||||
s=m:field(DummyValue,"tunnel_run",translate("DNS Tunnel"))
|
||||
s.rawhtml = true
|
||||
if tunnel_run == 1 then
|
||||
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
|
||||
else
|
||||
s.value = translate("Not Running")
|
||||
end
|
||||
|
||||
s=m:field(DummyValue,"kcptun_run",translate("KcpTun"))
|
||||
s.rawhtml = true
|
||||
if kcptun_run == 1 then
|
||||
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
|
||||
else
|
||||
s.value = translate("Not Running")
|
||||
end
|
||||
|
||||
s=m:field(DummyValue,"udp2raw_run",translate("udp2raw"))
|
||||
s.rawhtml = true
|
||||
if udp2raw_run == 1 then
|
||||
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
|
||||
else
|
||||
s.value = translate("Not Running")
|
||||
end
|
||||
|
||||
s=m:field(DummyValue,"udpspeeder_run",translate("UDPspeeder"))
|
||||
s.rawhtml = true
|
||||
if udpspeeder_run == 1 then
|
||||
s.value =font_blue .. bold_on .. translate("Running") .. bold_off .. font_off
|
||||
else
|
||||
s.value = translate("Not Running")
|
||||
end
|
||||
|
||||
s=m:field(DummyValue,"google",translate("Google Connectivity"))
|
||||
s.value = translate("No Check")
|
||||
s.template = "shadowsocksr/check"
|
||||
|
||||
s=m:field(DummyValue,"baidu",translate("Baidu Connectivity"))
|
||||
s.value = translate("No Check")
|
||||
s.template = "shadowsocksr/check"
|
||||
|
||||
if gfwmode==1 then
|
||||
s=m:field(DummyValue,"gfw_data",translate("GFW List Data"))
|
||||
s.rawhtml = true
|
||||
s.template = "shadowsocksr/refresh"
|
||||
s.value =tostring(math.ceil(gfw_count)) .. " " .. translate("Records")
|
||||
|
||||
s=m:field(DummyValue,"ad_data",translate("Advertising Data"))
|
||||
s.rawhtml = true
|
||||
s.template = "shadowsocksr/refresh"
|
||||
s.value =tostring(math.ceil(ad_count)) .. " " .. translate("Records")
|
||||
end
|
||||
|
||||
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,"check_port",translate("Check Server Port"))
|
||||
s.template = "shadowsocksr/checkport"
|
||||
s.value =translate("No Check")
|
||||
|
||||
s=m:field(DummyValue,"version",translate("IPK Version"))
|
||||
s.rawhtml = true
|
||||
s.value =IPK_Version
|
||||
|
||||
s=m:field(DummyValue,"ipk_project",translate("IPK Project"))
|
||||
s.rawhtml = true
|
||||
s.value =bold_on .. [[<a href="]] .. "https://github.com/ywb94/openwrt-ssr" .. [[" >]]
|
||||
.. "https://github.com/ywb94/openwrt-ssr" .. [[</a>]] .. bold_off
|
||||
|
||||
s=m:field(DummyValue,"kcp_version",translate("KcpTun Version"))
|
||||
s.rawhtml = true
|
||||
s.value =kcptun_version
|
||||
|
||||
s=m:field(DummyValue,"kcptun_project",translate("Kcp Tun Project"))
|
||||
s.rawhtml = true
|
||||
s.value =bold_on .. [[<a href="]] .. "https://github.com/xtaci/kcptun" .. [[" >]]
|
||||
.. "https://github.com/xtaci/kcptun" .. [[</a>]] .. bold_off
|
||||
|
||||
s=m:field(DummyValue,"udp2raw_version",translate("udp2raw Version"))
|
||||
s.rawhtml = true
|
||||
s.value =udp2raw_version
|
||||
|
||||
s=m:field(DummyValue,"udp2raw_project",translate("udp2raw tunnel Project"))
|
||||
s.rawhtml = true
|
||||
s.value =bold_on .. [[<a href="]] .. "https://github.com/wangyu-/udp2raw-tunnel" .. [[" >]]
|
||||
.. "https://github.com/wangyu-/udp2raw-tunnel" .. [[</a>]] .. bold_off
|
||||
|
||||
s=m:field(DummyValue,"udpspeeder_version",translate("UDPspeeder Version"))
|
||||
s.rawhtml = true
|
||||
s.value =udpspeeder_version
|
||||
|
||||
s=m:field(DummyValue,"udpspeeder_project",translate("UDPspeeder Project"))
|
||||
s.rawhtml = true
|
||||
s.value =bold_on .. [[<a href="]] .. "https://github.com/wangyu-/UDPspeeder" .. [[" >]]
|
||||
.. "https://github.com/wangyu-/UDPspeeder" .. [[</a>]] .. bold_off
|
||||
|
||||
return m
|
@ -0,0 +1,38 @@
|
||||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function check_connect(btn,urlname)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Check...%>';
|
||||
murl=urlname;
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr","check")%>',
|
||||
{ set:murl },
|
||||
function(x,rv)
|
||||
{
|
||||
var s = document.getElementById(urlname+'-status');
|
||||
if (s)
|
||||
{
|
||||
if (rv.ret=="0")
|
||||
s.innerHTML ="<font color='green'>"+"<%:Connect OK%>"+"</font>";
|
||||
else
|
||||
s.innerHTML ="<font color='red'>"+"<%:Connect Error%>"+"</font>";
|
||||
|
||||
|
||||
}
|
||||
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:Check Connect%>';
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Check Connect%>" onclick="return check_connect(this,'<%=self.option%>')" />
|
||||
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||
|
||||
<%+cbi/valuefooter%>
|
@ -0,0 +1,36 @@
|
||||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function check_port(btn)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Check...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr","checkport")%>',
|
||||
null,
|
||||
function(x,rv)
|
||||
{
|
||||
var s = document.getElementById('<%=self.option%>-status');
|
||||
if (s)
|
||||
{
|
||||
|
||||
s.innerHTML =rv.ret;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:Check Server%>';
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Check Server%>" onclick="return check_port(this)" />
|
||||
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||
|
||||
|
||||
|
||||
<%+cbi/valuefooter%>
|
@ -0,0 +1,44 @@
|
||||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function refresh_data(btn,dataname)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Refresh...%> ';
|
||||
murl=dataname;
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "shadowsocksr","refresh")%>',
|
||||
{ set:murl },
|
||||
function(x,rv)
|
||||
{
|
||||
var s = document.getElementById(dataname+'-status');
|
||||
if (s)
|
||||
{
|
||||
if (rv.ret=="0")
|
||||
s.innerHTML ="<font color='green'>"+"<%:No new data!%> "+"</font>";
|
||||
else if(rv.ret=="-1")
|
||||
{
|
||||
s.innerHTML ="<font color='red'>"+"<%:Refresh Error!%> "+"</font>";
|
||||
}
|
||||
else
|
||||
{
|
||||
s.innerHTML ="<font color='green'>"+"<%:Refresh OK!%> "+"<%:Total Records:%>"+rv.ret+"</font>";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:Refresh Data %>';
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
|
||||
<input type="button" class="cbi-button cbi-input-reload" value="<%:Refresh Data%> " onclick="return refresh_data(this,'<%=self.option%>')" />
|
||||
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||
|
||||
<%+cbi/valuefooter%>
|
139
package/lean/openwrt-ssr/files/luci/view/shadowsocksr/ssrurl.htm
Normal file
139
package/lean/openwrt-ssr/files/luci/view/shadowsocksr/ssrurl.htm
Normal file
@ -0,0 +1,139 @@
|
||||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function padright(str, cnt, pad){
|
||||
return str + Array(cnt+1).join(pad);
|
||||
}
|
||||
function b64EncodeUnicode(str) {
|
||||
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
|
||||
return String.fromCharCode('0x' + p1);
|
||||
}));
|
||||
}
|
||||
function b64encutf8safe(str) {
|
||||
return b64EncodeUnicode(str).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,'');
|
||||
}
|
||||
function b64DecodeUnicode(str) {
|
||||
return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
|
||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
||||
}).join(''));
|
||||
}
|
||||
function b64decutf8safe(str) {
|
||||
var l;
|
||||
str = str.replace(/-/g,"+").replace(/_/g,"/");
|
||||
l = str.length;
|
||||
l = (4 - l % 4)%4;
|
||||
if( l )
|
||||
str = padright(str,l,"=");
|
||||
return b64DecodeUnicode(str);
|
||||
}
|
||||
function b64encsafe(str){
|
||||
return btoa(str).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,'')
|
||||
}
|
||||
function b64decsafe(str){
|
||||
var l;
|
||||
str = str.replace(/-/g,"+").replace(/_/g,"/");
|
||||
l = str.length;
|
||||
l = (4 - l % 4)%4;
|
||||
if( l )
|
||||
str = padright(str,l,"=");
|
||||
return atob(str);
|
||||
}
|
||||
function dictvalue(d,key) {
|
||||
var v = d[key];
|
||||
if( typeof(v)=='undefined' || v=='' )
|
||||
return '';
|
||||
return b64decsafe(v);
|
||||
}
|
||||
function export_ssr_url(btn,urlname,sid) {
|
||||
var s = document.getElementById(urlname+'-status');
|
||||
if(!s)
|
||||
return false;
|
||||
var v_server = document.getElementById('cbid.shadowsocksr.'+sid+'.server');
|
||||
var v_port = document.getElementById('cbid.shadowsocksr.'+sid+'.server_port');
|
||||
var v_protocol = document.getElementById('cbid.shadowsocksr.'+sid+'.protocol');
|
||||
var v_method = document.getElementById('cbid.shadowsocksr.'+sid+'.encrypt_method');
|
||||
var v_obfs = document.getElementById('cbid.shadowsocksr.'+sid+'.obfs');
|
||||
var v_password = document.getElementById('cbid.shadowsocksr.'+sid+'.password');
|
||||
var v_obfs_param = document.getElementById('cbid.shadowsocksr.'+sid+'.obfs_param');
|
||||
var v_protocol_param = document.getElementById('cbid.shadowsocksr.'+sid+'.protocol_param');
|
||||
var v_alias = document.getElementById('cbid.shadowsocksr.'+sid+'.alias');
|
||||
|
||||
var ssr_str = v_server.value+":"+
|
||||
v_port.value+":"+
|
||||
v_protocol.value+":"+
|
||||
v_method.value+":"+
|
||||
v_obfs.value+":"+
|
||||
b64encsafe(v_password.value)+
|
||||
"/?obfsparam="+b64encsafe(v_obfs_param.value)+
|
||||
"&protoparam="+b64encsafe(v_protocol_param.value)+
|
||||
"&remarks="+b64encutf8safe(v_alias.value);
|
||||
var textarea = document.createElement("textarea");
|
||||
textarea.textContent = "ssr://"+b64encsafe(ssr_str);
|
||||
textarea.style.position = "fixed";
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
try {
|
||||
document.execCommand("copy"); // Security exception may be thrown by some browsers.
|
||||
s.innerHTML = "<font color='green'><%:Copy SSR to clipboard successfully.%></font>";
|
||||
} catch (ex) {
|
||||
s.innerHTML = "<font color='red'><%:Unable to copy SSR to clipboard.%></font>";
|
||||
} finally {
|
||||
document.body.removeChild(textarea);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function import_ssr_url(btn,urlname,sid) {
|
||||
var s = document.getElementById(urlname+'-status');
|
||||
if(!s)
|
||||
return false;
|
||||
var ssrurl = prompt("<%:Paste ssr url here%>", "ssr://");
|
||||
if (ssrurl == null || ssrurl == "") {
|
||||
s.innerHTML = "<font color='red'><%:User cancelled.%></font>";
|
||||
return false;
|
||||
}
|
||||
s.innerHTML = "<font color='red'><%:Invalid SSR format.%></font>";
|
||||
var ssu = ssrurl.match(/ssr:\/\/([A-Za-z0-9_-]+)/i);
|
||||
if( !ssu || ssu.length<2 )
|
||||
return false;
|
||||
var sstr = b64decsafe(ssu[1]);
|
||||
var ploc = sstr.indexOf("/?");
|
||||
var url0, param="";
|
||||
if( ploc>0 ) {
|
||||
url0 = sstr.substr(0,ploc);
|
||||
param = sstr.substr(ploc+2);
|
||||
}
|
||||
var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
|
||||
if( !ssm || ssm.length<7 )
|
||||
return false;
|
||||
var pdict = {};
|
||||
if( param.length>2 )
|
||||
{
|
||||
var a = param.split('&');
|
||||
for( var i=0;i<a.length; i++ ) {
|
||||
var b = a[i].split('=');
|
||||
pdict[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
|
||||
}
|
||||
}
|
||||
document.getElementById('cbid.shadowsocksr.'+sid+'.server').value = ssm[1];
|
||||
document.getElementById('cbid.shadowsocksr.'+sid+'.server_port').value = ssm[2];
|
||||
document.getElementById('cbid.shadowsocksr.'+sid+'.protocol').value = ssm[3];
|
||||
document.getElementById('cbid.shadowsocksr.'+sid+'.encrypt_method').value = ssm[4];
|
||||
document.getElementById('cbid.shadowsocksr.'+sid+'.obfs').value = ssm[5];
|
||||
document.getElementById('cbid.shadowsocksr.'+sid+'.password').value = b64decsafe(ssm[6]);
|
||||
document.getElementById('cbid.shadowsocksr.'+sid+'.obfs_param').value = dictvalue(pdict,'obfsparam');
|
||||
document.getElementById('cbid.shadowsocksr.'+sid+'.protocol_param').value = dictvalue(pdict,'protoparam');
|
||||
|
||||
var rem = pdict['remarks'];
|
||||
if( typeof(rem)!='undefined' && rem!='' && rem.length>0 )
|
||||
document.getElementById('cbid.shadowsocksr.'+sid+'.alias').value = b64decutf8safe(rem);
|
||||
|
||||
s.innerHTML = "<font color='green'><%:Import SSR successfully.%></font>";
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Import SSR%>" onclick="return import_ssr_url(this,'<%=self.option%>','<%=self.value%>')" />
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Export SSR%>" onclick="return export_ssr_url(this,'<%=self.option%>','<%=self.value%>')" />
|
||||
<span id="<%=self.option%>-status"><%:ssr://%></span>
|
||||
|
||||
<%+cbi/valuefooter%>
|
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@shadowsocksr[-1]
|
||||
add ucitrack shadowsocksr
|
||||
set ucitrack.@shadowsocksr[-1].init=shadowsocksr
|
||||
commit ucitrack
|
||||
delete firewall.shadowsocksr
|
||||
set firewall.shadowsocksr=include
|
||||
set firewall.shadowsocksr.type=script
|
||||
set firewall.shadowsocksr.path=/var/etc/shadowsocksr.include
|
||||
set firewall.shadowsocksr.reload=1
|
||||
commit firewall
|
||||
EOF
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
BIN
package/lean/openwrt-ssr/files/root/usr/bin/ssr-server
Normal file
BIN
package/lean/openwrt-ssr/files/root/usr/bin/ssr-server
Normal file
Binary file not shown.
169
package/lean/openwrt-ssr/files/root/usr/share/shadowsocksr/subscribe.sh
Executable file
169
package/lean/openwrt-ssr/files/root/usr/share/shadowsocksr/subscribe.sh
Executable file
@ -0,0 +1,169 @@
|
||||
#!/bin/bash
|
||||
# Copyright (C) 2017 XiaoShan https://www.mivm.cn
|
||||
|
||||
urlsafe_b64decode() {
|
||||
local d="====" data=$(echo $1 | sed 's/_/\//g; s/-/+/g')
|
||||
local mod4=$((${#data}%4))
|
||||
[ $mod4 -gt 0 ] && data=${data}${d:mod4}
|
||||
echo $data | base64 -d
|
||||
}
|
||||
|
||||
CheckIPAddr() {
|
||||
echo $1 | grep "^[0-9]\{1,3\}\.\([0-9]\{1,3\}\.\)\{2\}[0-9]\{1,3\}$" >/dev/null 2>&1
|
||||
[ $? -ne 0 ] && return 1
|
||||
local ipaddr=($(echo $1 | sed 's/\./ /g'))
|
||||
[ ${#ipaddr[@]} -ne 4 ] && return 1
|
||||
for ((i=0;i<${#ipaddr[@]};i++))
|
||||
do
|
||||
[ ${ipaddr[i]} -gt 255 -a ${ipaddr[i]} -lt 0 ] && return 1
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
Server_Update() {
|
||||
local uci_set="uci -q set $name.$1."
|
||||
${uci_set}alias="[$ssr_group] $ssr_remarks"
|
||||
${uci_set}auth_enable="0"
|
||||
${uci_set}switch_enable="0"
|
||||
${uci_set}server="$ssr_host"
|
||||
${uci_set}server_port="$ssr_port"
|
||||
${uci_set}local_port="1234"
|
||||
uci -q get $name.@servers[$1].timeout >/dev/null || ${uci_set}timeout="60"
|
||||
${uci_set}password="$ssr_passwd"
|
||||
${uci_set}encrypt_method="$ssr_method"
|
||||
${uci_set}protocol="$ssr_protocol"
|
||||
${uci_set}protocol_param="$ssr_protoparam"
|
||||
${uci_set}obfs="$ssr_obfs"
|
||||
${uci_set}obfs_param="$ssr_obfsparam"
|
||||
${uci_set}fast_open="0"
|
||||
${uci_set}kcp_enable="0"
|
||||
${uci_set}kcp_port="0"
|
||||
${uci_set}kcp_param="--nocomp"
|
||||
}
|
||||
|
||||
name=shadowsocksr
|
||||
subscribe_url=($(uci get $name.@server_subscribe[0].subscribe_url))
|
||||
[ ${#subscribe_url[@]} -eq 0 ] && exit 1
|
||||
[ $(uci -q get $name.@server_subscribe[0].proxy || echo 0) -eq 0 ] && /etc/init.d/$name stop >/dev/null 2>&1
|
||||
log_name=${name}_subscribe
|
||||
for ((o=0;o<${#subscribe_url[@]};o++))
|
||||
do
|
||||
subscribe_data=$(curl -s -L --connect-timeout 3 ${subscribe_url[o]})
|
||||
curl_code=$?
|
||||
if [ $curl_code -eq 0 ];then
|
||||
ssr_url=($(echo $subscribe_data | base64 -d | sed 's/\r//g')) # 解码数据并删除 \r 换行符
|
||||
subscribe_max=$(echo ${ssr_url[0]} | grep -i MAX= | awk -F = '{print $2}')
|
||||
subscribe_max_x=()
|
||||
if [ -n "$subscribe_max" ]; then
|
||||
while [ ${#subscribe_max_x[@]} -ne $subscribe_max ]
|
||||
do
|
||||
if [ ${#ssr_url[@]} -ge 10 ]; then
|
||||
if [ $((${RANDOM:0:2}%2)) -eq 0 ]; then
|
||||
temp_x=${RANDOM:0:1}
|
||||
else
|
||||
temp_x=${RANDOM:0:2}
|
||||
fi
|
||||
else
|
||||
temp_x=${RANDOM:0:1}
|
||||
fi
|
||||
[ $temp_x -lt ${#ssr_url[@]} -a -z "$(echo "${subscribe_max_x[*]}" | grep -w ${temp_x})" ] && subscribe_max_x[${#subscribe_max_x[@]}]="$temp_x"
|
||||
done
|
||||
else
|
||||
subscribe_max=${#ssr_url[@]}
|
||||
fi
|
||||
ssr_group=$(urlsafe_b64decode $(urlsafe_b64decode ${ssr_url[$((${#ssr_url[@]} - 1))]//ssr:\/\//} | sed 's/&/\n/g' | grep group= | awk -F = '{print $2}'))
|
||||
if [ -n "$ssr_group" ]; then
|
||||
subscribe_i=0
|
||||
subscribe_n=0
|
||||
subscribe_o=0
|
||||
subscribe_x=""
|
||||
temp_host_o=()
|
||||
curr_ssr=$(uci show $name | grep @servers | grep -c server=)
|
||||
for ((x=0;x<$curr_ssr;x++)) # 循环已有服务器信息,匹配当前订阅群组
|
||||
do
|
||||
temp_alias=$(uci -q get $name.@servers[$x].alias | grep "\[$ssr_group\]")
|
||||
[ -n "$temp_alias" ] && temp_host_o[${#temp_host_o[@]}]=$(uci get $name.@servers[$x].server)
|
||||
done
|
||||
for ((x=0;x<$subscribe_max;x++)) # 循环链接
|
||||
do
|
||||
[ ${#subscribe_max_x[@]} -eq 0 ] && temp_x=$x || temp_x=${subscribe_max_x[x]}
|
||||
temp_info=$(urlsafe_b64decode ${ssr_url[temp_x]//ssr:\/\//}) # 解码 SSR 链接
|
||||
# 依次获取基本信息
|
||||
info=${temp_info///?*/}
|
||||
temp_info_array=(${info//:/ })
|
||||
ssr_host=${temp_info_array[0]}
|
||||
ssr_port=${temp_info_array[1]}
|
||||
ssr_protocol=${temp_info_array[2]}
|
||||
ssr_method=${temp_info_array[3]}
|
||||
ssr_obfs=${temp_info_array[4]}
|
||||
ssr_passwd=$(urlsafe_b64decode ${temp_info_array[5]})
|
||||
info=${temp_info:$((${#info} + 2))}
|
||||
info=(${info//&/ })
|
||||
ssr_protoparam=""
|
||||
ssr_obfsparam=""
|
||||
ssr_remarks="$temp_x"
|
||||
for ((i=0;i<${#info[@]};i++)) # 循环扩展信息
|
||||
do
|
||||
temp_info=($(echo ${info[i]} | sed 's/=/ /g'))
|
||||
case "${temp_info[0]}" in
|
||||
protoparam)
|
||||
ssr_protoparam=$(urlsafe_b64decode ${temp_info[1]})
|
||||
;;
|
||||
obfsparam)
|
||||
ssr_obfsparam=$(urlsafe_b64decode ${temp_info[1]})
|
||||
;;
|
||||
remarks)
|
||||
ssr_remarks=$(urlsafe_b64decode ${temp_info[1]})
|
||||
;;
|
||||
esac
|
||||
done
|
||||
CheckIPAddr $ssr_host
|
||||
if [ $? -ne 0 ]; then # 如果地址不是IP 则解析IP
|
||||
ssr_hosts=($(dig $ssr_host a +short))
|
||||
for ((i=0;i<${#ssr_hosts[@]};i++))
|
||||
do
|
||||
ssr_host=${ssr_hosts[i]}
|
||||
CheckIPAddr $ssr_host
|
||||
[ $? -eq 0 ] && continue
|
||||
ssr_host=""
|
||||
done
|
||||
[ -z "$ssr_host" ] && continue
|
||||
fi
|
||||
|
||||
uci_name_tmp=$(uci show $name | grep -w $ssr_host | awk -F . '{print $2}')
|
||||
if [ -z "$uci_name_tmp" ]; then # 判断当前服务器信息是否存在
|
||||
uci_name_tmp=$(uci add $name servers)
|
||||
subscribe_n=$(($subscribe_n + 1))
|
||||
fi
|
||||
Server_Update $uci_name_tmp
|
||||
subscribe_x=${subscribe_x}$ssr_host" "
|
||||
|
||||
# echo "服务器地址: $ssr_host"
|
||||
# echo "服务器端口 $ssr_port"
|
||||
# echo "密码: $ssr_passwd"
|
||||
# echo "加密: $ssr_method"
|
||||
# echo "协议: $ssr_protocol"
|
||||
# echo "协议参数: $ssr_protoparam"
|
||||
# echo "混淆: $ssr_obfs"
|
||||
# echo "混淆参数: $ssr_obfsparam"
|
||||
# echo "备注: $ssr_remarks"
|
||||
done
|
||||
for ((x=0;x<${#temp_host_o[@]};x++)) # 新旧服务器信息匹配,如果旧服务器信息不存在于新服务器信息则删除
|
||||
do
|
||||
if [ -z "$(echo "$subscribe_x" | grep -w ${temp_host_o[x]})" ]; then
|
||||
uci_name_tmp=$(uci show $name | grep ${temp_host_o[x]} | awk -F . '{print $2}')
|
||||
uci delete $name.$uci_name_tmp
|
||||
subscribe_o=$(($subscribe_o + 1))
|
||||
fi
|
||||
done
|
||||
subscribe_log="$ssr_group 服务器订阅更新成功 服务器数量: ${#ssr_url[@]} 新增服务器: $subscribe_n 删除服务器: $subscribe_o"
|
||||
logger -st $log_name[$$] -p6 "$subscribe_log"
|
||||
uci commit $name
|
||||
else
|
||||
logger -st $log_name[$$] -p3 "${subscribe_url[$o]} 订阅数据解析失败 无法获取 Group"
|
||||
fi
|
||||
else
|
||||
logger -st $log_name[$$] -p3 "${subscribe_url[$o]} 订阅数据获取失败 错误代码: $curl_code"
|
||||
fi
|
||||
done
|
||||
/etc/init.d/$name restart >/dev/null 2>&1
|
6
package/lean/openwrt-ssr/files/shadowsocksr.ad
Normal file
6
package/lean/openwrt-ssr/files/shadowsocksr.ad
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
if [ -f /tmp/adnew.conf ]; then
|
||||
cat /tmp/adnew.conf | grep ^\|\|[^\*]*\^$ | sed -e 's:||:address\=\/:' -e 's:\^:/0\.0\.0\.0:' > /tmp/ad.conf
|
||||
fi
|
||||
|
76
package/lean/openwrt-ssr/files/shadowsocksr.config
Normal file
76
package/lean/openwrt-ssr/files/shadowsocksr.config
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
config global
|
||||
option global_server 'nil'
|
||||
option monitor_enable '1'
|
||||
option tunnel_enable '0'
|
||||
option tunnel_port '5300'
|
||||
option tunnel_forward '8.8.4.4:53'
|
||||
option tunnel_address '0.0.0.0'
|
||||
option pdnsd_enable '0'
|
||||
option run_mode 'router'
|
||||
|
||||
config servers
|
||||
option auth_enable '0'
|
||||
option fast_open '0'
|
||||
option server '127.0.0.1'
|
||||
option server_port '8388'
|
||||
option local_port '1234'
|
||||
option password 'hello!!'
|
||||
option timeout '60'
|
||||
option encrypt_method 'rc4-md5'
|
||||
option protocol 'origin'
|
||||
option obfs 'plain'
|
||||
option obfs_param ''
|
||||
option kcp_enable '0'
|
||||
option kcp_port '4000'
|
||||
option kcp_password ''
|
||||
option kcp_param '--nocomp'
|
||||
|
||||
config socks5_proxy
|
||||
option server 'nil'
|
||||
option local_port '1080'
|
||||
option local_address '0.0.0.0'
|
||||
|
||||
config access_control
|
||||
option lan_ac_mode '0'
|
||||
option router_proxy '1'
|
||||
option wan_bp_list '/etc/china_ssr.txt'
|
||||
|
||||
config server_global
|
||||
option enable_server '0'
|
||||
|
||||
config server_config
|
||||
option server '0.0.0.0'
|
||||
option server_port '8388'
|
||||
option password 'hello!!'
|
||||
option timeout '60'
|
||||
option encrypt_method 'rc4-md5'
|
||||
option protocol 'origin'
|
||||
option obfs 'plain'
|
||||
option obfs_param ''
|
||||
option fast_open '0'
|
||||
option enable '1'
|
||||
|
||||
config server_subscribe
|
||||
option auto_update '0'
|
||||
|
||||
config udp2raw
|
||||
option server '127.0.0.1'
|
||||
option server_port '600'
|
||||
option local_port '400'
|
||||
option key 'passwd'
|
||||
option raw_mode 'faketcp'
|
||||
option seq_mode '3'
|
||||
option cipher_mode 'xor'
|
||||
option auth_mode 'simple'
|
||||
|
||||
config udpspeeder
|
||||
option server '127.0.0.1'
|
||||
option server_port '400'
|
||||
option local_port '500'
|
||||
option key 'passwd'
|
||||
option speeder_mode '0'
|
||||
option fec '2:4'
|
||||
option mtu '1250'
|
||||
option queue_len '1'
|
||||
option timeout '8'
|
33
package/lean/openwrt-ssr/files/shadowsocksr.gfw
Normal file
33
package/lean/openwrt-ssr/files/shadowsocksr.gfw
Normal file
@ -0,0 +1,33 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
generate_china_banned()
|
||||
{
|
||||
|
||||
cat $1 | base64 -d > /tmp/gfwlist.txt
|
||||
rm -f $1
|
||||
|
||||
|
||||
cat /tmp/gfwlist.txt | sort -u |
|
||||
sed 's#!.\+##; s#|##g; s#@##g; s#http:\/\/##; s#https:\/\/##;' |
|
||||
sed '/\*/d; /apple\.com/d; /sina\.cn/d; /sina\.com\.cn/d; /baidu\.com/d; /byr\.cn/d; /jlike\.com/d; /weibo\.com/d; /zhongsou\.com/d; /youdao\.com/d; /sogou\.com/d; /so\.com/d; /soso\.com/d; /aliyun\.com/d; /taobao\.com/d; /jd\.com/d; /qq\.com/d' |
|
||||
sed '/^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/d' |
|
||||
grep '^[0-9a-zA-Z\.-]\+$' | grep '\.' | sed 's#^\.\+##' | sort -u |
|
||||
awk '
|
||||
BEGIN { prev = "________"; } {
|
||||
cur = $0;
|
||||
if (index(cur, prev) == 1 && substr(cur, 1 + length(prev) ,1) == ".") {
|
||||
} else {
|
||||
print cur;
|
||||
prev = cur;
|
||||
}
|
||||
}' | sort -u
|
||||
|
||||
}
|
||||
|
||||
generate_china_banned /tmp/gfw.b64 > /tmp/gfw.txt
|
||||
rm -f /tmp/gfwlist.txt
|
||||
datestr=`date`
|
||||
echo -e "# gfw list ipset rules for dnsmasq\n# updated on $datestr\n#">/tmp/gfwnew.txt
|
||||
sed '/.*/s/.*/server=\/\.&\/127.0.0.1#5353\nipset=\/\.&\/gfwlist/' /tmp/gfw.txt >>/tmp/gfwnew.txt
|
||||
rm -f /tmp/gfw.txt
|
||||
|
503
package/lean/openwrt-ssr/files/shadowsocksr.init
Normal file
503
package/lean/openwrt-ssr/files/shadowsocksr.init
Normal file
@ -0,0 +1,503 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (C) 2017 openwrt-ssr
|
||||
# Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
START=90
|
||||
STOP=15
|
||||
|
||||
SERVICE_DAEMONIZE=1
|
||||
NAME=shadowsocksr
|
||||
EXTRA_COMMANDS=rules
|
||||
CONFIG_FILE=/var/etc/${NAME}.json
|
||||
CONFIG_UDP_FILE=/var/etc/${NAME}_u.json
|
||||
CONFIG_SOCK5_FILE=/var/etc/${NAME}_s.json
|
||||
server_count=0
|
||||
redir_tcp=0
|
||||
redir_udp=0
|
||||
tunnel_enable=0
|
||||
local_enable=0
|
||||
kcp_enable_flag=0
|
||||
kcp_flag=0
|
||||
pdnsd_enable_flag=0
|
||||
switch_enable=0
|
||||
switch_server=$1
|
||||
MAXFD=32768
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
run_mode=$(uci_get_by_type global run_mode)
|
||||
|
||||
gen_config_file() {
|
||||
local host=$(uci_get_by_name $1 server)
|
||||
if echo $host|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
|
||||
hostip=${host}
|
||||
elif [ "$host" != "${host#*:[0-9a-fA-F]}" ] ;then
|
||||
hostip=${host}
|
||||
else
|
||||
hostip=`ping ${host} -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1`
|
||||
if echo $hostip|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
|
||||
hostip=${hostip}
|
||||
else
|
||||
hostip=`cat /etc/ssr_ip`
|
||||
fi
|
||||
fi
|
||||
[ $2 = "0" -a $kcp_flag = "1" ] && hostip="127.0.0.1"
|
||||
|
||||
if [ $2 = "0" ] ;then
|
||||
config_file=$CONFIG_FILE
|
||||
elif [ $2 = "1" ]; then
|
||||
config_file=$CONFIG_UDP_FILE
|
||||
else
|
||||
config_file=$CONFIG_SOCK5_FILE
|
||||
fi
|
||||
if [ $(uci_get_by_name $1 fast_open) = "1" ] ;then
|
||||
fastopen="true";
|
||||
else
|
||||
fastopen="false";
|
||||
fi
|
||||
cat <<-EOF >$config_file
|
||||
{
|
||||
|
||||
"server": "$hostip",
|
||||
"server_port": $(uci_get_by_name $1 server_port),
|
||||
"local_address": "0.0.0.0",
|
||||
"local_port": $(uci_get_by_name $1 local_port),
|
||||
"password": "$(uci_get_by_name $1 password)",
|
||||
"timeout": $(uci_get_by_name $1 timeout 60),
|
||||
"method": "$(uci_get_by_name $1 encrypt_method)",
|
||||
"protocol": "$(uci_get_by_name $1 protocol)",
|
||||
"protocol_param": "$(uci_get_by_name $1 protocol_param)",
|
||||
"obfs": "$(uci_get_by_name $1 obfs)",
|
||||
"obfs_param": "$(uci_get_by_name $1 obfs_param)",
|
||||
"fast_open": $fastopen
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
get_arg_out() {
|
||||
case "$(uci_get_by_type access_control router_proxy 1)" in
|
||||
1) echo "-o";;
|
||||
2) echo "-O";;
|
||||
esac
|
||||
}
|
||||
|
||||
start_rules() {
|
||||
local server=$(uci_get_by_name $GLOBAL_SERVER server)
|
||||
#resolve name
|
||||
if echo $server|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
|
||||
server=${server}
|
||||
elif [ "$server" != "${server#*:[0-9a-fA-F]}" ] ;then
|
||||
server=${server}
|
||||
else
|
||||
server=`ping ${server} -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1`
|
||||
if echo $server|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
|
||||
echo $server >/etc/ssr_ip
|
||||
else
|
||||
server=`cat /etc/ssr_ip`
|
||||
fi
|
||||
fi
|
||||
|
||||
kcp_server=$server
|
||||
|
||||
local kcp_enable=$(uci_get_by_name $GLOBAL_SERVER kcp_enable)
|
||||
if [ $kcp_enable = "1" ] ;then
|
||||
kcp_flag=1
|
||||
fi
|
||||
|
||||
local local_port=$(uci_get_by_name $GLOBAL_SERVER local_port)
|
||||
local lan_ac_ips=$(uci_get_by_type access_control lan_ac_ips)
|
||||
local lan_ac_mode=$(uci_get_by_type access_control lan_ac_mode)
|
||||
local router_proxy=$(uci_get_by_type access_control router_proxy)
|
||||
if [ "$GLOBAL_SERVER" = "$UDP_RELAY_SERVER" -a $kcp_flag = 0 ]; then
|
||||
ARG_UDP="-u"
|
||||
elif [ -n "$UDP_RELAY_SERVER" ]; then
|
||||
ARG_UDP="-U"
|
||||
local udp_server=$(uci_get_by_name $UDP_RELAY_SERVER server)
|
||||
local udp_local_port=$(uci_get_by_name $UDP_RELAY_SERVER local_port)
|
||||
fi
|
||||
|
||||
if [ -n "$lan_ac_ips" ]; then
|
||||
case "$lan_ac_mode" in
|
||||
w|W|b|B) local ac_ips="$lan_ac_mode$lan_ac_ips";;
|
||||
esac
|
||||
fi
|
||||
|
||||
#deal gfw firewall rule
|
||||
local gfwmode=""
|
||||
if [ "$run_mode" = "gfw" ]; then
|
||||
gfwmode="-g"
|
||||
fi
|
||||
|
||||
|
||||
/usr/bin/ssr-rules \
|
||||
-s "$server" \
|
||||
-l "$local_port" \
|
||||
-S "$udp_server" \
|
||||
-L "$udp_local_port" \
|
||||
-a "$ac_ips" \
|
||||
-i "$(uci_get_by_type access_control wan_bp_list)" \
|
||||
-b "$(uci_get_by_type access_control wan_bp_ips)" \
|
||||
-w "$(uci_get_by_type access_control wan_fw_ips)" \
|
||||
$(get_arg_out) $gfwmode $ARG_UDP
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
start_pdnsd() {
|
||||
local usr_dns="$1"
|
||||
local usr_port="$2"
|
||||
|
||||
local tcp_dns_list="208.67.222.222, 208.67.220.220"
|
||||
[ -z "$usr_dns" ] && usr_dns="8.8.8.8"
|
||||
[ -z "$usr_port" ] && usr_port="53"
|
||||
mkdir -p /var/etc /var/pdnsd
|
||||
|
||||
if ! test -f "/var/pdnsd/pdnsd.cache"; then
|
||||
dd if=/dev/zero of="/var/pdnsd/pdnsd.cache" bs=1 count=4 2> /dev/null
|
||||
chown -R nobody.nogroup /var/pdnsd
|
||||
fi
|
||||
|
||||
cat > /var/etc/pdnsd.conf <<EOF
|
||||
global {
|
||||
perm_cache=10240;
|
||||
cache_dir="/var/pdnsd";
|
||||
pid_file = /var/run/pdnsd.pid;
|
||||
run_as="nobody";
|
||||
server_ip = 127.0.0.1;
|
||||
server_port = 5353;
|
||||
status_ctl = on;
|
||||
query_method = tcp_only;
|
||||
min_ttl=1h;
|
||||
max_ttl=1w;
|
||||
timeout=10;
|
||||
neg_domain_pol=on;
|
||||
proc_limit=2;
|
||||
procq_limit=8;
|
||||
}
|
||||
server {
|
||||
label= "ssr-usrdns";
|
||||
ip = $usr_dns;
|
||||
port = $usr_port;
|
||||
timeout=6;
|
||||
uptest=none;
|
||||
interval=10m;
|
||||
purge_cache=off;
|
||||
}
|
||||
server {
|
||||
label= "ssr-pdnsd";
|
||||
ip = $tcp_dns_list;
|
||||
port = 5353;
|
||||
timeout=6;
|
||||
uptest=none;
|
||||
interval=10m;
|
||||
purge_cache=off;
|
||||
}
|
||||
EOF
|
||||
|
||||
/usr/sbin/pdnsd -c /var/etc/pdnsd.conf -d
|
||||
}
|
||||
|
||||
start_tunnel() {
|
||||
local tunnel_config_file=$CONFIG_FILE
|
||||
if [ "$ARG_UDP" = "-U" ]; then
|
||||
tunnel_config_file=$CONFIG_UDP_FILE
|
||||
fi
|
||||
|
||||
local local_dns_port=$(uci_get_by_type global tunnel_port)
|
||||
if [ "$run_mode" = "gfw" ] ;then
|
||||
local_dns_port=5353
|
||||
fi
|
||||
|
||||
/usr/bin/ssr-tunnel \
|
||||
-c $tunnel_config_file $ARG_OTA -u \
|
||||
-l $local_dns_port \
|
||||
-b $(uci_get_by_type global tunnel_address 0.0.0.0) \
|
||||
-L $(uci_get_by_type global tunnel_forward 8.8.4.4:53) \
|
||||
-f /var/run/ssr-tunnel.pid
|
||||
tunnel_enable=1
|
||||
return $?
|
||||
}
|
||||
|
||||
start_redir() {
|
||||
case "$(uci_get_by_name $GLOBAL_SERVER auth_enable)" in
|
||||
1|on|true|yes|enabled) ARG_OTA="-A";;
|
||||
*) ARG_OTA="";;
|
||||
esac
|
||||
|
||||
#deal kcp
|
||||
local kcp_enable=$(uci_get_by_name $GLOBAL_SERVER kcp_enable)
|
||||
if [ $kcp_enable = "1" ] ;then
|
||||
[ ! -f "/usr/bin/ssr-kcptun" ] && return 1
|
||||
|
||||
local kcp_str=`/usr/bin/ssr-kcptun -v |grep kcptun|wc -l`
|
||||
[ "0" = $kcp_str ] && return 1
|
||||
local kcp_port=$(uci_get_by_name $GLOBAL_SERVER kcp_port)
|
||||
local server_port=$(uci_get_by_name $GLOBAL_SERVER server_port)
|
||||
local password=$(uci_get_by_name $GLOBAL_SERVER kcp_password)
|
||||
local kcp_param=$(uci_get_by_name $GLOBAL_SERVER kcp_param)
|
||||
[ "$password" != "" ] && password="--key "${password}
|
||||
service_start /usr/bin/ssr-kcptun \
|
||||
-r $kcp_server:$kcp_port \
|
||||
-l :$server_port $password $kcp_param
|
||||
kcp_enable_flag=1
|
||||
fi
|
||||
|
||||
gen_config_file $GLOBAL_SERVER 0
|
||||
|
||||
redir_tcp=1
|
||||
local last_config_file=$CONFIG_FILE
|
||||
local pid_file="/var/run/ssr-retcp.pid"
|
||||
|
||||
if [ "$ARG_UDP" = "-U" ]; then
|
||||
/usr/bin/ssr-redir \
|
||||
-c $CONFIG_FILE $ARG_OTA \
|
||||
-f /var/run/ssr-retcp.pid
|
||||
|
||||
case "$(uci_get_by_name $UDP_RELAY_SERVER auth_enable)" in
|
||||
1|on|true|yes|enabled) ARG_OTA="-A";;
|
||||
*) ARG_OTA="";;
|
||||
esac
|
||||
gen_config_file $UDP_RELAY_SERVER 1
|
||||
last_config_file=$CONFIG_UDP_FILE
|
||||
pid_file="/var/run/ssr-reudp.pid"
|
||||
redir_udp=1
|
||||
fi
|
||||
|
||||
/usr/bin/ssr-redir \
|
||||
-c $last_config_file $ARG_OTA $ARG_UDP \
|
||||
-f $pid_file
|
||||
|
||||
#deal with dns
|
||||
if [ "$run_mode" = "gfw" ] ;then
|
||||
if [ "$(uci_get_by_type global pdnsd_enable)" = "0" ] ;then
|
||||
start_tunnel
|
||||
fi
|
||||
|
||||
if [ "$(uci_get_by_type global pdnsd_enable)" = "1" ] ;then
|
||||
local dnsstr="$(uci_get_by_type global tunnel_forward 8.8.4.4:53)"
|
||||
local dnsserver=`echo "$dnsstr"|awk -F ':' '{print $1}'`
|
||||
local dnsport=`echo "$dnsstr"|awk -F ':' '{print $2}'`
|
||||
ipset add gfwlist $dnsserver 2>/dev/null
|
||||
start_pdnsd $dnsserver $dnsport
|
||||
pdnsd_enable_flag=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$(uci_get_by_type global enable_switch)" = "1" ] ;then
|
||||
if [ "$(uci_get_by_name $GLOBAL_SERVER switch_enable)" = "1" ] ;then
|
||||
if [ -z "$switch_server" ] ;then
|
||||
local switch_time=$(uci_get_by_type global switch_time)
|
||||
local switch_timeout=$(uci_get_by_type global switch_timeout)
|
||||
service_start /usr/bin/ssr-switch start $switch_time $switch_timeout
|
||||
switch_enable=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
start_udp2raw() {
|
||||
cat > /var/etc/udp2raw.conf <<EOF
|
||||
# udp2raw config file
|
||||
-c
|
||||
-l0.0.0.0:$(uci_get_by_type udp2raw local_port)
|
||||
-r$(uci_get_by_type udp2raw server):$(uci_get_by_type udp2raw server_port)
|
||||
-a
|
||||
-k $(uci_get_by_type udp2raw key)
|
||||
--raw-mode $(uci_get_by_type udp2raw raw_mode)
|
||||
--seq-mode $(uci_get_by_type udp2raw seq_mode)
|
||||
--cipher-mode $(uci_get_by_type udp2raw cipher_mode)
|
||||
--auth-mode $(uci_get_by_type udp2raw auth_mode)
|
||||
EOF
|
||||
/usr/bin/udp2raw --conf-file /var/etc/udp2raw.conf >/dev/null 2>&1 &
|
||||
}
|
||||
|
||||
start_udpspeeeder() {
|
||||
/usr/bin/udpspeeder -c -l0.0.0.0:$(uci_get_by_type udpspeeder local_port) \
|
||||
-r$(uci_get_by_type udpspeeder server):$(uci_get_by_type udpspeeder server_port) \
|
||||
-k $(uci_get_by_type udpspeeder key) \
|
||||
--mode $(uci_get_by_type udpspeeder speeder_mode) \
|
||||
--mtu $(uci_get_by_type udpspeeder mtu) \
|
||||
-f$(uci_get_by_type udpspeeder fec) \
|
||||
-q$(uci_get_by_type udpspeeder queue_len) \
|
||||
--timeout $(uci_get_by_type udpspeeder timeout) \
|
||||
>/dev/null 2>&1 &
|
||||
}
|
||||
|
||||
gen_service_file() {
|
||||
if [ $(uci_get_by_name $1 fast_open) = "1" ] ;then
|
||||
fastopen="true";
|
||||
else
|
||||
fastopen="false";
|
||||
fi
|
||||
cat <<-EOF >$2
|
||||
{
|
||||
"server": "$(uci_get_by_name $1 server)",
|
||||
"server_port": $(uci_get_by_name $1 server_port),
|
||||
"password": "$(uci_get_by_name $1 password)",
|
||||
"timeout": $(uci_get_by_name $1 timeout 60),
|
||||
"method": "$(uci_get_by_name $1 encrypt_method)",
|
||||
"protocol": "$(uci_get_by_name $1 protocol)",
|
||||
"protocol_param": "$(uci_get_by_name $1 protocol_param)",
|
||||
"obfs": "$(uci_get_by_name $1 obfs)",
|
||||
"obfs_param": "$(uci_get_by_name $1 obfs_param)",
|
||||
"fast_open": $fastopen
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
start_service() {
|
||||
[ $(uci_get_by_name $1 enable) = "0" ] && return 1
|
||||
let server_count=server_count+1
|
||||
if [ $server_count = 1 ] ;then
|
||||
iptables -N SSR-SERVER-RULE && \
|
||||
iptables -t filter -I INPUT -j SSR-SERVER-RULE
|
||||
fi
|
||||
|
||||
gen_service_file $1 /var/etc/${NAME}_${server_count}.json
|
||||
/usr/bin/ssr-server -c /var/etc/${NAME}_${server_count}.json -u -f /var/run/ssr-server${server_count}.pid
|
||||
iptables -t filter -A SSR-SERVER-RULE -p tcp --dport $(uci_get_by_name $1 server_port) -j ACCEPT
|
||||
iptables -t filter -A SSR-SERVER-RULE -p udp --dport $(uci_get_by_name $1 server_port) -j ACCEPT
|
||||
return 0
|
||||
}
|
||||
gen_serv_include() {
|
||||
FWI=$(uci get firewall.shadowsocksr.path 2>/dev/null)
|
||||
[ -n "$FWI" ] || return 0
|
||||
if [ ! -f $FWI ] ;then
|
||||
echo '#!/bin/sh' >$FWI
|
||||
fi
|
||||
extract_rules() {
|
||||
echo "*filter"
|
||||
iptables-save -t filter | grep SSR-SERVER-RULE|sed -e "s/^-A INPUT/-I INPUT/"
|
||||
echo 'COMMIT'
|
||||
}
|
||||
cat <<-EOF >>$FWI
|
||||
iptables-save -c | grep -v "SSR-SERVER" | iptables-restore -c
|
||||
iptables-restore -n <<-EOT
|
||||
$(extract_rules)
|
||||
EOT
|
||||
EOF
|
||||
|
||||
}
|
||||
start_server() {
|
||||
SERVER_ENABLE=$(uci_get_by_type server_global enable_server)
|
||||
[ "$SERVER_ENABLE" = 0 ] && return 0
|
||||
mkdir -p /var/run /var/etc
|
||||
|
||||
config_load $NAME
|
||||
config_foreach start_service server_config
|
||||
gen_serv_include
|
||||
return 0
|
||||
}
|
||||
|
||||
start_local() {
|
||||
local local_server=$(uci_get_by_type socks5_proxy server)
|
||||
[ "$local_server" = "nil" ] && return 1
|
||||
mkdir -p /var/run /var/etc
|
||||
gen_config_file $local_server 2
|
||||
/usr/bin/ssr-local -c $CONFIG_SOCK5_FILE -u \
|
||||
-l $(uci_get_by_type socks5_proxy local_port 1080) \
|
||||
-b $(uci_get_by_type socks5_proxy local_address 0.0.0.0) \
|
||||
-f /var/run/ssr-local.pid
|
||||
local_enable=1
|
||||
}
|
||||
|
||||
rules() {
|
||||
[ "$GLOBAL_SERVER" = "nil" ] && return 1
|
||||
mkdir -p /var/run /var/etc
|
||||
UDP_RELAY_SERVER=$(uci_get_by_type global udp_relay_server)
|
||||
[ "$UDP_RELAY_SERVER" = "same" ] && UDP_RELAY_SERVER=$GLOBAL_SERVER
|
||||
if start_rules ;then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
start() {
|
||||
case "$(uci_get_by_type udp2raw udp2raw_enable)" in
|
||||
1|on|true|yes|enabled)
|
||||
start_udp2raw
|
||||
;;
|
||||
esac
|
||||
case "$(uci_get_by_type udpspeeder udpspeeder_enable)" in
|
||||
1|on|true|yes|enabled)
|
||||
start_udpspeeeder
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$switch_server" ] ;then
|
||||
GLOBAL_SERVER=$(uci_get_by_type global global_server)
|
||||
else
|
||||
GLOBAL_SERVER=$switch_server
|
||||
switch_enable=1
|
||||
fi
|
||||
if rules ;then
|
||||
start_redir
|
||||
|
||||
if ! [ "$run_mode" = "gfw" ] ;then
|
||||
case "$(uci_get_by_type global tunnel_enable)" in
|
||||
1|on|true|yes|enabled)
|
||||
start_tunnel
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
fi
|
||||
start_server
|
||||
start_local
|
||||
if [ $(uci_get_by_type global monitor_enable) = 1 ] ;then
|
||||
let total_count=server_count+redir_tcp+redir_udp+tunnel_enable+kcp_enable_flag+local_enable+pdnsd_enable_flag+switch_enable
|
||||
if [ $total_count -gt 0 ] ;then
|
||||
#param:server(count) redir_tcp(0:no,1:yes) redir_udp tunnel kcp local gfw
|
||||
service_start /usr/bin/ssr-monitor \
|
||||
$server_count $redir_tcp $redir_udp $tunnel_enable \
|
||||
$kcp_enable_flag $local_enable $pdnsd_enable_flag $switch_enable
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
boot() {
|
||||
(sleep 5 && start >/dev/null 2>&1) &
|
||||
}
|
||||
|
||||
stop() {
|
||||
/usr/bin/ssr-rules -f
|
||||
srulecount=`iptables -L|grep SSR-SERVER-RULE|wc -l`
|
||||
if [ $srulecount -gt 0 ] ;then
|
||||
iptables -F SSR-SERVER-RULE
|
||||
iptables -t filter -D INPUT -j SSR-SERVER-RULE
|
||||
iptables -X SSR-SERVER-RULE 2>/dev/null
|
||||
fi
|
||||
|
||||
killall -q -9 ssr-monitor
|
||||
|
||||
killall -q -9 udp2raw
|
||||
killall -q -9 udpspeeder
|
||||
/usr/bin/udp2raw --clear >/dev/null
|
||||
|
||||
if [ -z "$switch_server" ] ;then
|
||||
killall -q -9 ssr-switch
|
||||
fi
|
||||
killall -q -9 ssr-redir
|
||||
killall -q -9 ssr-tunnel
|
||||
killall -q -9 ssr-server
|
||||
killall -q -9 ssr-kcptun
|
||||
killall -q -9 ssr-local
|
||||
killall -q pdnsd
|
||||
}
|
151
package/lean/openwrt-ssr/files/shadowsocksr.monitor
Normal file
151
package/lean/openwrt-ssr/files/shadowsocksr.monitor
Normal file
@ -0,0 +1,151 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2017 openwrt-ssr
|
||||
# Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
|
||||
NAME=shadowsocksr
|
||||
|
||||
uci_get_by_name() {
|
||||
local ret=$(uci get $NAME.$1.$2 2>/dev/null)
|
||||
echo ${ret:=$3}
|
||||
}
|
||||
|
||||
uci_get_by_type() {
|
||||
local ret=$(uci get $NAME.@$1[0].$2 2>/dev/null)
|
||||
echo ${ret:=$3}
|
||||
}
|
||||
|
||||
server_process_count=$1
|
||||
redir_tcp_process=$2
|
||||
redir_udp_process=$3
|
||||
tunnel_process=$4
|
||||
kcp_process=$5
|
||||
local_process=$6
|
||||
pdnsd_process=$7
|
||||
if [ -z "$pdnsd_process" ] ;then
|
||||
pdnsd_process=0
|
||||
fi
|
||||
|
||||
i=0
|
||||
|
||||
GLOBAL_SERVER=$(uci_get_by_type global global_server)
|
||||
local server=$(uci_get_by_name $GLOBAL_SERVER server)
|
||||
local kcp_port=$(uci_get_by_name $GLOBAL_SERVER kcp_port)
|
||||
local server_port=$(uci_get_by_name $GLOBAL_SERVER server_port)
|
||||
local password=$(uci_get_by_name $GLOBAL_SERVER kcp_password)
|
||||
local kcp_param=$(uci_get_by_name $GLOBAL_SERVER kcp_param)
|
||||
[ "$password" != "" ] && password="--key "${password}
|
||||
|
||||
local sock5_port=$(uci_get_by_type socks5_proxy local_port 1080)
|
||||
|
||||
if echo $server|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
|
||||
server=${server}
|
||||
else
|
||||
server=`cat /etc/ssr_ip`
|
||||
fi
|
||||
|
||||
while [ "1" = "1" ] #死循环
|
||||
do
|
||||
sleep 30
|
||||
#redir tcp
|
||||
if [ $redir_tcp_process -gt 0 ] ;then
|
||||
icount=`ps -w | grep ssr-retcp |grep -v grep| wc -l`
|
||||
if [ $icount = 0 ] ;then
|
||||
logger -t "$NAME" "ssr redir tcp error.restart!"
|
||||
/etc/init.d/shadowsocksr restart
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
#redir udp
|
||||
if [ $redir_udp_process -gt 0 ] ;then
|
||||
icount=`ps -w | grep ssr-reudp|grep -v grep| wc -l`
|
||||
if [ $icount = 0 ] ;then
|
||||
logger -t "$NAME" "ssr redir udp error.restart!"
|
||||
/etc/init.d/shadowsocksr restart
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
#ssr-dns tunnel
|
||||
if [ $tunnel_process -gt 0 ] ;then
|
||||
icount=`ps -w | grep ssr-tunnel |grep -v grep| wc -l`
|
||||
if [ $icount = 0 ] ;then
|
||||
logger -t "$NAME" "ssr tunnel error.restart!"
|
||||
/etc/init.d/shadowsocksr restart
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
#server
|
||||
if [ $server_process_count -gt 0 ] ;then
|
||||
icount=`ps -w | grep ssr-server |grep -v grep| wc -l`
|
||||
if [ $icount -lt $server_process_count ] #如果进程挂掉就重启它
|
||||
then
|
||||
logger -t "$NAME" "ssr server error.restart!"
|
||||
killall -q -9 ssr-server
|
||||
for i in `seq $server_process_count`
|
||||
do
|
||||
/usr/bin/ssr-server -c /var/etc/shadowsocksr_$i.json -u -f /var/run/ssr-server$i.pid
|
||||
done
|
||||
fi
|
||||
fi
|
||||
#kcptun
|
||||
if [ $kcp_process -gt 0 ] ;then
|
||||
icount=`ps -w | grep ssr-kcptun |grep -v grep| wc -l`
|
||||
if [ $icount -lt $kcp_process ] #如果进程挂掉就重启它
|
||||
then
|
||||
logger -t "$NAME" "ssr kcptun error.restart!"
|
||||
killall -q -9 ssr-kcptun
|
||||
|
||||
( /usr/bin/ssr-kcptun -r $server:$kcp_port -l :$server_port $password $kcp_param &)
|
||||
fi
|
||||
fi
|
||||
#local
|
||||
if [ $local_process -gt 0 ] ;then
|
||||
icount=`ps -w | grep ssr-local |grep -v grep| wc -l`
|
||||
if [ $icount -lt $local_process ] #如果进程挂掉就重启它
|
||||
then
|
||||
logger -t "$NAME" "ssr local error.restart!"
|
||||
killall -q -9 ssr-local
|
||||
|
||||
( /usr/bin/ssr-local -c /var/etc/shadowsocksr_s.json -u -l $sock5_port -f /var/run/ssr-local.pid &)
|
||||
fi
|
||||
fi
|
||||
#pdnsd
|
||||
if [ $pdnsd_process -gt 0 ] ;then
|
||||
icount=`ps -w | grep pdnsd |grep -v grep| wc -l`
|
||||
if [ $icount -lt $pdnsd_process ] #如果进程挂掉就重启它
|
||||
then
|
||||
logger -t "$NAME" "pdnsd tunnel error.restart!"
|
||||
killall -q -9 pdnsd
|
||||
|
||||
( /usr/sbin/pdnsd -c /var/etc/pdnsd.conf -d &)
|
||||
fi
|
||||
fi
|
||||
#udp2raw
|
||||
if [ $(uci_get_by_type udp2raw udp2raw_enable) = 1 ] ;then
|
||||
ucount=`ps -w | grep udp2raw |grep -v grep| wc -l`
|
||||
if [ $ucount = 0 ] ;then
|
||||
/usr/bin/udp2raw --clear >/dev/null
|
||||
/usr/bin/udp2raw --conf-file /var/etc/udp2raw.conf >/dev/null 2>&1 &
|
||||
fi
|
||||
fi
|
||||
#udpspeeder
|
||||
if [ $(uci_get_by_type udpspeeder udpspeeder_enable) = 1 ] ;then
|
||||
scount=`ps -w | grep udpspeeder |grep -v grep| wc -l`
|
||||
if [ $scount = 0 ] ;then
|
||||
/usr/bin/udpspeeder -c -l0.0.0.0:$(uci_get_by_type udpspeeder local_port) \
|
||||
-r$(uci_get_by_type udpspeeder server):$(uci_get_by_type udpspeeder server_port) \
|
||||
-k $(uci_get_by_type udpspeeder key) \
|
||||
--mode $(uci_get_by_type udpspeeder speeder_mode) \
|
||||
--mtu $(uci_get_by_type udpspeeder mtu) \
|
||||
-f$(uci_get_by_type udpspeeder fec) \
|
||||
-q$(uci_get_by_type udpspeeder queue_len) \
|
||||
--timeout $(uci_get_by_type udpspeeder timeout) \
|
||||
>/dev/null 2>&1 &
|
||||
fi
|
||||
fi
|
||||
done
|
291
package/lean/openwrt-ssr/files/shadowsocksr.rule
Normal file
291
package/lean/openwrt-ssr/files/shadowsocksr.rule
Normal file
@ -0,0 +1,291 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2017 openwrt-ssr
|
||||
# Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
TAG="_SS_SPEC_RULE_" # comment tag
|
||||
IPT="iptables -t nat" # alias of iptables
|
||||
FWI=$(uci get firewall.shadowsocksr.path 2>/dev/null) # firewall include file
|
||||
|
||||
usage() {
|
||||
cat <<-EOF
|
||||
Usage: ssr-rules [options]
|
||||
|
||||
Valid options are:
|
||||
|
||||
-s <server_ip> ip address of shadowsocksr remote server
|
||||
-l <local_port> port number of shadowsocksr local server
|
||||
-S <server_ip> ip address of shadowsocksr remote UDP server
|
||||
-L <local_port> port number of shadowsocksr local UDP server
|
||||
-i <ip_list_file> a file content is bypassed ip list
|
||||
-a <lan_ips> lan ip of access control, need a prefix to
|
||||
define access control mode
|
||||
-b <wan_ips> wan ip of will be bypassed
|
||||
-w <wan_ips> wan ip of will be forwarded
|
||||
-e <extra_options> extra options for iptables
|
||||
-o apply the rules to the OUTPUT chain
|
||||
-O apply the global rules to the OUTPUT chain
|
||||
-u enable udprelay mode, TPROXY is required
|
||||
-U enable udprelay mode, using different IP
|
||||
and ports for TCP and UDP
|
||||
-f flush the rules
|
||||
-g gfw list mode
|
||||
-h show this help message and exit
|
||||
EOF
|
||||
exit $1
|
||||
}
|
||||
|
||||
loger() {
|
||||
# 1.alert 2.crit 3.err 4.warn 5.notice 6.info 7.debug
|
||||
logger -st ssr-rules[$$] -p$1 $2
|
||||
}
|
||||
|
||||
flush_r() {
|
||||
flush_iptables() {
|
||||
local ipt="iptables -t $1"
|
||||
local DAT=$(iptables-save -t $1)
|
||||
eval $(echo "$DAT" | grep "$TAG" | sed -e 's/^-A/$ipt -D/' -e 's/$/;/')
|
||||
for chain in $(echo "$DAT" | awk '/^:SS_SPEC/{print $1}'); do
|
||||
$ipt -F ${chain:1} 2>/dev/null && $ipt -X ${chain:1}
|
||||
done
|
||||
}
|
||||
flush_iptables nat
|
||||
flush_iptables mangle
|
||||
ip rule del fwmark 0x01/0x01 table 100 2>/dev/null
|
||||
ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null
|
||||
ipset -X ss_spec_lan_ac 2>/dev/null
|
||||
ipset -X ss_spec_wan_ac 2>/dev/null
|
||||
ipset -X ssr_gen_router 2>/dev/null
|
||||
[ -n "$FWI" ] && echo '#!/bin/sh' >$FWI
|
||||
return 0
|
||||
}
|
||||
|
||||
ipset_r() {
|
||||
if [ -z "$GFWMODE" ] ;then
|
||||
ipset -! -R <<-EOF || return 1
|
||||
create ss_spec_wan_ac hash:net
|
||||
$(gen_iplist | sed -e "s/^/add ss_spec_wan_ac /")
|
||||
$(for ip in $WAN_FW_IP; do echo "add ss_spec_wan_ac $ip nomatch"; done)
|
||||
EOF
|
||||
$IPT -N SS_SPEC_WAN_AC && \
|
||||
$IPT -A SS_SPEC_WAN_AC -m set --match-set ss_spec_wan_ac dst -j RETURN && \
|
||||
$IPT -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW
|
||||
else
|
||||
ipset -N gfwlist iphash 2>/dev/null
|
||||
for ip in $WAN_FW_IP; do ipset add gfwlist $ip ; done
|
||||
$IPT -N SS_SPEC_WAN_AC
|
||||
$IPT -A SS_SPEC_WAN_AC -m set --match-set gfwlist dst -j SS_SPEC_WAN_FW
|
||||
fi
|
||||
return $?
|
||||
}
|
||||
|
||||
fw_rule() {
|
||||
$IPT -N SS_SPEC_WAN_FW && \
|
||||
$IPT -A SS_SPEC_WAN_FW -p tcp \
|
||||
-j REDIRECT --to-ports $local_port 2>/dev/null || {
|
||||
loger 3 "Can't redirect, please check the iptables."
|
||||
exit 1
|
||||
}
|
||||
return $?
|
||||
}
|
||||
|
||||
ac_rule() {
|
||||
if [ -n "$LAN_AC_IP" ]; then
|
||||
case "${LAN_AC_IP:0:1}" in
|
||||
w|W)
|
||||
MATCH_SET="-m set --match-set ss_spec_lan_ac src"
|
||||
;;
|
||||
b|B)
|
||||
MATCH_SET="-m set ! --match-set ss_spec_lan_ac src"
|
||||
;;
|
||||
*)
|
||||
loger 3 "Bad argument \`-a $LAN_AC_IP\`."
|
||||
return 2
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
IFNAME=$(uci get -P/var/state network.lan.ifname 2>/dev/null)
|
||||
ipset -! -R <<-EOF || return 1
|
||||
create ss_spec_lan_ac hash:net
|
||||
$(for ip in ${LAN_AC_IP:1}; do echo "add ss_spec_lan_ac $ip"; done)
|
||||
EOF
|
||||
$IPT -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p tcp $EXT_ARGS $MATCH_SET \
|
||||
-m comment --comment "$TAG" -j SS_SPEC_WAN_AC
|
||||
if [ "$OUTPUT" = 1 ]; then
|
||||
$IPT -I OUTPUT 1 -p tcp $EXT_ARGS \
|
||||
-m comment --comment "$TAG" -j SS_SPEC_WAN_AC
|
||||
elif [ "$OUTPUT" = 2 ]; then
|
||||
ipset -! -R <<-EOF || return 1
|
||||
create ssr_gen_router hash:net
|
||||
$(gen_spec_iplist | sed -e "s/^/add ssr_gen_router /")
|
||||
EOF
|
||||
$IPT -N SS_SPEC_ROUTER && \
|
||||
$IPT -A SS_SPEC_ROUTER -m set --match-set ssr_gen_router dst -j RETURN && \
|
||||
$IPT -A SS_SPEC_ROUTER -j SS_SPEC_WAN_FW
|
||||
$IPT -I OUTPUT 1 -p tcp -m comment --comment "$TAG" -j SS_SPEC_ROUTER
|
||||
fi
|
||||
return $?
|
||||
}
|
||||
|
||||
tp_rule() {
|
||||
[ -n "$TPROXY" ] || return 0
|
||||
ip rule add fwmark 0x01/0x01 table 100
|
||||
ip route add local 0.0.0.0/0 dev lo table 100
|
||||
local ipt="iptables -t mangle"
|
||||
$ipt -N SS_SPEC_TPROXY
|
||||
if [ -z "$GFWMODE" ] ;then
|
||||
$ipt -A SS_SPEC_TPROXY -p udp -m set ! --match-set ss_spec_wan_ac dst \
|
||||
-j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
|
||||
else
|
||||
$ipt -A SS_SPEC_TPROXY -p udp -m set --match-set gfwlist dst \
|
||||
-j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
|
||||
fi
|
||||
$ipt -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p udp $EXT_ARGS $MATCH_SET \
|
||||
-m comment --comment "$TAG" -j SS_SPEC_TPROXY
|
||||
return $?
|
||||
}
|
||||
|
||||
get_wan_ip() {
|
||||
cat <<-EOF | grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}"
|
||||
$server
|
||||
$SERVER
|
||||
$WAN_BP_IP
|
||||
EOF
|
||||
}
|
||||
|
||||
gen_iplist() {
|
||||
cat <<-EOF
|
||||
0.0.0.0/8
|
||||
10.0.0.0/8
|
||||
100.64.0.0/10
|
||||
127.0.0.0/8
|
||||
169.254.0.0/16
|
||||
172.16.0.0/12
|
||||
192.0.0.0/24
|
||||
192.0.2.0/24
|
||||
192.88.99.0/24
|
||||
192.168.0.0/16
|
||||
198.18.0.0/15
|
||||
198.51.100.0/24
|
||||
203.0.113.0/24
|
||||
224.0.0.0/4
|
||||
240.0.0.0/4
|
||||
255.255.255.255
|
||||
$(get_wan_ip)
|
||||
$(cat ${IGNORE_LIST:=/dev/null} 2>/dev/null)
|
||||
EOF
|
||||
}
|
||||
|
||||
gen_spec_iplist() {
|
||||
cat <<-EOF
|
||||
0.0.0.0/8
|
||||
10.0.0.0/8
|
||||
100.64.0.0/10
|
||||
127.0.0.0/8
|
||||
169.254.0.0/16
|
||||
172.16.0.0/12
|
||||
192.0.0.0/24
|
||||
192.0.2.0/24
|
||||
192.88.99.0/24
|
||||
192.168.0.0/16
|
||||
198.18.0.0/15
|
||||
198.51.100.0/24
|
||||
203.0.113.0/24
|
||||
224.0.0.0/4
|
||||
240.0.0.0/4
|
||||
255.255.255.255
|
||||
$(get_wan_ip)
|
||||
EOF
|
||||
}
|
||||
|
||||
gen_include() {
|
||||
[ -n "$FWI" ] || return 0
|
||||
extract_rules() {
|
||||
echo "*$1"
|
||||
iptables-save -t $1 | grep SS_SPEC_ |\
|
||||
sed -e "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/"
|
||||
echo 'COMMIT'
|
||||
}
|
||||
cat <<-EOF >>$FWI
|
||||
iptables-save -c | grep -v "SS_SPEC" | iptables-restore -c
|
||||
iptables-restore -n <<-EOT
|
||||
$(extract_rules nat)
|
||||
$(extract_rules mangle)
|
||||
EOT
|
||||
EOF
|
||||
return 0
|
||||
}
|
||||
|
||||
while getopts ":s:l:S:L:i:e:a:b:w:oOuUfgh" arg; do
|
||||
case "$arg" in
|
||||
s)
|
||||
server=$OPTARG
|
||||
;;
|
||||
l)
|
||||
local_port=$OPTARG
|
||||
;;
|
||||
S)
|
||||
SERVER=$OPTARG
|
||||
;;
|
||||
L)
|
||||
LOCAL_PORT=$OPTARG
|
||||
;;
|
||||
i)
|
||||
IGNORE_LIST=$OPTARG
|
||||
;;
|
||||
e)
|
||||
EXT_ARGS=$OPTARG
|
||||
;;
|
||||
a)
|
||||
LAN_AC_IP=$OPTARG
|
||||
;;
|
||||
b)
|
||||
WAN_BP_IP=$(for ip in $OPTARG; do echo $ip; done)
|
||||
;;
|
||||
w)
|
||||
WAN_FW_IP=$OPTARG
|
||||
;;
|
||||
o)
|
||||
OUTPUT=1
|
||||
;;
|
||||
O)
|
||||
OUTPUT=2
|
||||
;;
|
||||
u)
|
||||
TPROXY=1
|
||||
;;
|
||||
U)
|
||||
TPROXY=2
|
||||
;;
|
||||
g)
|
||||
GFWMODE=1
|
||||
;;
|
||||
f)
|
||||
flush_r
|
||||
exit 0
|
||||
;;
|
||||
h)
|
||||
usage 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$server" -o -z "$local_port" ]; then
|
||||
usage 2
|
||||
fi
|
||||
|
||||
if [ "$TPROXY" = 1 ]; then
|
||||
SERVER=$server
|
||||
LOCAL_PORT=$local_port
|
||||
elif [ "$TPROXY" = 2 ]; then
|
||||
: ${SERVER:?"You must assign an ip for the udp relay server."}
|
||||
: ${LOCAL_PORT:?"You must assign a port for the udp relay server."}
|
||||
fi
|
||||
|
||||
flush_r && fw_rule && ipset_r && ac_rule && tp_rule && gen_include
|
||||
[ "$?" = 0 ] || loger 3 "Start failed!"
|
||||
exit $?
|
165
package/lean/openwrt-ssr/files/shadowsocksr.switch
Normal file
165
package/lean/openwrt-ssr/files/shadowsocksr.switch
Normal file
@ -0,0 +1,165 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (C) 2017 openwrt-ssr
|
||||
# Copyright (C) 2017 yushi studio <ywb94@qq.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
local cycle_time=60
|
||||
local switch_time=3
|
||||
local normal_flag=0
|
||||
local server_locate=0
|
||||
local server_count=0
|
||||
NAME=shadowsocksr
|
||||
ENABLE_SERVER=nil
|
||||
CONFIG_SWTICH_FILE=/var/etc/${NAME}_t.json
|
||||
|
||||
|
||||
[ -n "$1" ] && cycle_time=$1
|
||||
[ -n "$2" ] && switch_time=$2
|
||||
|
||||
uci_get_by_name() {
|
||||
local ret=$(uci get $NAME.$1.$2 2>/dev/null)
|
||||
echo ${ret:=$3}
|
||||
}
|
||||
|
||||
uci_get_by_type() {
|
||||
local ret=$(uci get $NAME.@$1[0].$2 2>/dev/null)
|
||||
echo ${ret:=$3}
|
||||
}
|
||||
|
||||
DEFAULT_SERVER=$(uci_get_by_type global global_server)
|
||||
CURRENT_SERVER=$DEFAULT_SERVER
|
||||
|
||||
#判断代理是否正常
|
||||
check_proxy() {
|
||||
/usr/bin/ssr-check www.google.com 80 $switch_time 1
|
||||
if [ "$?" == "0" ]; then
|
||||
return 0
|
||||
else
|
||||
/usr/bin/ssr-check www.baidu.com 80 $switch_time 1
|
||||
if [ "$?" == "0" ]; then
|
||||
#goole不通baidu通则不正常
|
||||
return 1
|
||||
else
|
||||
return 2
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
test_proxy() {
|
||||
local servername=$(uci_get_by_name $1 server)
|
||||
local serverport=$(uci_get_by_name $1 server_port)
|
||||
ret=$(ping -c 3 $servername | grep 'loss' | awk -F ',' '{ print $3 }' | awk -F "%" '{ print $1 }')
|
||||
[ -z "$ret" ] && return 1
|
||||
[ "$ret" -gt "50" ] && return 1
|
||||
ipset add ss_spec_wan_ac $servername 2>/dev/null
|
||||
ret=$?
|
||||
/usr/bin/ssr-check $servername $serverport $switch_time
|
||||
local ret2=$?
|
||||
if [ "$ret" = "0" ] ;then
|
||||
ipset del ss_spec_wan_ac $servername 2>/dev/null
|
||||
fi
|
||||
if [ "$ret2" = "0" ] ;then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
search_proxy() {
|
||||
let server_count=server_count+1
|
||||
[ "$normal_flag" = "1" -a "$server_count" -le "$server_locate" ] && return 0
|
||||
[ "$(uci_get_by_name $1 switch_enable)" != "1" ] && return 1
|
||||
[ $ENABLE_SERVER != nil ] && return 0
|
||||
[ "$1" = "$CURRENT_SERVER" ] && return 0
|
||||
local servername=$(uci_get_by_name $1 server)
|
||||
local serverport=$(uci_get_by_name $1 server_port)
|
||||
ipset add ss_spec_wan_ac $servername 2>/dev/null
|
||||
ret=$?
|
||||
/usr/bin/ssr-check $servername $serverport $switch_time
|
||||
local ret2=$?
|
||||
if [ "$ret" = "0" ] ;then
|
||||
ipset del ss_spec_wan_ac $servername 2>/dev/null
|
||||
fi
|
||||
if [ "$ret2" = "0" ] ;then
|
||||
server_locate=$server_count
|
||||
ENABLE_SERVER=$1
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
|
||||
}
|
||||
#选择可用的代理
|
||||
select_proxy() {
|
||||
|
||||
config_load $NAME
|
||||
ENABLE_SERVER=nil
|
||||
mkdir -p /var/run /var/etc
|
||||
server_count=0
|
||||
config_foreach search_proxy servers
|
||||
|
||||
}
|
||||
|
||||
#切换代理
|
||||
switch_proxy() {
|
||||
/etc/init.d/shadowsocksr restart $1
|
||||
return 0
|
||||
}
|
||||
|
||||
start() {
|
||||
#不支持kcptun启用时的切换
|
||||
[ $(uci_get_by_name $DEFAULT_SERVER kcp_enable) = "1" ] && return 1
|
||||
|
||||
while [ "1" = "1" ] #死循环
|
||||
do
|
||||
sleep $cycle_time
|
||||
|
||||
|
||||
#判断当前代理是否为缺省服务器
|
||||
if [ "$CURRENT_SERVER" != "$DEFAULT_SERVER" ] ;then
|
||||
#echo "not default proxy"
|
||||
|
||||
#检查缺省服务器是否正常
|
||||
if test_proxy $DEFAULT_SERVER ;then
|
||||
#echo "switch to default proxy"
|
||||
#缺省服务器正常,切换回来
|
||||
CURRENT_SERVER=$DEFAULT_SERVER
|
||||
switch_proxy $CURRENT_SERVER
|
||||
logger -t "$NAME" "switch to default ["$(uci_get_by_name $CURRENT_SERVER server)"] proxy!"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
#判断当前代理是否正常
|
||||
check_proxy
|
||||
current_ret=$?
|
||||
|
||||
if [ "$current_ret" = "1" ] ;then
|
||||
#当前代理错误,判断有无可用的服务器
|
||||
#echo "current error"
|
||||
|
||||
select_proxy
|
||||
if [ "$ENABLE_SERVER" != nil ] ;then
|
||||
#有其他服务器可用,进行切换
|
||||
#echo $(uci_get_by_name $new_proxy server)
|
||||
CURRENT_SERVER=$ENABLE_SERVER
|
||||
switch_proxy $CURRENT_SERVER
|
||||
normal_flag=1
|
||||
logger -t "$NAME" "switch proxy ["$(uci_get_by_name $CURRENT_SERVER server)"] success!"
|
||||
#echo "switch ok"
|
||||
else
|
||||
normal_flag=0
|
||||
fi
|
||||
else
|
||||
normal_flag=0
|
||||
fi
|
||||
|
||||
|
||||
done
|
||||
}
|
315
package/lean/openwrt-ssr/patches/0001-ss-check-Backport.patch
Normal file
315
package/lean/openwrt-ssr/patches/0001-ss-check-Backport.patch
Normal file
@ -0,0 +1,315 @@
|
||||
From 4a153bc0bb8ed20517871bddbf92ba69057bef97 Mon Sep 17 00:00:00 2001
|
||||
From: WouldChar <wouldchar@gmail.com>
|
||||
Date: Mon, 18 Dec 2017 19:33:51 +0800
|
||||
Subject: [PATCH 1/7] Backport ss-check
|
||||
|
||||
* from https://github.com/ywb94/shadowsocks-libev
|
||||
---
|
||||
src/Makefile.am | 5 ++
|
||||
src/check.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
src/redir.c | 2 +-
|
||||
3 files changed, 248 insertions(+), 1 deletion(-)
|
||||
create mode 100644 src/check.c
|
||||
|
||||
diff --git a/src/Makefile.am b/src/Makefile.am
|
||||
index eea1300..d2c6d24 100644
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -22,7 +22,7 @@ SS_COMMON_LIBS += $(top_builddir)/libev/libev.la \
|
||||
$(top_builddir)/libsodium/src/libsodium/libsodium.la
|
||||
endif
|
||||
|
||||
-bin_PROGRAMS = ss-local
|
||||
+bin_PROGRAMS = ss-local ss-check
|
||||
#bin_PROGRAMS += ss-tunnel
|
||||
if !BUILD_WINCOMPAT
|
||||
#bin_PROGRAMS += ss-server ss-manager
|
||||
@@ -42,6 +43,8 @@ ss_local_SOURCES = utils.c \
|
||||
local.c \
|
||||
$(sni_src)
|
||||
|
||||
+ss_check_SOURCES = check.c
|
||||
+
|
||||
#ss_tunnel_SOURCES = utils.c \
|
||||
# jconf.c \
|
||||
# json.c \
|
||||
@@ -69,6 +72,7 @@ ss_local_SOURCES = utils.c \
|
||||
# manager.c
|
||||
|
||||
ss_local_LDADD = $(SS_COMMON_LIBS)
|
||||
+ss_check_LDADD = $(SS_COMMON_LIBS)
|
||||
#ss_tunnel_LDADD = $(SS_COMMON_LIBS)
|
||||
#ss_server_LDADD = $(SS_COMMON_LIBS)
|
||||
#ss_manager_LDADD = $(SS_COMMON_LIBS)
|
||||
@@ -83,6 +87,7 @@ ss_local_LDADD += $(top_builddir)/libudns/libudns.la
|
||||
endif
|
||||
|
||||
ss_local_CFLAGS = $(AM_CFLAGS) -DMODULE_LOCAL
|
||||
+ss_check_CFLAGS = $(AM_CFLAGS) -DMODULE_CHECK
|
||||
#ss_tunnel_CFLAGS = $(AM_CFLAGS) -DMODULE_TUNNEL
|
||||
#ss_server_CFLAGS = $(AM_CFLAGS) -DMODULE_REMOTE
|
||||
#ss_manager_CFLAGS = $(AM_CFLAGS) -DMODULE_MANAGER
|
||||
diff --git a/src/check.c b/src/check.c
|
||||
new file mode 100644
|
||||
index 0000000..9243686
|
||||
--- /dev/null
|
||||
+++ b/src/check.c
|
||||
@@ -0,0 +1,242 @@
|
||||
+/*
|
||||
+ * check.c - check remote shadowsocks server port
|
||||
+ *
|
||||
+ * Copyright (C) 2017, yushi studio <ywb94@qq.com>
|
||||
+ *
|
||||
+ * This file is part of the shadowsocks-libev.
|
||||
+ *
|
||||
+ * shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
+ * <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+#include <unistd.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/socket.h>
|
||||
+#include <netdb.h>
|
||||
+#include <netinet/in.h>
|
||||
+#include <errno.h>
|
||||
+#include <time.h>
|
||||
+#include <arpa/inet.h>
|
||||
+#include <setjmp.h>
|
||||
+#include <signal.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+//#define __DEBUG__
|
||||
+#ifdef __DEBUG__
|
||||
+#define DEBUG(format,...) printf("File: "__FILE__", Line: %05d: "format"/n", __LINE__, ##__VA_ARGS__)
|
||||
+#else
|
||||
+#define DEBUG(format,...)
|
||||
+#endif
|
||||
+
|
||||
+static sigjmp_buf jmpbuf;
|
||||
+
|
||||
+static void alarm_func()
|
||||
+{
|
||||
+ siglongjmp(jmpbuf, 1);
|
||||
+}
|
||||
+
|
||||
+static struct hostent *timeGethostbyname(const char *domain, int timeout)
|
||||
+{
|
||||
+ struct hostent *ipHostent = NULL;
|
||||
+ signal(SIGALRM, alarm_func);
|
||||
+ if (sigsetjmp(jmpbuf, 1) != 0) {
|
||||
+ alarm(0); //timout
|
||||
+ signal(SIGALRM, SIG_IGN);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ alarm(timeout); //setting alarm
|
||||
+ ipHostent = gethostbyname(domain);
|
||||
+ signal(SIGALRM, SIG_IGN);
|
||||
+ return ipHostent;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+#define MY_HTTP_DEFAULT_PORT 80
|
||||
+#define BUFFER_SIZE 1024
|
||||
+#define HTTP_POST "POST /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n"\
|
||||
+ "Content-Type:application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s"
|
||||
+#define HTTP_GET "GET /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n\r\n"
|
||||
+
|
||||
+static int http_parse_url(const char *url, char *host, char *file, int *port)
|
||||
+{
|
||||
+ char *ptr1, *ptr2;
|
||||
+ int len = 0;
|
||||
+ if (!url || !host || !file || !port)
|
||||
+ return 1;
|
||||
+
|
||||
+ ptr1 = (char *)url;
|
||||
+
|
||||
+ if (!strncmp(ptr1, "http://", strlen("http://")))
|
||||
+ ptr1 += strlen("http://");
|
||||
+ else
|
||||
+ return 1;
|
||||
+
|
||||
+ ptr2 = strchr(ptr1, '/');
|
||||
+ if (ptr2) {
|
||||
+ len = strlen(ptr1) - strlen(ptr2);
|
||||
+ memcpy(host, ptr1, len);
|
||||
+ host[len] = '\0';
|
||||
+ if (*(ptr2 + 1)) {
|
||||
+ memcpy(file, ptr2 + 1, strlen(ptr2) - 1);
|
||||
+ file[strlen(ptr2) - 1] = '\0';
|
||||
+ }
|
||||
+ }
|
||||
+ else {
|
||||
+ memcpy(host,ptr1,strlen(ptr1));
|
||||
+ host[strlen(ptr1)] = '\0';
|
||||
+ }
|
||||
+
|
||||
+ //get host and ip
|
||||
+ ptr1 = strchr(host, ':');
|
||||
+ if (ptr1) {
|
||||
+ *ptr1++ = '\0';
|
||||
+ *port = atoi(ptr1);
|
||||
+ }
|
||||
+ else
|
||||
+ *port = MY_HTTP_DEFAULT_PORT;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int http_tcpclient_recv(int socket, char *lpbuff)
|
||||
+{
|
||||
+ int recvnum = 0;
|
||||
+
|
||||
+ recvnum = recv(socket, lpbuff, BUFFER_SIZE*4, 0);
|
||||
+
|
||||
+ return recvnum;
|
||||
+}
|
||||
+
|
||||
+static int http_tcpclient_send(int socket, char *buff, int size)
|
||||
+{
|
||||
+ int sent = 0, tmpres = 0;
|
||||
+
|
||||
+ while (sent < size) {
|
||||
+ tmpres = send(socket, buff + sent, size - sent, 0);
|
||||
+ if (tmpres == -1)
|
||||
+ return 1;
|
||||
+ sent += tmpres;
|
||||
+ }
|
||||
+ return sent;
|
||||
+}
|
||||
+
|
||||
+int http_get(const char *url, int socket_fd)
|
||||
+{
|
||||
+ char lpbuf[BUFFER_SIZE * 4] = {'\0'};
|
||||
+
|
||||
+ char host_addr[BUFFER_SIZE] = {'\0'};
|
||||
+ char file[BUFFER_SIZE] = {'\0'};
|
||||
+ int port = 0;
|
||||
+
|
||||
+ if (!url) {
|
||||
+ DEBUG("url failed\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (http_parse_url(url, host_addr, file, &port)) {
|
||||
+ DEBUG("http_parse_url failed\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ DEBUG("url: %s\thost_addr: %s\tfile: %s\t, %d\n", url, host_addr, file, port);
|
||||
+
|
||||
+ if (socket_fd < 0) {
|
||||
+ DEBUG("http_tcpclient_create failed\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ sprintf(lpbuf, HTTP_GET, file, host_addr, port);
|
||||
+
|
||||
+ if (http_tcpclient_send(socket_fd, lpbuf, strlen(lpbuf)) < 0) {
|
||||
+ DEBUG("http_tcpclient_send failed\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ DEBUG("request:\n%s\n", lpbuf);
|
||||
+
|
||||
+ if (http_tcpclient_recv(socket_fd, lpbuf) <= 0) {
|
||||
+ DEBUG("http_tcpclient_recv failed\n");
|
||||
+ close(socket_fd);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ DEBUG("rec:\n%s\n", lpbuf);
|
||||
+ close(socket_fd);
|
||||
+
|
||||
+ //return http_parse_result(lpbuf);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int main(int argc, char *argv[])
|
||||
+{
|
||||
+ int fd, http_flag = 0, http_ret = 1;
|
||||
+ struct sockaddr_in addr;
|
||||
+ struct hostent *host;
|
||||
+ struct timeval timeo = {3, 0};
|
||||
+ socklen_t len = sizeof(timeo);
|
||||
+
|
||||
+ char http_url[100] = "http://";
|
||||
+
|
||||
+ fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
+ if (argc >= 4)
|
||||
+ timeo.tv_sec = atoi(argv[3]);
|
||||
+ if (argc >= 5)
|
||||
+ http_flag=1;
|
||||
+
|
||||
+ if ((host = timeGethostbyname(argv[1], timeo.tv_sec)) == NULL) {
|
||||
+ DEBUG("gethostbyname err\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, len) == -1) {
|
||||
+ DEBUG("setsockopt send err\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, len) == -1) {
|
||||
+ DEBUG("setsockopt recv err\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ addr.sin_family = AF_INET;
|
||||
+ addr.sin_addr = *((struct in_addr *)host->h_addr);
|
||||
+ //addr.sin_addr.s_addr = inet_addr(argv[1]);
|
||||
+ addr.sin_port = htons(atoi(argv[2]));
|
||||
+
|
||||
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||
+ if (errno == EINPROGRESS) {
|
||||
+ DEBUG("timeout err\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ DEBUG("connect err\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (http_flag == 0) {
|
||||
+ close(fd);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ strcat(http_url, argv[1]);
|
||||
+ http_ret = http_get(http_url, fd);
|
||||
+
|
||||
+ if (http_ret == 1) {
|
||||
+ DEBUG("recv err");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ else {
|
||||
+ DEBUG("recv ok");
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/redir.c b/src/redir.c
|
||||
index 4345a36..e2bdd0e 100644
|
||||
--- a/src/redir.c
|
||||
+++ b/src/redir.c
|
||||
@@ -203,7 +203,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
// continue to wait for recv
|
||||
return;
|
||||
} else {
|
||||
- ERROR("server recv");
|
||||
+ //ERROR("server recv");
|
||||
close_and_free_remote(EV_A_ remote);
|
||||
close_and_free_server(EV_A_ server);
|
||||
return;
|
||||
--
|
||||
2.7.4
|
||||
|
12
package/lean/openwrt-ssr/tools/po2lmo/Makefile
Normal file
12
package/lean/openwrt-ssr/tools/po2lmo/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
INSTALL = install
|
||||
PREFIX = /usr/bin
|
||||
|
||||
po2lmo: src/po2lmo.o src/template_lmo.o
|
||||
$(CC) -o src/po2lmo src/po2lmo.o src/template_lmo.o
|
||||
|
||||
install:
|
||||
$(INSTALL) -m 755 src/po2lmo $(PREFIX)
|
||||
|
||||
clean:
|
||||
$(RM) src/po2lmo src/*.o
|
BIN
package/lean/openwrt-ssr/tools/po2lmo/src/po2lmo
Executable file
BIN
package/lean/openwrt-ssr/tools/po2lmo/src/po2lmo
Executable file
Binary file not shown.
247
package/lean/openwrt-ssr/tools/po2lmo/src/po2lmo.c
Normal file
247
package/lean/openwrt-ssr/tools/po2lmo/src/po2lmo.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* lmo - Lua Machine Objects - PO to LMO conversion tool
|
||||
*
|
||||
* Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "template_lmo.h"
|
||||
|
||||
static void die(const char *msg)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void usage(const char *name)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s input.po output.lmo\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void print(const void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
{
|
||||
if( fwrite(ptr, size, nmemb, stream) == 0 )
|
||||
die("Failed to write stdout");
|
||||
}
|
||||
|
||||
static int extract_string(const char *src, char *dest, int len)
|
||||
{
|
||||
int pos = 0;
|
||||
int esc = 0;
|
||||
int off = -1;
|
||||
|
||||
for( pos = 0; (pos < strlen(src)) && (pos < len); pos++ )
|
||||
{
|
||||
if( (off == -1) && (src[pos] == '"') )
|
||||
{
|
||||
off = pos + 1;
|
||||
}
|
||||
else if( off >= 0 )
|
||||
{
|
||||
if( esc == 1 )
|
||||
{
|
||||
switch (src[pos])
|
||||
{
|
||||
case '"':
|
||||
case '\\':
|
||||
off++;
|
||||
break;
|
||||
}
|
||||
dest[pos-off] = src[pos];
|
||||
esc = 0;
|
||||
}
|
||||
else if( src[pos] == '\\' )
|
||||
{
|
||||
dest[pos-off] = src[pos];
|
||||
esc = 1;
|
||||
}
|
||||
else if( src[pos] != '"' )
|
||||
{
|
||||
dest[pos-off] = src[pos];
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[pos-off] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (off > -1) ? strlen(dest) : -1;
|
||||
}
|
||||
|
||||
static int cmp_index(const void *a, const void *b)
|
||||
{
|
||||
uint32_t x = ((const lmo_entry_t *)a)->key_id;
|
||||
uint32_t y = ((const lmo_entry_t *)b)->key_id;
|
||||
|
||||
if (x < y)
|
||||
return -1;
|
||||
else if (x > y)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_uint32(uint32_t x, FILE *out)
|
||||
{
|
||||
uint32_t y = htonl(x);
|
||||
print(&y, sizeof(uint32_t), 1, out);
|
||||
}
|
||||
|
||||
static void print_index(void *array, int n, FILE *out)
|
||||
{
|
||||
lmo_entry_t *e;
|
||||
|
||||
qsort(array, n, sizeof(*e), cmp_index);
|
||||
|
||||
for (e = array; n > 0; n--, e++)
|
||||
{
|
||||
print_uint32(e->key_id, out);
|
||||
print_uint32(e->val_id, out);
|
||||
print_uint32(e->offset, out);
|
||||
print_uint32(e->length, out);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char line[4096];
|
||||
char key[4096];
|
||||
char val[4096];
|
||||
char tmp[4096];
|
||||
int state = 0;
|
||||
int offset = 0;
|
||||
int length = 0;
|
||||
int n_entries = 0;
|
||||
void *array = NULL;
|
||||
lmo_entry_t *entry = NULL;
|
||||
uint32_t key_id, val_id;
|
||||
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
|
||||
if( (argc != 3) || ((in = fopen(argv[1], "r")) == NULL) || ((out = fopen(argv[2], "w")) == NULL) )
|
||||
usage(argv[0]);
|
||||
|
||||
memset(line, 0, sizeof(key));
|
||||
memset(key, 0, sizeof(val));
|
||||
memset(val, 0, sizeof(val));
|
||||
|
||||
while( (NULL != fgets(line, sizeof(line), in)) || (state >= 2 && feof(in)) )
|
||||
{
|
||||
if( state == 0 && strstr(line, "msgid \"") == line )
|
||||
{
|
||||
switch(extract_string(line, key, sizeof(key)))
|
||||
{
|
||||
case -1:
|
||||
die("Syntax error in msgid");
|
||||
case 0:
|
||||
state = 1;
|
||||
break;
|
||||
default:
|
||||
state = 2;
|
||||
}
|
||||
}
|
||||
else if( state == 1 || state == 2 )
|
||||
{
|
||||
if( strstr(line, "msgstr \"") == line || state == 2 )
|
||||
{
|
||||
switch(extract_string(line, val, sizeof(val)))
|
||||
{
|
||||
case -1:
|
||||
state = 4;
|
||||
break;
|
||||
default:
|
||||
state = 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(extract_string(line, tmp, sizeof(tmp)))
|
||||
{
|
||||
case -1:
|
||||
state = 2;
|
||||
break;
|
||||
default:
|
||||
strcat(key, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( state == 3 )
|
||||
{
|
||||
switch(extract_string(line, tmp, sizeof(tmp)))
|
||||
{
|
||||
case -1:
|
||||
state = 4;
|
||||
break;
|
||||
default:
|
||||
strcat(val, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if( state == 4 )
|
||||
{
|
||||
if( strlen(key) > 0 && strlen(val) > 0 )
|
||||
{
|
||||
key_id = sfh_hash(key, strlen(key));
|
||||
val_id = sfh_hash(val, strlen(val));
|
||||
|
||||
if( key_id != val_id )
|
||||
{
|
||||
n_entries++;
|
||||
array = realloc(array, n_entries * sizeof(lmo_entry_t));
|
||||
entry = (lmo_entry_t *)array + n_entries - 1;
|
||||
|
||||
if (!array)
|
||||
die("Out of memory");
|
||||
|
||||
entry->key_id = key_id;
|
||||
entry->val_id = val_id;
|
||||
entry->offset = offset;
|
||||
entry->length = strlen(val);
|
||||
|
||||
length = strlen(val) + ((4 - (strlen(val) % 4)) % 4);
|
||||
|
||||
print(val, length, 1, out);
|
||||
offset += length;
|
||||
}
|
||||
}
|
||||
|
||||
state = 0;
|
||||
memset(key, 0, sizeof(key));
|
||||
memset(val, 0, sizeof(val));
|
||||
}
|
||||
|
||||
memset(line, 0, sizeof(line));
|
||||
}
|
||||
|
||||
print_index(array, n_entries, out);
|
||||
|
||||
if( offset > 0 )
|
||||
{
|
||||
print_uint32(offset, out);
|
||||
fsync(fileno(out));
|
||||
fclose(out);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(out);
|
||||
unlink(argv[2]);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
return(0);
|
||||
}
|
328
package/lean/openwrt-ssr/tools/po2lmo/src/template_lmo.c
Normal file
328
package/lean/openwrt-ssr/tools/po2lmo/src/template_lmo.c
Normal file
@ -0,0 +1,328 @@
|
||||
/*
|
||||
* lmo - Lua Machine Objects - Base functions
|
||||
*
|
||||
* Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "template_lmo.h"
|
||||
|
||||
/*
|
||||
* Hash function from http://www.azillionmonkeys.com/qed/hash.html
|
||||
* Copyright (C) 2004-2008 by Paul Hsieh
|
||||
*/
|
||||
|
||||
uint32_t sfh_hash(const char *data, int len)
|
||||
{
|
||||
uint32_t hash = len, tmp;
|
||||
int rem;
|
||||
|
||||
if (len <= 0 || data == NULL) return 0;
|
||||
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
for (;len > 0; len--) {
|
||||
hash += sfh_get16(data);
|
||||
tmp = (sfh_get16(data+2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2*sizeof(uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3: hash += sfh_get16(data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= data[sizeof(uint16_t)] << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2: hash += sfh_get16(data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1: hash += *data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint32_t lmo_canon_hash(const char *str, int len)
|
||||
{
|
||||
char res[4096];
|
||||
char *ptr, prev;
|
||||
int off;
|
||||
|
||||
if (!str || len >= sizeof(res))
|
||||
return 0;
|
||||
|
||||
for (prev = ' ', ptr = res, off = 0; off < len; prev = *str, off++, str++)
|
||||
{
|
||||
if (isspace(*str))
|
||||
{
|
||||
if (!isspace(prev))
|
||||
*ptr++ = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = *str;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ptr > res) && isspace(*(ptr-1)))
|
||||
ptr--;
|
||||
|
||||
return sfh_hash(res, ptr - res);
|
||||
}
|
||||
|
||||
lmo_archive_t * lmo_open(const char *file)
|
||||
{
|
||||
int in = -1;
|
||||
uint32_t idx_offset = 0;
|
||||
struct stat s;
|
||||
|
||||
lmo_archive_t *ar = NULL;
|
||||
|
||||
if (stat(file, &s) == -1)
|
||||
goto err;
|
||||
|
||||
if ((in = open(file, O_RDONLY)) == -1)
|
||||
goto err;
|
||||
|
||||
if ((ar = (lmo_archive_t *)malloc(sizeof(*ar))) != NULL)
|
||||
{
|
||||
memset(ar, 0, sizeof(*ar));
|
||||
|
||||
ar->fd = in;
|
||||
ar->size = s.st_size;
|
||||
|
||||
fcntl(ar->fd, F_SETFD, fcntl(ar->fd, F_GETFD) | FD_CLOEXEC);
|
||||
|
||||
if ((ar->mmap = mmap(NULL, ar->size, PROT_READ, MAP_SHARED, ar->fd, 0)) == MAP_FAILED)
|
||||
goto err;
|
||||
|
||||
idx_offset = ntohl(*((const uint32_t *)
|
||||
(ar->mmap + ar->size - sizeof(uint32_t))));
|
||||
|
||||
if (idx_offset >= ar->size)
|
||||
goto err;
|
||||
|
||||
ar->index = (lmo_entry_t *)(ar->mmap + idx_offset);
|
||||
ar->length = (ar->size - idx_offset - sizeof(uint32_t)) / sizeof(lmo_entry_t);
|
||||
ar->end = ar->mmap + ar->size;
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
err:
|
||||
if (in > -1)
|
||||
close(in);
|
||||
|
||||
if (ar != NULL)
|
||||
{
|
||||
if ((ar->mmap != NULL) && (ar->mmap != MAP_FAILED))
|
||||
munmap(ar->mmap, ar->size);
|
||||
|
||||
free(ar);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void lmo_close(lmo_archive_t *ar)
|
||||
{
|
||||
if (ar != NULL)
|
||||
{
|
||||
if ((ar->mmap != NULL) && (ar->mmap != MAP_FAILED))
|
||||
munmap(ar->mmap, ar->size);
|
||||
|
||||
close(ar->fd);
|
||||
free(ar);
|
||||
|
||||
ar = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lmo_catalog_t *_lmo_catalogs = NULL;
|
||||
lmo_catalog_t *_lmo_active_catalog = NULL;
|
||||
|
||||
int lmo_load_catalog(const char *lang, const char *dir)
|
||||
{
|
||||
DIR *dh = NULL;
|
||||
char pattern[16];
|
||||
char path[PATH_MAX];
|
||||
struct dirent *de = NULL;
|
||||
|
||||
lmo_archive_t *ar = NULL;
|
||||
lmo_catalog_t *cat = NULL;
|
||||
|
||||
if (!lmo_change_catalog(lang))
|
||||
return 0;
|
||||
|
||||
if (!dir || !(dh = opendir(dir)))
|
||||
goto err;
|
||||
|
||||
if (!(cat = malloc(sizeof(*cat))))
|
||||
goto err;
|
||||
|
||||
memset(cat, 0, sizeof(*cat));
|
||||
|
||||
snprintf(cat->lang, sizeof(cat->lang), "%s", lang);
|
||||
snprintf(pattern, sizeof(pattern), "*.%s.lmo", lang);
|
||||
|
||||
while ((de = readdir(dh)) != NULL)
|
||||
{
|
||||
if (!fnmatch(pattern, de->d_name, 0))
|
||||
{
|
||||
snprintf(path, sizeof(path), "%s/%s", dir, de->d_name);
|
||||
ar = lmo_open(path);
|
||||
|
||||
if (ar)
|
||||
{
|
||||
ar->next = cat->archives;
|
||||
cat->archives = ar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dh);
|
||||
|
||||
cat->next = _lmo_catalogs;
|
||||
_lmo_catalogs = cat;
|
||||
|
||||
if (!_lmo_active_catalog)
|
||||
_lmo_active_catalog = cat;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (dh) closedir(dh);
|
||||
if (cat) free(cat);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lmo_change_catalog(const char *lang)
|
||||
{
|
||||
lmo_catalog_t *cat;
|
||||
|
||||
for (cat = _lmo_catalogs; cat; cat = cat->next)
|
||||
{
|
||||
if (!strncmp(cat->lang, lang, sizeof(cat->lang)))
|
||||
{
|
||||
_lmo_active_catalog = cat;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static lmo_entry_t * lmo_find_entry(lmo_archive_t *ar, uint32_t hash)
|
||||
{
|
||||
unsigned int m, l, r;
|
||||
uint32_t k;
|
||||
|
||||
l = 0;
|
||||
r = ar->length - 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
m = l + ((r - l) / 2);
|
||||
|
||||
if (r < l)
|
||||
break;
|
||||
|
||||
k = ntohl(ar->index[m].key_id);
|
||||
|
||||
if (k == hash)
|
||||
return &ar->index[m];
|
||||
|
||||
if (k > hash)
|
||||
{
|
||||
if (!m)
|
||||
break;
|
||||
|
||||
r = m - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = m + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lmo_translate(const char *key, int keylen, char **out, int *outlen)
|
||||
{
|
||||
uint32_t hash;
|
||||
lmo_entry_t *e;
|
||||
lmo_archive_t *ar;
|
||||
|
||||
if (!key || !_lmo_active_catalog)
|
||||
return -2;
|
||||
|
||||
hash = lmo_canon_hash(key, keylen);
|
||||
|
||||
for (ar = _lmo_active_catalog->archives; ar; ar = ar->next)
|
||||
{
|
||||
if ((e = lmo_find_entry(ar, hash)) != NULL)
|
||||
{
|
||||
*out = ar->mmap + ntohl(e->offset);
|
||||
*outlen = ntohl(e->length);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void lmo_close_catalog(const char *lang)
|
||||
{
|
||||
lmo_archive_t *ar, *next;
|
||||
lmo_catalog_t *cat, *prev;
|
||||
|
||||
for (prev = NULL, cat = _lmo_catalogs; cat; prev = cat, cat = cat->next)
|
||||
{
|
||||
if (!strncmp(cat->lang, lang, sizeof(cat->lang)))
|
||||
{
|
||||
if (prev)
|
||||
prev->next = cat->next;
|
||||
else
|
||||
_lmo_catalogs = cat->next;
|
||||
|
||||
for (ar = cat->archives; ar; ar = next)
|
||||
{
|
||||
next = ar->next;
|
||||
lmo_close(ar);
|
||||
}
|
||||
|
||||
free(cat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
92
package/lean/openwrt-ssr/tools/po2lmo/src/template_lmo.h
Normal file
92
package/lean/openwrt-ssr/tools/po2lmo/src/template_lmo.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* lmo - Lua Machine Objects - General header
|
||||
*
|
||||
* Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _TEMPLATE_LMO_H_
|
||||
#define _TEMPLATE_LMO_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if (defined(__GNUC__) && defined(__i386__))
|
||||
#define sfh_get16(d) (*((const uint16_t *) (d)))
|
||||
#else
|
||||
#define sfh_get16(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
|
||||
|
||||
struct lmo_entry {
|
||||
uint32_t key_id;
|
||||
uint32_t val_id;
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef struct lmo_entry lmo_entry_t;
|
||||
|
||||
|
||||
struct lmo_archive {
|
||||
int fd;
|
||||
int length;
|
||||
uint32_t size;
|
||||
lmo_entry_t *index;
|
||||
char *mmap;
|
||||
char *end;
|
||||
struct lmo_archive *next;
|
||||
};
|
||||
|
||||
typedef struct lmo_archive lmo_archive_t;
|
||||
|
||||
|
||||
struct lmo_catalog {
|
||||
char lang[6];
|
||||
struct lmo_archive *archives;
|
||||
struct lmo_catalog *next;
|
||||
};
|
||||
|
||||
typedef struct lmo_catalog lmo_catalog_t;
|
||||
|
||||
|
||||
uint32_t sfh_hash(const char *data, int len);
|
||||
uint32_t lmo_canon_hash(const char *data, int len);
|
||||
|
||||
lmo_archive_t * lmo_open(const char *file);
|
||||
void lmo_close(lmo_archive_t *ar);
|
||||
|
||||
|
||||
extern lmo_catalog_t *_lmo_catalogs;
|
||||
extern lmo_catalog_t *_lmo_active_catalog;
|
||||
|
||||
int lmo_load_catalog(const char *lang, const char *dir);
|
||||
int lmo_change_catalog(const char *lang);
|
||||
int lmo_translate(const char *key, int keylen, char **out, int *outlen);
|
||||
void lmo_close_catalog(const char *lang);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user