add luci-app-passwall

This commit is contained in:
CN_SZTL 2019-08-03 00:02:17 +08:00
parent 9c14693e6d
commit dd5ee40e3b
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
55 changed files with 26568 additions and 0 deletions

View File

@ -0,0 +1,71 @@
#
# Copyright (C) 2015-2016 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
ifeq ($(ARCH),x86_64)
PKG_ARCH_BROOK:=
endif
ifeq ($(ARCH),mipsel)
PKG_ARCH_BROOK:=_linux_mipsle
endif
ifeq ($(ARCH),mips)
PKG_ARCH_BROOK:=_linux_mips
endif
ifeq ($(ARCH),i386)
PKG_ARCH_BROOK:=_linux_386
endif
ifeq ($(ARCH),arm)
PKG_ARCH_BROOK:=_linux_arm7
endif
ifeq ($(BOARD),bcm53xx)
PKG_ARCH_BROOK:=_linux_arm6
endif
ifeq ($(BOARD),kirkwood)
PKG_ARCH_BROOK:=_linux_arm5
endif
ifeq ($(ARCH),aarch64)
PKG_ARCH_BROOK:=_linux_arm64
endif
PKG_NAME:=brook
PKG_VERSION:=20190601
PKG_RELEASE:=2
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE:=brook$(PKG_ARCH_BROOK)
PKG_SOURCE_URL:=https://github.com/txthinking/brook/releases/download/v$(PKG_VERSION)
PKG_HASH:=skip
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
SECTION:=net
CATEGORY:=Network
TITLE:=Brook is a cross-platform proxy software
DEPENDS:=
URL:=https://github.com/txthinking/brook
endef
define Package/$(PKG_NAME)/description
Brook is a cross-platform proxy software
endef
define Build/Prepare
mv $(DL_DIR)/$(PKG_SOURCE) $(PKG_BUILD_DIR)
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/brook$(PKG_ARCH_BROOK) $(1)/usr/bin/brook
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -0,0 +1,55 @@
#
# Copyright (C) 2015 OpenWrt-dist
# Copyright (C) 2015 Jian Chang <aa65535@live.com>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=dns-forwarder
PKG_VERSION:=1.2.1
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/aa65535/hev-dns-forwarder.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE)
PKG_SOURCE_VERSION:=289e8c9c7167200668dff83b1e0cbce258665387
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_LICENSE:=GPLv3
PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=Jian Chang <aa65535@live.com>
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(PKG_SOURCE_SUBDIR)
PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk
define Package/dns-forwarder
SECTION:=net
CATEGORY:=Network
TITLE:=Forwarding DNS queries on TCP transport
URL:=https://github.com/aa65535/hev-dns-forwarder
endef
define Package/dns-forwarder/description
Forwarding DNS queries on TCP transport.
endef
define Package/dns-forwarder/conffiles
/etc/config/dns-forwarder
endef
define Package/dns-forwarder/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/hev-dns-forwarder $(1)/usr/bin/dns-forwarder
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_DATA) ./files/dns-forwarder.config $(1)/etc/config/dns-forwarder
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/dns-forwarder.init $(1)/etc/init.d/dns-forwarder
endef
$(eval $(call BuildPackage,dns-forwarder))

View File

@ -0,0 +1,6 @@
config dns-forwarder
option enable '0'
option listen_addr '0.0.0.0'
option listen_port '5300'
option dns_servers '8.8.8.8'

View File

@ -0,0 +1,46 @@
#!/bin/sh /etc/rc.common
#
# Copyright (C) 2016 Jian Chang <aa65535@live.com>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
START=75
USE_PROCD=1
append_parm() {
local section="$1"
local option="$2"
local switch="$3"
local default="$4"
local _loctmp
config_get _loctmp "$section" "$option"
[ -n "$_loctmp" -o -n "$default" ] || return 0
procd_append_param command "$switch" "${_loctmp:-$default}"
}
start_instance() {
local enable
config_get_bool enable $1 enable
[ "$enable" = 1 ] || return 0
procd_open_instance
procd_set_param respawn
procd_set_param stderr 1
procd_set_param command /usr/bin/dns-forwarder
append_parm $1 listen_addr "-b"
append_parm $1 listen_port "-p"
append_parm $1 dns_servers "-s"
procd_close_instance
}
start_service() {
config_load dns-forwarder
config_foreach start_instance dns-forwarder
}
service_triggers() {
procd_add_reload_trigger "dns-forwarder"
}

View File

@ -0,0 +1,66 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=dns2socks
PKG_VERSION:=2.0
PKG_RELEASE:=20150628
PKG_SOURCE:=SourceCode.zip
PKG_SOURCE_SUBDIR:=DNS2SOCKS
PKG_SOURCE_URL:=@SF/dns2socks
PKG_MD5SUM:=6a6d5462113929cb8ba3511a884211cf
PKG_MAINTAINER:=ghostmaker
PKG_LICENSE:=BSD-3-Clause
PKG_BUILD_DIR:=$(BUILD_DIR)/$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
PKG_INSTALL:=1
PKG_USE_MIPS16:=0
PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk
define Package/dns2socks/Default
SECTION:=net
CATEGORY:=Network
SUBMENU:=IP Addresses and Names
TITLE:=The utility to resolve DNS requests via a SOCKS5 tunnel.
URL:=http://dns2socks.sourceforge.net/
MAINTAINER:=ghostmaker
DEPENDS:=+libpthread
endef
define Package/dns2socks
$(call Package/dns2socks/Default)
endef
define Package/dns2socks/description
This is a utility to resolve DNS requests via a SOCKS5 tunnel and caches the answers.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
unzip $(DL_DIR)/$(PKG_SOURCE) -d $(PKG_BUILD_DIR)
endef
define Build/Compile
$(TARGET_CC) \
$(TARGET_CFLAGS) \
$(TARGET_CPPFLAGS) \
$(FPIC) \
-o $(PKG_BUILD_DIR)/$(PKG_SOURCE_SUBDIR)/$(PKG_NAME) \
$(PKG_BUILD_DIR)/$(PKG_SOURCE_SUBDIR)/DNS2SOCKS.c \
$(TARGET_LDFLAGS) -pthread
endef
define Build/Install
endef
define Package/dns2socks/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_SOURCE_SUBDIR)/$(PKG_NAME) $(1)/usr/bin/dns2socks
endef
#$(shell $(RM) $(DL_DIR)/$(PKG_SOURCE))
$(eval $(call BuildPackage,dns2socks))

View File

@ -0,0 +1,125 @@
# Copyright (C) 2018-2019 Lienol
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=2.0
PKG_RELEASE:=76-20190731
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PO2LMO:=./po2lmo
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)/config
menu "Configuration"
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks
bool "Include Shadowsocks Redir (ss-redir)"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR
bool "Include ShadowsocksR Redir (ssr-redir)"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_socks
bool "Include Shadowsocks Socks (ss-local)"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_socks
bool "Include ShadowsocksR Socks (ssr-local)"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray
bool "Include V2ray"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Brook
bool "Include Brook"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_kcptun
bool "Include kcptun"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_haproxy
bool "Include haproxy"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS
bool "Include ChinaDNS"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_pdnsd
bool "Include pdnsd"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_dns2socks
bool "Include dns2socks"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_dns-forwarder
bool "Include dns-forwarder"
default n
endmenu
endef
define Package/$(PKG_NAME)
CATEGORY:=LuCI for Lienol
SUBMENU:=3. Applications
TITLE:=LuCI support for PassWall(fanqiang) By Lienol
PKGARCH:=all
DEPENDS:=+curl +libcurl +libmbedtls +ca-bundle +ca-certificates +resolveip +iptables-mod-tproxy +kmod-ipt-tproxy +iptables-mod-ipopt +kmod-ipt-ipopt +ip +ipset +coreutils +coreutils-base64 +coreutils-nohup +luci-lib-jsonc +unzip \
+dnsmasq-full \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks:shadowsocks-libev-ss-redir \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR:shadowsocksr-libev-alt \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_socks:shadowsocks-libev-ss-local \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_socks:shadowsocksr-libev-ssr-local \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \
+PACKAGE_$(PKG_NAME)_INCLUDE_Brook:brook \
+PACKAGE_$(PKG_NAME)_INCLUDE_kcptun:kcptun-client \
+PACKAGE_$(PKG_NAME)_INCLUDE_haproxy:haproxy \
+PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS:openwrt_chinadns \
+PACKAGE_$(PKG_NAME)_INCLUDE_pdnsd:pdnsd-alt \
+PACKAGE_$(PKG_NAME)_INCLUDE_dns2socks:dns2socks \
+PACKAGE_$(PKG_NAME)_INCLUDE_dns-forwarder:dns-forwarder
endef
define Build/Prepare
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_DIR) $(1)/usr/share/passwall
$(INSTALL_CONF) ./root/etc/config/passwall $(1)/etc/config/passwall
$(INSTALL_CONF) ./root/etc/config/passwall_show $(1)/etc/config/passwall_show
$(INSTALL_CONF) ./root/etc/uci-defaults/* $(1)/etc/uci-defaults
$(INSTALL_BIN) ./root/etc/init.d/passwall $(1)/etc/init.d/passwall
$(INSTALL_DIR) $(1)/usr/lib/lua/luci
cp -pR ./luasrc/* $(1)/usr/lib/lua/luci/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
cp -pR ./root/usr/share/passwall/* $(1)/usr/share/passwall
chmod 755 $(PO2LMO)
$(PO2LMO) ./po/zh-cn/passwall.po $(1)/usr/lib/lua/luci/i18n/passwall.zh-cn.lmo
endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
chmod a+x $${IPKG_INSTROOT}/usr/share/passwall/* >/dev/null 2>&1
rm -rf $${IPKG_INSTROOT}/etc/chinadns_chnroute.txt >/dev/null 2>&1
exit 0
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -0,0 +1,320 @@
-- Copyright 2018-2019 Lienol <lawlienol@gmail.com>
module("luci.controller.passwall", package.seeall)
local appname = "passwall"
local http = require "luci.http"
local kcptun = require "luci.model.cbi.passwall.api.kcptun"
local brook = require "luci.model.cbi.passwall.api.brook"
local v2ray = require "luci.model.cbi.passwall.api.v2ray"
function index()
if not nixio.fs.access("/etc/config/passwall") then return end
entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false
entry({"admin", "vpn", "passwall", "show"}, call("show_menu")).leaf = true
entry({"admin", "vpn", "passwall", "hide"}, call("hide_menu")).leaf = true
if nixio.fs.access("/etc/config/passwall") and
nixio.fs.access("/etc/config/passwall_show") then
entry({"admin", "vpn", "passwall"},
alias("admin", "vpn", "passwall", "settings"), _("Pass Wall"), 1).dependent =
true
end
entry({"admin", "vpn", "passwall", "settings"}, cbi("passwall/global"),
_("Basic Settings"), 1).dependent = true
entry({"admin", "vpn", "passwall", "server_list"},
cbi("passwall/server_list"), _("Server List"), 2).dependent = true
entry({"admin", "vpn", "passwall", "auto_switch"},
cbi("passwall/auto_switch"), _("Auto Switch"), 3).leaf = true
entry({"admin", "vpn", "passwall", "other"}, cbi("passwall/other"),
_("Other Settings"), 94).leaf = true
if nixio.fs.access("/usr/sbin/haproxy") then
entry({"admin", "vpn", "passwall", "balancing"},
cbi("passwall/balancing"), _("Load Balancing"), 95).leaf = true
end
entry({"admin", "vpn", "passwall", "rule"}, cbi("passwall/rule"),
_("Rule Update"), 96).leaf = true
entry({"admin", "vpn", "passwall", "acl"}, cbi("passwall/acl"),
_("Access control"), 97).leaf = true
entry({"admin", "vpn", "passwall", "rulelist"}, cbi("passwall/rulelist"),
_("Set Blacklist And Whitelist"), 98).leaf = true
entry({"admin", "vpn", "passwall", "log"}, cbi("passwall/log"),
_("Watch Logs"), 99).leaf = true
entry({"admin", "vpn", "passwall", "serverconfig"},
cbi("passwall/serverconfig")).leaf = true
entry({"admin", "vpn", "passwall", "link_add_server"},
call("link_add_server")).leaf = true
entry({"admin", "vpn", "passwall", "get_log"}, call("get_log")).leaf = true
entry({"admin", "vpn", "passwall", "clear_log"}, call("clear_log")).leaf =
true
entry({"admin", "vpn", "passwall", "server_status"}, call("server_status")).leaf =
true
entry({"admin", "vpn", "passwall", "connect_status"}, call("connect_status")).leaf =
true
entry({"admin", "vpn", "passwall", "check_port"}, call("check_port")).leaf =
true
entry({"admin", "vpn", "passwall", "auto_ping_server"},
call("auto_ping_server")).leaf = true
entry({"admin", "vpn", "passwall", "ping_server"}, call("ping_server")).leaf =
true
entry({"admin", "vpn", "passwall", "set_server"}, call("set_server")).leaf =
true
entry({"admin", "vpn", "passwall", "copy_server"}, call("copy_server")).leaf =
true
entry({"admin", "vpn", "passwall", "update_rules"}, call("update_rules")).leaf =
true
entry({"admin", "vpn", "passwall", "kcptun_check"}, call("kcptun_check")).leaf =
true
entry({"admin", "vpn", "passwall", "kcptun_update"}, call("kcptun_update")).leaf =
true
entry({"admin", "vpn", "passwall", "brook_check"}, call("brook_check")).leaf =
true
entry({"admin", "vpn", "passwall", "brook_update"}, call("brook_update")).leaf =
true
entry({"admin", "vpn", "passwall", "v2ray_check"}, call("v2ray_check")).leaf =
true
entry({"admin", "vpn", "passwall", "v2ray_update"}, call("v2ray_update")).leaf =
true
end
local function http_write_json(content)
http.prepare_content("application/json")
http.write_json(content or {code = 1})
end
function show_menu()
luci.sys.call("touch /etc/config/passwall_show")
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall"))
end
function hide_menu()
luci.sys.call("rm -rf /etc/config/passwall_show")
luci.http.redirect(luci.dispatcher.build_url("admin", "status", "overview"))
end
function link_add_server()
local type = luci.http.formvalue("type")
local link = luci.http.formvalue("link")
if type == "SSR" then
luci.sys.call('rm -f /tmp/ssr_links.conf && echo "' .. link ..
'" >> /tmp/ssr_links.conf')
luci.sys.call("/usr/share/passwall/subscription_ssr.sh add >/dev/null")
elseif type == "V2ray" then
luci.sys.call('rm -f /tmp/v2ray_links.conf && echo "' .. link ..
'" >> /tmp/v2ray_links.conf')
luci.sys
.call("/usr/share/passwall/subscription_v2ray.sh add >/dev/null")
end
end
function get_log()
-- luci.sys.exec("[ -f /var/log/passwall.log ] && sed '1!G;h;$!d' /var/log/passwall.log > /var/log/passwall_show.log")
luci.http.write(luci.sys.exec("cat /var/log/passwall.log"))
end
function clear_log() luci.sys.call("rm -rf > /var/log/passwall.log") end
function server_status()
local tcp_redir_port = luci.sys.exec(
"echo -n `uci get " .. appname ..
".@global_proxy[0].tcp_redir_port`")
local udp_redir_port = luci.sys.exec(
"echo -n `uci get " .. appname ..
".@global_proxy[0].udp_redir_port`")
-- local dns_mode = luci.sys.exec("echo -n `uci get " .. appname .. ".@global[0].dns_mode`")
local e = {}
e.tcp_redir_status = luci.sys.call("ps -w | grep -v grep | grep -i -E '" ..
appname ..
"/TCP|brook tproxy -l 0.0.0.0:" ..
tcp_redir_port .. "' >/dev/null") ==
0
e.udp_redir_status = luci.sys.call("ps -w | grep -v grep | grep -i -E '" ..
appname ..
"/UDP|brook tproxy -l 0.0.0.0:" ..
udp_redir_port .. "' >/dev/null") ==
0
e.socks5_proxy_status = luci.sys.call(
"ps -w | grep -v grep | grep -i -E '" .. appname ..
"/SOCKS5|brook client' >/dev/null") == 0
e.dns_mode_status = luci.sys.call("netstat -apn | grep 7913 >/dev/null") ==
0
e.haproxy_status = luci.sys.call(
"ps -w | grep -v grep | grep -i 'haproxy -f /var/etc/" ..
appname .. "/haproxy.cfg' >/dev/null") == 0
e.kcptun_status = luci.sys.call(
"ps -w | grep -v grep | grep -i 'log /var/etc/" ..
appname .. "/kcptun' >/dev/null") == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function connect_status()
local e = {}
if luci.http.formvalue("type") == "google" then
e.status = luci.sys.call(
"echo `curl -I -o /dev/null -s -m 10 --connect-timeout 5 -w %{http_code} 'https://www.google.com'` | grep 200 >/dev/null") ==
0
else
e.status = luci.sys.call(
"echo `curl -I -o /dev/null -s -m 10 --connect-timeout 2 -w %{http_code} 'http://www.baidu.com'` | grep 200 >/dev/null") ==
0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function auto_ping_server()
local e = {}
e.index = luci.http.formvalue("index")
e.ping = luci.sys.exec(
"ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print$2}'" %
luci.http.formvalue("domain"))
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function ping_server()
local e = {}
local server = luci.http.formvalue("server")
e.ping = luci.sys.exec(
"echo -n `ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print$2}'`" %
server)
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function set_server()
local e = {}
local protocol = luci.http.formvalue("protocol")
local section = luci.http.formvalue("section")
if protocol == "tcp" then
luci.sys.call(
"uci set passwall.@global[0].tcp_redir_server=" .. section ..
" && uci commit passwall && /etc/init.d/passwall restart")
elseif protocol == "udp" then
luci.sys.call(
"uci set passwall.@global[0].udp_redir_server=" .. section ..
" && uci commit passwall && /etc/init.d/passwall restart")
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function copy_server()
local e = {}
local section = luci.http.formvalue("section")
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function check_port()
local retstring = "<br />"
retstring = retstring ..
"<font color='red'>暂时不支持UDP检测</font><br />"
local s
local server_name = ""
local uci = luci.model.uci.cursor()
uci:foreach("passwall", "servers", function(s)
local ret = ""
local tcp_socket
local udp_socket
if (s.use_kcp and s.use_kcp == "1" and s.kcp_port) or
(s.v2ray_transport and s.v2ray_transport == "mkcp" and s.server_port) then
--[[local port = (s.use_kcp == "1" and s.kcp_port) and s.kcp_port or (s.v2ray_transport == "mkcp" and s.server_port) and s.server_port or nil
if port then
udp_socket = nixio.socket("inet", "dgram")
udp_socket:setopt("socket", "rcvtimeo", 3)
udp_socket:setopt("socket", "sndtimeo", 3)
udp_socket:sendto("test", s.server, port)
r,c,d=udp_socket:recvfrom(10)
ret=""
end--]]
else
if s.server_type and s.server and s.server_port and s.remarks then
server_name = "%s[%s] %s:%s" %
{
s.server_type, s.remarks, s.server, s.server_port
}
end
tcp_socket = nixio.socket("inet", "stream")
tcp_socket:setopt("socket", "rcvtimeo", 3)
tcp_socket:setopt("socket", "sndtimeo", 3)
ret = tcp_socket:connect(s.server, s.server_port)
if tostring(ret) == "true" then
retstring =
retstring .. "<font color='green'>" .. server_name ..
" OK.</font><br />"
else
retstring = retstring .. "<font color='red'>" .. server_name ..
" Error.</font><br />"
end
ret = ""
end
if tcp_socket then tcp_socket:close() end
if udp_socket then udp_socket:close() end
end)
luci.http.prepare_content("application/json")
luci.http.write_json({ret = retstring})
end
function update_rules()
local update = luci.http.formvalue("update")
luci.sys.call("nohup /usr/share/passwall/rule_update.sh '" .. update ..
"' 2>&1 &")
end
function kcptun_check()
local json = kcptun.to_check("")
http_write_json(json)
end
function kcptun_update()
local json = nil
local task = http.formvalue("task")
if task == "extract" then
json = kcptun.to_extract(http.formvalue("file"),
http.formvalue("subfix"))
elseif task == "move" then
json = kcptun.to_move(http.formvalue("file"))
else
json = kcptun.to_download(http.formvalue("url"))
end
http_write_json(json)
end
function brook_check()
local json = brook.to_check("")
http_write_json(json)
end
function brook_update()
local json = nil
local task = http.formvalue("task")
if task == "move" then
json = brook.to_move(http.formvalue("file"))
else
json = brook.to_download(http.formvalue("url"))
end
http_write_json(json)
end
function v2ray_check()
local json = v2ray.to_check("")
http_write_json(json)
end
function v2ray_update()
local json = nil
local task = http.formvalue("task")
if task == "extract" then
json =
v2ray.to_extract(http.formvalue("file"), http.formvalue("subfix"))
elseif task == "move" then
json = v2ray.to_move(http.formvalue("file"))
else
json = v2ray.to_download(http.formvalue("url"))
end
http_write_json(json)
end

View File

@ -0,0 +1,71 @@
local sys = require "luci.sys"
local webadmin = require "luci.tools.webadmin"
m = Map("passwall")
-- [[ ACLs Settings ]]--
s = m:section(TypedSection, "acl_rule", translate("ACLs"), translate(
"ACLs is a tools which used to designate specific IP proxy mode"))
s.template = "cbi/tblsection"
s.sortable = true
s.anonymous = true
s.addremove = true
---- Enable
o = s:option(Flag, "enabled", translate("Enable"))
o.rmempty = false
---- ACL Remarks
o = s:option(Value, "aclremarks", translate("ACL Remarks"))
o.rmempty = true
---- IP Address
o = s:option(Value, "ipaddr", translate("IP Address"))
o.datatype = "ip4addr"
o.rmempty = true
local temp = {}
for index, n in ipairs(luci.ip.neighbors({family = 4})) do
if n.dest then temp[index] = n.dest:string() end
end
local ips = {}
for _, key in pairs(temp) do table.insert(ips, key) end
table.sort(ips)
for index, key in pairs(ips) do o:value(key, temp[key]) end
-- webadmin.cbi_add_knownips(o)
---- MAC Address
o = s:option(Value, "macaddr", translate("MAC Address"))
o.rmempty = true
sys.net.mac_hints(function(e, t) o:value(e, "%s (%s)" % {e, t}) end)
---- Proxy Mode
o = s:option(ListValue, "proxy_mode", translate("Proxy Mode"))
o.default = "default"
o.rmempty = false
o:value("default", translate("Default"))
o:value("disable", translate("No Proxy"))
o:value("global", translate("Global Proxy"))
o:value("gfwlist", translate("GFW List"))
o:value("chnroute", translate("China WhiteList"))
o:value("gamemode", translate("Game Mode"))
o:value("returnhome", translate("Return Home"))
---- TCP Redir Ports
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
o.default = "default"
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o:value("80,443", "80,443")
o:value("80:", "80 " .. translate("or more"))
o:value(":443", "443 " .. translate("or less"))
---- UDP Redir Ports
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
o.default = "default"
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o:value("53", "53")
return m

View File

@ -0,0 +1,165 @@
module("luci.model.cbi.passwall.api.api", package.seeall)
local fs = require "nixio.fs"
local sys = require "luci.sys"
local uci = require"luci.model.uci".cursor()
local util = require "luci.util"
local i18n = require "luci.i18n"
local wget = "/usr/bin/wget"
local wget_args = {
"--no-check-certificate", "--quiet", "--timeout=100", "--tries=3"
}
local curl = "/usr/bin/curl"
local command_timeout = 300
local LEDE_BOARD = nil
local DISTRIB_TARGET = nil
function _unpack(t, i)
i = i or 1
if t[i] ~= nil then return t[i], _unpack(t, i + 1) end
end
function exec(cmd, args, writer, timeout)
local os = require "os"
local nixio = require "nixio"
local fdi, fdo = nixio.pipe()
local pid = nixio.fork()
if pid > 0 then
fdo:close()
if writer or timeout then
local starttime = os.time()
while true do
if timeout and os.difftime(os.time(), starttime) >= timeout then
nixio.kill(pid, nixio.const.SIGTERM)
return 1
end
if writer then
local buffer = fdi:read(2048)
if buffer and #buffer > 0 then
writer(buffer)
end
end
local wpid, stat, code = nixio.waitpid(pid, "nohang")
if wpid and stat == "exited" then return code end
if not writer and timeout then nixio.nanosleep(1) end
end
else
local wpid, stat, code = nixio.waitpid(pid)
return wpid and stat == "exited" and code
end
elseif pid == 0 then
nixio.dup(fdo, nixio.stdout)
fdi:close()
fdo:close()
nixio.exece(cmd, args, nil)
nixio.stdout:close()
os.exit(1)
end
end
function compare_versions(ver1, comp, ver2)
local table = table
local av1 = util.split(ver1, "[%.%-]", nil, true)
local av2 = util.split(ver2, "[%.%-]", nil, true)
local max = table.getn(av1)
local n2 = table.getn(av2)
if (max < n2) then max = n2 end
for i = 1, max, 1 do
local s1 = av1[i] or ""
local s2 = av2[i] or ""
if comp == "~=" and (s1 ~= s2) then return true end
if (comp == "<" or comp == "<=") and (s1 < s2) then return true end
if (comp == ">" or comp == ">=") and (s1 > s2) then return true end
if (s1 ~= s2) then return false end
end
return not (comp == "<" or comp == ">")
end
function auto_get_arch()
local arch = nixio.uname().machine or ""
if fs.access("/usr/lib/os-release") then
LEDE_BOARD = sys.exec(
"echo -n `grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}'`")
end
if fs.access("/etc/openwrt_release") then
DISTRIB_TARGET = sys.exec(
"echo -n `grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}'`")
end
if arch == "mips" then
if LEDE_BOARD and LEDE_BOARD ~= "" then
if string.match(LEDE_BOARD, "ramips") == "ramips" then
arch = "ramips"
else
arch = sys.exec("echo '" .. LEDE_BOARD ..
"' | grep -oE 'ramips|ar71xx'")
end
elseif DISTRIB_TARGET and DISTRIB_TARGET ~= "" then
if string.match(DISTRIB_TARGET, "ramips") == "ramips" then
arch = "ramips"
else
arch = sys.exec("echo '" .. DISTRIB_TARGET ..
"' | grep -oE 'ramips|ar71xx'")
end
end
end
return util.trim(arch)
end
function get_file_info(arch)
local file_tree = ""
local sub_version = ""
if arch == "x86_64" then
file_tree = "amd64"
elseif arch == "aarch64" then
file_tree = "arm64"
elseif arch == "ramips" then
file_tree = "mipsle"
elseif arch == "ar71xx" then
file_tree = "mips"
elseif arch:match("^i[%d]86$") then
file_tree = "386"
elseif arch:match("^armv[5-8]") then
file_tree = "arm"
sub_version = arch:match("[5-8]")
if LEDE_BOARD and string.match(LEDE_BOARD, "bcm53xx") == "bcm53xx" then
sub_version = "5"
elseif DISTRIB_TARGET and string.match(DISTRIB_TARGET, "bcm53xx") ==
"bcm53xx" then
sub_version = "5"
end
sub_version = "5"
end
return file_tree, sub_version
end
function get_api_json(url)
local jsonc = require "luci.jsonc"
local output = {}
-- exec(wget, { "-O-", url, _unpack(wget_args) },
-- function(chunk) output[#output + 1] = chunk end)
-- local json_content = util.trim(table.concat(output))
local json_content = luci.sys.exec(curl .. " -sL " .. url)
if json_content == "" then return {} end
return jsonc.parse(json_content) or {}
end

View File

@ -0,0 +1,178 @@
module("luci.model.cbi.passwall.api.brook", package.seeall)
local fs = require "nixio.fs"
local sys = require "luci.sys"
local uci = require"luci.model.uci".cursor()
local util = require "luci.util"
local i18n = require "luci.i18n"
local api = require "luci.model.cbi.passwall.api.api"
local brook_api =
"https://api.github.com/repos/txthinking/brook/releases/latest"
local wget = "/usr/bin/wget"
local wget_args = {
"--no-check-certificate", "--quiet", "--timeout=100", "--tries=3"
}
local command_timeout = 300
local LEDE_BOARD = nil
local DISTRIB_TARGET = nil
function get_brook_file_path()
return uci:get("passwall", "global_app", "brook_client_file") or
luci.sys.exec(
"echo -n `uci get passwall.@global_app[0].brook_client_file`")
end
function get_brook_version(file)
if file == nil then file = get_brook_file_path() end
if file and file ~= "" then
if not fs.access(file, "rwx", "rx", "rx") then
fs.chmod(file, 755)
end
local info = util.trim(sys.exec("%s -v 2>/dev/null" % file))
if info ~= "" then
local tb = util.split(info, "%s+", nil, true)
return tb[1] == "Brook" and tb[3] or ""
end
end
return ""
end
function to_check(arch)
if not arch or arch == "" then arch = api.auto_get_arch() end
local file_tree, sub_version = api.get_file_info(arch)
if file_tree == "" then
return {
code = 1,
error = i18n.translate(
"Can't determine ARCH, or ARCH not supported.")
}
end
file_tree = "_linux_" .. file_tree
if file_tree == "_linux_amd64" then file_tree = "" end
local json = api.get_api_json(brook_api)
if json.tag_name == nil then
return {
code = 1,
error = i18n.translate("Get remote version info failed.")
}
end
local remote_version = json.tag_name:match("[^v]+")
local client_file = get_brook_file_path()
local needs_update = api.compare_versions(get_brook_version(client_file),
"<", remote_version)
local html_url, download_url
if needs_update then
html_url = json.html_url
for _, v in ipairs(json.assets) do
if v.name and v.name:match(file_tree .. sub_version) then
download_url = v.browser_download_url
break
end
end
end
if needs_update and not download_url then
return {
code = 1,
now_version = get_brook_version(client_file),
version = remote_version,
html_url = html_url,
error = i18n.translate(
"New version found, but failed to get new version download url.")
}
end
return {
code = 0,
update = needs_update,
now_version = get_brook_version(client_file),
version = remote_version,
url = {html = html_url, download = download_url}
}
end
function to_download(url)
if not url or url == "" then
return {code = 1, error = i18n.translate("Download url is required.")}
end
sys.call("/bin/rm -f /tmp/brook_download.*")
local tmp_file = util.trim(util.exec("mktemp -u -t brook_download.XXXXXX"))
local result = api.exec(wget, {"-O", tmp_file, url, api._unpack(wget_args)},
nil, command_timeout) == 0
if not result then
api.exec("/bin/rm", {"-f", tmp_file})
return {
code = 1,
error = i18n.translatef("File download failed or timed out: %s", url)
}
end
return {code = 0, file = tmp_file}
end
function to_move(file)
if not file or file == "" or not fs.access(file) then
sys.call("/bin/rm -rf /tmp/brook_download.*")
return {code = 1, error = i18n.translate("Client file is required.")}
end
local version = get_brook_version(file)
if version == "" then
sys.call("/bin/rm -rf /tmp/brook_download.*")
return {
code = 1,
error = i18n.translate(
"The client file is not suitable for current device.")
}
end
local client_file = get_brook_file_path()
local client_file_bak
if fs.access(client_file) then
client_file_bak = client_file .. ".bak"
api.exec("/bin/mv", {"-f", client_file, client_file_bak})
end
local result = api.exec("/bin/mv", {"-f", file, client_file}, nil,
command_timeout) == 0
if not result or not fs.access(client_file) then
sys.call("/bin/rm -rf /tmp/brook_download.*")
if client_file_bak then
api.exec("/bin/mv", {"-f", client_file_bak, client_file})
end
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s",
client_file)
}
end
api.exec("/bin/chmod", {"755", client_file})
if client_file_bak then api.exec("/bin/rm", {"-f", client_file_bak}) end
sys.call("/bin/rm -rf /tmp/brook_download.*")
return {code = 0}
end

View File

@ -0,0 +1,97 @@
local ucursor = require"luci.model.uci".cursor()
local json = require "luci.jsonc"
local server_section = arg[1]
local proto = arg[2]
local redir_port = arg[3]
local socks5_proxy_port = arg[4]
local server = ucursor:get_all("passwall", server_section)
local inbound_json = {}
if socks5_proxy_port ~= "nil" then
inbound_json = {
listen = "0.0.0.0",
port = socks5_proxy_port,
protocol = "socks",
settings = {auth = "noauth", udp = true, ip = "127.0.0.1"}
}
end
if redir_port ~= "nil" then
inbound_json = {
port = redir_port,
protocol = "dokodemo-door",
settings = {network = proto, followRedirect = true},
sniffing = {enabled = true, destOverride = {"http", "tls"}}
}
end
local v2ray = {
log = {
-- error = "/var/log/v2ray.log",
loglevel = "warning"
},
-- 传入连接
inbound = inbound_json,
-- 传出连接
outbound = {
protocol = server.v2ray_protocol,
settings = {
vnext = {
{
address = server.server,
port = tonumber(server.server_port),
users = {
{
id = server.v2ray_VMess_id,
alterId = tonumber(server.v2ray_VMess_alterId),
level = tonumber(server.v2ray_VMess_level),
security = server.v2ray_security
}
}
}
}
},
mux = {
enabled = (server.v2ray_mux == "1") and true or false,
concurrency = (server.v2ray_mux_concurrency) and
tonumber(server.v2ray_mux_concurrency) or 8
},
-- 底层传输配置
streamSettings = {
network = server.v2ray_transport,
security = server.v2ray_stream_security,
tlsSettings = (server.v2ray_tls) and {} or nil,
kcpSettings = (server.v2ray_transport == "mkcp") and {
mtu = tonumber(server.v2ray_mkcp_mtu),
tti = tonumber(server.v2ray_mkcp_tti),
uplinkCapacity = tonumber(server.v2ray_mkcp_uplinkCapacity),
downlinkCapacity = tonumber(server.v2ray_mkcp_downlinkCapacity),
congestion = (server.v2ray_mkcp_congestion == "1") and true or
false,
readBufferSize = tonumber(server.v2ray_mkcp_readBufferSize),
writeBufferSize = tonumber(server.v2ray_mkcp_writeBufferSize),
header = {type = server.v2ray_mkcp_guise}
} or nil,
wsSettings = (server.v2ray_transport == "ws") and {
path = server.v2ray_ws_path,
headers = (server.v2ray_ws_host ~= nil) and
{Host = server.v2ray_ws_host} or nil
} or nil,
httpSettings = (server.v2ray_transport == "h2") and
{path = server.v2ray_h2_path, host = server.v2ray_h2_host} or
nil,
dsSettings = (server.v2ray_transport == "ds") and
{path = server.v2ray_ds_path} or nil,
quicSettings = (server.v2ray_transport == "quic") and {
security = server.v2ray_quic_security,
key = server.v2ray_quic_key,
header = {type = server.v2ray_quic_guise}
} or nil
}
},
-- 额外传出连接
outboundDetour = {
{protocol = "freedom", tag = "direct", settings = {keep = ""}}
}
}
print(json.stringify(v2ray, 1))

View File

@ -0,0 +1,218 @@
module("luci.model.cbi.passwall.api.kcptun", package.seeall)
local fs = require "nixio.fs"
local sys = require "luci.sys"
local uci = require"luci.model.uci".cursor()
local util = require "luci.util"
local i18n = require "luci.i18n"
local api = require "luci.model.cbi.passwall.api.api"
local kcptun_api = "https://api.github.com/repos/xtaci/kcptun/releases/latest"
local wget = "/usr/bin/wget"
local wget_args = {
"--no-check-certificate", "--quiet", "--timeout=100", "--tries=3"
}
local command_timeout = 300
local LEDE_BOARD = nil
local DISTRIB_TARGET = nil
function get_kcptun_file_path()
return uci:get("passwall", "global_app", "kcptun_client_file") or
luci.sys.exec(
"echo -n `uci get passwall.@global_app[0].kcptun_client_file`")
end
function get_kcptun_version(file)
if file == nil then file = get_kcptun_file_path() end
if file and file ~= "" then
if not fs.access(file, "rwx", "rx", "rx") then
fs.chmod(file, 755)
end
local info = util.trim(sys.exec("%s -v 2>/dev/null" % file))
if info ~= "" then
local tb = util.split(info, "%s+", nil, true)
return tb[1] == "kcptun" and tb[3] or ""
end
end
return ""
end
function to_check(arch)
if not arch or arch == "" then arch = api.auto_get_arch() end
local file_tree, sub_version = api.get_file_info(arch)
if file_tree == "" then
return {
code = 1,
error = i18n.translate(
"Can't determine ARCH, or ARCH not supported.")
}
end
local json = api.get_api_json(kcptun_api)
if json.tag_name == nil then
return {
code = 1,
error = i18n.translate("Get remote version info failed.")
}
end
local remote_version = json.tag_name:match("[^v]+")
local client_file = get_kcptun_file_path()
local needs_update = api.compare_versions(get_kcptun_version(client_file),
"<", remote_version)
local html_url, download_url
if needs_update then
html_url = json.html_url
for _, v in ipairs(json.assets) do
if v.name and v.name:match("linux%-" .. file_tree .. sub_version) then
download_url = v.browser_download_url
break
end
end
end
if needs_update and not download_url then
return {
code = 1,
now_version = get_kcptun_version(client_file),
version = remote_version,
html_url = html_url,
error = i18n.translate(
"New version found, but failed to get new version download url.")
}
end
return {
code = 0,
update = needs_update,
now_version = get_kcptun_version(client_file),
version = remote_version,
url = {html = html_url, download = download_url}
}
end
function to_download(url)
if not url or url == "" then
return {code = 1, error = i18n.translate("Download url is required.")}
end
sys.call("/bin/rm -f /tmp/kcptun_download.*")
local tmp_file = util.trim(util.exec("mktemp -u -t kcptun_download.XXXXXX"))
local result = api.exec(wget, {"-O", tmp_file, url, api._unpack(wget_args)},
nil, command_timeout) == 0
if not result then
api.exec("/bin/rm", {"-f", tmp_file})
return {
code = 1,
error = i18n.translatef("File download failed or timed out: %s", url)
}
end
return {code = 0, file = tmp_file}
end
function to_extract(file, subfix)
if not file or file == "" or not fs.access(file) then
return {code = 1, error = i18n.translate("File path required.")}
end
sys.call("/bin/rm -rf /tmp/kcptun_extract.*")
local tmp_dir = util.trim(util.exec("mktemp -d -t kcptun_extract.XXXXXX"))
local output = {}
api.exec("/bin/tar", {"-C", tmp_dir, "-zxvf", file},
function(chunk) output[#output + 1] = chunk end)
local files = util.split(table.concat(output))
api.exec("/bin/rm", {"-f", file})
local new_file = nil
for _, f in pairs(files) do
if f:match("client_linux_%s" % subfix) then
new_file = tmp_dir .. "/" .. util.trim(f)
break
end
end
if not new_file then
for _, f in pairs(files) do
if f:match("client_") then
new_file = tmp_dir .. "/" .. util.trim(f)
break
end
end
end
if not new_file then
api.exec("/bin/rm", {"-rf", tmp_dir})
return {
code = 1,
error = i18n.translatef("Can't find client in file: %s", file)
}
end
return {code = 0, file = new_file}
end
function to_move(file)
if not file or file == "" or not fs.access(file) then
sys.call("/bin/rm -rf /tmp/kcptun_extract.*")
return {code = 1, error = i18n.translate("Client file is required.")}
end
local version = get_kcptun_version(file)
if version == "" then
sys.call("/bin/rm -rf /tmp/kcptun_extract.*")
return {
code = 1,
error = i18n.translate(
"The client file is not suitable for current device.")
}
end
local client_file = get_kcptun_file_path()
local client_file_bak
if fs.access(client_file) then
client_file_bak = client_file .. ".bak"
api.exec("/bin/mv", {"-f", client_file, client_file_bak})
end
local result = api.exec("/bin/mv", {"-f", file, client_file}, nil,
command_timeout) == 0
if not result or not fs.access(client_file) then
sys.call("/bin/rm -rf /tmp/kcptun_extract.*")
if client_file_bak then
api.exec("/bin/mv", {"-f", client_file_bak, client_file})
end
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s",
client_file)
}
end
api.exec("/bin/chmod", {"755", client_file})
if client_file_bak then api.exec("/bin/rm", {"-f", client_file_bak}) end
sys.call("/bin/rm -rf /tmp/kcptun_extract.*")
return {code = 0}
end

View File

@ -0,0 +1,185 @@
module("luci.model.cbi.passwall.api.v2ray", package.seeall)
local fs = require "nixio.fs"
local sys = require "luci.sys"
local uci = require"luci.model.uci".cursor()
local util = require "luci.util"
local i18n = require "luci.i18n"
local ipkg = require("luci.model.ipkg")
local api = require "luci.model.cbi.passwall.api.api"
local v2ray_api =
"https://api.github.com/repos/v2ray/v2ray-core/releases/latest"
local wget = "/usr/bin/wget"
local wget_args = {
"--no-check-certificate", "--quiet", "--timeout=100", "--tries=3"
}
local command_timeout = 300
local LEDE_BOARD = nil
local DISTRIB_TARGET = nil
local is_armv7 = false
function get_v2ray_file_path()
return uci:get("passwall", "global_app", "v2ray_client_file") or
sys.exec(
"echo -n `uci get passwall.@global_app[0].v2ray_client_file`")
end
function get_v2ray_version()
if get_v2ray_file_path() and get_v2ray_file_path() ~= "" then
if fs.access(get_v2ray_file_path() .. "/v2ray") then
return sys.exec("echo -n `" .. get_v2ray_file_path() ..
"/v2ray -version | awk '{print $2}' | sed -n 1P" ..
"`")
end
end
return ""
end
function to_check(arch)
if not arch or arch == "" then arch = api.auto_get_arch() end
local file_tree, sub_version = api.get_file_info(arch)
if sub_version == "7" then is_armv7 = true end
if file_tree == "" then
return {
code = 1,
error = i18n.translate(
"Can't determine ARCH, or ARCH not supported.")
}
end
if file_tree == "amd64" then file_tree = "64" end
if file_tree == "386" then file_tree = "32" end
local json = api.get_api_json(v2ray_api)
if json.tag_name == nil then
return {
code = 1,
error = i18n.translate("Get remote version info failed.")
}
end
local remote_version = json.tag_name:match("[^v]+")
local needs_update = api.compare_versions(get_v2ray_version(), "<",
remote_version)
local html_url, download_url
if needs_update then
html_url = json.html_url
for _, v in ipairs(json.assets) do
if v.name and v.name:match("linux%-" .. file_tree) then
download_url = v.browser_download_url
break
end
end
end
if needs_update and not download_url then
return {
code = 1,
now_version = get_v2ray_version(),
version = remote_version,
html_url = html_url,
error = i18n.translate(
"New version found, but failed to get new version download url.")
}
end
return {
code = 0,
update = needs_update,
now_version = get_v2ray_version(),
version = remote_version,
url = {html = html_url, download = download_url}
}
end
function to_download(url)
if not url or url == "" then
return {code = 1, error = i18n.translate("Download url is required.")}
end
sys.call("/bin/rm -f /tmp/v2ray_download.*")
local tmp_file = util.trim(util.exec("mktemp -u -t v2ray_download.XXXXXX"))
local result = api.exec(wget, {"-O", tmp_file, url, api._unpack(wget_args)},
nil, command_timeout) == 0
if not result then
api.exec("/bin/rm", {"-f", tmp_file})
return {
code = 1,
error = i18n.translatef("File download failed or timed out: %s", url)
}
end
return {code = 0, file = tmp_file}
end
function to_extract(file, subfix)
local isinstall_unzip = ipkg.installed("unzip")
if isinstall_unzip == nil then
ipkg.update()
ipkg.install("unzip")
end
if not file or file == "" or not fs.access(file) then
return {code = 1, error = i18n.translate("File path required.")}
end
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
local tmp_dir = util.trim(util.exec("mktemp -d -t v2ray_extract.XXXXXX"))
local output = {}
api.exec("/usr/bin/unzip", {"-o", file, "-d", tmp_dir},
function(chunk) output[#output + 1] = chunk end)
local files = util.split(table.concat(output))
api.exec("/bin/rm", {"-f", file})
return {code = 0, file = tmp_dir}
end
function to_move(file)
if not file or file == "" then
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
return {code = 1, error = i18n.translate("Client file is required.")}
end
local client_file = get_v2ray_file_path()
sys.call("mkdir -p " .. client_file)
if not arch or arch == "" then arch = api.auto_get_arch() end
local file_tree, sub_version = api.get_file_info(arch)
if sub_version == "7" then is_armv7 = true end
local result = nil
if is_armv7 and is_armv7 == true then
result = api.exec("/bin/mv", {
"-f", file .. "/v2ray_armv7", file .. "/v2ctl_armv7", client_file
}, nil, command_timeout) == 0
else
result = api.exec("/bin/mv", {
"-f", file .. "/v2ray", file .. "/v2ctl", client_file
}, nil, command_timeout) == 0
end
if not result or not fs.access(client_file) then
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s",
client_file)
}
end
api.exec("/bin/chmod", {"-R", "755", client_file})
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
return {code = 0}
end

View File

@ -0,0 +1,37 @@
local uci = require "luci.model.uci".cursor()
local appname = "passwall"
local n = {}
uci:foreach(appname, "servers", function(e)
if e.server_type and e.server and e.remarks then
n[e[".name"]] = "%s[%s] %s" % {e.server_type, e.remarks, e.server}
end
end)
local key_table = {}
for key, _ in pairs(n) do table.insert(key_table, key) end
table.sort(key_table)
m = Map(appname)
-- [[ Auto Switch Settings ]]--
s = m:section(TypedSection, "auto_switch", translate("Auto Switch"))
s.anonymous = true
---- Enable
o = s:option(Flag, "enable", translate("Enable"))
o.default = 0
o.rmempty = false
---- Testing Time
o = s:option(Value, "testing_time", translate("How often is a diagnosis made"),
translate("Units:minutes"))
o.default = "10"
---- Tcp Redir Server
o = s:option(DynamicList, "tcp_redir_server",
translate("List of alternate TCP forwarding servers"), translate(
"When there is no server, an automatic reconnect scheme is used"))
for _, key in pairs(key_table) do o:value(key, n[key]) end
return m

View File

@ -0,0 +1,105 @@
local e = require "nixio.fs"
local e = require "luci.sys"
local net = require "luci.model.network".init()
local uci = require "luci.model.uci".cursor()
local ifaces = e.net:devices()
local appname = "passwall"
local servers_name = {}
local servers_port = {}
uci:foreach(appname, "servers", function(e)
if e.server and e.server_port and e.server ~= "127.0.0.1" then
servers_name[e[".name"]] = "%s" % {e.server}
servers_port[e[".name"]] = "%s" % {e.server_port}
end
end)
m = Map("passwall")
-- [[ Haproxy Settings ]]--
s = m:section(TypedSection, "global_haproxy", translate("Admin Status"),
translate(
"In the browser input routing IP plus port access, such as:192.168.1.1:1188") ..
"<br><input type='button' class='cbi-button cbi-input-reload' value='" ..
translate("Click here to setting your Load Balancing") ..
"' onclick=javascript:window.open('http://koolshare.cn/thread-65561-1-1.html','target'); />")
s.anonymous = true
---- Admin Enable
o = s:option(Flag, "admin_enable", translate("Enable Admin Status"))
o.rmempty = false
o.default = false
---- Admin Port
o = s:option(Value, "admin_port", translate("Admin Status port setting"))
o.default = "1188"
o:depends("admin_enable", 1)
---- Admin User
o = s:option(Value, "admin_user", translate("Admin Status User"))
o.default = "admin"
o:depends("admin_enable", 1)
---- Admin Password
o = s:option(Value, "admin_password", translate("Admin Status Password"))
o.password = true
o.default = "admin"
o:depends("admin_enable", 1)
---- Balancing Enable
o = s:option(Flag, "balancing_enable",
translate("Enable or Disable Load Balancing"))
o.rmempty = false
o.default = false
---- Haproxy Port
o = s:option(Value, "haproxy_port", translate("Haproxy port setting"))
o.default = "1181"
o:depends("balancing_enable", 1)
-- [[ Balancing Settings ]]--
s = m:section(TypedSection, "balancing",
translate("Load Balancing Server Setting"), translate(
"Add a load balancing server, note reading above requirements."))
s.template = "cbi/tblsection"
s.sortable = true
s.anonymous = true
s.addremove = true
---- Server Address
o = s:option(Value, "lbss", translate("Server Address"))
for m, s in pairs(servers_name) do o:value(s) end
o.rmempty = false
---- Server Port
o = s:option(Value, "lbort", translate("Server Port"))
for m, s in pairs(servers_port) do o:value(s) end
o.rmempty = false
---- Server weight
o = s:option(Value, "lbweight", translate("Server weight"))
o.default = "5"
o.rmempty = false
---- Export
o = s:option(ListValue, "export", translate("Export Of Multi WAN"))
o:value(0, translate("Auto"))
for _, iface in ipairs(ifaces) do
if (iface:match("^pppoe*")) then
local nets = net:get_interface(iface)
nets = nets and nets:get_networks() or {}
for k, v in pairs(nets) do nets[k] = nets[k].sid end
nets = table.concat(nets, ",")
o:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface))
end
end
o.default = 0
o.rmempty = false
---- Backup
o = s:option(ListValue, "backup", translate("Server Mode"))
o:value(0, translate("Primary Server"))
o:value(1, translate("Standby Server"))
o.rmempty = false
return m

View File

@ -0,0 +1,139 @@
local o = require "luci.dispatcher"
local fs = require "nixio.fs"
local sys = require "luci.sys"
local ipkg = require("luci.model.ipkg")
local uci = require"luci.model.uci".cursor()
local appname = "passwall"
local function is_installed(e) return ipkg.installed(e) end
local function is_finded(e)
return
sys.exec("find /usr/*bin -iname " .. e .. " -type f") ~= "" and true or
false
end
local function has_udp_relay()
return sys.call("lsmod | grep TPROXY >/dev/null") == 0
end
local n = {}
uci:foreach(appname, "servers", function(e)
if e.server_type and e.server and e.remarks then
if e.use_kcp and e.use_kcp == "1" then
n[e[".name"]] = "%s+%s[%s] %s" %
{e.server_type, "Kcptun", e.remarks, e.server}
else
n[e[".name"]] = "%s[%s] %s" %
{e.server_type, e.remarks, e.server}
end
end
end)
local key_table = {}
for key, _ in pairs(n) do table.insert(key_table, key) end
table.sort(key_table)
m = Map(appname)
m:append(Template("passwall/global/status"))
-- [[ Global Settings ]]--
s = m:section(TypedSection, "global", translate("Global Settings"))
s.anonymous = true
s.addremove = false
---- TCP Redir Server
o = s:option(ListValue, "tcp_redir_server", translate("TCP Redir Server"),
translate("For used to surf the Internet."))
o:value("nil", translate("Close"))
for _, key in pairs(key_table) do o:value(key, n[key]) end
---- UDP Redir Server
if has_udp_relay() then
o = s:option(ListValue, "udp_redir_server", translate("UDP Redir Server"),
translate("For Game Mode or DNS resolution and more.") ..
translate("The selected server will not use Kcptun."))
o:value("nil", translate("Close"))
o:value("default", translate("Same as the tcp redir server"))
for _, key in pairs(key_table) do o:value(key, n[key]) end
end
---- Socks5 Proxy Server
o = s:option(ListValue, "socks5_proxy_server", translate("Socks5 Proxy Server"),
translate("The client can use the router's Socks5 proxy"))
o:value("nil", translate("Close"))
for _, key in pairs(key_table) do o:value(key, n[key]) end
---- DNS Forward Mode
o = s:option(ListValue, "dns_mode", translate("DNS Forward Mode"))
o.rmempty = false
o:reset_values()
if is_installed("ChinaDNS") or is_finded("chinadns") then
o:value("chinadns", "ChinaDNS")
end
if (is_installed("dns2socks") or is_finded("dns2socks")) and
(is_finded("ss-local") or is_finded("ssr-local")) then
o:value("dns2socks",
"dns2socks " .. translate("Only SS/R servers are supported"))
end
if is_installed("pcap-dnsproxy") or is_finded("Pcap_DNSProxy") then
o:value("Pcap_DNSProxy", "Pcap_DNSProxy")
end
if is_installed("pdnsd") or is_installed("pdnsd-alt") or is_finded("pdnsd") then
o:value("pdnsd", "pdnsd")
end
o:value("local_7913", translate("Use local port 7913 as DNS"))
---- upstreamm DNS Server for ChinaDNS
o = s:option(ListValue, "up_chinadns_mode",
translate("upstreamm DNS Server for ChinaDNS"), translate(
"Domestic DNS server 1 in advanced Settings is used as domestic DNS by default"))
o.default = "OpenDNS_1"
o:depends("dns_mode", "chinadns")
if is_installed("dnsproxy") or is_finded("dnsproxy") then
o:value("dnsproxy", "dnsproxy")
end
if is_installed("dns-forwarder") or is_finded("dns-forwarder") then
o:value("dns-forwarder", "dns-forwarder")
end
o:value("OpenDNS_1", "OpenDNS_1")
o:value("OpenDNS_2", "OpenDNS_2")
o:value("custom", translate("custom"))
---- upstreamm DNS Server
o = s:option(Value, "up_chinadns_custom", translate("DNS Server"), translate(
"example: 114.114.114.114,208.67.222.222:443,8.8.8.8<br>Need at least one,Other DNS services can be used as upstream, such as smartdns."))
o.default = "114.114.114.114,208.67.222.222:5353"
o:depends("up_chinadns_mode", "custom")
---- Default Proxy Mode
o = s:option(ListValue, "proxy_mode",
translate("Default") .. translate("Proxy Mode"))
o.default = "gfwlist"
o.rmempty = false
o:value("disable", translate("No Proxy"))
o:value("global", translate("Global Proxy"))
o:value("gfwlist", translate("GFW List"))
o:value("chnroute", translate("China WhiteList"))
o:value("gamemode", translate("Game Mode"))
o:value("returnhome", translate("Return Home"))
---- Localhost Proxy Mode
o = s:option(ListValue, "localhost_proxy_mode",
translate("Localhost") .. translate("Proxy Mode"), translate(
"The server client can also use this rule to scientifically surf the Internet"))
o:value("default", translate("Default"))
-- o:value("global", translate("Global Proxy")..""..translate("Danger").."")
o:value("gfwlist", translate("GFW List"))
-- o:value("chnroute", translate("China WhiteList"))
o.default = "default"
o.rmempty = false
--[[
local apply = luci.http.formvalue("cbi.apply")
if apply then
os.execute("/etc/init.d/passwall restart")
end
--]]
return m

View File

@ -0,0 +1,3 @@
m = Map("passwall")
m:append(Template("passwall/log/log"))
return m

View File

@ -0,0 +1,227 @@
local fs = require "nixio.fs"
local net = require"luci.model.network".init()
local ifaces = require"luci.sys".net:devices()
m = Map("passwall")
-- [[ Delay Settings ]]--
s = m:section(TypedSection, "global_delay", translate("Delay Settings"))
s.anonymous = true
s.addremove = false
---- Delay Start
o = s:option(Value, "start_delay", translate("Delay Start"),
translate("Units:seconds"))
o.default = "0"
o.rmempty = true
---- Open and close Daemon
o = s:option(Flag, "start_daemon", translate("Open and close Daemon"))
o.default = 1
o.rmempty = false
---- Open and close automatically
o = s:option(Flag, "auto_on", translate("Open and close automatically"))
o.default = 0
o.rmempty = false
---- Automatically turn off time
o = s:option(ListValue, "time_off", translate("Automatically turn off time"))
o.default = nil
o:depends("auto_on", "1")
o:value(nil, translate("Disable"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
---- Automatically turn on time
o = s:option(ListValue, "time_on", translate("Automatically turn on time"))
o.default = nil
o:depends("auto_on", "1")
o:value(nil, translate("Disable"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
---- Automatically restart time
o = s:option(ListValue, "time_restart", translate("Automatically restart time"))
o.default = nil
o:depends("auto_on", "1")
o:value(nil, translate("Disable"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
-- [[ DNS Settings ]]--
s = m:section(TypedSection, "global_dns", translate("DNS Settings"))
s.anonymous = true
s.addremove = false
---- DNS Forward Address
o = s:option(Value, "dns_forward", translate("DNS Forward Address"))
o.rmempty = false
o.default = "8.8.4.4:53"
o:value("8.8.4.4:53", "8.8.4.4:53(Google DNS1)")
o:value("8.8.8.8:53", "8.8.8.8:53(Google DNS2)")
o:value("208.67.222.222:53", "208.67.222.222:53(OpenDNS DNS1_53)")
o:value("208.67.222.222:5353", "208.67.222.222:5353(OpenDNS DNS1_5353)")
o:value("208.67.222.222:443", "208.67.222.222:443(OpenDNS DNS1_443)")
o:value("208.67.220.220:53", "208.67.220.220:53(OpenDNS DNS2_53)")
o:value("208.67.220.220:5353", "208.67.220.220:5353(OpenDNS DNS2_5353)")
o:value("208.67.220.220:443", "208.67.220.220:443(OpenDNS DNS2_443)")
---- Mainland DNS Sever 1
o = s:option(Value, "dns_1", translate("Mainland DNS Sever 1"))
o.rmempty = false
o.default = "dnsbyisp"
o:value("dnsbyisp", translate("dnsbyisp"))
o:value("223.5.5.5", "223.5.5.5(" .. translate("Ali") .. "DNS1)")
o:value("223.6.6.6", "223.6.6.6(" .. translate("Ali") .. "DNS2)")
o:value("114.114.114.114", "114.114.114.114(114DNS1)")
o:value("114.114.115.115", "114.114.115.115(114DNS2)")
o:value("119.29.29.29", "119.29.29.29(DNSPOD DNS1)")
o:value("182.254.116.116", "182.254.116.116(DNSPOD DNS2)")
o:value("1.2.4.8", "1.2.4.8(CNNIC DNS1)")
o:value("210.2.4.8", "210.2.4.8(CNNIC DNS2)")
o:value("180.76.76.76", "180.76.76.76(" .. translate("Baidu") .. "DNS)")
---- Mainland DNS Sever 2
o = s:option(Value, "dns_2", translate("Mainland DNS Sever 2"))
o.rmempty = false
o.default = "223.5.5.5"
o:value("dnsbyisp", translate("dnsbyisp"))
o:value("223.5.5.5", "223.5.5.5(" .. translate("Ali") .. "DNS1)")
o:value("223.6.6.6", "223.6.6.6(" .. translate("Ali") .. "DNS2)")
o:value("114.114.114.114", "114.114.114.114(114DNS1)")
o:value("114.114.115.115", "114.114.115.115(114DNS2)")
o:value("119.29.29.29", "119.29.29.29(DNSPOD DNS1)")
o:value("182.254.116.116", "182.254.116.116(DNSPOD DNS2)")
o:value("1.2.4.8", "1.2.4.8(CNNIC DNS1)")
o:value("210.2.4.8", "210.2.4.8(CNNIC DNS2)")
o:value("180.76.76.76", "180.76.76.76(" .. translate("Baidu") .. "DNS)")
---- DNS Export Of Multi WAN
o = s:option(ListValue, "dns_port", translate("DNS Export Of Multi WAN"))
o.rmempty = false
o.default = 0
o:value(0, translate("Auto"))
for _, iface in ipairs(ifaces) do
if (iface:match("^pppoe*")) then
local nets = net:get_interface(iface)
nets = nets and nets:get_networks() or {}
for k, v in pairs(nets) do nets[k] = nets[k].sid end
nets = table.concat(nets, ",")
o:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface))
end
end
---- Designated Export for Client
o = s:option(ListValue, "wan_port", translate("Designated Export for Client"))
o.default = 0
o.rmempty = false
o:value(0, translate("Auto"))
for _, iface in ipairs(ifaces) do
if (iface:match("^pppoe*")) then
local nets = net:get_interface(iface)
nets = nets and nets:get_networks() or {}
for k, v in pairs(nets) do nets[k] = nets[k].sid end
nets = table.concat(nets, ",")
o:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface))
end
end
---- DNS Hijack
o = s:option(Flag, "dns_53", translate("DNS Hijack"))
o.default = 0
o.rmempty = false
-- [[ Forwarding Settings ]]--
s = m:section(TypedSection, "global_forwarding",
translate("Forwarding Settings"))
s.anonymous = true
s.addremove = false
---- TCP Redir Ports
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
o.default = "80,443"
o:value("1:65535", translate("All"))
o:value("80,443", "80,443")
o:value("80:", "80 " .. translate("or more"))
o:value(":443", "443 " .. translate("or less"))
---- UDP Redir Ports
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
o.default = "1:65535"
o:value("1:65535", translate("All"))
o:value("53", "53")
---- Multi SS/SSR Process Option
o = s:option(Value, "process", translate("Multi Process Option"),
translate("you can start SS/SSR with multiple process"))
o.default = "0"
o.rmempty = false
o:value("0", translate("Auto"))
o:value("1", translate("1 Process"))
o:value("2", "2 " .. translate("Process"))
o:value("3", "3 " .. translate("Process"))
o:value("4", "4 " .. translate("Process"))
-- [[ Proxy Settings ]]--
s = m:section(TypedSection, "global_proxy", translate("Proxy Settings"))
s.anonymous = true
s.addremove = false
---- TCP Redir Port
o = s:option(Value, "tcp_redir_port", translate("TCP Redir Port"))
o.datatype = "port"
o.default = 1031
o.rmempty = true
---- UDP Redir Port
o = s:option(Value, "udp_redir_port", translate("UDP Redir Port"))
o.datatype = "port"
o.default = 1032
o.rmempty = true
---- Socks5 Proxy Port
o = s:option(Value, "socks5_port", translate("Socks5 Proxy Port"))
o.datatype = "port"
o.default = 1033
---- Kcptun Port
o = s:option(Value, "kcptun_port", translate("Kcptun Port"))
o.datatype = "port"
o.default = 11183
o.rmempty = true
---- Proxy IPv6
o = s:option(Flag, "proxy_ipv6", translate("Proxy IPv6"),
translate("The IPv6 traffic can be proxyed when selected"))
o.default = 0
-- [[ Other Settings ]]--
s = m:section(TypedSection, "global_other", translate("Other Settings"))
s.anonymous = true
s.addremove = false
---- Hide Menu
o = s:option(Button, "hide", translate("Hide Menu"), translate(
"After the hidden to the display, type in the address bar enter the admin/vpn/passwall/show, such as: http://192.168.1.1/cgi-bin/luci/admin/vpn/passwall/show"))
o.inputstyle = "remove"
function o.write(e, e)
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall",
"hide"))
end
-- [[ Custom Dnsmasq Settings ]]--
--[[
s = m:section(TypedSection, "global", translate("Custom Dnsmasq"))
s.anonymous = true
local e = "/usr/share/passwall/dnsmasq.d/user.conf"
o = s:option(TextValue, "userconf")
o.description = translate("Setting a parameter error will cause dnsmasq fail to start.")
o.rows = 15
o.wrap = "off"
o.cfgvalue = function(a, a)
return fs.readfile(e)or""
end
o.write = function(o, o, a)
fs.writefile(e, a:gsub("\r\n", "\n"))
end
]] --
return m

View File

@ -0,0 +1,123 @@
local e = require "nixio.fs"
local e = require "luci.sys"
-- local t = luci.sys.exec("cat /usr/share/passwall/dnsmasq.d/gfwlist.conf|grep -c ipset")
m = Map("passwall")
-- [[ Rule Settings ]]--
s = m:section(TypedSection, "global_rules", translate("Rule status"))
s.anonymous = true
s:append(Template("passwall/rule/rule_version"))
---- Auto Update
o = s:option(Flag, "auto_update", translate("Enable auto update rules"))
o.default = 0
o.rmempty = false
---- Week Update
o = s:option(ListValue, "week_update", translate("Week update rules"))
o:value(7, translate("Every day"))
for e = 1, 6 do o:value(e, translate("Week") .. e) end
o:value(0, translate("Week") .. translate("day"))
o.default = 0
o:depends("auto_update", 1)
---- Time Update
o = s:option(ListValue, "time_update", translate("Day update rules"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
o.default = 0
o:depends("auto_update", 1)
-- [[ V2ray Settings ]]--
s = m:section(TypedSection, "global_app", translate("App Update"),
translate("Please confirm that your firmware supports FPU."))
s.anonymous = true
s:append(Template("passwall/rule/v2ray_version"))
s:append(Template("passwall/rule/kcptun_version"))
s:append(Template("passwall/rule/brook_version"))
---- V2ray client path
o = s:option(Value, "v2ray_client_file", translate("V2ray client path"),
translate(
"if you want to run from memory, change the path, such as /tmp/v2ray/, Then save the application and update it manually."))
o.default = "/usr/bin/v2ray/"
o.rmempty = false
---- Kcptun client path
o = s:option(Value, "kcptun_client_file", translate("Kcptun client path"),
translate(
"if you want to run from memory, change the path, such as /tmp/kcptun-client, Then save the application and update it manually."))
o.default = "/usr/bin/kcptun-client"
o.rmempty = false
--[[
o = s:option(Button, "_check_kcptun", translate("Manually update"), translate("Make sure there is enough space to install Kcptun"))
o.template = "passwall/kcptun"
o.inputstyle = "apply"
o.btnclick = "onBtnClick_kcptun(this);"
o.id = "_kcptun-check_btn"]] --
---- Brook client path
o = s:option(Value, "brook_client_file", translate("Brook client path"),
translate(
"if you want to run from memory, change the path, such as /tmp/brook, Then save the application and update it manually."))
o.default = "/usr/bin/brook"
o.rmempty = false
-- [[ Subscribe Settings ]]--
s = m:section(TypedSection, "global_subscribe", translate("Server Subscribe"))
s.anonymous = true
---- Subscribe URL
o = s:option(DynamicList, "baseurl_ssr", translate("SSR Subscribe URL"),
translate(
"Servers unsubscribed will be deleted in next update; Please summit the Subscribe URL first before manually update."))
o = s:option(DynamicList, "baseurl_v2ray", translate("V2ray Subscribe URL"),
translate(
"Servers unsubscribed will be deleted in next update; Please summit the Subscribe URL first before manually update."))
---- Subscribe Manually update
o = s:option(Button, "_update", translate("Manually update"))
o.inputstyle = "apply"
function o.write(e, e)
luci.sys
.call("nohup /usr/share/passwall/subscription.sh > /dev/null 2>&1 &")
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall",
"log"))
end
---- Subscribe Delete All
o = s:option(Button, "_stop", translate("Delete All Subscribe"))
o.inputstyle = "remove"
function o.write(e, e)
luci.sys.call(
"nohup /usr/share/passwall/subscription.sh stop > /dev/null 2>&1 &")
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall",
"log"))
end
---- Subscribe via proxy
o = s:option(Flag, "subscribe_by_ss", translate("Subscribe via proxy"))
o.default = 0
o.rmempty = false
---- Enable auto update subscribe
o = s:option(Flag, "auto_update_subscribe",
translate("Enable auto update subscribe"))
o.default = 0
o.rmempty = false
---- Week update rules
o = s:option(ListValue, "week_update_subscribe", translate("Week update rules"))
o:value(7, translate("Every day"))
for e = 1, 6 do o:value(e, translate("Week") .. e) end
o:value(0, translate("Week") .. translate("day"))
o.default = 0
o:depends("auto_update_subscribe", 1)
---- Day update rules
o = s:option(ListValue, "time_update_subscribe", translate("Day update rules"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
o.default = 0
o:depends("auto_update_subscribe", 1)
return m

View File

@ -0,0 +1,83 @@
local fs = require "nixio.fs"
m = Map("passwall")
-- [[ Rule List Settings ]]--
s = m:section(TypedSection, "global", translate("Set Blacklist And Whitelist"))
s.anonymous = true
---- Whitelist Hosts
local t = "/usr/share/passwall/rule/whitelist_host"
o = s:option(TextValue, "whitelist_host", translate("Whitelist Hosts"))
o.description = translate(
"Join the white list of domain names will not go agent.")
o.rows = 5
o.wrap = "off"
o.cfgvalue = function(a, a) return fs.readfile(t) or "" end
o.write = function(o, o, a)
fs.writefile("/tmp/whitelist_host", a:gsub("\r\n", "\n"))
if (luci.sys.call(
"cmp -s /tmp/whitelist_host /usr/share/passwall/rule/whitelist_host") ==
1) then
fs.writefile(t, a:gsub("\r\n", "\n"))
luci.sys.call("rm -f /tmp/dnsmasq.d/whitelist_host.conf >/dev/null")
end
fs.remove("/tmp/whitelist_host")
end
---- Whitelist IP
local t = "/usr/share/passwall/rule/whitelist_ip"
o = s:option(TextValue, "whitelist_ip", translate("Whitelist IP"))
o.description = translate(
"These had been joined ip addresses will not use proxy.Please input the ip address or ip address segment,every line can input only one ip address.For example,112.123.134.145/24 or 112.123.134.145.")
o.rows = 5
o.wrap = "off"
o.cfgvalue = function(a, a) return fs.readfile(t) or "" end
o.write = function(o, o, a) fs.writefile(t, a:gsub("\r\n", "\n")) end
---- Blacklist Hosts
local t = "/usr/share/passwall/rule/blacklist_host"
o = s:option(TextValue, "blacklist_host", translate("Blacklist Hosts"))
o.description = translate(
"These had been joined websites will use proxy.Please input the domain names of websites,every line can input only one website domain.For example,google.com.")
o.rows = 5
o.wrap = "off"
o.cfgvalue = function(a, a) return fs.readfile(t) or "" end
o.write = function(o, o, a)
fs.writefile("/tmp/blacklist_host", a:gsub("\r\n", "\n"))
if (luci.sys.call(
"cmp -s /tmp/blacklist_host /usr/share/passwall/rule/blacklist_host") ==
1) then
fs.writefile(t, a:gsub("\r\n", "\n"))
luci.sys.call("rm -f /tmp/dnsmasq.d/blacklist_host.conf >/dev/null")
end
fs.remove("/tmp/blacklist_host")
end
---- Blacklist IP
local t = "/usr/share/passwall/rule/blacklist_ip"
o = s:option(TextValue, "blacklist_ip", translate("Blacklist IP"))
o.description = translate(
"These had been joined ip addresses will use proxy.Please input the ip address or ip address segment,every line can input only one ip address.For example,112.123.134.145/24 or 112.123.134.145.")
o.rows = 5
o.wrap = "off"
o.cfgvalue = function(a, a) return fs.readfile(t) or "" end
o.write = function(o, o, a) fs.writefile(t, a:gsub("\r\n", "\n")) end
---- Router Hosts
local t = "/usr/share/passwall/rule/router"
o = s:option(TextValue, "routerlist", translate("Router Hosts"))
o.description = translate(
"These had been joined websites will use proxy,but only Router model.Please input the domain names of websites,every line can input only one website domain.For example,google.com.")
o.rows = 5
o.wrap = "off"
o.cfgvalue = function(a, a) return fs.readfile(t) or "" end
o.write = function(o, o, a)
fs.writefile("/tmp/router", a:gsub("\r\n", "\n"))
if (luci.sys.call("cmp -s /tmp/router /usr/share/passwall/rule/router") == 1) then
fs.writefile(t, a:gsub("\r\n", "\n"))
luci.sys.call("rm -f /tmp/dnsmasq.d/router.conf >/dev/null")
end
fs.remove("/tmp/router")
end
return m

View File

@ -0,0 +1,92 @@
local d = require "luci.dispatcher"
local fs = require "nixio.fs"
local sys = require "luci.sys"
local uci = require "luci.model.uci".cursor()
local appname = "passwall"
m = Map(appname)
-- [[ Other Settings ]]--
s = m:section(TypedSection, "global_other")
s.anonymous = true
---- Auto Ping
o = s:option(Flag, "auto_ping", translate("Auto Ping"),
translate("This will automatically ping the server for latency"))
o.default = 0
-- [[ Add the server via the link ]]--
s:append(Template("passwall/server_list/link_add_server"))
-- [[ Servers List ]]--
s = m:section(TypedSection, "servers")
s.anonymous = true
s.sortable = true
s.addremove = true
s.template = "cbi/tblsection"
s.extedit = d.build_url("admin", "vpn", "passwall", "serverconfig", "%s")
function s.create(e, t)
local e = TypedSection.create(e, t)
luci.http.redirect(
d.build_url("admin", "vpn", "passwall", "serverconfig", e))
end
function s.remove(t, a)
s.map.proceed = true
s.map:del(a)
luci.http.redirect(d.build_url("admin", "vpn", "passwall", "server_list"))
end
---- Node Remarks
o = s:option(DummyValue, "remarks", translate("Node Remarks"))
o.width = "20%"
---- Server Type
o = s:option(DummyValue, "server_type", translate("Server Type"))
o.width = "10%"
---- Server Address
o = s:option(DummyValue, "server", translate("Server Address"))
o.width = "15%"
---- Server Port
o = s:option(DummyValue, "server_port", translate("Server Port"))
o.width = "10%"
---- Encrypt Method
--[[o = s:option(DummyValue, "encrypt_method", translate("Encrypt Method"))
o.width="15%"
o.cfgvalue=function(t, n)
local str=""
local type = m.uci:get(appname, n, "server_type") or ""
if type == "SSR" then
return m.uci:get(appname, n, "ssr_encrypt_method")
elseif type == "SS" then
return m.uci:get(appname, n, "ss_encrypt_method")
elseif type == "V2ray" then
return m.uci:get(appname, n, "v2ray_security")
end
return str
end--]]
---- Ping
o = s:option(DummyValue, "server", translate("Ping"))
if uci:get(appname, "@global_other[0]", "auto_ping") == "0" then
o.template = "passwall/server_list/ping"
else
o.template = "passwall/server_list/auto_ping"
end
o.width = "10%"
---- Apply
o = s:option(DummyValue, "apply", translate("Apply"))
o.width = "15%"
o.template = "passwall/server_list/apply"
m:append(Template("passwall/server_list/server_list"))
if luci.http.formvalue("cbi.apply") then
luci.http.redirect(d.build_url("admin", "vpn", "passwall", "server_list"))
end
return m

View File

@ -0,0 +1,290 @@
local d = require "luci.dispatcher"
local ipkg = require("luci.model.ipkg")
local appname = "passwall"
local function is_finded(e)
return luci.sys.exec("find /usr/*bin -iname " .. e .. " -type f") ~= "" and
true or false
end
local function is_installed(e) return ipkg.installed(e) end
local ss_encrypt_method = {
"rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb",
"aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb",
"camellia-192-cfb", "camellia-256-cfb", "salsa20", "chacha20",
"chacha20-ietf", -- aead
"aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305",
"xchacha20-ietf-poly1305"
}
local ssr_encrypt_method = {
"none", "table", "rc2-cfb", "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", "seed-cfb", "salsa20", "chacha20",
"chacha20-ietf"
}
local ssr_protocol = {
"origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple",
"auth_sha1", "auth_sha1_v2", "auth_sha1_v4", "auth_aes128_md5",
"auth_aes128_sha1", "auth_chain_a", "auth_chain_b", "auth_chain_c",
"auth_chain_d", "auth_chain_e", "auth_chain_f"
}
local ssr_obfs = {
"plain", "http_simple", "http_post", "random_head", "tls_simple",
"tls1.0_session_auth", "tls1.2_ticket_auth"
}
local v2ray_security = {"none", "auto", "aes-128-gcm", "chacha20-poly1305"}
local v2ray_header_type = {
"none", "srtp", "utp", "wechat-video", "dtls", "wireguard"
}
m = Map(appname, translate("ShadowSocks Server Config"),
translate("TCP quick open server does not support do not open.") ..
translate("HAProxy cannot be used with KCP."))
m.redirect = d.build_url("admin", "vpn", "passwall")
s = m:section(NamedSection, arg[1], "servers", "")
s.addremove = false
s.dynamic = false
o = s:option(Value, "remarks", translate("Node Remarks"))
o.default = translate("Node Remarks")
o.rmempty = false
serverType = s:option(ListValue, "server_type", translate("Server Type"))
if is_finded("ss-redir") then
serverType:value("SS", translate("Shadowsocks Server"))
end
if is_finded("ssr-redir") then
serverType:value("SSR", translate("ShadowsocksR Server"))
end
if is_installed("v2ray") then
serverType:value("V2ray", translate("V2ray Server"))
end
if is_installed("brook") or is_finded("brook") then
serverType:value("Brook", translate("Brook Server"))
end
o = s:option(ListValue, "v2ray_protocol", translate("V2ray Protocol"))
o:value("vmess", translate("Vmess"))
o:depends("server_type", "V2ray")
o.rmempty = false
o = s:option(Value, "server", translate("Server Address (Support Domain Name)"))
o.rmempty = false
o = s:option(Flag, "use_ipv6", translate("Use IPv6"))
o.default = 0
o = s:option(Value, "server_port", translate("Server Port"))
o.datatype = "port"
o.rmempty = false
o = s:option(Value, "password", translate("Password"))
o.password = true
o.rmempty = false
o:depends("server_type", "SS")
o:depends("server_type", "SSR")
o:depends("server_type", "Brook")
o = s:option(ListValue, "ss_encrypt_method", translate("Encrypt Method"))
for a, t in ipairs(ss_encrypt_method) do o:value(t) end
o:depends("server_type", "SS")
o = s:option(ListValue, "ssr_encrypt_method", translate("Encrypt Method"))
for a, t in ipairs(ssr_encrypt_method) do o:value(t) end
o:depends("server_type", "SSR")
o = s:option(ListValue, "v2ray_security", translate("Encrypt Method"))
for a, t in ipairs(v2ray_security) do o:value(t) end
o:depends("server_type", "V2ray")
o = s:option(ListValue, "protocol", translate("Protocol"))
for a, t in ipairs(ssr_protocol) do o:value(t) end
o:depends("server_type", "SSR")
o = s:option(Value, "protocol_param", translate("Protocol_param"))
o:depends("server_type", "SSR")
o = s:option(ListValue, "obfs", translate("Obfs"))
for a, t in ipairs(ssr_obfs) do o:value(t) end
o:depends("server_type", "SSR")
o = s:option(Value, "obfs_param", translate("Obfs_param"))
o:depends("server_type", "SSR")
o = s:option(Value, "timeout", translate("Connection Timeout"))
o.datatype = "uinteger"
o.default = 300
o.rmempty = false
o:depends("server_type", "SS")
o:depends("server_type", "SSR")
o = s:option(ListValue, "fast_open", translate("Fast_open"))
o:value("false")
o:value("true")
o.rmempty = false
o:depends("server_type", "SS")
o:depends("server_type", "SSR")
o = s:option(Flag, "use_kcp", translate("Use Kcptun"),
"<span style='color:red'>" .. translate(
"Please confirm whether the Kcptun is installed. If not, please go to Rule Update download installation.") ..
"</span>")
o.default = 0
o:depends("server_type", "SS")
o:depends("server_type", "SSR")
o:depends("server_type", "Brook")
o = s:option(Value, "kcp_server", translate("Kcptun Server"))
o.placeholder = translate("Default:Current Server")
o:depends("use_kcp", "1")
o = s:option(Flag, "kcp_use_ipv6", translate("Use IPv6"))
o.default = 0
o:depends("use_kcp", "1")
o = s:option(Value, "kcp_port", translate("Kcptun Port"))
o.datatype = "port"
o:depends("use_kcp", "1")
o = s:option(TextValue, "kcp_opts", translate("Kcptun Config"), translate(
"--crypt aes192 --key abc123 --mtu 1350 --sndwnd 128 --rcvwnd 1024 --mode fast"))
o.placeholder =
"--crypt aes192 --key abc123 --mtu 1350 --sndwnd 128 --rcvwnd 1024 --mode fast"
o:depends("use_kcp", "1")
o = s:option(Value, "v2ray_VMess_id", translate("ID"))
o.password = true
o.rmempty = false
o:depends("v2ray_protocol", "vmess")
o = s:option(Value, "v2ray_VMess_alterId", translate("Alter ID"))
o.rmempty = false
o:depends("v2ray_protocol", "vmess")
o = s:option(Value, "v2ray_VMess_level", translate("User Level"))
o.default = 1
o:depends("server_type", "V2ray")
o = s:option(ListValue, "v2ray_stream_security",
translate("Transport Layer Encryption"), translate(
'Whether or not transport layer encryption is enabled, the supported options are "none" for unencrypted (default) and "TLS" for using TLS.'))
o:value("none", "none")
o:value("tls", "tls")
o:depends("server_type", "V2ray")
o = s:option(ListValue, "v2ray_transport", translate("Transport"))
o:value("tcp", "TCP")
o:value("mkcp", "mKCP")
o:value("ws", "WebSocket")
o:value("h2", "HTTP/2")
o:value("ds", "DomainSocket")
o:value("quic", "QUIC")
o:depends("server_type", "V2ray")
-- [[ TCP部分 ]]--
-- TCP伪装
o = s:option(ListValue, "v2ray_tcp_guise", translate("Camouflage Type"))
o:depends("v2ray_transport", "tcp")
o:value("none", "none")
o:value("http", "http")
-- HTTP域名
o = s:option(DynamicList, "v2ray_tcp_guise_http_host", translate("HTTP Host"))
o:depends("v2ray_tcp_guise", "http")
-- HTTP路径
o = s:option(DynamicList, "v2ray_tcp_guise_http_path", translate("HTTP Path"))
o:depends("v2ray_tcp_guise", "http")
-- [[ mKCP部分 ]]--
o = s:option(ListValue, "v2ray_mkcp_guise", translate("Camouflage Type"),
translate(
'<br>none: default, no masquerade, data sent is packets with no characteristics.<br>srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br>utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br>wechat-video: packets disguised as WeChat video calls.<br>dtls: disguised as DTLS 1.2 packet.<br>wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
for a, t in ipairs(v2ray_header_type) do o:value(t) end
o:depends("v2ray_transport", "mkcp")
o = s:option(Value, "v2ray_mkcp_mtu", translate("KCP MTU"))
o:depends("v2ray_transport", "mkcp")
o = s:option(Value, "v2ray_mkcp_tti", translate("KCP TTI"))
o:depends("v2ray_transport", "mkcp")
o =
s:option(Value, "v2ray_mkcp_uplinkCapacity", translate("KCP uplinkCapacity"))
o:depends("v2ray_transport", "mkcp")
o = s:option(Value, "v2ray_mkcp_downlinkCapacity",
translate("KCP downlinkCapacity"))
o:depends("v2ray_transport", "mkcp")
o = s:option(Flag, "v2ray_mkcp_congestion", translate("KCP Congestion"))
o:depends("v2ray_transport", "mkcp")
o =
s:option(Value, "v2ray_mkcp_readBufferSize", translate("KCP readBufferSize"))
o:depends("v2ray_transport", "mkcp")
o = s:option(Value, "v2ray_mkcp_writeBufferSize",
translate("KCP writeBufferSize"))
o:depends("v2ray_transport", "mkcp")
-- [[ WebSocket部分 ]]--
o = s:option(Value, "v2ray_ws_host", translate("WebSocket Host"))
o:depends("v2ray_transport", "ws")
o = s:option(Value, "v2ray_ws_path", translate("WebSocket Path"))
o:depends("v2ray_transport", "ws")
-- [[ HTTP/2部分 ]]--
o = s:option(DynamicList, "v2ray_h2_host", translate("HTTP/2 Host"))
o:depends("v2ray_transport", "h2")
o = s:option(Value, "v2ray_h2_path", translate("HTTP/2 Path"))
o:depends("v2ray_transport", "h2")
-- [[ DomainSocket部分 ]]--
o = s:option(Value, "v2ray_ds_path", "Path", translate(
"A legal file path. This file must not exist before running V2Ray."))
o:depends("v2ray_transport", "ds")
-- [[ QUIC部分 ]]--
o = s:option(ListValue, "v2ray_quic_security", translate("Encrypt Method"))
o:value("none")
o:value("aes-128-gcm")
o:value("chacha20-poly1305")
o:depends("v2ray_transport", "quic")
o = s:option(Value, "v2ray_quic_key",
translate("Encrypt Method") .. translate("Key"))
o:depends("v2ray_transport", "quic")
o = s:option(ListValue, "v2ray_quic_guise", translate("Camouflage Type"))
for a, t in ipairs(v2ray_header_type) do o:value(t) end
o:depends("v2ray_transport", "quic")
-- [[ 其它 ]]--
o = s:option(Flag, "v2ray_mux", translate("Mux"))
o:depends("server_type", "V2ray")
o = s:option(Value, "v2ray_mux_concurrency", translate("Mux Concurrency"))
o.default = 8
o:depends("v2ray_mux", "1")
-- o = s:option(Flag, "v2ray_insecure", translate("allowInsecure"))
-- o:depends("server_type", "V2ray")
return m

View File

@ -0,0 +1,191 @@
<%
local dsp = require "luci.dispatcher"
local ipkg = require "luci.model.ipkg"
local function is_finded(e)
local result=luci.sys.exec("find /usr/*bin -iname "..e.." -type f")
if result~="" then
return true
end
return false
end
local function has_udp_relay()
return luci.sys.call("lsmod | grep TPROXY >/dev/null") == 0
end
-%>
<fieldset id="_ss_status_fieldset" class="cbi-section">
<legend>
<%:Running Status%>
</legend>
<fieldset class="cbi-section">
<div class="cbi-value">
<label class="cbi-value-title">TCP
<%:Status%>
</label>
<div class="cbi-value-field" id="_tcp_redir_status">
<%:Collecting data...%>
</div>
</div>
<% if has_udp_relay() then %>
<div class="cbi-value">
<label class="cbi-value-title">UDP
<%:Status%>
</label>
<div class="cbi-value-field" id="_udp_redir_status">
<%:Collecting data...%>
</div>
</div>
<% end %>
<div class="cbi-value">
<label class="cbi-value-title">Socks5
<%:Status%>
</label>
<div class="cbi-value-field" id="_socks5_proxy_status">
<%:Collecting data...%>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">DNS
<%:Status%>
</label>
<div class="cbi-value-field" id="_dns_mode_status">
<%:Collecting data...%>
</div>
</div>
<% if ipkg.installed("haproxy") or is_finded("haproxy*") then %>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Load Balancing%>
</label>
<div class="cbi-value-field" id="_haproxy_status">
<%:Collecting data...%>
</div>
</div>
<% end %>
<% if ipkg.installed("kcptun") or is_finded("kcptun*") then %>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Kcptun Client%>
</label>
<div class="cbi-value-field" id="_kcptun_status">
<%:Collecting data...%>
</div>
</div>
<% end %>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Baidu Connection%>
</label>
<div class="cbi-value-field">
<input type="button" class="cbi-button cbi-input-apply" value="<%:Check%>" onclick="return check_connect(this,'baidu')" />
<font id="_baidu_status"></font>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Google Connection%>
</label>
<div class="cbi-value-field">
<input type="button" class="cbi-button cbi-input-apply" value="<%:Check%>" onclick="return check_connect(this,'google')" />
<font id="_google_status"></font>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Server Check%>
</label>
<div class="cbi-value-field">
<input type="button" class="cbi-button cbi-input-apply" value="<%:Check%>" onclick="return check_port(this)" />
<input id="clear_check_port_btn" type="button" class="cbi-button cbi-button-remove" style="display:none" value="<%:Clear%>" onclick="return clear_check_port(this)" />
<font id="_server_status"></font>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title"></label>
<div class="cbi-value-field">
<input type="button" class="cbi-button cbi-input-reload" value="IP111.cn" onclick="javascript:window.open('http://www.ip111.cn/','target');" />
</div>
</div>
</fieldset>
</fieldset>
<script type="text/javascript">
//<![CDATA[
var tcp_redir_status = document.getElementById('_tcp_redir_status');
var udp_redir_status = document.getElementById('_udp_redir_status');
var socks5_proxy_status = document.getElementById('_socks5_proxy_status');
var dns_mode_status = document.getElementById('_dns_mode_status');
var haproxy_status = document.getElementById('_haproxy_status');
var kcptun_status = document.getElementById('_kcptun_status');
var baidu_status = document.getElementById('_baidu_status');
var google_status = document.getElementById('_google_status');
XHR.poll(3, '<%=dsp.build_url("admin/vpn/passwall/server_status")%>', null,
function(x, json) {
if(x && x.status == 200) {
if(tcp_redir_status)
tcp_redir_status.innerHTML = json.tcp_redir_status ? '<font color=green><%:RUNNING%> ✓</font>' : '<font color=red><%:NOT RUNNING%> X</font>';
if(udp_redir_status)
udp_redir_status.innerHTML = json.udp_redir_status ? '<font color=green><%:RUNNING%> ✓</font>' : '<font color=red><%:NOT RUNNING%> X</font>';
if(socks5_proxy_status)
socks5_proxy_status.innerHTML = json.socks5_proxy_status ? '<font color=green><%:RUNNING%> ✓</font>' : '<font color=red><%:NOT RUNNING%> X</font>';
if(dns_mode_status)
dns_mode_status.innerHTML = json.dns_mode_status ? '<font color=green><%:RUNNING%> ✓</font>' : '<font color=red><%:NOT RUNNING%> X</font>';
if(haproxy_status)
haproxy_status.innerHTML = json.haproxy_status ? '<font color=green><%:RUNNING%> ✓</font>' : '<font color=red><%:NOT RUNNING%> X</font>';
if(kcptun_status)
kcptun_status.innerHTML = json.kcptun_status ? '<font color=green><%:RUNNING%> ✓</font>' : '<font color=red><%:NOT RUNNING%> X</font>';
}
});
function check_connect(btn, type) {
btn.disabled = true;
btn.value = '<%:Check...%>';
XHR.get('<%=dsp.build_url("admin/vpn/passwall/connect_status")%>', {
type: type
},
function(x, rv) {
var s = document.getElementById('_' + type + '_status');
if(s) {
if(rv.status) {
s.setAttribute("color","green");
s.innerHTML = '<%:Working...%> ✓';
}
else {
s.setAttribute("color","red");
s.innerHTML = '<%:Problem detected!%> X';
}
}
btn.disabled = false;
btn.value = '<%:Check%>';
}
);
return false;
}
function check_port(btn) {
btn.disabled = true;
btn.value = '<%:Check...%>';
XHR.get('<%=dsp.build_url("admin/vpn/passwall/check_port")%>', null,
function(x, rv) {
var s = document.getElementById('_server_status');
if(s) {
s.innerHTML = rv.ret;
var clear_btn = document.getElementById('clear_check_port_btn');
clear_btn.style.display = "inline-block";
}
btn.disabled = false;
btn.value = '<%:Check%>';
}
);
return false;
}
function clear_check_port(btn) {
btn.style.display = 'none';
var s = document.getElementById('_server_status');
s.innerHTML = "";
return false;
}
//]]>
</script>

View File

@ -0,0 +1,35 @@
<%
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">
//<![CDATA[
function clearlog(btn) {
XHR.get('<%=dsp.build_url("admin/vpn/passwall/clear_log")%>', null,
function(x, data) {
if(x && x.status == 200) {
var log_textarea = document.getElementById('log_textarea');
log_textarea.innerHTML = "";
log_textarea.scrollTop = log_textarea.scrollHeight;
}
}
);
}
XHR.poll(3, '<%=dsp.build_url("admin/vpn/passwall/get_log")%>', null,
function(x, data) {
if(x && x.status == 200) {
var log_textarea = document.getElementById('log_textarea');
log_textarea.innerHTML = x.responseText;
log_textarea.scrollTop = log_textarea.scrollHeight;
}
}
);
//]]>
</script>
<fieldset class="cbi-section" id="_log_fieldset">
<legend>
<%:These is logs.%>
</legend>
<input class="cbi-button cbi-input-remove" type="button" onclick="clearlog()" value="<%:Clear logs%>">
<textarea id="log_textarea" class="cbi-input-textarea" style="width: 100%;margin-top: 10px;" data-update="change" rows="40" wrap="off" readonly="readonly"></textarea>
</fieldset>

View File

@ -0,0 +1,158 @@
<%
local brook_path = luci.sys.exec("echo -n `uci get passwall.@global_app[0].brook_client_file`")
local brook_version = luci.sys.exec(brook_path.." -v | awk '{print $3}'")
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">
//<![CDATA[
var brookInfo;
var tokenStr = '<%=token%>';
var noUpdateText = '<%:It is the latest version%>';
var updateSuccessText = '<%:Update successful%>';
var clickToUpdateText = '<%:Click to update%>';
var inProgressText = '<%:Updating...%>';
var unexpectedErrorText = '<%:Unexpected error%>';
var updateInProgressNotice = '<%:Updating, are you sure to close?%>';
var downloadingText = '<%:Downloading...%>';
var decompressioningText = '<%:Unpacking...%>';
var movingText = '<%:Moving...%>';
window.onload = function() {
var brookCheckBtn = document.getElementById('_brook-check_btn');
var brookDetailElm = document.getElementById('_brook-check_btn-detail');
};
function addPageNotice_brook() {
window.onbeforeunload = function(e) {
e.returnValue = updateInProgressNotice;
return updateInProgressNotice;
};
}
function removePageNotice_brook() {
window.onbeforeunload = undefined;
}
function onUpdateSuccess_brook(btn) {
alert(updateSuccessText);
if(btn) {
btn.value = updateSuccessText;
btn.placeholder = updateSuccessText;
btn.disabled = true;
}
window.setTimeout(function() {
window.location.reload();
}, 1000);
}
function onRequestError_brook(btn, errorMessage) {
btn.disabled = false;
btn.value = btn.placeholder;
if(errorMessage) {
alert(errorMessage);
}
}
function onBtnClick_brook(btn) {
if(brookInfo === undefined) {
checkUpdate_brook(btn);
} else {
doUpdate_brook(btn);
}
}
function checkUpdate_brook(btn) {
btn.disabled = true;
btn.value = inProgressText;
addPageNotice_brook();
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=dsp.build_url("admin/vpn/passwall/brook_check")%>', {
token: tokenStr,
arch: ''
}, function(x,json) {
removePageNotice_brook();
if(json.code) {
brookInfo = undefined;
onRequestError_brook(btn, json.error);
} else {
if(json.update) {
brookInfo = json;
btn.disabled = false;
btn.value = clickToUpdateText;
btn.placeholder = clickToUpdateText;
if(ckeckDetailElm) {
var urlNode = '';
if(json.version) {
urlNode = '<em style="color:red;">最新版本号:' + json.version + '</em>';
if(json.url && json.url.html) {
urlNode = '<a href="' + json.url.html + '" target="_blank">' + urlNode + '</a>';
}
}
ckeckDetailElm.innerHTML = urlNode;
}
} else {
btn.disabled = true;
btn.value = noUpdateText;
}
}
},300);
}
function doUpdate_brook(btn) {
btn.disabled = true;
btn.value = downloadingText;
addPageNotice_brook();
var brookUpdateUrl = '<%=dsp.build_url("admin/vpn/passwall/brook_update")%>';
// Download file
XHR.get(brookUpdateUrl, {
token: tokenStr,
url: brookInfo ? brookInfo.url.download : ''
}, function(x,json) {
if(json.code) {
removePageNotice_brook();
onRequestError_brook(btn, json.error);
} else {
btn.value = decompressioningText;
// Move file to target dir
XHR.get(brookUpdateUrl, {
token: tokenStr,
task: 'move',
file: json.file
}, function(x,json) {
removePageNotice_brook();
if(json.code) {
onRequestError_brook(btn, json.error);
} else {
onUpdateSuccess_brook(btn);
}
},300)
}
},300)
}
//]]>
</script>
<div class="cbi-value">
<label class="cbi-value-title">Brook
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<img src="/luci-static/resources/cbi/help.gif">
<span><%=brook_version%>】</span>
<input class="cbi-button cbi-input-apply" type="submit" id="_brook-check_btn" onclick="onBtnClick_brook(this);" value="<%:Manually update%>">
<span id="_brook-check_btn-detail"></span>
</div>
</div>
</div>

View File

@ -0,0 +1,174 @@
<%
local kcptun_path = luci.sys.exec("echo -n `uci get passwall.@global_app[0].kcptun_client_file`")
local kcptun_version = luci.sys.exec(kcptun_path.." -v | awk '{print $3}'")
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">
//<![CDATA[
var kcptunInfo;
var tokenStr = '<%=token%>';
var noUpdateText = '<%:It is the latest version%>';
var updateSuccessText = '<%:Update successful%>';
var clickToUpdateText = '<%:Click to update%>';
var inProgressText = '<%:Updating...%>';
var unexpectedErrorText = '<%:Unexpected error%>';
var updateInProgressNotice = '<%:Updating, are you sure to close?%>';
var downloadingText = '<%:Downloading...%>';
var decompressioningText = '<%:Unpacking...%>';
var movingText = '<%:Moving...%>';
window.onload = function() {
var kcptunCheckBtn = document.getElementById('_kcptun-check_btn');
var kcptunDetailElm = document.getElementById('_kcptun-check_btn-detail');
};
function addPageNotice_kcptun() {
window.onbeforeunload = function(e) {
e.returnValue = updateInProgressNotice;
return updateInProgressNotice;
};
}
function removePageNotice_kcptun() {
window.onbeforeunload = undefined;
}
function onUpdateSuccess_kcptun(btn) {
alert(updateSuccessText);
if(btn) {
btn.value = updateSuccessText;
btn.placeholder = updateSuccessText;
btn.disabled = true;
}
window.setTimeout(function() {
window.location.reload();
}, 1000);
}
function onRequestError_kcptun(btn, errorMessage) {
btn.disabled = false;
btn.value = btn.placeholder;
if(errorMessage) {
alert(errorMessage);
}
}
function onBtnClick_kcptun(btn) {
if(kcptunInfo === undefined) {
checkUpdate_kcptun(btn);
} else {
doUpdate_kcptun(btn);
}
}
function checkUpdate_kcptun(btn) {
btn.disabled = true;
btn.value = inProgressText;
addPageNotice_kcptun();
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=dsp.build_url("admin/vpn/passwall/kcptun_check")%>', {
token: tokenStr,
arch: ''
}, function(x,json) {
removePageNotice_kcptun();
if(json.code) {
kcptunInfo = undefined;
onRequestError_kcptun(btn, json.error);
} else {
if(json.update) {
kcptunInfo = json;
btn.disabled = false;
btn.value = clickToUpdateText;
btn.placeholder = clickToUpdateText;
if(ckeckDetailElm) {
var urlNode = '';
if(json.version) {
urlNode = '<em style="color:red;">最新版本号:' + json.version + '</em>';
if(json.url && json.url.html) {
urlNode = '<a href="' + json.url.html + '" target="_blank">' + urlNode + '</a>';
}
}
ckeckDetailElm.innerHTML = urlNode;
}
} else {
btn.disabled = true;
btn.value = noUpdateText;
}
}
},300);
}
function doUpdate_kcptun(btn) {
btn.disabled = true;
btn.value = downloadingText;
addPageNotice_kcptun();
var kcptunUpdateUrl = '<%=dsp.build_url("admin/vpn/passwall/kcptun_update")%>';
// Download file
XHR.get(kcptunUpdateUrl, {
token: tokenStr,
url: kcptunInfo ? kcptunInfo.url.download : ''
}, function(x,json) {
if(json.code) {
removePageNotice_kcptun();
onRequestError_kcptun(btn, json.error);
} else {
btn.value = decompressioningText;
// Extract file
XHR.get(kcptunUpdateUrl, {
token: tokenStr,
task: 'extract',
file: json.file,
subfix: kcptunInfo ? kcptunInfo.type : ''
}, function(x,json) {
if(json.code) {
removePageNotice_kcptun();
onRequestError_kcptun(btn, json.error);
} else {
btn.value = movingText;
// Move file to target dir
XHR.get(kcptunUpdateUrl, {
token: tokenStr,
task: 'move',
file: json.file
}, function(x,json) {
removePageNotice_kcptun();
if(json.code) {
onRequestError_kcptun(btn, json.error);
} else {
onUpdateSuccess_kcptun(btn);
}
},300)
}
},300)
}
},300)
}
//]]>
</script>
<div class="cbi-value">
<label class="cbi-value-title">Kcptun
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<img src="/luci-static/resources/cbi/help.gif">
<span><%=kcptun_version%>】</span>
<input class="cbi-button cbi-input-apply" type="submit" id="_kcptun-check_btn" onclick="onBtnClick_kcptun(this);" value="<%:Manually update%>">
<span id="_kcptun-check_btn-detail"></span>
</div>
</div>
</div>

View File

@ -0,0 +1,115 @@
<%
local appname = "passwall"
local ipkg = require "luci.model.ipkg"
local dsp = require "luci.dispatcher"
local uci = require "luci.model.uci".cursor()
local gfwlist_version = uci:get(appname,"@global_rules[0]","gfwlist_version")
local chnroute_version = uci:get(appname,"@global_rules[0]","chnroute_version")
local Pcap_Routing_version = uci:get(appname,"@global_rules[0]","pcap_Routing_version")
local Pcap_WhiteList_version = uci:get(appname,"@global_rules[0]","pcap_WhiteList_version")
local gfwlist_update = uci:get(appname,"@global_rules[0]","gfwlist_update")=="1" and "checked='checked'" or ""
local chnroute_update = uci:get(appname,"@global_rules[0]","chnroute_update")=="1" and "checked='checked'" or ""
local Pcap_Routing_update = uci:get(appname,"@global_rules[0]","pcap_Routing_update")=="1" and "checked='checked'" or ""
local Pcap_WhiteList_update = uci:get(appname,"@global_rules[0]","pcap_WhiteList_update")=="1" and "checked='checked'" or ""
-%>
<script type="text/javascript">
//<![CDATA[
function update_rules(btn) {
btn.disabled = true;
btn.value = '<%:Updating...%>';
var table = document.getElementById('_rule_fieldset');
var domList = table.getElementsByTagName('input');
var checkBoxList = [];
var len = domList.length;
while(len--) {
var dom = domList[len];  
if(dom.type == 'checkbox' && dom.checked) {  
checkBoxList.push(dom.name);  
}
}
XHR.get('<%=dsp.build_url("admin/vpn/passwall/update_rules")%>', {
update: checkBoxList
},
function(x, data) {
if(x && x.status == 200) {
window.location.href = '<%=dsp.build_url("admin/vpn/passwall/log")%>';
} else {
alert("<%:Error%>");
btn.disabled = false;
btn.value = '<%:Manually update%>';
}
}
);
return false;
}
//]]>
</script>
<fieldset class="cbi-section">
<fieldset class="cbi-section" id="_rule_fieldset">
<div class="cbi-value">
<label class="cbi-value-title">gfwlist
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<img src="/luci-static/resources/cbi/help.gif">
<span><%=gfwlist_version%> 】</span>
<input type="checkbox" name="gfwlist_update" value="1" <%=gfwlist_update%> />
</div>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">chnroute
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<img src="/luci-static/resources/cbi/help.gif">
<span><%=chnroute_version%> 】</span>
<input type="checkbox" name="chnroute_update" value="1" <%=chnroute_update%> />
</div>
</div>
</div>
<% if ipkg.installed("pcap-dnsproxy") then %>
<div class="cbi-value">
<label class="cbi-value-title">Pcap_Routing
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<img src="/luci-static/resources/cbi/help.gif">
<span><%=Pcap_Routing_version%> 】</span>
<input type="checkbox" name="Pcap_Routing_update" value="1" <%=Pcap_Routing_update%> />
</div>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">Pcap_WhiteList
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<img src="/luci-static/resources/cbi/help.gif">
<span><%=Pcap_WhiteList_version%> 】</span>
<input type="checkbox" name="Pcap_WhiteList_update" value="1" <%=Pcap_WhiteList_update%> />
</div>
</div>
</div>
<% end %>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Manually update%>
</label>
<div class="cbi-value-field">
<input class="cbi-button cbi-input-apply" type="submit" id="update_rules_btn" onclick="update_rules(this)" value="<%:Manually update%>">
</div>
</div>
</fieldset>
</fieldset>

View File

@ -0,0 +1,174 @@
<%
local V2ray_path = luci.sys.exec("echo -n `uci get passwall.@global_app[0].v2ray_client_file`")
local V2ray_version = luci.sys.exec(V2ray_path.."/v2ray -version | awk '{print $2}' | sed -n 1P")
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">
//<![CDATA[
var v2rayInfo;
var tokenStr = '<%=token%>';
var noUpdateText = '<%:It is the latest version%>';
var updateSuccessText = '<%:Update successful%>';
var clickToUpdateText = '<%:Click to update%>';
var inProgressText = '<%:Updating...%>';
var unexpectedErrorText = '<%:Unexpected error%>';
var updateInProgressNotice = '<%:Updating, are you sure to close?%>';
var downloadingText = '<%:Downloading...%>';
var decompressioningText = '<%:Unpacking...%>';
var movingText = '<%:Moving...%>';
window.onload = function() {
var v2rayCheckBtn = document.getElementById('_v2ray-check_btn');
var v2rayDetailElm = document.getElementById('_v2ray-check_btn-detail');
};
function addPageNotice_v2ray() {
window.onbeforeunload = function(e) {
e.returnValue = updateInProgressNotice;
return updateInProgressNotice;
};
}
function removePageNotice_v2ray() {
window.onbeforeunload = undefined;
}
function onUpdateSuccess_v2ray(btn) {
alert(updateSuccessText);
if(btn) {
btn.value = updateSuccessText;
btn.placeholder = updateSuccessText;
btn.disabled = true;
}
window.setTimeout(function() {
window.location.reload();
}, 1000);
}
function onRequestError_v2ray(btn, errorMessage) {
btn.disabled = false;
btn.value = btn.placeholder;
if(errorMessage) {
alert(errorMessage);
}
}
function onBtnClick_v2ray(btn) {
if(v2rayInfo === undefined) {
checkUpdate_v2ray(btn);
} else {
doUpdate_v2ray(btn);
}
}
function checkUpdate_v2ray(btn) {
btn.disabled = true;
btn.value = inProgressText;
addPageNotice_v2ray();
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=dsp.build_url("admin/vpn/passwall/v2ray_check")%>', {
token: tokenStr,
arch: ''
}, function(x,json) {
removePageNotice_v2ray();
if(json.code) {
v2rayInfo = undefined;
onRequestError_v2ray(btn, json.error);
} else {
if(json.update) {
v2rayInfo = json;
btn.disabled = false;
btn.value = clickToUpdateText;
btn.placeholder = clickToUpdateText;
if(ckeckDetailElm) {
var urlNode = '';
if(json.version) {
urlNode = '<em style="color:red;">最新版本号:' + json.version + '</em>';
if(json.url && json.url.html) {
urlNode = '<a href="' + json.url.html + '" target="_blank">' + urlNode + '</a>';
}
}
ckeckDetailElm.innerHTML = urlNode;
}
} else {
btn.disabled = true;
btn.value = noUpdateText;
}
}
},300);
}
function doUpdate_v2ray(btn) {
btn.disabled = true;
btn.value = downloadingText;
addPageNotice_v2ray();
var v2rayUpdateUrl = '<%=dsp.build_url("admin/vpn/passwall/v2ray_update")%>';
// Download file
XHR.get(v2rayUpdateUrl, {
token: tokenStr,
url: v2rayInfo ? v2rayInfo.url.download : ''
}, function(x,json) {
if(json.code) {
removePageNotice_v2ray();
onRequestError_v2ray(btn, json.error);
} else {
btn.value = decompressioningText;
// Extract file
XHR.get(v2rayUpdateUrl, {
token: tokenStr,
task: 'extract',
file: json.file,
subfix: v2rayInfo ? v2rayInfo.type : ''
}, function(x,json) {
if(json.code) {
removePageNotice_v2ray();
onRequestError_v2ray(btn, json.error);
} else {
btn.value = movingText;
// Move file to target dir
XHR.get(v2rayUpdateUrl, {
token: tokenStr,
task: 'move',
file: json.file
}, function(x,json) {
removePageNotice_v2ray();
if(json.code) {
onRequestError_v2ray(btn, json.error);
} else {
onUpdateSuccess_v2ray(btn);
}
},300)
}
},300)
}
},300)
}
//]]>
</script>
<div class="cbi-value">
<label class="cbi-value-title">V2ray
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<img src="/luci-static/resources/cbi/help.gif">
<span><%=V2ray_version%>】</span>
<input class="cbi-button cbi-input-apply" type="submit" id="_v2ray-check_btn" onclick="onBtnClick_v2ray(this);" value="<%:Manually update%>">
<span id="_v2ray-check_btn-detail"></span>
</div>
</div>
</div>

View File

@ -0,0 +1,13 @@
<style>
.apply a:hover{
text-decoration : underline;
}
</style>
<%+cbi/valueheader%>
<span class="apply" hint="<%=self:cfgvalue(section)%>">
<a href="javascript:set_server('tcp','<%=section%>')">TCP</a>
<a href="javascript:set_server('udp','<%=section%>')">UDP</a>
<!-- <a href="javascript:copy_server('<%=section%>')">Copy</a> -->
</span>
<%+cbi/valuefooter%>

View File

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

View File

@ -0,0 +1,99 @@
<%
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
local dsp = require "luci.dispatcher"
-%>
<style>
#div1{
display: none;
width: 30rem;
position: absolute;
left:50%;
top:50%;
transform: translate(-50%, -50%);
padding-top: 30px;
z-index: 99;
text-align: center;
background: white;
box-shadow: darkgrey 10px 10px 30px 5px;
}
</style>
<script type="text/javascript">
//<![CDATA[
function ajax_add_server(type,link) {
if(type && link) {
XHR.get('<%=dsp.build_url("admin/vpn/passwall/link_add_server")%>', {
'type': type,
'link': link
},
function(x, data) {
if(x && x.status == 200) {
window.location.href = '<%=dsp.build_url("admin/vpn/passwall/server_list")%>';
}
else {
alert("<%:Error%>");
}
});
}
}
function open_show_div() {
document.getElementById("div1").style.display="block";
document.getElementById("servers_link").focus();
}
function close_show_div() {
document.getElementById("div1").style.display="none";
}
function add_server() {
var servers_type_dom = document.getElementById("servers_type");
var servers_type_dom_index = servers_type_dom.selectedIndex;
var servers_type = servers_type_dom.options[servers_type_dom_index].value;
var servers_link = document.getElementById("servers_link").value;
if (servers_link.trim() != "") {
ajax_add_server(servers_type,servers_link);
}
else {
alert("<%:Please Enter The Link%>");
document.getElementById("servers_link").focus();
}
}
//]]>
</script>
<div class="cbi-value">
<label class="cbi-value-title"><%:Add Server%></label>
<div class="cbi-value-field">
<input class="cbi-button cbi-button-add" type="button" onclick="open_show_div()" value="<%:Add the server via the link%>">
</div>
</div>
<div id="div1">
<div class="cbi-value" data-index="1" data-depends="[]">
<label class="cbi-value-title"><%:Server Type%></label>
<div class="cbi-value-field">
<select id="servers_type" class="cbi-input-select" size="1">
<option value="SSR" selected="selected">SSR</option>
<option value="V2ray">V2ray</option>
</select>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title"><%:Please Enter The Link%></label>
<div class="cbi-value-field">
<textarea id="servers_link" rows="5" cols="50"></textarea>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title"></label>
<div class="cbi-value-field">
<input class="cbi-button cbi-button-add" type="button" onclick="add_server()" value="<%:Add%>">
<input class="cbi-button cbi-button-remove" type="button" onclick="close_show_div()" value="<%:Close%>">
</div>
</div>
</div>

View File

@ -0,0 +1,11 @@
<style>
.ping a:hover{
text-decoration : underline;
}
</style>
<%+cbi/valueheader%>
<span class="ping">
<a href="javascript:void(0)" onclick="javascript:ping_server('<%=self:cfgvalue(section)%>',this)">Ping</a>
</span>
<%+cbi/valuefooter%>

View File

@ -0,0 +1,41 @@
<%
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">
//<![CDATA[
var auto_ping_value = document.getElementsByClassName('auto_ping_value');
for(var i = 0; i < auto_ping_value.length; i++) {
XHR.get('<%=dsp.build_url("admin/vpn/passwall/auto_ping_server")%>', {
index: i,
domain: auto_ping_value[i].getAttribute("server")
},
function(x, result) {
auto_ping_value[result.index].innerHTML = (result.ping ? result.ping : "--") + " ms";
}
);
}
function set_server(protocol,section) {
if (confirm('<%:Are you sure set to%> '+protocol.toUpperCase()+' <%:the server?%>')==true){
XHR.get('<%=dsp.build_url("admin/vpn/passwall/set_server")%>', { "protocol" : protocol , "section" : section },
function(x, result) {
if(x && x.status == 200) {
window.location.href = '<%=dsp.build_url("admin/vpn/passwall/log")%>'
}
}
);
}
}
function ping_server(server,dom) {
XHR.get('<%=dsp.build_url("admin/vpn/passwall/ping_server")%>', { "server" : server },
function(x, result) {
if(x && x.status == 200) {
dom.outerHTML = result.ping + " ms";
}
}
);
}
//]]>
</script>

View File

@ -0,0 +1,710 @@
msgid "Pass Wall"
msgstr "科学上网"
msgid "Shadowsocks Server"
msgstr "ShadowSocks 服务器"
msgid "ShadowsocksR Server"
msgstr "ShadowSocksR 服务器"
msgid "V2ray Server"
msgstr "V2ray 服务器"
msgid "Brook Server"
msgstr "Brook 服务器"
msgid "Auto"
msgstr "自动"
msgid "RUNNING"
msgstr "运行中"
msgid "NOT RUNNING"
msgstr "未运行"
msgid "Working..."
msgstr "连接正常"
msgid "Problem detected!"
msgstr "连接失败"
msgid "Use IPv6"
msgstr "使用IPv6"
msgid "Parsing IP"
msgstr "域名解析IP"
msgid "Basic Settings"
msgstr "基本设置"
msgid "Server List"
msgstr "服务端列表"
msgid "Other Settings"
msgstr "高级设置"
msgid "Load Balancing"
msgstr "负载均衡"
msgid "Rule Update"
msgstr "自动更新"
msgid "Access control"
msgstr "访问控制"
msgid "Set Blacklist"
msgstr "黑名单设置"
msgid "Set whitelist"
msgstr "白名单设置"
msgid "Watch Logs"
msgstr "查看日志"
msgid "ShadowSocks Server Config"
msgstr "服务器配置"
msgid "Running Status"
msgstr "运行状态"
msgid "Kcptun Client"
msgstr "Kcptun客户端"
msgid "Baidu Connection"
msgstr "百度连接"
msgid "Google Connection"
msgstr "谷歌连接"
msgid "Server Check"
msgstr "服务器检测"
msgid "Check..."
msgstr "检测中..."
msgid "Clear"
msgstr "清除"
msgid "Global Setting"
msgstr "全局配置"
msgid "TCP Redir Server"
msgstr "TCP转发服务器"
msgid "UDP Redir Server"
msgstr "UDP转发服务器"
msgid "Same as the tcp redir server"
msgstr "与TCP转发服务器相同"
msgid "Start the TCP redir"
msgstr "TCP转发"
msgid "Start the UDP redir"
msgstr "UDP转发"
msgid "Start the Socks5 Proxy"
msgstr "Socks5代理"
msgid "The client can use the router's Socks5 proxy"
msgstr "客户端可以使用路由器的Socks5代理"
msgid "Socks5 Proxy Server"
msgstr "Socks5代理服务器"
msgid "For used to surf the Internet."
msgstr "用于科学上网。"
msgid "For Game Mode or DNS resolution and more."
msgstr "用于游戏模式或DNS解析等。"
msgid "The selected server will not use Kcptun."
msgstr "选中的服务器不会使用Kcptun。"
msgid "Use Local 7913 Port"
msgstr "使用本机7913端口"
msgid "upstreamm DNS Server for ChinaDNS"
msgstr "ChinaDNS的上游服务器"
msgid "Domestic DNS server 1 in advanced Settings is used as domestic DNS by default"
msgstr "默认使用高级设置里的国内DNS服务器1作为国内DNS"
msgid "custom"
msgstr "自定义"
msgid "DNS Server"
msgstr "DNS服务器"
msgid "example: 114.114.114.114,208.67.222.222:443,8.8.8.8<br>Need at least one,Other DNS services can be used as upstream, such as smartdns."
msgstr "例114.114.114.114,208.67.222.222:443,8.8.8.8<br>需要至少一个服务器其他DNS服务可以作为上游使用比如smartdns。"
msgid "Only SS/R servers are supported"
msgstr "仅支持SS/R服务器"
msgid "Multi Process Option"
msgstr "多进程并发转发"
msgid "you can start SS/SSR with multiple process"
msgstr "当使用SS/SSR时可使用多个进程并发转发"
msgid "Process"
msgstr "进程"
msgid "1 Process"
msgstr "单进程"
msgid "Proxy Mode"
msgstr "代理模式"
msgid "No Proxy"
msgstr "不代理"
msgid "Global Proxy"
msgstr "全局代理"
msgid "GFW List"
msgstr "GFW名单"
msgid "China WhiteList"
msgstr "大陆白名单"
msgid "Game Mode"
msgstr "游戏模式"
msgid "Return Home"
msgstr "回国模式"
msgid "DNS Forward Mode"
msgstr "DNS转发模式"
msgid "Use local port 7913 as DNS"
msgstr "使用本机7913端口的DNS"
msgid "Localhost"
msgstr "本机"
msgid "Danger"
msgstr "危险"
msgid "Please Enter The Link"
msgstr "请输入链接"
msgid "Add Server"
msgstr "添加服务器"
msgid "Are you sure set to"
msgstr "你确定要设为"
msgid "the server?"
msgstr "服务器吗?"
msgid "The server client can also use this rule to scientifically surf the Internet"
msgstr "本机服务器的客户端也可以使用这个代理模式上网"
msgid "Servers List"
msgstr "服务器列表"
msgid "Node Remarks"
msgstr "节点备注"
msgid "Server Type"
msgstr "类型"
msgid "Server Address"
msgstr "地址"
msgid "Server Address (Support Domain Name)"
msgstr "地址(支持域名)"
msgid "Server Port"
msgstr "端口"
msgid "Encrypt Method"
msgstr "加密"
msgid "Kcptun Switch"
msgstr "Kcptun开关"
msgid "Ping Latency"
msgstr "Ping延迟"
msgid "Ping Value"
msgstr "Ping值"
msgid "Auto Ping"
msgstr "自动Ping"
msgid "This will automatically ping the server for latency"
msgstr "选中后保存应用后刷新即可自动Ping服务器"
msgid "Apply"
msgstr "应用"
msgid "DNS Settings"
msgstr "DNS配置"
msgid "DNS Forward Address"
msgstr "DNS转发地址"
msgid "Mainland DNS Sever 1"
msgstr "国内DNS服务器1"
msgid "Mainland DNS Sever 2"
msgstr "国内DNS服务器2"
msgid "dnsbyisp"
msgstr "运营商DNS(自动分配)"
msgid "Ali"
msgstr "阿里"
msgid "Baidu"
msgstr "百度"
msgid "DNS Export Of Multi WAN"
msgstr "国内DNS指定解析出口"
msgid "Not Specify"
msgstr "不指定"
msgid "DNS Hijack"
msgstr "接管局域网DNS解析"
msgid "Designated Export for Client"
msgstr "客户端指定出口"
msgid "Delay Settings"
msgstr "定时配置"
msgid "Open and close Daemon"
msgstr "启动守护进程"
msgid "Delay Start"
msgstr "开机时延时启动"
msgid "Units:seconds"
msgstr "单位:秒"
msgid "Units:minutes"
msgstr "单位:分钟"
msgid "Open and close automatically"
msgstr "定时自动开关"
msgid "Automatically turn off time"
msgstr "自动关闭时间"
msgid "Automatically turn on time"
msgstr "自动开启时间"
msgid "Automatically restart time"
msgstr "自动重启时间"
msgid "Forwarding Settings"
msgstr "转发配置"
msgid "TCP Redir Ports"
msgstr "TCP代理转发端口"
msgid "UDP Redir Ports"
msgstr "UDP代理转发端口"
msgid "All"
msgstr "所有"
msgid "or more"
msgstr "及以上"
msgid "or less"
msgstr "及以下"
msgid "Default"
msgstr "默认"
msgid "Close"
msgstr "关闭"
msgid "Proxy Settings"
msgstr "代理配置"
msgid "TCP Redir Port"
msgstr "TCP透明代理端口"
msgid "UDP Redir Port"
msgstr "UDP透明代理端口"
msgid "Socks5 Proxy Port"
msgstr "Socks5代理端口"
msgid "Kcptun Port"
msgstr "Kcptun端口"
msgid "Custom Dnsmasq"
msgstr "自定义Dnsmasq设置"
msgid "Setting a parameter error will cause dnsmasq fail to start."
msgstr "参数设置错误将会导致Dnsmasq无法启动。"
msgid "Click here to setting your Load Balancing"
msgstr "点击这里查看负载均衡设置教程。"
msgid "Auto Switch"
msgstr "自动切换"
msgid "When there is no server, an automatic reconnect scheme is used"
msgstr "当没有服务器时,则使用自动重连方案"
msgid "How often is a diagnosis made"
msgstr "检测时间"
msgid "Automatic switching cannot be used when this option is checked"
msgstr "当勾选此选项时,不能使用自动切换"
msgid "List of alternate TCP forwarding servers"
msgstr "备用TCP转发服务器的列表"
msgid "Load Balancing Setting"
msgstr "负载均衡设置"
msgid "Enable or Disable Load Balancing"
msgstr "开启或关闭负载均衡"
msgid "Haproxy port setting"
msgstr "负载均衡服务器端口"
msgid "Admin Status"
msgstr "负载均衡控制台"
msgid "In the browser input routing IP plus port access, such as:192.168.1.1:1188"
msgstr "在浏览器输入路由IP加端口访问192.168.1.1:1188"
msgid "Enable Admin Status"
msgstr "开启控制台"
msgid "Admin Status port setting"
msgstr "控制台端口"
msgid "Admin Status User"
msgstr "登陆用户名"
msgid "Admin Status Password"
msgstr "登陆密码"
msgid "Load Balancing Server Setting"
msgstr "负载均衡服务器设置"
msgid "Add a load balancing server, note reading above requirements."
msgstr "添加负载均衡服务器指定出口功能是为多WAN用户准备的。负载比重范围1-256。多个主服务器可以负载均衡备服务器只有在主服务器离线时才会启用"
msgid "Server weight"
msgstr "负载比重"
msgid "Export Of Multi WAN"
msgstr "多WAN指定出口"
msgid "Server Mode"
msgstr "服务器模式"
msgid "Primary Server"
msgstr "主服务器"
msgid "Standby Server"
msgstr "备服务器"
msgid "Manually update"
msgstr "手动更新"
msgid "Rule status"
msgstr "规则版本"
msgid "Enable auto update rules"
msgstr "开启自动更新规则"
msgid "Week update rules"
msgstr "更新时间星期"
msgid "Day update rules"
msgstr "更新时间小时"
msgid "Every day"
msgstr "每天"
msgid "day"
msgstr "日"
msgid "Week"
msgstr "周"
msgid "oclock"
msgstr "点"
msgid "Update..."
msgstr "更新中"
msgid "It is the latest version"
msgstr "已是最新版本"
msgid "Update successful"
msgstr "更新成功"
msgid "Click to update"
msgstr "点击更新"
msgid "Updating..."
msgstr "更新中"
msgid "Unexpected error"
msgstr "意外错误"
msgid "Updating, are you sure to close?"
msgstr "正在更新,你确认要关闭吗?"
msgid "Downloading..."
msgstr "下载中"
msgid "Unpacking..."
msgstr "解压中"
msgid "Moving..."
msgstr "移动中"
msgid "App Update"
msgstr "更新主程序"
msgid "Please confirm that your firmware supports FPU."
msgstr "请确认你的固件支持FPU。"
msgid "V2ray client path"
msgstr "V2ray客户端路径"
msgid "if you want to run from memory, change the path, such as /tmp/v2ray/, Then save the application and update it manually."
msgstr "如果你希望从内存中运行,请更改路径,例如/tmp/v2ray/,然后保存应用后,再手动更新。"
msgid "Kcptun client path"
msgstr "Kcptun客户端路径"
msgid "if you want to run from memory, change the path, such as /tmp/kcptun-client, Then save the application and update it manually."
msgstr "如果你希望从内存中运行,请更改路径,例如/tmp/kcptun-client然后保存应用后再手动更新。"
msgid "Make sure there is enough space to install Kcptun"
msgstr "确保有足够的空间安装Kcptun"
msgid "Brook client path"
msgstr "Brook客户端路径"
msgid "if you want to run from memory, change the path, such as /tmp/brook, Then save the application and update it manually."
msgstr "如果你希望从内存中运行,请更改路径,例如/tmp/brook然后保存应用后再手动更新。"
msgid "Server Subscribe"
msgstr "服务器订阅"
msgid "SSR Subscribe URL"
msgstr "SSR订阅网址"
msgid "V2ray Subscribe URL"
msgstr "V2ray订阅网址"
msgid "Servers unsubscribed will be deleted in next update; Please summit the Subscribe URL first before manually update."
msgstr "取消订阅的服务器将在下次更新时删除,请先输入订阅网址保存提交之后再更新。"
msgid "Delete All Subscribe"
msgstr "删除所有订阅"
msgid "Subscribe via proxy"
msgstr "通过代理订阅"
msgid "Enable auto update subscribe"
msgstr "开启自动更新订阅"
msgid "Add the server via the link"
msgstr "通过链接添加服务器"
msgid "Add Server"
msgstr "添加服务器"
msgid "Add"
msgstr "添加"
msgid "ACLs"
msgstr "访问控制"
msgid "ACLs is a tools which used to designate specific IP proxy mode"
msgstr "访问控制列表是用于指定特殊IP代理模式的工具。IP、MAC地址可只填写一项。"
msgid "ACL Remarks"
msgstr "主机备注"
msgid "IP Address"
msgstr "内部IP地址"
msgid "MAC Address"
msgstr "MAC地址"
msgid "Set Blacklist And Whitelist"
msgstr "黑白名单"
msgid "Whitelist Hosts"
msgstr "域名白名单"
msgid "Whitelist IP"
msgstr "IP白名单"
msgid "Blacklist Hosts"
msgstr "域名黑名单"
msgid "Blacklist IP"
msgstr "IP黑名单"
msgid "Router Hosts"
msgstr "路由器本机黑名单"
msgid "These had been joined websites will use proxy.Please input the domain names of websites,every line can input only one website domain.For example,google.com."
msgstr "加入的域名将走代理对所有模式有效。输入网站域名google.com每个地址段一行。"
msgid "These had been joined ip addresses will use proxy.Please input the ip address or ip address segment,every line can input only one ip address.For example,112.123.134.145/24 or 112.123.134.145."
msgstr "加入的地址段将走代理对所有模式有效。可输入IP地址或地址段112.123.134.145/24或112.123.134.145,每个地址段一行。"
msgid "Join the white list of domain names will not go agent."
msgstr "加入的域名不走代理通道,对所有模式有效。且优先于黑名单。"
msgid "These had been joined ip addresses will not use proxy.Please input the ip address or ip address segment,every line can input only one ip address.For example,112.123.134.145/24 or 112.123.134.145."
msgstr "加入的地址段不走代理通道对所有模式有效。且优先于黑名单。可输入IP地址或地址段112.123.134.145/24或112.123.134.145,每个地址段一行。"
msgid "These had been joined websites will use proxy,but only Router model.Please input the domain names of websites,every line can input only one website domain.For example,google.com."
msgstr "加入的域名将走代理仅限路由器本机使用。输入网站域名google.com每个地址段一行。"
msgid "These is logs."
msgstr "这里显示的是最近的日志。"
msgid "Clear logs"
msgstr "清空日志"
msgid "TCP quick open server does not support do not open."
msgstr "TCP快速打开服务器不支持不要打开。"
msgid "HAProxy cannot be used with KCP."
msgstr "HAProxy不能和KCP一起使用"
msgid "Password"
msgstr "密码"
msgid "Connection Timeout"
msgstr "连接超时时间"
msgid "Local Port"
msgstr "本地端口"
msgid "Fast_open"
msgstr "TCP快速打开"
msgid "Protocol"
msgstr "协议名称"
msgid "Protocol_param"
msgstr "协议参数"
msgid "Obfs"
msgstr "混淆"
msgid "Obfs_param"
msgstr "混淆参数"
msgid "Plugin Name"
msgstr "插件名称"
msgid "Plugin Arguments"
msgstr "插件参数"
msgid "Proxy IPv6"
msgstr "代理IPv6"
msgid "The IPv6 traffic can be proxyed when selected"
msgstr "选中后可以代理IPv6流量"
msgid "Use Kcptun"
msgstr "使用Kcptun"
msgid "Please confirm whether the Kcptun is installed. If not, please go to Rule Update download installation."
msgstr "请确认KCP是否已安装若没有请到自动更新下载安装。"
msgid "Kcptun Server"
msgstr "Kcptun服务器"
msgid "Default:Current Server"
msgstr "留空则使用当前服务器"
msgid "Kcptun Config"
msgstr "Kcptun参数配置"
msgid "--crypt aes192 --key abc123 --mtu 1350 --sndwnd 128 --rcvwnd 1024 --mode fast"
msgstr "默认Kcptun和SS服务器相同IP,参数中无需配置服务器IP和本地端口需要配置的参数和格式如--crypt aes192 --key abc123 --mtu 1350 --sndwnd 128 --rcvwnd 1024 --mode fast"
msgid "V2ray Protocol"
msgstr "V2ray协议"
msgid "Alter ID"
msgstr "额外ID(alterId)"
msgid "User Level"
msgstr "用户等级(level)"
msgid "Transport"
msgstr "传输方式"
msgid "Camouflage Type"
msgstr "伪装类型"
msgid "Transport Layer Encryption"
msgstr "传输层加密"
msgid "Whether or not transport layer encryption is enabled, the supported options are \"none\" for unencrypted (default) and \"TLS\" for using TLS."
msgstr "是否启入传输层加密,支持的选项有 \"none\" 表示不加密(默认值),\"tls\" 表示使用 TLS。"
msgid "<br>none: default, no masquerade, data sent is packets with no characteristics.<br>srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br>utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br>wechat-video: packets disguised as WeChat video calls.<br>dtls: disguised as DTLS 1.2 packet.<br>wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)"
msgstr "<br>none默认值不进行伪装发送的数据是没有特征的数据包。<br>srtp伪装成 SRTP 数据包,会被识别为视频通话数据(如 FaceTime。<br>utp伪装成 uTP 数据包,会被识别为 BT 下载数据。<br>wechat-video伪装成微信视频通话的数据包。<br>dtls伪装成 DTLS 1.2 数据包。<br>wireguard伪装成 WireGuard 数据包。(并不是真正的 WireGuard 协议)"
msgid "A legal file path. This file must not exist before running V2Ray."
msgstr "一个合法的文件路径。在运行 V2Ray 之前,这个文件必须不存在。"
msgid "Hide Menu"
msgstr "隐藏菜单"
msgid "After the hidden to the display, type in the address bar enter the admin/vpn/passwall/show, such as: http://192.168.1.1/cgi-bin/luci/admin/vpn/passwall/show"
msgstr "当你隐藏后想再次显示在地址栏后面输入admin/vpn/passwall/show例如:http://192.168.1.1/cgi-bin/luci/admin/vpn/passwall/show"
msgid "Can't determine ARCH, or ARCH not supported."
msgstr "无法确认ARCH架构或是不支持。"
msgid "Get remote version info failed."
msgstr "获取远程版本信息失败。"
msgid "New version found, but failed to get new version download url."
msgstr "发现新版本,但未能获得新版本的下载地址。"
msgid "Download url is required."
msgstr "请指定下载地址。"
msgid "File download failed or timed out: %s"
msgstr "文件下载失败或超时:%s"
msgid "File path required."
msgstr "请指定文件路径。"
msgid "Can't find client in file: %s"
msgstr "无法在文件中找到客户端:%s"
msgid "Client file is required."
msgstr "请指定客户端文件。"
msgid "The client file is not suitable for current device."
msgstr "客户端文件不适合当前设备。"
msgid "Can't move new file to path: %s"
msgstr "无法移动新文件到:%s"
msgid "NOT RUNNING"
msgstr "未运行"
msgid "RUNNING"
msgstr "运行中"

Binary file not shown.

View File

@ -0,0 +1,63 @@
config global
option proxy_mode 'chnroute'
option dns_mode 'chinadns'
option up_chinadns_mode 'OpenDNS_1'
option socks5_proxy_server 'nil'
option udp_redir_server 'nil'
option tcp_redir_server 'nil'
option localhost_proxy_mode 'default'
config global_haproxy
option admin_enable '0'
option balancing_enable '0'
config global_delay
option auto_on '0'
option start_daemon '1'
option start_delay '20'
config global_dns
option dns_port '0'
option wan_port '0'
option dns_53 '0'
option dns_forward '8.8.4.4:53'
option dns_1 '114.114.114.114'
option dns_2 '119.29.29.29'
config global_forwarding
option udp_redir_ports '1:65535'
option tcp_redir_ports '1:65535'
option process '1'
config global_proxy
option tcp_redir_port '1031'
option udp_redir_port '1032'
option socks5_port '1033'
option kcptun_port '11183'
option proxy_ipv6 '0'
config global_other
option auto_ping '1'
config global_rules
option gfwlist_update '1'
option chnroute_update '1'
option Pcap_Routing_update '1'
option Pcap_WhiteList_update '1'
option auto_update '0'
option chnroute_version '2019-07-13'
option gfwlist_version '2019-07-16'
config global_app
option v2ray_client_file '/usr/bin/v2ray/'
option kcptun_client_file '/usr/bin/kcptun-client'
option brook_client_file '/usr/bin/brook'
config global_subscribe
option subscribe_by_ss '0'
option auto_update_subscribe '0'
config auto_switch
option testing_time '50'
option enable '0'

View File

@ -0,0 +1,22 @@
#!/bin/sh /etc/rc.common
START=99
STOP=15
boot() {
/usr/share/passwall/app.sh boot
}
start() {
/usr/share/passwall/app.sh start
}
stop() {
/usr/share/passwall/app.sh stop
}
restart() {
stop
sleep 3
start
}

View File

@ -0,0 +1,12 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@passwall[-1]
add ucitrack passwall
set ucitrack.@passwall[-1].init=passwall
commit ucitrack
EOF
killall -9 kcptun haproxy shadowsocks-libev shadowsocksr-libev
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,985 @@
#!/bin/sh
# Copyright (C) 2018-2019 Lienol <lawlienol@gmail.com>
. $IPKG_INSTROOT/lib/functions.sh
. $IPKG_INSTROOT/lib/functions/service.sh
CONFIG=passwall
CONFIG_PATH=/var/etc/$CONFIG
RUN_PID_PATH=$CONFIG_PATH/pid
HAPROXY_FILE=$CONFIG_PATH/haproxy.cfg
CONFIG_TCP_FILE=$CONFIG_PATH/TCP.json
CONFIG_UDP_FILE=$CONFIG_PATH/UDP.json
CONFIG_SOCKS5_FILE=$CONFIG_PATH/SOCKS5.json
LOCK_FILE=$CONFIG_PATH/$CONFIG.lock
LOG_FILE=/var/log/$CONFIG.log
APP_PATH=/usr/share/$CONFIG
APP_PATH_RULE=$APP_PATH/rule
APP_PATH_DNSMASQ=$APP_PATH/dnsmasq.d
TMP_DNSMASQ_PATH=/var/etc/dnsmasq-passwall.d
DNSMASQ_PATH=/etc/dnsmasq.d
lanip=$(uci get network.lan.ipaddr)
get_date(){
echo "$(date "+%Y-%m-%d %H:%M:%S")"
}
echolog()
{
echo -e "$(get_date): $1" >> $LOG_FILE
}
find_bin(){
bin_name=$1
result=`find /usr/*bin -iname "$bin_name" -type f`
if [ -z "$result" ]; then
echo ""
echolog "找不到$bin_name主程序,无法启动!"
else
echo "$result"
fi
}
config_n_get() {
local ret=$(uci get $CONFIG.$1.$2 2>/dev/null)
echo ${ret:=$3}
}
config_t_get() {
local index=0
[ -n "$4" ] && index=$4
local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null)
echo ${ret:=$3}
}
get_host_ip() {
local network_type host isip
network_type=$1
host=$2
isip=""
ip=$host
if [ "$network_type" == "ipv6" ]; then
isip=`echo $host | grep -E "([[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,7}::[a-f0-9]{0,4}(:[a-f0-9]{1,4}){0,7}])"`
if [ -n "$isip" ];then
isip=`echo $host | cut -d '[' -f2 | cut -d ']' -f1`
else
isip=`echo $host | grep -E "([a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,7}::[a-f0-9]{0,4}(:[a-f0-9]{1,4}){0,7})"`
fi
else
isip=`echo $host|grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}"`
fi
if [ -z "$isip" ];then
vpsrip=""
if [ "$use_ipv6" == "1" ];then
vpsrip=`resolveip -6 -t 2 $host|awk 'NR==1{print}'`
[ -z "$vpsrip" ] && vpsrip=`dig @208.67.222.222 $host AAAA 2>/dev/null |grep 'IN'|awk -F ' ' '{print $5}'|grep -E "([a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,7}::[a-f0-9]{0,4}(:[a-f0-9]{1,4}){0,7})"|head -n1`
else
vpsrip=`resolveip -4 -t 2 $host|awk 'NR==1{print}'`
[ -z "$vpsrip" ] && vpsrip=`dig @208.67.222.222 $host 2>/dev/null |grep 'IN'|awk -F ' ' '{print $5}'|grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}"|head -n1`
fi
ip=$vpsrip
fi
echo $ip
}
SOCKS5_PROXY_SERVER=$(config_t_get global socks5_proxy_server nil)
TCP_REDIR_SERVER=$(config_t_get global tcp_redir_server nil)
UDP_REDIR_SERVER=$(config_t_get global udp_redir_server nil)
[ "$UDP_REDIR_SERVER" == "default" ] && UDP_REDIR_SERVER=$TCP_REDIR_SERVER
TCP_REDIR_SERVER_IP=""
UDP_REDIR_SERVER_IP=""
SOCKS5_PROXY_SERVER_IP=""
TCP_REDIR_SERVER_IPV6=""
UDP_REDIR_SERVER_IPV6=""
SOCKS5_PROXY_SERVER_IPV6=""
TCP_REDIR_SERVER_PORT=""
UDP_REDIR_SERVER_PORT=""
SOCKS5_PROXY_SERVER_PORT=""
TCP_REDIR_SERVER_TYPE=""
UDP_REDIR_SERVER_TYPE=""
SOCKS5_PROXY_SERVER_TYPE=""
BROOK_SOCKS5_CMD=""
BROOK_TCP_CMD=""
BROOK_UDP_CMD=""
AUTO_SWITCH_ENABLE=$(config_t_get auto_switch enable 0)
TCP_REDIR_PORTS=$(config_t_get global_forwarding tcp_redir_ports '80,443')
UDP_REDIR_PORTS=$(config_t_get global_forwarding udp_redir_ports '1:65535')
KCPTUN_REDIR_PORT=$(config_t_get global_proxy kcptun_port 11183)
PROXY_MODE=$(config_t_get global proxy_mode gfwlist)
load_config() {
[ "$TCP_REDIR_SERVER" == "nil" -a "$UDP_REDIR_SERVER" == "nil" -a "$SOCKS5_PROXY_SERVER" == "nil" ] && {
echolog "没有选择服务器!"
return 1
}
DNS_MODE=$(config_t_get global dns_mode ChinaDNS)
UP_CHINADNS_MODE=$(config_t_get global up_chinadns_mode OpenDNS_1)
process=1
if [ "$(config_t_get global_forwarding process 0)" = "0" ] ;then
process=$(cat /proc/cpuinfo | grep 'processor' | wc -l)
else
process=$(config_t_get global_forwarding process)
fi
LOCALHOST_PROXY_MODE=$(config_t_get global localhost_proxy_mode default)
DNS_FORWARD=$(config_t_get global_dns dns_forward 208.67.222.222:443)
DNS_FORWARD_IP=$(echo "$DNS_FORWARD" | awk -F':' '{print $1}')
DNS_FORWARD_PORT=$(echo "$DNS_FORWARD" | awk -F':' '{print $2}')
DNS1=$(config_t_get global_dns dns_1)
DNS2=$(config_t_get global_dns dns_2)
TCP_REDIR_PORT=$(config_t_get global_proxy tcp_redir_port 1031)
UDP_REDIR_PORT=$(config_t_get global_proxy udp_redir_port 1032)
SOCKS5_PROXY_PORT=$(config_t_get global_proxy socks5_proxy_port 1033)
PROXY_IPV6=$(config_t_get global_proxy proxy_ipv6 0)
mkdir -p /var/etc $CONFIG_PATH $RUN_PID_PATH
config_load $CONFIG
[ "$TCP_REDIR_SERVER" != "nil" ] && {
TCP_REDIR_SERVER_TYPE=`echo $(config_get $TCP_REDIR_SERVER server_type) | tr 'A-Z' 'a-z'`
gen_config_file $TCP_REDIR_SERVER TCP
echo "$TCP_REDIR_SERVER" > $CONFIG_PATH/tcp_server_id
}
[ "$UDP_REDIR_SERVER" != "nil" ] && {
UDP_REDIR_SERVER_TYPE=`echo $(config_get $UDP_REDIR_SERVER server_type) | tr 'A-Z' 'a-z'`
gen_config_file $UDP_REDIR_SERVER UDP
echo "$UDP_REDIR_SERVER" > $CONFIG_PATH/udp_server_id
}
[ "$SOCKS5_PROXY_SERVER" != "nil" ] && {
SOCKS5_PROXY_SERVER_TYPE=`echo $(config_get $SOCKS5_PROXY_SERVER server_type) | tr 'A-Z' 'a-z'`
gen_config_file $SOCKS5_PROXY_SERVER Socks5
echo "$SOCKS5_PROXY_SERVER" > $CONFIG_PATH/socks5_server_id
}
return 0
}
gen_ss_ssr_config_file() {
local server_type local_port kcptun server configfile
server_type=$1
local_port=$2
kcptun=$3
server=$4
configfile=$5
local server_port encrypt_method
server_port=$(config_get $server server_port)
encrypt_method=$(config_get $server ss_encrypt_method)
[ "$server_type" == "ssr" ] && encrypt_method=$(config_get $server ssr_encrypt_method)
[ "$kcptun" == "1" ] && {
server_ip=127.0.0.1
server_host=127.0.0.1
server_port=$KCPTUN_REDIR_PORT
}
cat <<-EOF >$configfile
{
"server": "$server_host",
"_comment": "$server_ip",
"server_port": $server_port,
"local_address": "0.0.0.0",
"local_port": $local_port,
"password": "$(config_get $server password)",
"timeout": $(config_get $server timeout),
"method": "$encrypt_method",
"fast_open": $(config_get $server fast_open),
"reuse_port": true,
EOF
[ "$1" == "ssr" ] && {
cat <<-EOF >>$configfile
"protocol": "$(config_get $server protocol)",
"protocol_param": "$(config_get $server protocol_param)",
"obfs": "$(config_get $server obfs)",
"obfs_param": "$(config_get $server obfs_param)"
EOF
}
echo -e "}" >> $configfile
}
gen_config_file() {
local server_host server_ip server_port server_type use_ipv6 network_type
server_host=$(config_get $1 server)
use_ipv6=$(config_get $1 use_ipv6)
network_type="ipv4"
[ "$use_ipv6" == "1" ] && network_type="ipv6"
server_ip=$(get_host_ip $network_type $server_host)
server_port=$(config_get $1 server_port)
server_type=`echo $(config_get $1 server_type) | tr 'A-Z' 'a-z'`
echolog "$2服务器IP地址:$server_ip"
if [ "$2" == "Socks5" ]; then
if [ "$network_type" == "ipv6" ];then
SOCKS5_PROXY_SERVER_IPV6=$server_ip
else
SOCKS5_PROXY_SERVER_IP=$server_ip
fi
SOCKS5_PROXY_SERVER_PORT=$server_port
if [ "$server_type" == "ss" -o "$server_type" == "ssr" ]; then
gen_ss_ssr_config_file $server_type $SOCKS5_PROXY_PORT 0 $SOCKS5_PROXY_SERVER $CONFIG_SOCKS5_FILE
fi
if [ "$server_type" == "v2ray" ]; then
lua /usr/lib/lua/luci/model/cbi/passwall/api/gen_v2ray_client_config_file.lua $SOCKS5_PROXY_SERVER nil nil $SOCKS5_PROXY_PORT > $CONFIG_SOCKS5_FILE
fi
if [ "$server_type" == "brook" ]; then
BROOK_SOCKS5_CMD="client -l 0.0.0.0:$SOCKS5_PROXY_PORT -i 0.0.0.0 -s $server_ip:$server_port -p $(config_get $SOCKS5_PROXY_SERVER password)"
fi
fi
if [ "$2" == "UDP" ]; then
if [ "$network_type" == "ipv6" ];then
UDP_REDIR_SERVER_IPV6=$server_ip
else
UDP_REDIR_SERVER_IP=$server_ip
fi
UDP_REDIR_SERVER_PORT=$server_port
if [ "$server_type" == "ss" -o "$server_type" == "ssr" ]; then
gen_ss_ssr_config_file $server_type $UDP_REDIR_PORT 0 $UDP_REDIR_SERVER $CONFIG_UDP_FILE
fi
if [ "$server_type" == "v2ray" ]; then
lua /usr/lib/lua/luci/model/cbi/passwall/api/gen_v2ray_client_config_file.lua $UDP_REDIR_SERVER udp $UDP_REDIR_PORT nil > $CONFIG_UDP_FILE
fi
if [ "$server_type" == "brook" ]; then
BROOK_UDP_CMD="tproxy -l 0.0.0.0:$UDP_REDIR_PORT -s $server_ip:$server_port -p $(config_get $UDP_REDIR_SERVER password)"
fi
fi
if [ "$2" == "TCP" ]; then
if [ "$network_type" == "ipv6" ];then
TCP_REDIR_SERVER_IPV6=$server_ip
else
TCP_REDIR_SERVER_IP=$server_ip
fi
TCP_REDIR_SERVER_PORT=$server_port
if [ "$server_type" == "v2ray" ]; then
lua /usr/lib/lua/luci/model/cbi/passwall/api/gen_v2ray_client_config_file.lua $TCP_REDIR_SERVER tcp $TCP_REDIR_PORT nil > $CONFIG_TCP_FILE
else
local kcptun_use kcptun_server_host kcptun_port kcptun_config
kcptun_use=$(config_get $1 use_kcp)
kcptun_server_host=$(config_get $1 kcp_server)
kcptun_port=$(config_get $1 kcp_port)
kcptun_config=$(config_get $1 kcp_opts)
kcptun_path=""
lbenabled=$(config_t_get global_haproxy balancing_enable 0)
if [ "$kcptun_use" == "1" ] && ([ -z "$kcptun_port" ] || [ -z "$kcptun_config" ]); then
echolog "【检测到启用KCP但未配置KCP参数】跳过~"
fi
if [ "$kcptun_use" == "1" -a -n "$kcptun_port" -a -n "$kcptun_config" -a "$lbenabled" == "1" ];then
echolog "【检测到启用KCP但KCP与负载均衡二者不能同时开启】跳过~"
fi
if [ "$kcptun_use" == "1" ];then
if [ -f "$(config_t_get global_kcptun kcptun_client_file)" ];then
kcptun_path=$(config_t_get global_kcptun kcptun_client_file)
else
temp=$(find_bin kcptun_client)
[ -n "$temp" ] && kcptun_path=$temp
fi
fi
if [ "$kcptun_use" == "1" -a -z "$kcptun_path" ] && ([ -n "$kcptun_port" ] || [ -n "$kcptun_config" ]);then
echolog "【检测到启用KCP但未安装KCP主程序请自行到自动更新下载KCP】跳过~"
fi
if [ "$kcptun_use" == "1" -a -n "$kcptun_port" -a -n "$kcptun_config" -a "$lbenabled" == "0" -a -n "$kcptun_path" ];then
if [ -z "$kcptun_server_host" ]; then
start_kcptun "$kcptun_path" $server_ip $kcptun_port "$kcptun_config"
else
kcptun_use_ipv6=$(config_get $1 kcp_use_ipv6)
network_type="ipv4"
[ "$kcptun_use_ipv6" == "1" ] && network_type="ipv6"
kcptun_server_ip=$(get_host_ip $network_type $kcptun_server_host)
echolog "KCP服务器IP地址:$kcptun_server_ip"
TCP_REDIR_SERVER_IP=$kcptun_server_ip
start_kcptun "$kcptun_path" $kcptun_server_ip $kcptun_port "$kcptun_config"
fi
echolog "运行Kcptun..."
if [ "$server_type" == "ss" -o "$server_type" == "ssr" ]; then
gen_ss_ssr_config_file $server_type $TCP_REDIR_PORT 1 $TCP_REDIR_SERVER $CONFIG_TCP_FILE
fi
if [ "$server_type" == "brook" ]; then
BROOK_TCP_CMD="tproxy -l 0.0.0.0:$TCP_REDIR_PORT -s 127.0.0.1:$KCPTUN_REDIR_PORT -p $(config_get $TCP_REDIR_SERVER password)"
fi
else
if [ "$server_type" == "ss" -o "$server_type" == "ssr" ]; then
gen_ss_ssr_config_file $server_type $TCP_REDIR_PORT 0 $TCP_REDIR_SERVER $CONFIG_TCP_FILE
fi
if [ "$server_type" == "brook" ]; then
BROOK_TCP_CMD="tproxy -l 0.0.0.0:$TCP_REDIR_PORT -s $server_ip:$server_port -p $(config_get $TCP_REDIR_SERVER password)"
fi
fi
fi
fi
return 0
}
start_kcptun() {
kcptun_bin=$1
if [ -z "$kcptun_bin" ]; then
echolog "找不到Kcptun客户端主程序无法启用"
else
$kcptun_bin --log $CONFIG_PATH/kcptun -l 0.0.0.0:$KCPTUN_REDIR_PORT -r $2:$3 $4 >/dev/null 2>&1 &
fi
}
start_tcp_redir() {
if [ "$TCP_REDIR_SERVER" != "nil" ];then
echolog "运行TCP透明代理..."
if [ "$TCP_REDIR_SERVER_TYPE" == "v2ray" ]; then
v2ray_path=$(config_t_get global_v2ray v2ray_client_file)
if [ -f "${v2ray_path}/v2ray" ];then
${v2ray_path}/v2ray -config=$CONFIG_TCP_FILE > /dev/null &
else
v2ray_bin=$(find_bin V2ray)
[ -n "$v2ray_bin" ] && $v2ray_bin -config=$CONFIG_TCP_FILE > /dev/null &
fi
elif [ "$TCP_REDIR_SERVER_TYPE" == "brook" ]; then
brook_bin=$(find_bin Brook)
[ -n "$brook_bin" ] && $brook_bin $BROOK_TCP_CMD &>/dev/null &
else
ss_bin=$(find_bin "$TCP_REDIR_SERVER_TYPE"-redir)
[ -n "$ss_bin" ] && {
for i in $(seq 1 $process)
do
$ss_bin -c $CONFIG_TCP_FILE -f $RUN_PID_PATH/tcp_${TCP_REDIR_SERVER_TYPE}_$i > /dev/null 2>&1 &
done
}
fi
fi
}
start_udp_redir() {
if [ "$UDP_REDIR_SERVER" != "nil" ];then
echolog "运行UDP透明代理..."
if [ "$UDP_REDIR_SERVER_TYPE" == "v2ray" ]; then
v2ray_path=$(config_t_get global_v2ray v2ray_client_file)
if [ -f "${v2ray_path}/v2ray" ];then
${v2ray_path}/v2ray -config=$CONFIG_UDP_FILE > /dev/null &
else
v2ray_bin=$(find_bin V2ray)
[ -n "$v2ray_bin" ] && $v2ray_bin -config=$CONFIG_UDP_FILE > /dev/null &
fi
elif [ "$UDP_REDIR_SERVER_TYPE" == "brook" ]; then
brook_bin=$(find_bin brook)
[ -n "$brook_bin" ] && $brook_bin $BROOK_UDP_CMD &>/dev/null &
else
ss_bin=$(find_bin "$UDP_REDIR_SERVER_TYPE"-redir)
[ -n "$ss_bin" ] && {
$ss_bin -c $CONFIG_UDP_FILE -f $RUN_PID_PATH/udp_${UDP_REDIR_SERVER_TYPE}_1 -U > /dev/null 2>&1 &
}
fi
fi
}
start_socks5_proxy() {
if [ "$SOCKS5_PROXY_SERVER" != "nil" ];then
echolog "运行Socks5代理..."
if [ "$SOCKS5_PROXY_SERVER_TYPE" == "v2ray" ]; then
v2ray_path=$(config_t_get global_v2ray v2ray_client_file)
if [ -f "${v2ray_path}/v2ray" ];then
${v2ray_path}/v2ray -config=$CONFIG_SOCKS5_FILE > /dev/null &
else
v2ray_bin=$(find_bin V2ray)
[ -n "$v2ray_bin" ] && $v2ray_bin -config=$CONFIG_SOCKS5_FILE > /dev/null &
fi
elif [ "$SOCKS5_PROXY_SERVER_TYPE" == "brook" ]; then
brook_bin=$(find_bin brook)
[ -n "$brook_bin" ] && $brook_bin $BROOK_SOCKS5_CMD &>/dev/null &
else
ss_bin=$(find_bin "$SOCKS5_PROXY_SERVER_TYPE"-local)
[ -n "$ss_bin" ] && $ss_bin -c $CONFIG_SOCKS5_FILE -b 0.0.0.0 > /dev/null 2>&1 &
fi
fi
}
clean_log() {
logsnum=$(cat $LOG_FILE 2>/dev/null | wc -l)
if [ "$logsnum" -gt 300 ];then
rm -f $LOG_FILE >/dev/null 2>&1 &
echolog "日志文件过长,清空处理!"
fi
}
set_cru() {
autoupdate=$(config_t_get global_rules auto_update)
weekupdate=$(config_t_get global_rules week_update)
dayupdate=$(config_t_get global_rules time_update)
autoupdatesubscribe=$(config_t_get global_subscribe auto_update_subscribe)
weekupdatesubscribe=$(config_t_get global_subscribe week_update_subscribe)
dayupdatesubscribe=$(config_t_get global_subscribe time_update_subscribe)
if [ "$autoupdate" = "1" ];then
if [ "$weekupdate" = "7" ];then
echo "0 $dayupdate * * * $APP_PATH/rule_update.sh" >> /etc/crontabs/root
echolog "设置自动更新规则在每天 $dayupdate 点。"
else
echo "0 $dayupdate * * $weekupdate $APP_PATH/rule_update.sh" >> /etc/crontabs/root
echolog "设置自动更新规则在星期 $weekupdate$dayupdate 点。"
fi
else
sed -i '/rule_update.sh/d' /etc/crontabs/root >/dev/null 2>&1 &
fi
if [ "$autoupdatesubscribe" = "1" ];then
if [ "$weekupdatesubscribe" = "7" ];then
echo "0 $dayupdatesubscribe * * * $APP_PATH/subscription.sh" >> /etc/crontabs/root
echolog "设置服务器订阅自动更新规则在每天 $dayupdatesubscribe 点。"
else
echo "0 $dayupdatesubscribe * * $weekupdate $APP_PATH/subscription.sh" >> /etc/crontabs/root
echolog "设置服务器订阅自动更新规则在星期 $weekupdate$dayupdatesubscribe 点。"
fi
else
sed -i '/subscription.sh/d' /etc/crontabs/root >/dev/null 2>&1 &
fi
}
start_crontab() {
sed -i '/$CONFIG/d' /etc/crontabs/root >/dev/null 2>&1 &
start_daemon=$(config_t_get global_delay start_daemon)
if [ "$start_daemon" = "1" ];then
echo "*/2 * * * * nohup $APP_PATH/monitor.sh > /dev/null 2>&1" >> /etc/crontabs/root
echolog "已启动守护进程。"
fi
auto_on=$(config_t_get global_delay auto_on)
if [ "$auto_on" = "1" ];then
time_off=$(config_t_get global_delay time_off)
time_on=$(config_t_get global_delay time_on)
time_restart=$(config_t_get global_delay time_restart)
[ -z "$time_off" -o "$time_off" != "nil" ] && {
echo "0 $time_off * * * /etc/init.d/$CONFIG stop" >> /etc/crontabs/root
echolog "设置自动关闭在每天 $time_off 点。"
}
[ -z "$time_on" -o "$time_on" != "nil" ] && {
echo "0 $time_on * * * /etc/init.d/$CONFIG start" >> /etc/crontabs/root
echolog "设置自动开启在每天 $time_on 点。"
}
[ -z "$time_restart" -o "$time_restart" != "nil" ] && {
echo "0 $time_restart * * * /etc/init.d/$CONFIG restart" >> /etc/crontabs/root
echolog "设置自动重启在每天 $time_restart 点。"
}
fi
[ "$AUTO_SWITCH_ENABLE" = "1" ] && {
testing_time=$(config_t_get auto_switch testing_time)
[ -n "$testing_time" ] && {
echo "*/$testing_time * * * * nohup $APP_PATH/test.sh > /dev/null 2>&1" >> /etc/crontabs/root
echolog "设置每$testing_time分钟执行检测脚本"
}
}
/etc/init.d/cron restart
}
stop_crontab() {
sed -i "/$CONFIG/d" /etc/crontabs/root >/dev/null 2>&1 &
ps | grep "$APP_PATH/test.sh" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
rm -f /var/lock/passwall_test.lock >/dev/null 2>&1 &
/etc/init.d/cron restart
echolog "清除定时执行命令。"
}
start_dns() {
case "$DNS_MODE" in
dns2socks)
dns2socks_bin=$(find_bin dns2socks)
sslocal_bin=$(find_bin "$TCP_REDIR_SERVER_TYPE"-local)
[ -n "$dns2socks_bin" -a -n "$sslocal_bin" ] && {
nohup $sslocal_bin -c $CONFIG_TCP_FILE -l 3080 -f $RUN_PID_PATH/$TCP_REDIR_SERVER_TYPE-local.pid >/dev/null 2>&1 &
nohup $dns2socks_bin 127.0.0.1:3080 $DNS_FORWARD 127.0.0.1:7913 >/dev/null 2>&1 &
echolog "运行DNS转发模式dns2socks+$TCP_REDIR_SERVER_TYPE-local..."
}
;;
Pcap_DNSProxy)
Pcap_DNSProxy_bin=$(find_bin Pcap_DNSProxy)
[ -n "$Pcap_DNSProxy_bin" ] && {
nohup $Pcap_DNSProxy_bin -c /etc/pcap-dnsproxy >/dev/null 2>&1 &
echolog "运行DNS转发模式Pcap_DNSProxy..."
}
;;
pdnsd)
pdnsd_bin=$(find_bin pdnsd)
[ -n "$pdnsd_bin" ] && {
gen_pdnsd_config
nohup $pdnsd_bin --daemon -c $CACHEDIR/pdnsd.conf -p $RUN_PID_PATH/pdnsd.pid -d >/dev/null 2>&1 &
echolog "运行DNS转发模式Pdnsd..."
}
;;
local_7913)
echolog "运行DNS转发模式使用本机7913端口DNS服务解析域名..."
;;
chinadns)
chinadns_bin=$(find_bin ChinaDNS)
[ -n "$chinadns_bin" ] && {
other=1
echolog "运行DNS转发模式ChinaDNS..."
dns1=$(config_t_get global_dns dns_1)
[ "$dns1" = "dnsbyisp" ] && dns1=`cat /tmp/resolv.conf.auto 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" |sort -u |grep -v 0.0.0.0 |grep -v 127.0.0.1|sed -n '2P'`
case "$UP_CHINADNS_MODE" in
OpenDNS_1)
other=0
nohup $chinadns_bin -p 7913 -c $APP_PATH_RULE/chnroute -m -d -s $dns1,208.67.222.222:443,208.67.222.222:5353 >/dev/null 2>&1 &
echolog "运行ChinaDNS上游转发模式$dns1,208.67.222.222..."
;;
OpenDNS_2)
other=0
nohup $chinadns_bin -p 7913 -c $APP_PATH_RULE/chnroute -m -d -s $dns1,208.67.220.220:443,208.67.220.220:5353 >/dev/null 2>&1 &
echolog "运行ChinaDNS上游转发模式$dns1,208.67.220.220..."
;;
custom)
other=0
UP_CHINADNS_CUSTOM=$(config_t_get global up_chinadns_custom '114.114.114.114,208.67.222.222:5353')
nohup $chinadns_bin -p 7913 -c $APP_PATH_RULE/chnroute -m -d -s $UP_CHINADNS_CUSTOM >/dev/null 2>&1 &
echolog "运行ChinaDNS上游转发模式$UP_CHINADNS_CUSTOM..."
;;
dnsproxy)
dnsproxy_bin=$(find_bin dnsproxy)
[ -n "$dnsproxy_bin" ] && {
nohup $dnsproxy_bin -d -T -p 7913 -R $DNS_FORWARD_IP -P $DNS_FORWARD_PORT >/dev/null 2>&1 &
echolog "运行ChinaDNS上游转发模式dnsproxy..."
}
;;
dns-forwarder)
dnsforwarder_bin=$(find_bin dns-forwarder)
[ -n "$dnsforwarder_bin" ] && {
nohup $dnsforwarder_bin -p 7913 -s $DNS_FORWARD >/dev/null 2>&1 &
echolog "运行ChinaDNS上游转发模式dns-forwarder..."
}
;;
esac
if [ "$other" = "1" ];then
nohup $chinadns_bin -p 7923 -c $APP_PATH_RULE/chnroute -m -d -s $dns1,127.0.0.1:7913 >/dev/null 2>&1 &
fi
}
;;
esac
echolog "若不正常,请尝试其他模式!"
}
add_dnsmasq() {
mkdir -p $TMP_DNSMASQ_PATH $DNSMASQ_PATH /var/dnsmasq.d
local wirteconf dnsconf dnsport isp_dns isp_ip
dnsport=$(config_t_get global_dns dns_port)
[ -z "$dnsport" ] && dnsport=0
if [ "$DNS1" = "dnsbyisp" -o "$DNS2" = "dnsbyisp" ]; then
cat > /etc/dnsmasq.conf <<EOF
all-servers
no-poll
no-resolv
cache-size=2048
local-ttl=60
neg-ttl=3600
max-cache-ttl=1200
EOF
echolog "生成Dnsmasq配置文件。"
if [ "$dnsport" != "0" ]; then
isp_dns=`cat /tmp/resolv.conf.auto 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u | grep -v 0.0.0.0 | grep -v 127.0.0.1`
failcount=0
while [ "$failcount" -lt "10" ]
do
interface=`ifconfig | grep "$dnsport" | awk '{print $1}'`
if [ -z "$interface" ];then
echolog "找不到出口接口:$dnsport1分钟后再重试"
let "failcount++"
[ "$failcount" -ge 10 ] && exit 0
sleep 1m
else
[ -n "$isp_dns" ] && {
for isp_ip in $isp_dns
do
echo server=$isp_ip >> /etc/dnsmasq.conf
route add -host ${isp_ip} dev ${dnsport}
echolog "添加运营商DNS出口路由表$dnsport"
done
}
[ "$DNS1" != "dnsbyisp" ] && {
route add -host ${DNS1} dev ${dnsport}
echolog "添加DNS1出口路由表$dnsport"
echo server=$DNS1 >> /etc/dnsmasq.conf
}
[ "$DNS2" != "dnsbyisp" ] && {
route add -host ${DNS2} dev ${dnsport}
echolog "添加DNS2出口路由表$dnsport"
echo server=$DNS2 >> /etc/dnsmasq.conf
}
break
fi
done
else
isp_dns=`cat /tmp/resolv.conf.auto 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u | grep -v 0.0.0.0 | grep -v 127.0.0.1`
[ -n "$isp_dns" ] && {
for isp_ip in $isp_dns
do
echo server=$isp_ip >> /etc/dnsmasq.conf
done
}
[ "$DNS1" != "dnsbyisp" ] && {
echo server=$DNS1 >> /etc/dnsmasq.conf
}
[ "$DNS2" != "dnsbyisp" ] && {
echo server=$DNS2 >> /etc/dnsmasq.conf
}
fi
else
wirteconf=$(cat /etc/dnsmasq.conf 2>/dev/null | grep "server=$DNS1")
dnsconf=$(cat /etc/dnsmasq.conf 2>/dev/null | grep "server=$DNS2")
if [ "$dnsport" != "0" ]; then
failcount=0
while [ "$failcount" -lt "10" ]
do
interface=`ifconfig | grep "$dnsport" | awk '{print $1}'`
if [ -z "$interface" ];then
echolog "找不到出口接口:$dnsport1分钟后再重试"
let "failcount++"
[ "$failcount" -ge 10 ] && exit 0
sleep 1m
else
route add -host ${DNS1} dev ${dnsport}
echolog "添加DNS1出口路由表$dnsport"
route add -host ${DNS2} dev ${dnsport}
echolog "添加DNS2出口路由表$dnsport"
break
fi
done
fi
if [ -z "$wirteconf" ] || [ -z "$dnsconf" ];then
cat > /etc/dnsmasq.conf <<EOF
all-servers
no-poll
no-resolv
server=$DNS1
server=$DNS2
cache-size=2048
local-ttl=60
neg-ttl=3600
max-cache-ttl=1200
EOF
echolog "生成Dnsmasq配置文件。"
fi
fi
# if [ -n "cat /var/state/network |grep pppoe|awk -F '.' '{print $2}'" ]; then
# sed -i '/except-interface/d' /etc/dnsmasq.conf >/dev/null 2>&1 &
# for wanname in $(cat /var/state/network |grep pppoe|awk -F '.' '{print $2}')
# do
# echo "except-interface=$(uci get network.$wanname.ifname)" >>/etc/dnsmasq.conf
# done
# fi
subscribe_by_ss=$(config_t_get global_subscribe subscribe_by_ss)
[ -z "$subscribe_by_ss" ] && subscribe_by_ss=0
[ "$subscribe_by_ss" -eq 1 ] && {
baseurl=$(config_t_get global_subscribe baseurl)
[ -n "$baseurl" ] && {
for url in $baseurl
do
if [ -n "`echo -n "$url" |grep "//"`" ]; then
echo -n "$url" | awk -F'/' '{print $3}' | sed "s/^/server=&\/./g" | sed "s/$/\/127.0.0.1#7913/g" >> $TMP_DNSMASQ_PATH/subscribe.conf
echo -n "$url" | awk -F'/' '{print $3}' | sed "s/^/ipset=&\/./g" | sed "s/$/\/router/g" >> $TMP_DNSMASQ_PATH/subscribe.conf
else
echo -n "$url" | awk -F'/' '{print $1}' | sed "s/^/server=&\/./g" | sed "s/$/\/127.0.0.1#7913/g" >> $TMP_DNSMASQ_PATH/subscribe.conf
echo -n "$url" | awk -F'/' '{print $1}' | sed "s/^/ipset=&\/./g" | sed "s/$/\/router/g" >> $TMP_DNSMASQ_PATH/subscribe.conf
fi
done
restdns=1
}
}
if [ ! -f "$TMP_DNSMASQ_PATH/gfwlist.conf" ];then
ln -s $APP_PATH_DNSMASQ/gfwlist.conf $TMP_DNSMASQ_PATH/gfwlist.conf
restdns=1
fi
if [ ! -f "$TMP_DNSMASQ_PATH/blacklist_host.conf" ];then
cat $APP_PATH_RULE/blacklist_host | awk '{print "server=/."$1"/127.0.0.1#7913\nipset=/."$1"/blacklist"}' >> $TMP_DNSMASQ_PATH/blacklist_host.conf
restdns=1
fi
if [ ! -f "$TMP_DNSMASQ_PATH/whitelist_host.conf" ];then
cat $APP_PATH_RULE/whitelist_host | sed "s/^/ipset=&\/./g" | sed "s/$/\/&whitelist/g" | sort | awk '{if ($0!=line) print;line=$0}' >$TMP_DNSMASQ_PATH/whitelist_host.conf
restdns=1
fi
if [ ! -f "$TMP_DNSMASQ_PATH/router.conf" ];then
cat $APP_PATH_RULE/router | awk '{print "server=/."$1"/127.0.0.1#7913\nipset=/."$1"/router"}' >> $TMP_DNSMASQ_PATH/router.conf
restdns=1
fi
userconf=$(grep -c "" $APP_PATH_DNSMASQ/user.conf)
if [ "$userconf" -gt 0 ];then
ln -s $APP_PATH_DNSMASQ/user.conf $TMP_DNSMASQ_PATH/user.conf
restdns=1
fi
backhome=$(config_t_get global proxy_mode gfwlist)
if [ "$backhome" == "returnhome" ];then
rm -rf $TMP_DNSMASQ_PATH/gfwlist.conf
rm -rf $TMP_DNSMASQ_PATH/blacklist_host.conf
rm -rf $TMP_DNSMASQ_PATH/whitelist_host.conf
restdns=1
echolog "生成回国模式Dnsmasq配置文件。"
fi
echo "conf-dir=$TMP_DNSMASQ_PATH" > /var/dnsmasq.d/dnsmasq-$CONFIG.conf
echo "conf-dir=$TMP_DNSMASQ_PATH" > $DNSMASQ_PATH/dnsmasq-$CONFIG.conf
if [ "$restdns" == 1 ];then
echolog "重启Dnsmasq。。。"
/etc/init.d/dnsmasq restart 2>/dev/null
fi
}
gen_pdnsd_config() {
CACHEDIR=/var/pdnsd
CACHE=$CACHEDIR/pdnsd.cache
if ! test -f "$CACHE"; then
mkdir -p `dirname $CACHE`
touch $CACHE
chown -R root.nogroup $CACHEDIR
fi
cat > $CACHEDIR/pdnsd.conf <<-EOF
global {
perm_cache=1024;
cache_dir="/var/pdnsd";
run_as="root";
server_ip = 127.0.0.1;
server_port=7913;
status_ctl = on;
query_method=tcp_only;
min_ttl=1d;
max_ttl=1w;
timeout=10;
tcp_qtimeout=1;
par_queries=2;
neg_domain_pol=on;
udpbufsize=1024;
}
server {
label = "opendns";
ip = 208.67.222.222, 208.67.220.220;
edns_query=on;
port = 5353;
timeout = 4;
interval=60;
uptest = none;
purge_cache=off;
caching=on;
}
source {
ttl=86400;
owner="localhost.";
serve_aliases=on;
file="/etc/hosts";
}
EOF
}
stop_dnsmasq() {
if [ "$TCP_REDIR_SERVER" == "nil" ]; then
rm -rf /var/dnsmasq.d/dnsmasq-$CONFIG.conf
rm -rf $DNSMASQ_PATH/dnsmasq-$CONFIG.conf
rm -rf $TMP_DNSMASQ_PATH
/etc/init.d/dnsmasq restart 2>/dev/null
echolog "没有选择服务器!"
fi
}
start_haproxy(){
enabled=$(config_t_get global_haproxy balancing_enable 0)
[ "$enabled" = "1" ] && {
haproxy_bin=$(find_bin haproxy)
[ -n "$haproxy_bin" ] && {
bport=$(config_t_get global_haproxy haproxy_port)
cat <<-EOF >$HAPROXY_FILE
global
log 127.0.0.1 local2
chroot /usr/bin
pidfile $RUN_PID_PATH/haproxy.pid
maxconn 60000
stats socket $RUN_PID_PATH/haproxy.sock
user root
daemon
defaults
mode tcp
log global
option tcplog
option dontlognull
option http-server-close
#option forwardfor except 127.0.0.0/8
option redispatch
retries 2
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
listen shadowsocks
bind 0.0.0.0:$bport
mode tcp
EOF
for i in $(seq 0 100)
do
bips=$(config_t_get balancing lbss '' $i)
bports=$(config_t_get balancing lbort '' $i)
bweight=$(config_t_get balancing lbweight '' $i)
exports=$(config_t_get balancing export '' $i)
bbackup=$(config_t_get balancing backup '' $i)
if [ -z "$bips" ] || [ -z "$bports" ] ; then
break
fi
if [ "$bbackup" = "1" ] ; then
bbackup=" backup"
echolog "添加故障转移备服务器$bips"
else
bbackup=""
echolog "添加负载均衡主服务器$bips"
fi
si=`echo $bips|grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}"`
if [ -z "$si" ];then
bips=`resolveip -4 -t 2 $bips|awk 'NR==1{print}'`
if [ -z "$bips" ];then
bips=`nslookup $bips localhost | sed '1,4d' | awk '{print $3}' | grep -v :|awk 'NR==1{print}'`
fi
echolog "服务器IP为$bips"
fi
echo " server ss$i $bips:$bports weight $bweight check inter 1500 rise 1 fall 3 $bbackup" >> $HAPROXY_FILE
if [ "$exports" != "0" ]; then
failcount=0
while [ "$failcount" -lt "10" ]
do
interface=`ifconfig | grep "$exports" | awk '{print $1}'`
if [ -z "$interface" ];then
echolog "找不到出口接口:$exports1分钟后再重试"
let "failcount++"
[ "$failcount" -ge 10 ] && exit 0
sleep 1m
else
route add -host ${bips} dev ${exports}
echolog "添加SS出口路由表$exports"
echo "$bips" >> /tmp/balancing_ip
break
fi
done
fi
done
#生成负载均衡控制台
adminstatus=$(config_t_get global_haproxy admin_enable)
if [ "$adminstatus" = "1" ];then
adminport=$(config_t_get global_haproxy admin_port)
adminuser=$(config_t_get global_haproxy admin_user)
adminpassword=$(config_t_get global_haproxy admin_password)
cat <<-EOF >>$HAPROXY_FILE
listen status
bind 0.0.0.0:$adminport
mode http
stats refresh 30s
stats uri /
stats auth $adminuser:$adminpassword
#stats hide-version
stats admin if TRUE
EOF
fi
nohup $haproxy_bin -f $HAPROXY_FILE 2>&1
echolog "负载均衡服务运行成功!"
}
}
}
add_vps_port() {
multiwan=$(config_t_get global_dns wan_port 0)
if [ "$multiwan" != "0" ]; then
failcount=0
while [ "$failcount" -lt "10" ]
do
interface=`ifconfig | grep "$multiwan" | awk '{print $1}'`
if [ -z "$interface" ];then
echolog "找不到出口接口:$multiwan1分钟后再重试"
let "failcount++"
[ "$failcount" -ge 10 ] && exit 0
sleep 1m
else
route add -host ${TCP_REDIR_SERVER_IP} dev ${multiwan}
route add -host ${UDP_REDIR_SERVER_IP} dev ${multiwan}
echolog "添加SS出口路由表$multiwan"
echo "$TCP_REDIR_SERVER_IP" > $CONFIG_PATH/tcp_ip
echo "$UDP_REDIR_SERVER_IP" > $CONFIG_PATH/udp_ip
break
fi
done
fi
}
del_vps_port() {
tcp_ip=$(cat $CONFIG_PATH/tcp_ip 2> /dev/null)
udp_ip=$(cat $CONFIG_PATH/udp_ip 2> /dev/null)
[ -n "$tcp_ip" ] && route del -host ${tcp_ip}
[ -n "$udp_ip" ] && route del -host ${udp_ip}
}
kill_all() {
kill -9 $(pidof $@) >/dev/null 2>&1 &
}
boot() {
local delay=$(config_t_get global_delay start_delay 0)
if [ "$delay" -gt 0 ]; then
[ "$TCP_REDIR_SERVER" != "nil" -o "$UDP_REDIR_SERVER" != "nil" ] && {
echolog "执行启动延时 $delay 秒后再启动!"
sleep $delay && start >/dev/null 2>&1 &
}
else
start
fi
return 0
}
start() {
echolog "开始运行脚本!"
! load_config && return 1
add_vps_port
start_haproxy
#防止并发开启服务
[ -f "$LOCK_FILE" ] && return 3
touch "$LOCK_FILE"
start_tcp_redir
start_udp_redir
start_socks5_proxy
start_dns
add_dnsmasq
source $APP_PATH/iptables.sh start
/etc/init.d/dnsmasq restart >/dev/null 2>&1 &
start_crontab
set_cru
rm -f "$LOCK_FILE"
echolog "运行完成!"
return 0
}
stop() {
while [ -f "$LOCK_FILE" ]; do
sleep 1s
done
clean_log
source $APP_PATH/iptables.sh stop
del_vps_port
kill_all pdnsd Pcap_DNSProxy brook dns2socks haproxy dns-forwarder chinadns dnsproxy redsocks2
ps -w | grep -E "$CONFIG_TCP_FILE|$CONFIG_UDP_FILE|$CONFIG_SOCKS5_FILE" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
ps -w | grep "kcptun_client" | grep "$KCPTUN_REDIR_PORT" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
rm -rf /var/pdnsd/pdnsd.cache
rm -rf $TMP_DNSMASQ_PATH
rm -rf $CONFIG_PATH
stop_dnsmasq
stop_crontab
echolog "关闭相关服务,清理相关文件和缓存完成。\n"
sleep 1s
}
case $1 in
stop)
stop
;;
start)
start
;;
boot)
boot
;;
*)
echo "Usage: $0 (start|stop|restart)"
;;
esac

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,489 @@
#!/bin/sh
IPSET_LANIPLIST="laniplist"
IPSET_VPSIPLIST="vpsiplist"
IPSET_ROUTER="router"
IPSET_GFW="gfwlist"
IPSET_CHN="chnroute"
IPSET_BLACKLIST="blacklist"
IPSET_WHITELIST="whitelist"
iptables_nat="iptables -t nat"
iptables_mangle="iptables -t mangle"
ip6tables_nat="ip6tables -t nat"
factor(){
if [ -z "$1" ] || [ -z "$2" ]; then
echo ""
else
echo "$2 $1"
fi
}
get_jump_mode(){
case "$1" in
disable)
echo "j"
;;
*)
echo "g"
;;
esac
}
get_ip_mark(){
if [ -z "$1" ]; then
echo ""
else
echo $1 | awk -F "." '{printf ("0x%02X", $1)} {printf ("%02X", $2)} {printf ("%02X", $3)} {printf ("%02X", $4)}'
fi
}
get_action_chain() {
case "$1" in
disable)
echo "RETURN"
;;
global)
echo "SS_GLO"
;;
gfwlist)
echo "SS_GFW"
;;
chnroute)
echo "SS_CHN"
;;
gamemode)
echo "SS_GAME"
;;
returnhome)
echo "SS_HOME"
;;
esac
}
get_action_chain_name() {
case "$1" in
disable)
echo "不代理"
;;
global)
echo "全局"
;;
gfwlist)
echo "GFW"
;;
chnroute)
echo "大陆白名单"
;;
gamemode)
echo "游戏"
;;
returnhome)
echo "回国"
;;
esac
}
gen_laniplist() {
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.168.0.0/16
224.0.0.0/4
240.0.0.0/4
EOF
}
load_acl(){
local enabled
local aclremarks
local ipaddr
local macaddr
local proxy_mode
local tcp_redir_ports
local udp_redir_ports
config_get enabled $1 enabled
config_get aclremarks $1 aclremarks
config_get ipaddr $1 ipaddr
config_get macaddr $1 macaddr
config_get proxy_mode $1 proxy_mode
config_get tcp_redir_ports $1 tcp_redir_ports
config_get udp_redir_ports $1 udp_redir_ports
[ -z "$proxy_mode" -o "$proxy_mode" = "default" ] && proxy_mode=$PROXY_MODE
[ -z "$tcp_redir_ports" -o "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS
[ -z "$udp_redir_ports" -o "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
local ip_mark=`get_ip_mark $ipaddr`
[ "$enabled" == "1" -a -n "$proxy_mode" ] && {
if [ -n "$ipaddr" ] || [ -n "$macaddr" ]; then
if [ -n "$ipaddr" -a -n "$macaddr" ]; then
echolog "访问控制IP$ipaddrMAC$macaddr,代理模式:$(get_action_chain_name $proxy_mode)"
else
[ -n "$ipaddr" ] && echolog "访问控制IP$ipaddr,代理模式:$(get_action_chain_name $proxy_mode)"
[ -n "$macaddr" ] && echolog "访问控制MAC$macaddr,代理模式:$(get_action_chain_name $proxy_mode)"
fi
$iptables_mangle -A SS_ACL $(factor $ipaddr "-s") -p tcp $(factor $macaddr "-m mac --mac-source") $(factor $tcp_redir_ports "-m multiport --dport") -m comment --comment "$aclremarks" -$(get_jump_mode $proxy_mode) $(get_action_chain $proxy_mode)
[ "$UDP_REDIR_SERVER" != "nil" ] && $iptables_mangle -A SS_ACL $(factor $ipaddr "-s") -p udp $(factor $macaddr "-m mac --mac-source") $(factor $udp_redir_ports "-m multiport --dport") -m comment --comment "$aclremarks" -$(get_jump_mode $proxy_mode) $(get_action_chain $proxy_mode)
[ -z "$ipaddr" ] && {
lower_macaddr=`echo $macaddr | tr '[A-Z]' '[a-z]'`
ipaddr=`ip neigh show | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | grep $lower_macaddr | awk '{print $1}'`
[ -z "$ipaddr" ] && {
dhcp_index=`uci show dhcp | grep $lower_macaddr |awk -F'.' '{print $2}'`
ipaddr=`uci -q get dhcp.$dhcp_index.ip`
}
[ -z "$ipaddr" ] && ipaddr=`cat /tmp/dhcp.leases | grep -E "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" |grep $lower_macaddr |awk '{print $3}'`
}
fi
}
}
filter_vpsip(){
local server_host server_ip use_ipv6 network_type
server_host=$(config_get $1 server)
use_ipv6=$(config_get $1 use_ipv6)
network_type="ipv4"
[ "$use_ipv6" == "1" ] && network_type="ipv6"
server_ip=$(get_host_ip $network_type $server_host)
[ -n "$server_ip" -a "$server_ip" != "$TCP_REDIR_SERVER_IP" ] && {
[ "$network_type" == "ipv4" ] && ipset add $IPSET_VPSIPLIST $server_ip >/dev/null 2>&1 &
}
}
dns_hijack(){
dnshijack=$(config_t_get global_dns dns_53)
if [ "$dnshijack" = "1" -o "$1" = "force" ];then
chromecast_nu=`$iptables_nat -L SS -v -n --line-numbers|grep "dpt:53"|awk '{print $1}'`
is_right_lanip=`$iptables_nat -L SS -v -n --line-numbers|grep "dpt:53" |grep "$lanip"`
if [ -z "$chromecast_nu" ]; then
echolog "添加接管局域网DNS解析规则..."
$iptables_nat -I SS -i br-lan -p udp --dport 53 -j DNAT --to $lanip 2>/dev/null
else
if [ -z "$is_right_lanip" ]; then
echolog "添加接管局域网DNS解析规则..."
$iptables_nat -D SS $chromecast_nu >/dev/null 2>&1 &
$iptables_nat -I SS -i br-lan -p udp --dport 53 -j DNAT --to $lanip 2>/dev/null
else
echolog " DNS劫持规则已经添加跳过~" >>$LOG_FILE
fi
fi
fi
}
add_firewall_rule() {
echolog "开始加载防火墙规则..."
echolog "默认代理模式:$(get_action_chain_name $PROXY_MODE)"
ipset -! create $IPSET_LANIPLIST nethash && ipset flush $IPSET_LANIPLIST
ipset -! create $IPSET_VPSIPLIST nethash && ipset flush $IPSET_VPSIPLIST
ipset -! create $IPSET_ROUTER nethash && ipset flush $IPSET_ROUTER
ipset -! create $IPSET_GFW nethash && ipset flush $IPSET_GFW
ipset -! create $IPSET_CHN nethash && ipset flush $IPSET_CHN
ipset -! create $IPSET_BLACKLIST nethash && ipset flush $IPSET_BLACKLIST
ipset -! create $IPSET_WHITELIST nethash && ipset flush $IPSET_WHITELIST
sed -e "s/^/add $IPSET_CHN &/g" $APP_PATH_RULE/chnroute | awk '{print $0} END{print "COMMIT"}' | ipset -R
sed -e "s/^/add $IPSET_BLACKLIST &/g" $APP_PATH_RULE/blacklist_ip | awk '{print $0} END{print "COMMIT"}' | ipset -R
sed -e "s/^/add $IPSET_WHITELIST &/g" $APP_PATH_RULE/whitelist_ip | awk '{print $0} END{print "COMMIT"}' | ipset -R
ipset -! -R <<-EOF || return 1
$(gen_laniplist | sed -e "s/^/add $IPSET_LANIPLIST /")
EOF
ISP_DNS=`cat /tmp/resolv.conf.auto 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u |grep -v 0.0.0.0 |grep -v 127.0.0.1`
[ -n "$ISP_DNS" ] && {
for ispip in $ISP_DNS
do
ipset -! add $IPSET_WHITELIST $ispip >/dev/null 2>&1 &
done
}
# 忽略特殊IP段
lan_ip=`ifconfig br-lan | grep "inet addr" | awk '{print $2}' | awk -F : '{print $2}'` #路由器lan IP
lan_ipv4=`ip address show br-lan | grep -w "inet" |awk '{print $2}'` #当前LAN IPv4段
[ -n "$lan_ipv4" ] && ipset add $IPSET_LANIPLIST $lan_ipv4 >/dev/null 2>&1 &
# 过滤所有节点IP
config_foreach filter_vpsip "servers"
$iptables_mangle -N SS
$iptables_mangle -A SS -m set --match-set $IPSET_LANIPLIST dst -j RETURN
$iptables_mangle -A SS -m set --match-set $IPSET_VPSIPLIST dst -j RETURN
$iptables_mangle -A SS -m set --match-set $IPSET_WHITELIST dst -j RETURN
$iptables_mangle -N SS_ACL
$iptables_mangle -N SS_GLO
$iptables_mangle -N SS_GFW
$iptables_mangle -N SS_CHN
$iptables_mangle -N SS_HOME
$iptables_mangle -N SS_GAME
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
# 生成TCP转发规则
if [ "$TCP_REDIR_SERVER" != "nil" ];then
[ -n "$SOCKS5_PROXY_SERVER_IP" -a -n "$SOCKS5_PROXY_SERVER_PORT" ] && $iptables_mangle -A SS -p tcp -d $SOCKS5_PROXY_SERVER_IP -m multiport --dports $SOCKS5_PROXY_SERVER_PORT -j RETURN
[ -n "$TCP_REDIR_SERVER_IP" -a -n "$TCP_REDIR_SERVER_PORT" ] && $iptables_mangle -A SS -p tcp -d $TCP_REDIR_SERVER_IP -m multiport --dports $TCP_REDIR_SERVER_PORT -j RETURN
if [ "$TCP_REDIR_SERVER_TYPE" == "brook" ]; then
$iptables_mangle -A PREROUTING -p tcp -m socket -j MARK --set-mark 1
$iptables_mangle -A PREROUTING -p tcp -j SS
$iptables_mangle -A SS -p tcp -m set --match-set $IPSET_BLACKLIST dst -j TPROXY --on-port $TCP_REDIR_PORT --tproxy-mark 0x1/0x1
# 全局模式
$iptables_mangle -A SS_GLO -p tcp -j TPROXY --tproxy-mark 0x1/0x1 --on-port $TCP_REDIR_PORT
# GFWLIST模式
$iptables_mangle -A SS_GFW -p tcp -m set --match-set $IPSET_GFW dst -j TPROXY --on-port $TCP_REDIR_PORT --tproxy-mark 0x1/0x1
$iptables_mangle -A SS_GFW -p tcp -m set --match-set $IPSET_ROUTER dst -j TPROXY --on-port $TCP_REDIR_PORT --tproxy-mark 0x1/0x1
# 大陆白名单模式
$iptables_mangle -A SS_CHN -p tcp -m set --match-set $IPSET_CHN dst -j RETURN
$iptables_mangle -A SS_CHN -p tcp -j TPROXY --on-port $TCP_REDIR_PORT --tproxy-mark 0x1/0x1
# 回国模式
$iptables_mangle -A SS_HOME -p tcp -m set --match-set $IPSET_CHN dst -j TPROXY --on-port $TCP_REDIR_PORT --tproxy-mark 0x1/0x1
# 游戏模式
$iptables_mangle -A SS_GAME -p tcp -m set --match-set $IPSET_CHN dst -j RETURN
# 用于本机流量转发默认只走router
$iptables_mangle -A SS -s $lan_ip -p tcp -m set --match-set $IPSET_ROUTER dst -j TPROXY --on-port $TCP_REDIR_PORT --tproxy-mark 0x1/0x1
$iptables_mangle -A OUTPUT -p tcp -m multiport --dport $TCP_REDIR_PORTS -m set --match-set $IPSET_ROUTER dst -j MARK --set-mark 1
else
$iptables_mangle -A PREROUTING -j SS
$iptables_mangle -A SS -p tcp -m set --match-set $IPSET_BLACKLIST dst -j TTL --ttl-set 188
# 全局模式
$iptables_mangle -A SS_GLO -p tcp -j TTL --ttl-set 188
# GFWLIST模式
$iptables_mangle -A SS_GFW -p tcp -m set --match-set $IPSET_GFW dst -j TTL --ttl-set 188
$iptables_mangle -A SS_GFW -p tcp -m set --match-set $IPSET_ROUTER dst -j TTL --ttl-set 188
# 大陆白名单模式
$iptables_mangle -A SS_CHN -p tcp -m set --match-set $IPSET_CHN dst -j RETURN
#$iptables_mangle -A SS_CHN -p tcp -m geoip ! --destination-country CN -j TTL --ttl-set 188
$iptables_mangle -A SS_CHN -p tcp -j TTL --ttl-set 188
# 回国模式
#$iptables_mangle -A SS_HOME -p tcp -m geoip --destination-country CN -j TTL --ttl-set 188
$iptables_mangle -A SS_HOME -p tcp -m set --match-set $IPSET_CHN dst -j TTL --ttl-set 188
# 游戏模式
$iptables_mangle -A SS_GAME -p tcp -m set --match-set $IPSET_CHN dst -j RETURN
# 重定所有流量到透明代理端口
$iptables_nat -N SS
$iptables_nat -A SS -p tcp -m ttl --ttl-eq 188 -j REDIRECT --to $TCP_REDIR_PORT
is_add_prerouting=0
KP_INDEX=`$iptables_nat -L PREROUTING|tail -n +3|sed -n -e '/^KOOLPROXY/='`
if [ -n "$KP_INDEX" ]; then
let KP_INDEX+=1
#确保添加到KOOLPROXY规则之后
$iptables_nat -I PREROUTING $KP_INDEX -j SS
is_add_prerouting=1
fi
ADBYBY_INDEX=`$iptables_nat -L PREROUTING|tail -n +3|sed -n -e '/^ADBYBY/='`
if [ -n "$ADBYBY_INDEX" ]; then
let ADBYBY_INDEX+=1
#确保添加到ADBYBY规则之后
$iptables_nat -I PREROUTING $ADBYBY_INDEX -j SS
is_add_prerouting=1
fi
if [ "$is_add_prerouting" == 0 ]; then
#如果去广告没有运行确保添加到prerouting_rule规则之后
PR_INDEX=`$iptables_nat -L PREROUTING|tail -n +3|sed -n -e '/^prerouting_rule/='`
if [ -z "$PR_INDEX" ]; then
PR_INDEX=1
else
let PR_INDEX+=1
fi
$iptables_nat -I PREROUTING $PR_INDEX -j SS
fi
# 用于本机流量转发默认只走router
#$iptables_nat -I OUTPUT -j SS
$iptables_nat -A OUTPUT -m set --match-set $IPSET_LANIPLIST dst -j RETURN
$iptables_nat -A OUTPUT -m set --match-set $IPSET_VPSIPLIST dst -j RETURN
$iptables_nat -A OUTPUT -m set --match-set $IPSET_WHITELIST dst -j RETURN
$iptables_nat -A OUTPUT -p tcp -m multiport --dport $TCP_REDIR_PORTS -m set --match-set $IPSET_ROUTER dst -j REDIRECT --to-ports $TCP_REDIR_PORT
$iptables_nat -A OUTPUT -p tcp -m multiport --dport $TCP_REDIR_PORTS -m set --match-set $IPSET_BLACKLIST dst -j REDIRECT --to-ports $TCP_REDIR_PORT
[ "$LOCALHOST_PROXY_MODE" == "global" ] && $iptables_nat -A OUTPUT -p tcp -m multiport --dport $TCP_REDIR_PORTS -j REDIRECT --to-ports $TCP_REDIR_PORT
[ "$LOCALHOST_PROXY_MODE" == "gfwlist" ] && $iptables_nat -A OUTPUT -p tcp -m multiport --dport $TCP_REDIR_PORTS -m set --match-set $IPSET_GFW dst -j REDIRECT --to-ports $TCP_REDIR_PORT
[ "$LOCALHOST_PROXY_MODE" == "chnroute" ] && {
$iptables_nat -A OUTPUT -p tcp -m multiport --dport $TCP_REDIR_PORTS -m set --match-set $IPSET_CHN dst -j RETURN
$iptables_nat -A OUTPUT -p tcp -m multiport --dport $TCP_REDIR_PORTS -j REDIRECT --to-ports $TCP_REDIR_PORT
}
echolog "IPv4 防火墙TCP转发规则加载完成"
fi
else
echolog "主服务器未选择无法转发TCP"
fi
# 生成UDP转发规则
if [ "$UDP_REDIR_SERVER" != "nil" ];then
[ -n "$UDP_REDIR_SERVER_IP" -a -n "$UDP_REDIR_SERVER_PORT" ] && $iptables_mangle -A SS -p udp -d $UDP_REDIR_SERVER_IP -m multiport --dports $UDP_REDIR_SERVER_PORT -j RETURN
if [ "$UDP_REDIR_SERVER_TYPE" == "brook" ]; then
$iptables_mangle -A PREROUTING -p udp -m socket -j MARK --set-mark 1
$iptables_mangle -A PREROUTING -p udp -j SS
fi
$iptables_mangle -A SS -p udp -m set --match-set $IPSET_BLACKLIST dst -j TPROXY --on-port $UDP_REDIR_PORT --tproxy-mark 0x1/0x1
# 全局模式
$iptables_mangle -A SS_GLO -p udp -j TPROXY --on-port $UDP_REDIR_PORT --tproxy-mark 0x1/0x1
# GFWLIST模式
$iptables_mangle -A SS_GFW -p udp -m set --match-set $IPSET_GFW dst -j TPROXY --on-port $UDP_REDIR_PORT --tproxy-mark 0x1/0x1
$iptables_mangle -A SS_GFW -p udp -m set --match-set $IPSET_ROUTER dst -j TPROXY --on-port $UDP_REDIR_PORT --tproxy-mark 0x1/0x1
# 大陆白名单模式
$iptables_mangle -A SS_CHN -p udp -m set --match-set $IPSET_CHN dst -j RETURN
$iptables_mangle -A SS_CHN -p udp -j TPROXY --on-port $UDP_REDIR_PORT --tproxy-mark 0x1/0x1
# 回国模式
$iptables_mangle -A SS_HOME -p udp -m set --match-set $IPSET_CHN dst -j TPROXY --on-port $UDP_REDIR_PORT --tproxy-mark 0x1/0x1
# 游戏模式
$iptables_mangle -A SS_GAME -p udp -m set --match-set $IPSET_CHN dst -j RETURN
$iptables_mangle -A SS_GAME -p udp -j TPROXY --on-port $UDP_REDIR_PORT --tproxy-mark 0x1/0x1
#$iptables_mangle -A SS_GAME -p udp -m geoip ! --destination-country CN -j TTL --ttl-set 188
echolog "IPv4 防火墙UDP转发规则加载完成"
else
echolog "UDP服务器未选择无法转发UDP"
fi
# 加载ACLS
$iptables_mangle -A SS -j SS_ACL
config_foreach load_acl "acl_rule"
# 加载默认代理模式
if [ "$PROXY_MODE" == "disable" ];then
[ "$TCP_REDIR_SERVER" != "nil" ] && $iptables_mangle -A SS_ACL -p tcp -m comment --comment "Default" -j $(get_action_chain $PROXY_MODE)
[ "$UDP_REDIR_SERVER" != "nil" ] && $iptables_mangle -A SS_ACL -p udp -m comment --comment "Default" -j $(get_action_chain $PROXY_MODE)
else
[ "$PROXY_MODE" == "gfwlist" ] && dns_hijack "force"
[ "$TCP_REDIR_SERVER" != "nil" ] && $iptables_mangle -A SS_ACL -p tcp -m multiport --dport $TCP_REDIR_PORTS -m comment --comment "Default" -j $(get_action_chain $PROXY_MODE)
[ "$UDP_REDIR_SERVER" != "nil" ] && $iptables_mangle -A SS_ACL -p udp -m multiport --dport $UDP_REDIR_PORTS -m comment --comment "Default" -j $(get_action_chain $PROXY_MODE)
fi
if [ "$PROXY_IPV6" == "1" ];then
lan_ipv6=`ip address show br-lan | grep -w "inet6" |awk '{print $2}'` #当前LAN IPv6段
$ip6tables_nat -N SS
$ip6tables_nat -N SS_ACL
$ip6tables_nat -A PREROUTING -j SS
[ -n "$lan_ipv6" ] && {
for ip in $lan_ipv6
do
$ip6tables_nat -A SS -d $ip -j RETURN
done
}
[ "$use_ipv6" == "1" -a -n "$server_ip" ] && $ip6tables_nat -A SS -d $server_ip -j RETURN
$ip6tables_nat -N SS_GLO
$ip6tables_nat -N SS_GFW
$ip6tables_nat -N SS_CHN
$ip6tables_nat -N SS_HOME
$ip6tables_nat -A SS_GLO -p tcp -j REDIRECT --to $TCP_REDIR_PORT
$ip6tables_nat -A SS -j SS_GLO
$ip6tables_nat -I OUTPUT -p tcp -j SS
echolog "IPv6防火墙规则加载完成"
fi
}
del_firewall_rule() {
echolog "删除所有防火墙规则..."
ipv4_output_exist=`$iptables_nat -L OUTPUT 2>/dev/null | grep -c -E "SS|$TCP_REDIR_PORTS|$IPSET_LANIPLIST|$IPSET_VPSIPLIST|$IPSET_WHITELIST|$IPSET_ROUTER|$IPSET_BLACKLIST|$IPSET_GFW|$IPSET_CHN"`
[ -n "$ipv4_output_exist" ] && {
until [ "$ipv4_output_exist" = 0 ]
do
rules=`$iptables_nat -L OUTPUT --line-numbers | grep -E "SS|$TCP_REDIR_PORTS|$IPSET_LANIPLIST|$IPSET_VPSIPLIST|$IPSET_WHITELIST|$IPSET_ROUTER|$IPSET_BLACKLIST|$IPSET_GFW|$IPSET_CHN" | awk '{print $1}'`
for rule in $rules
do
$iptables_nat -D OUTPUT $rule 2> /dev/null
break
done
ipv4_output_exist=`expr $ipv4_output_exist - 1`
done
}
ipv6_output_ss_exist=`$ip6tables_nat -L OUTPUT 2>/dev/null | grep -c "SS"`
[ -n "$ipv6_output_ss_exist" ] && {
until [ "$ipv6_output_ss_exist" = 0 ]
do
rules=`$ip6tables_nat -L OUTPUT --line-numbers | grep "SS" | awk '{print $1}'`
for rule in $rules
do
$ip6tables_nat -D OUTPUT $rule 2> /dev/null
break
done
ipv6_output_ss_exist=`expr $ipv6_output_ss_exist - 1`
done
}
$iptables_mangle -D PREROUTING -p tcp -m socket -j MARK --set-mark 1 2>/dev/null
$iptables_mangle -D PREROUTING -p udp -m socket -j MARK --set-mark 1 2>/dev/null
$iptables_mangle -D OUTPUT -p tcp -m multiport --dport $TCP_REDIR_PORTS -m set --match-set $IPSET_ROUTER dst -j MARK --set-mark 1 2>/dev/null
$iptables_mangle -D OUTPUT -p tcp -m multiport --dport $TCP_REDIR_PORTS -m set --match-set $IPSET_GFW dst -j MARK --set-mark 1 2>/dev/null
$iptables_mangle -D OUTPUT -p tcp -m multiport --dport $TCP_REDIR_PORTS -j MARK --set-mark 1 2>/dev/null
$iptables_nat -D PREROUTING -j SS 2> /dev/null
$iptables_nat -F SS 2>/dev/null && $iptables_nat -X SS 2>/dev/null
$iptables_mangle -D PREROUTING -j SS 2>/dev/null
$iptables_mangle -F SS 2>/dev/null && $iptables_mangle -X SS 2>/dev/null
$iptables_mangle -F SS_ACL 2>/dev/null && $iptables_mangle -X SS_ACL 2>/dev/null
$iptables_mangle -F SS_GLO 2>/dev/null && $iptables_mangle -X SS_GLO 2>/dev/null
$iptables_mangle -F SS_GFW 2>/dev/null && $iptables_mangle -X SS_GFW 2>/dev/null
$iptables_mangle -F SS_CHN 2>/dev/null && $iptables_mangle -X SS_CHN 2>/dev/null
$iptables_mangle -F SS_GAME 2>/dev/null && $iptables_mangle -X SS_GAME 2>/dev/null
$iptables_mangle -F SS_HOME 2>/dev/null && $iptables_mangle -X SS_HOME 2>/dev/null
$ip6tables_nat -D PREROUTING -j SS 2>/dev/null
$ip6tables_nat -F SS 2>/dev/null && $ip6tables_nat -X SS 2>/dev/null
$ip6tables_nat -F SS_ACL 2>/dev/null && $ip6tables_nat -X SS_ACL 2>/dev/null
$ip6tables_nat -F SS_GLO 2>/dev/null && $ip6tables_nat -X SS_GLO 2>/dev/null
$ip6tables_nat -F SS_GFW 2>/dev/null && $ip6tables_nat -X SS_GFW 2>/dev/null
$ip6tables_nat -F SS_CHN 2>/dev/null && $ip6tables_nat -X SS_CHN 2>/dev/null
$ip6tables_nat -F SS_HOME 2>/dev/null && $ip6tables_nat -X SS_HOME 2>/dev/null
ip_rule_exist=`ip rule show | grep "from all fwmark 0x1 lookup 100" | grep -c 100`
if [ ! -z "$ip_rule_exist" ];then
until [ "$ip_rule_exist" = 0 ]
do
ip rule del fwmark 1 lookup 100
ip_rule_exist=`expr $ip_rule_exist - 1`
done
fi
ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null
ipset -F $IPSET_ROUTER >/dev/null 2>&1 && ipset -X $IPSET_ROUTER >/dev/null 2>&1 &
ipset -F $IPSET_GFW >/dev/null 2>&1 && ipset -X $IPSET_GFW >/dev/null 2>&1 &
#ipset -F $IPSET_CHN >/dev/null 2>&1 && ipset -X $IPSET_CHN >/dev/null 2>&1 &
ipset -F $IPSET_BLACKLIST >/dev/null 2>&1 && ipset -X $IPSET_BLACKLIST >/dev/null 2>&1 &
ipset -F $IPSET_WHITELIST >/dev/null 2>&1 && ipset -X $IPSET_WHITELIST >/dev/null 2>&1 &
ipset -F $IPSET_VPSIPLIST >/dev/null 2>&1 && ipset -X $IPSET_VPSIPLIST >/dev/null 2>&1 &
ipset -F $IPSET_LANIPLIST >/dev/null 2>&1 && ipset -X $IPSET_LANIPLIST >/dev/null 2>&1 &
}
start(){
add_firewall_rule
dns_hijack
}
stop(){
del_firewall_rule
}
case $1 in
stop)
stop
;;
start)
start
;;
*)
esac

View File

@ -0,0 +1,76 @@
#!/bin/sh
CONFIG=passwall
CONFIG_PATH=/var/etc/$CONFIG
uci_get_by_name() {
local ret=$(uci get $CONFIG.$1.$2 2>/dev/null)
echo ${ret:=$3}
}
uci_get_by_type() {
local ret=$(uci get $CONFIG.@$1[0].$2 2>/dev/null)
echo ${ret:=$3}
}
TCP_REDIR_SERVER=$(uci_get_by_type global tcp_redir_server nil)
UDP_REDIR_SERVER=$(uci_get_by_type global udp_redir_server nil)
[ "$UDP_REDIR_SERVER" == "default" ] && UDP_REDIR_SERVER=$TCP_REDIR_SERVER
SOCKS5_PROXY_SERVER=$(uci_get_by_type global socks5_proxy_server nil)
dns_mode=$(uci_get_by_type global dns_mode)
use_haproxy=$(uci_get_by_type global_haproxy balancing_enable 0)
haproxy_port=$(uci_get_by_type global_haproxy haproxy_port)
use_kcp=$(uci_get_by_name $TCP_REDIR_SERVER use_kcp 0)
kcp_port=$(uci_get_by_type global_proxy kcptun_port 11183)
#tcp
if [ $TCP_REDIR_SERVER != "nil" ] ;then
icount=`ps -w | grep -E "ss-redir|ssr-redir|v2ray" | grep $CONFIG_PATH/TCP.json | grep -v grep | wc -l`
if [ $icount = 0 ] ;then
/etc/init.d/passwall restart
exit 0
fi
fi
#udp
if [ $UDP_REDIR_SERVER != "nil" ] ;then
icount=`ps -w | grep -E "ss-redir|ssr-redir|v2ray" | grep $CONFIG_PATH/UDP.json | grep -v grep | wc -l`
if [ $icount = 0 ] ;then
/etc/init.d/passwall restart
exit 0
fi
fi
#socks5
if [ $SOCKS5_PROXY_SERVER != "nil" ] ;then
icount=`ps -w | grep -E "ss-redir|ssr-redir|v2ray" | grep $CONFIG_PATH/SOCKS5.json | grep -v grep | wc -l`
if [ $icount = 0 ] ;then
/etc/init.d/passwall restart
exit 0
fi
fi
#dns
icount=`netstat -apn | grep 7913 | wc -l`
if [ $icount = 0 ] ;then
/etc/init.d/passwall restart
exit 0
fi
#kcptun
if [ $use_kcp -gt 0 ] ;then
icount=`ps -w | grep kcptun_client | grep $kcp_port |grep -v grep | wc -l`
if [ $icount = 0 ] ;then
/etc/init.d/passwall restart
exit 0
fi
fi
#haproxy
if [ $use_haproxy -gt 0 ] ;then
icount=`ps -w | grep haproxy | grep $haproxy_port | grep -v grep | wc -l`
if [ $icount = 0 ] ;then
/etc/init.d/passwall restart
exit 0
fi
fi

View File

@ -0,0 +1,3 @@
formyip.com
myepisodecalendar.com
subhd.com

View File

@ -0,0 +1,5 @@
149.154.160.0/20
91.108.4.0/22
91.108.56.0/24
109.239.140.0/24
67.198.55.0/24

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
google.com
github.com
raw.githubusercontent.com
github-production-release-asset-2e65be.s3.amazonaws.com
openwrt.proxy.ustclug.org
easylist-downloads.adblockplus.org
adblockplus.org

View File

@ -0,0 +1,2 @@
apple.com
microsoft.com

View File

@ -0,0 +1,13 @@
114.114.114.114
114.114.115.115
223.5.5.5
223.6.6.6
112.124.47.27
114.215.126.16
1.2.4.8
210.2.4.8
119.29.29.29
208.67.222.222
208.67.220.220
8.8.8.8
8.8.4.4

View File

@ -0,0 +1,224 @@
#!/bin/sh
CONFIG=passwall
LOG_FILE=/var/log/$CONFIG.log
url_main="https://raw.githubusercontent.com/hq450/fancyss/master/rules"
SS_PATH=/usr/share/$CONFIG
DNSMASQ_PATH=$SS_PATH/dnsmasq.d
RULE_PATH=$SS_PATH/rule
Date=$(date "+%Y-%m-%d %H:%M:%S")
update=$1
gfwlist_update=0
chnroute_update=0
Pcap_Routing_update=0
Pcap_WhiteList_update=0
if [ -n "$update" ];then
[ -n "$(echo $update | grep "gfwlist_update")" ] && gfwlist_update=1
[ -n "$(echo $update | grep "chnroute_update")" ] && chnroute_update=1
[ -n "$(echo $update | grep "Pcap_Routing_update")" ] && Pcap_Routing_update=1
[ -n "$(echo $update | grep "Pcap_WhiteList_update")" ] && Pcap_WhiteList_update=1
else
gfwlist_update=uci get $CONFIG.@global_rules[0].gfwlist_update
chnroute_update=uci get $CONFIG.@global_rules[0].chnroute_update
Pcap_Routing_update=uci get $CONFIG.@global_rules[0].Pcap_Routing_update
Pcap_WhiteList_update=uci get $CONFIG.@global_rules[0].Pcap_WhiteList_update
fi
if [ "$gfwlist_update" == 0 -a "$chnroute_update" == 0 -a "$Pcap_Routing_update" == 0 -a "$Pcap_WhiteList_update" == 0 ];then
exit
fi
uci_get_by_type() {
local index=0
if [ -n $4 ]; then
index=$4
fi
local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null)
echo ${ret:=$3}
}
# detect ss version
#ss_basic_version_web1=`curl -s https://raw.githubusercontent.com/monokoo/koolshare.github.io/acelan_softcenter_ui/shadowsocks/version | sed -n 1p`
# rule update
echo $Date: 开始更新规则,请等待... > $LOG_FILE
#wget -q --no-check-certificate --timeout=15 https://raw.githubusercontent.com/monokoo/koolshare.github.io/acelan_softcenter_ui/maintain_files/version1 -O /tmp/version1
#旧接口https://raw.githubusercontent.com/monokoo/koolshare.github.io/acelan_softcenter_ui/maintain_files/version1
status1=`curl -w %{http_code} --connect-timeout 10 $url_main/version1 --silent -o /tmp/version1`
if [ -z "$status1" ] || [ "$status1" == "404" ];then
echo $Date: 无法访问更新接口,请更新接口! >> $LOG_FILE
exit
fi
online_content=$(cat /tmp/version1 2>/dev/null)
if [ -z "$online_content" ];then
rm -rf /tmp/version1
echo $Date: 没有检测到在线版本可能是访问github有问题去大陆白名单模式试试吧 >> $LOG_FILE
exit
fi
# update gfwlist
if [ "$gfwlist_update" == 1 ];then
gfwlist=$(cat /tmp/version1 | sed -n 1p)
version_gfwlist2=$(echo $gfwlist | sed 's/ /\n/g'| sed -n 1p)
md5sum_gfwlist2=$(echo $gfwlist | sed 's/ /\n/g'| tail -n 2 | head -n 1)
local_md5sum_gfwlist=`md5sum $DNSMASQ_PATH/gfwlist.conf |awk '{print $1}'`
if [ ! -z "$version_gfwlist2" ];then
version_gfwlist1=$(uci_get_by_type global_rules gfwlist_version)
if [ "$version_gfwlist1" != "$version_gfwlist2" -o "$md5sum_gfwlist2" != "$local_md5sum_gfwlist" ];then
echo $Date: 检测到新版本gfwlist开始更新... >> $LOG_FILE
echo $Date: 下载gfwlist到临时文件... >> $LOG_FILE
#wget --no-check-certificate --timeout=15 -q https://raw.githubusercontent.com/monokoo/koolshare.github.io/acelan_softcenter_ui/maintain_files/gfwlist.conf -O /tmp/gfwlist.conf
#旧接口https://raw.githubusercontent.com/monokoo/koolshare.github.io/acelan_softcenter_ui/maintain_files/gfwlist.conf
status2=`curl -w %{http_code} --connect-timeout 10 $url_main/gfwlist.conf --silent -o /tmp/gfwlist.conf`
if [ -z "$status2" ] || [ "$status2" == "404" ];then
echo $Date: 无法访问更新接口,请更新接口! >> $LOG_FILE
exit
fi
md5sum_gfwlist1=$(md5sum /tmp/gfwlist.conf | sed 's/ /\n/g'| sed -n 1p)
if [ "$md5sum_gfwlist1"x = "$md5sum_gfwlist2"x ];then
echo $Date: 下载完成校验通过将临时文件覆盖到原始gfwlist文件 >> $LOG_FILE
mv /tmp/gfwlist.conf $DNSMASQ_PATH/gfwlist.conf
uci set $CONFIG.@global_rules[0].gfwlist_version=$version_gfwlist2
rm -rf /tmp/dnsmasq.d/gfwlist.conf
reboot="1"
echo $Date: 你的gfwlist已经更新到最新了哦~ >> $LOG_FILE
else
echo $Date: 下载完成,但是校验没有通过! >> $LOG_FILE
fi
else
echo $Date: 检测到gfwlist本地版本号和在线版本号相同不用更新! >> $LOG_FILE
fi
else
echo $Date: gfwlist文件下载失败 >> $LOG_FILE
fi
rm -rf /tmp/gfwlist.conf
fi
# update chnroute
if [ "$chnroute_update" == 1 ];then
chnroute=$(cat /tmp/version1 | sed -n 2p)
version_chnroute2=$(echo $chnroute | sed 's/ /\n/g'| sed -n 1p)
md5sum_chnroute2=$(echo $chnroute | sed 's/ /\n/g'| tail -n 2 | head -n 1)
local_md5sum_chnroute=`md5sum $RULE_PATH/chnroute |awk '{print $1}'`
if [ ! -z "$version_chnroute2" ];then
version_chnroute1=$(uci_get_by_type global_rules chnroute_version)
if [ "$version_chnroute1" != "$version_chnroute2" -o "$md5sum_chnroute2" != "$local_md5sum_chnroute" ];then
echo $Date: 检测到新版本chnroute开始更新... >> $LOG_FILE
echo $Date: 下载chnroute到临时文件... >> $LOG_FILE
#wget --no-check-certificate --timeout=15 -q https://raw.githubusercontent.com/monokoo/koolshare.github.io/acelan_softcenter_ui/maintain_files/chnroute.txt -O /tmp/chnroute
#旧接口https://raw.githubusercontent.com/monokoo/koolshare.github.io/acelan_softcenter_ui/maintain_files/chnroute.txt
status3=`curl -w %{http_code} --connect-timeout 10 $url_main/chnroute.txt --silent -o /tmp/chnroute`
if [ -z "$status3" ] || [ "$status3" == "404" ];then
echo $Date: 无法访问更新接口,请更新接口! >> $LOG_FILE
exit
fi
md5sum_chnroute1=$(md5sum /tmp/chnroute | sed 's/ /\n/g'| sed -n 1p)
if [ "$md5sum_chnroute1"x = "$md5sum_chnroute2"x ];then
echo $Date: 下载完成校验通过将临时文件覆盖到原始chnroute文件 >> $LOG_FILE
mv /tmp/chnroute $RULE_PATH/chnroute
uci set $CONFIG.@global_rules[0].chnroute_version=$version_chnroute2
ipset flush chnroute
ipset destroy chnroute
reboot="1"
echo $Date: 你的chnroute已经更新到最新了哦~ >> $LOG_FILE
else
echo $Date: 下载完成,但是校验没有通过! >> $LOG_FILE
fi
else
echo $Date: 检测到chnroute本地版本号和在线版本号相同不用更新! >> $LOG_FILE
fi
else
echo $Date: chnroute文件下载失败 >> $LOG_FILE
fi
rm -rf /tmp/chnroute
fi
# update Routing
if [ "$Pcap_Routing_update" == 1 ];then
Routing=$(cat /tmp/version1 | sed -n 5p)
version_Routing2=$(echo $Routing | sed 's/ /\n/g'| sed -n 1p)
md5sum_Routing2=$(echo $Routing | sed 's/ /\n/g'| tail -n 2 | head -n 1)
local_md5sum_Routing=`md5sum /etc/pcap-dnsproxy/Routing.txt |awk '{print $1}'`
if [ ! -z "$version_Routing2" ];then
version_Routing1=$(uci_get_by_type global_rules pcap_Routing_version)
if [ "$version_Routing1" != "$version_Routing2" -o "$md5sum_Routing2" != "$local_md5sum_Routing" ];then
echo $Date: 检测到新版本Routing开始更新... >> $LOG_FILE
echo $Date: 下载Routing到临时文件... >> $LOG_FILE
status4=`curl -w %{http_code} --connect-timeout 10 $url_main/Routing.txt --silent -o /tmp/Routing.txt`
if [ -z "$status4" ] || [ "$status4" == "404" ];then
echo $Date: 无法访问更新接口,请更新接口! >> $LOG_FILE
exit
fi
md5sum_Routing1=$(md5sum /tmp/Routing.txt | sed 's/ /\n/g'| sed -n 1p)
if [ "$md5sum_Routing1"x = "$md5sum_Routing2"x ];then
echo $Date: 下载完成校验通过将临时文件覆盖到原始Routing文件 >> $LOG_FILE
mkdir -p /etc/pcap-dnsproxy
mv /tmp/Routing.txt /etc/pcap-dnsproxy/Routing.txt
uci set $CONFIG.@global_rules[0].pcap_Routing_version=$version_Routing2
reboot="1"
echo $Date: 你的Routing已经更新到最新了哦~ >> $LOG_FILE
else
echo $Date: 下载完成,但是校验没有通过! >> $LOG_FILE
fi
else
echo $Date: 检测到Routing本地版本号和在线版本号相同不用更新! >> $LOG_FILE
fi
else
echo $Date: Routing文件下载失败 >> $LOG_FILE
fi
rm -rf /tmp/Routing.txt
fi
# update WhiteList
if [ "$Pcap_WhiteList_update" == 1 ];then
WhiteList=$(cat /tmp/version1 | sed -n 7p)
version_WhiteList2=$(echo $WhiteList | sed 's/ /\n/g'| sed -n 1p)
md5sum_WhiteList2=$(echo $WhiteList | sed 's/ /\n/g'| tail -n 2 | head -n 1)
local_md5sum_WhiteList=`md5sum /etc/pcap-dnsproxy/WhiteList.txt |awk '{print $1}'`
if [ ! -z "$version_WhiteList2" ];then
version_WhiteList1=$(uci_get_by_type global_rules pcap_WhiteList_version)
if [ "$version_WhiteList1" != "$version_WhiteList2" -o "$md5sum_WhiteList2" != "$local_md5sum_WhiteList" ];then
echo $Date: 检测到新版本WhiteList开始更新... >> $LOG_FILE
echo $Date: 下载WhiteList到临时文件... >> $LOG_FILE
status4=`curl -w %{http_code} --connect-timeout 10 $url_main/WhiteList_new.txt --silent -o /tmp/WhiteList.txt`
if [ -z "$status4" ] || [ "$status4" == "404" ];then
echo $Date: 无法访问更新接口,请更新接口! >> $LOG_FILE
exit
fi
#wget --no-check-certificate --timeout=10 -qO - $url_main/WhiteList_new.txt > /tmp/WhiteList.txt
md5sum_WhiteList1=$(md5sum /tmp/WhiteList.txt | sed 's/ /\n/g'| sed -n 1p)
if [ "$md5sum_WhiteList1"x = "$md5sum_WhiteList2"x ];then
echo $Date: 下载完成校验通过将临时文件覆盖到原始WhiteList文件 >> $LOG_FILE
mkdir -p /etc/pcap-dnsproxy
mv /tmp/WhiteList.txt /etc/pcap-dnsproxy/WhiteList.txt
uci set $CONFIG.@global_rules[0].pcap_WhiteList_version=$version_WhiteList2
reboot="1"
echo $Date: 你的WhiteList已经更新到最新了哦~ >> $LOG_FILE
else
echo $Date: 下载完成,但是校验没有通过! >> $LOG_FILE
fi
else
echo $Date: 检测到WhiteList本地版本号和在线版本号相同不用更新! >> $LOG_FILE
fi
else
echo $Date: WhiteList文件下载失败 >> $LOG_FILE
fi
rm -rf /tmp/WhiteList.txt
fi
echo $Date: 更新进程运行完毕! >> $LOG_FILE
rm -rf /tmp/version1
# write number
uci set $CONFIG.@global_rules[0].gfwlist_update=$gfwlist_update
uci set $CONFIG.@global_rules[0].chnroute_update=$chnroute_update
uci set $CONFIG.@global_rules[0].Pcap_Routing_update=$Pcap_Routing_update
uci set $CONFIG.@global_rules[0].Pcap_WhiteList_update=$Pcap_WhiteList_update
uci commit
# reboot ss
if [ "$reboot" == "1" ];then
echo $Date: 重启软件,以应用新的规则文件!请稍后! >> $LOG_FILE
/etc/init.d/$CONFIG restart
fi
exit

View File

@ -0,0 +1,44 @@
#!/bin/sh
CONFIG=passwall
LOCK_FILE=/var/lock/${CONFIG}_subscription.lock
Date=$(date "+%Y-%m-%d %H:%M:%S")
LOG_FILE=/var/log/$CONFIG.log
config_t_get() {
local index=0
[ -n "$3" ] && index=$3
local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null)
#echo ${ret:=$3}
echo $ret
}
start() {
#防止并发开启服务
[ -f "$LOCK_FILE" ] && return 3
touch "$LOCK_FILE"
echo "$Date: 开始执行在线订阅脚本..." >> $LOG_FILE
/usr/share/$CONFIG/subscription_ssr.sh start 2>/dev/null
/usr/share/$CONFIG/subscription_v2ray.sh start 2>/dev/null
echo "$Date: 在线订阅脚本执行完毕..." >> $LOG_FILE
rm -f "$LOCK_FILE"
exit 0
}
stop() {
echo "$Date: 开始执行删除所有订阅脚本..." >> $LOG_FILE
/usr/share/$CONFIG/subscription_ssr.sh stop 2>/dev/null
/usr/share/$CONFIG/subscription_v2ray.sh stop 2>/dev/null
echo "$Date: 删除所有订阅脚本执行完毕..." >> $LOG_FILE
rm -f "$LOCK_FILE"
exit 0
}
case $1 in
stop)
stop
;;
*)
start
;;
esac

View File

@ -0,0 +1,290 @@
#!/bin/sh
CONFIG=passwall
LOCK_FILE=/var/lock/${CONFIG}_subscription_ssr.lock
Date=$(date "+%Y-%m-%d %H:%M:%S")
LOG_FILE=/var/log/$CONFIG.log
config_t_get() {
local index=0
[ -n "$3" ] && index=$3
local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null)
#echo ${ret:=$3}
echo $ret
}
config_t_set() {
index=$3
uci set $CONFIG.@$1[$index].$2=$4
}
decode_url_link(){
link=$1
num=$2
len=$((${#link}-$num))
mod4=$(($len%4))
if [ "$mod4" -gt 0 ]; then
var="===="
newlink=${link}${var:$mod4}
echo -n "$newlink" | sed 's/-/+/g; s/_/\//g' | /usr/bin/base64 -d -i 2> /dev/null
else
echo -n "$link" | sed 's/-/+/g; s/_/\//g' | /usr/bin/base64 -d -i 2> /dev/null
fi
}
get_server_index(){
[ -f "/etc/config/$CONFIG" ] && {
ssindex=$(uci show $CONFIG | grep -c "=servers")
}
}
get_local_servers(){
[ -f "/etc/config/$CONFIG" ] && [ "`uci show $CONFIG|grep -c 'AutoSuB_SSR'`" -gt 0 ] && {
get_server_index
for i in `seq $ssindex -1 1`
do
[ "$(uci show $CONFIG.@servers[$(($i-1))] | grep -c 'AutoSuB_SSR')" -eq 1 ] && {
if [ ! -f "/usr/share/$CONFIG/serverconfig_ssr/all_localservers" ]; then
echo $(config_t_get servers server $(($i-1))) > /usr/share/$CONFIG/serverconfig_ssr/all_localservers
else
echo $(config_t_get servers server $(($i-1))) >> /usr/share/$CONFIG/serverconfig_ssr/all_localservers
fi
}
done
}
}
get_remote_config(){
decode_link=$1
server=$(echo "$decode_link" |awk -F':' '{print $1}')
server_port=$(echo "$decode_link" |awk -F':' '{print $2}')
protocol=$(echo "$decode_link" |awk -F':' '{print $3}')
ssr_encrypt_method=$(echo "$decode_link" |awk -F':' '{print $4}')
obfs=$(echo "$decode_link" |awk -F':' '{print $5}')
password=$(decode_url_link $(echo "$decode_link" |awk -F':' '{print $6}'|awk -F'/' '{print $1}') 0)
obfsparm_temp=$(echo "$decode_link" |grep -Eo "obfsparam.+" |sed 's/obfsparam=//g'|awk -F'&' '{print $1}')
[ -n "$obfsparm_temp" ] && obfsparam=$(decode_url_link $obfsparm_temp 0) || obfsparam=''
protoparam_temp=$(echo "$decode_link" |grep -Eo "protoparam.+" |sed 's/protoparam=//g'|awk -F'&' '{print $1}')
[ -n "$protoparam_temp" ] && protoparam=$(decode_url_link $protoparam_temp 0) || protoparam=''
remarks_temp=$(echo "$decode_link" |grep -Eo "remarks.+" |sed 's/remarks=//g'|awk -F'&' '{print $1}')
[ -n "$remarks_temp" ] && remarks="订阅_$(decode_url_link $remarks_temp 0)" || remarks='订阅'
group_temp=$(echo "$decode_link" |grep -Eo "group.+" |sed 's/group=//g'|awk -F'&' '{print $1}')
[ -n "$group_temp" ] && group="AutoSuB_SSR_$(decode_url_link $group_temp 0)" || group='AutoSuB_SSR'
##把全部服务器节点写入文件 /usr/share/$CONFIG/serverconfig_ssr/all_onlineservers
if [ ! -f "/usr/share/$CONFIG/serverconfig_ssr/all_onlineservers" ]; then
echo $server > /usr/share/$CONFIG/serverconfig_ssr/all_onlineservers
else
echo $server >> /usr/share/$CONFIG/serverconfig_ssr/all_onlineservers
fi
}
add_servers(){
get_server_index
uci add $CONFIG servers >/dev/null
if [ -z "$1" ];then
config_t_set servers remarks $ssindex $remarks
config_t_set servers group $ssindex $group
else
config_t_set servers remarks $ssindex $remarks
fi
config_t_set servers server_type $ssindex "SSR"
config_t_set servers server $ssindex $server
config_t_set servers use_ipv6 $ssindex 0
config_t_set servers server_port $ssindex $server_port
config_t_set servers password $ssindex $password
config_t_set servers ssr_encrypt_method $ssindex $ssr_encrypt_method
config_t_set servers protocol $ssindex $protocol
config_t_set servers protocol_param $ssindex $protoparam
config_t_set servers obfs $ssindex $obfs
config_t_set servers obfs_param $ssindex $obfsparam
config_t_set servers timeout $ssindex 300
config_t_set servers fast_open $ssindex false
uci commit $CONFIG
}
update_config(){
isadded_server=$(uci show $CONFIG | grep -c "server='$server'")
if [ "$isadded_server" -eq 0 ]; then
add_servers
let addnum+=1
else
index=$(uci show $CONFIG | grep -w "server='$server'" | cut -d '[' -f2|cut -d ']' -f1)
local_server_port=$(config_t_get servers server_port $index)
local_protocol=$(config_t_get servers protocol $index)
local_protocol_param=$(config_t_get servers protocol_param $index)
local_ssr_encrypt_method=$(config_t_get servers ssr_encrypt_method $index)
local_obfs=$(config_t_get servers obfs $index)
local_password=$(config_t_get servers password $index)
local_group=$(config_t_get servers group $index)
local_remarks=$(config_t_get servers remarks $index)
local i=0
[ "$(uci show $CONFIG.@servers[$index] | grep -c "obfs_param")" -eq 0 ] && \
config_t_set servers obfs_param $index $obfsparam
if [ -n "$local_protocol_param" ]; then
if [ -n "$protoparam" ]; then
[ "$local_protocol_param" != "$protoparam" ] && config_t_set servers protocol_param $index $protoparam && let i+=1
else
config_t_set servers protocol_param $index $protoparam && let i+=1
fi
else
config_t_set servers protocol_param $index $protoparam && [ -n "$protoparam" ] && let i+=1
fi
[ "$local_server_port" != "$server_port" ] && config_t_set servers server_port $index $server_port && let i+=1
[ "$local_protocol" != "$protocol" ] && config_t_set servers protocol $index $protocol && let i+=1
[ "$local_ssr_encrypt_method" != "$ssr_encrypt_method" ] && config_t_set servers ssr_encrypt_method $index $ssr_encrypt_method && let i+=1
[ "$local_obfs" != "$obfs" ] && config_t_set servers obfs $index $obfs && let i+=1
[ "$local_password" != "$password" ] && config_t_set servers password $index $password && let i+=1
[ "$local_group" != "$group" ] && config_t_set servers group $index $group
[ "$local_remarks" != "$remarks" ] && config_t_set servers remarks $index $remarks
[ "$i" -gt 0 ] && uci commit $CONFIG && let updatenum+=1
fi
}
del_config(){
##删除订阅服务器已经不存在的节点
for localserver in $(cat /usr/share/$CONFIG/serverconfig_ssr/all_localservers)
do
[ "`cat /usr/share/$CONFIG/serverconfig_ssr/all_onlineservers |grep -c "$localserver"`" -eq 0 ] && {
for localindex in $(uci show $CONFIG|grep -w "$localserver" |grep -w "server=" |cut -d '[' -f2|cut -d ']' -f1)
do
uci delete $CONFIG.@servers[$localindex]
uci commit $CONFIG
let delnum+=1 #删除该节点
done
}
done
}
del_all_config(){
get_server_index
[ "`uci show $CONFIG | grep -c 'AutoSuB_SSR'`" -eq 0 ] && exit 0
current_tcp_redir_server=$(config_t_get global tcp_redir_server)
is_sub_server=`uci -q get $CONFIG.$current_tcp_redir_server.group`
for i in `seq $ssindex -1 1`
do
[ "$(uci show $CONFIG.@servers[$(($i-1))] | grep -c 'AutoSuB_SSR')" -eq 1 ] && uci delete $CONFIG.@servers[$(($i-1))] && uci commit $CONFIG
done
[ -n "$is_sub_server" ] && {
config_t_set global tcp_redir_server 0 'nil'
uci commit $CONFIG && /etc/init.d/$CONFIG stop
}
}
get_ss_config(){
decode_link=$1
server=$(echo "$decode_link" |awk -F':' '{print $2}'|awk -F'@' '{print $2}')
server_port=$(echo "$decode_link" |awk -F':' '{print $3}')
ssr_encrypt_method=$(echo "$decode_link" |awk -F':' '{print $1}')
password=$(echo "$decode_link" |awk -F':' '{print $2}'|awk -F'@' '{print $1}')
}
add() {
SSR_LINKS=$(cat /tmp/ssr_links.conf 2>/dev/null)
[ -n "$SSR_LINKS" ] && {
[ -f "$LOCK_FILE" ] && return 3
touch "$LOCK_FILE"
mkdir -p /usr/share/$CONFIG/serverconfig_ssr
rm -f /usr/share/$CONFIG/serverconfig_ssr/*
for ssrlink in $SSR_LINKS
do
if [ -n "`echo -n "$ssrlink" | grep 'ssr://'`" ]; then
new_ssrlink=`echo -n "$ssrlink" | sed 's/ssr:\/\///g'`
decode_ssrlink=$(decode_url_link $new_ssrlink 1)
get_remote_config "$decode_ssrlink"
is_added=$(uci show $CONFIG | grep -v 'AutoSuB_SSR' | grep -c "server='$server'")
[ "$is_added" -gt 0 ] && continue
add_servers 1
else
if [ -n "`echo -n "$ssrlink" | grep '#'`" ]; then
new_sslink=`echo -n "$ssrlink" | awk -F'#' '{print $1}' | sed 's/ss:\/\///g'`
remarks=`echo -n "$ssrlink" | awk -F'#' '{print $2}'`
else
new_sslink=`echo -n "$ssrlink" | sed 's/ss:\/\///g'`
remarks='AddedByLink'
fi
decode_sslink=$(decode_url_link $new_sslink 1)
get_ss_config $decode_sslink
is_added=$(uci show $CONFIG | grep -v 'AutoSuB_SSR' | grep -c "server='$server'")
[ "$is_added" -gt 0 ] && continue
fi
done
[ -f "/usr/share/$CONFIG/serverconfig_ssr/all_onlineservers" ] && rm -f /usr/share/$CONFIG/serverconfig_ssr/all_onlineservers
}
rm -f /tmp/ssr_links.conf
rm -f "$LOCK_FILE"
exit 0
}
start() {
#防止并发开启服务
[ -f "$LOCK_FILE" ] && return 3
touch "$LOCK_FILE"
addnum=0
updatenum=0
delnum=0
baseurl_ssr=$(uci get $CONFIG.@global_subscribe[0].baseurl_ssr) ##SSR订阅地址
[ -z "$baseurl_ssr" ] && echo "$Date: SSR订阅地址为空跳过" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0
echo "$Date: 开始订阅SSR..." >> $LOG_FILE
[ ! -d "/usr/share/$CONFIG/onlineurl_ssr" ] && mkdir -p /usr/share/$CONFIG/onlineurl_ssr
[ ! -d "/usr/share/$CONFIG/serverconfig_ssr" ] && mkdir -p /usr/share/$CONFIG/serverconfig_ssr
rm -f /usr/share/$CONFIG/onlineurl_ssr/*
/usr/bin/wget --no-check-certificate --timeout=8 -t 2 $baseurl_ssr -P /usr/share/$CONFIG/onlineurl_ssr
[ ! -d "/usr/share/$CONFIG/onlineurl_ssr" ] || [ "$(ls /usr/share/$CONFIG/onlineurl_ssr |wc -l)" -eq 0 ] && echo "$Date: 订阅链接下载失败,请重试!" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0
rm -f /usr/share/$CONFIG/serverconfig_ssr/*
get_local_servers
for file in /usr/share/$CONFIG/onlineurl_ssr/*
do
[ -z "$(du -sh $file 2> /dev/null)" ] && echo "$Date: 订阅链接下载 $file 失败,请重试!" >> $LOG_FILE && continue
maxnum=$(cat "$file" | /usr/bin/base64 -d 2> /dev/null| grep "MAX=" |awk -F"=" '{print $2}')
if [ -n "$maxnum" ]; then
urllinks=$(cat "$file" | /usr/bin/base64 -d 2> /dev/null| sed '/MAX=/d' | shuf -n${maxnum} | sed 's/ssr:\/\///g')
else
urllinks=$(cat "$file" | /usr/bin/base64 -d 2> /dev/null| sed 's/ssr:\/\///g')
fi
[ -z "$urllinks" ] && continue
for link in $urllinks
do
decode_link=$(decode_url_link $link 1)
get_remote_config "$decode_link"
update_config
done
done
[ -f "/usr/share/$CONFIG/serverconfig_ssr/all_localservers" ] && del_config
echo "$Date: 本次更新SSR新增服务器节点 $addnum 个,修改 $updatenum 个,删除 $delnum 个。" >> $LOG_FILE
rm -f "$LOCK_FILE"
exit 0
}
stop() {
[ "`uci show $CONFIG | grep -c 'AutoSuB_SSR'`" -gt 0 ] && {
echo "$Date: 在线订阅SSR节点已全部删除" >> $LOG_FILE
del_all_config
}
rm -rf /usr/share/$CONFIG/onlineurl_ssr
rm -rf /usr/share/$CONFIG/serverconfig_ssr
rm -f "$LOCK_FILE"
exit 0
}
case $1 in
stop)
stop
;;
add)
add
;;
*)
start
;;
esac

View File

@ -0,0 +1,249 @@
#!/bin/sh
. /usr/share/libubox/jshn.sh
CONFIG=passwall
LOCK_FILE=/var/lock/${CONFIG}_subscription_v2ray.lock
Date=$(date "+%Y-%m-%d %H:%M:%S")
LOG_FILE=/var/log/$CONFIG.log
config_t_get() {
local index=0
[ -n "$3" ] && index=$3
local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null)
#echo ${ret:=$3}
echo $ret
}
config_t_set() {
index=$3
uci set $CONFIG.@$1[$index].$2=$4
}
decode_url_link(){
link=$1
num=$2
len=$((${#link}-$num))
mod4=$(($len%4))
if [ "$mod4" -gt 0 ]; then
var="===="
newlink=${link}${var:$mod4}
echo -n "$newlink" | sed 's/-/+/g; s/_/\//g' | /usr/bin/base64 -d -i 2> /dev/null
else
echo -n "$link" | sed 's/-/+/g; s/_/\//g' | /usr/bin/base64 -d -i 2> /dev/null
fi
}
get_remote_config(){
json_load "$1"
json_get_var v v
json_get_var ps ps
json_get_var server add
json_get_var server_port port
json_get_var id id
json_get_var aid aid
json_get_var net net
json_get_var type type
json_get_var transport net
json_get_var tls tls
json_get_var ws_host host
json_get_var ws_path path
if [ "$tls" == "1" ]; then
tls="tls"
else
tls="none"
fi
remarks="订阅_$ps"
group='AutoSuB_V2ray'
##把全部服务器节点写入文件 /usr/share/$CONFIG/serverconfig_v2ray/all_onlineservers
if [ ! -f "/usr/share/$CONFIG/serverconfig_v2ray/all_onlineservers" ]; then
echo $server > /usr/share/$CONFIG/serverconfig_v2ray/all_onlineservers
else
echo $server >> /usr/share/$CONFIG/serverconfig_v2ray/all_onlineservers
fi
}
get_server_index(){
[ -f "/etc/config/$CONFIG" ] && {
v2ray_index=$(uci show $CONFIG | grep -c "=servers")
}
}
get_local_servers(){
[ -f "/etc/config/$CONFIG" ] && [ "`uci show $CONFIG | grep -c 'AutoSuB_V2ray'`" -gt 0 ] && {
get_server_index
for i in `seq $v2ray_index -1 1`
do
[ "$(uci show $CONFIG.@servers[$(($i-1))]|grep -c "AutoSuB_V2ray")" -eq 1 ] && {
if [ ! -f "/usr/share/$CONFIG/serverconfig_v2ray/all_localservers" ]; then
echo $(config_t_get servers server $(($i-1))) > /usr/share/$CONFIG/serverconfig_v2ray/all_localservers
else
echo $(config_t_get servers server $(($i-1))) >> /usr/share/$CONFIG/serverconfig_v2ray/all_localservers
fi
}
done
}
}
add_servers(){
get_server_index
uci add $CONFIG servers >/dev/null
if [ -z "$1" ];then
config_t_set servers remarks $v2ray_index $remarks
config_t_set servers group $v2ray_index $group
else
config_t_set servers remarks $v2ray_index $remarks
fi
config_t_set servers server_type $v2ray_index 'V2ray'
config_t_set servers v2ray_protocol $v2ray_index 'vmess'
config_t_set servers server $v2ray_index $server
config_t_set servers use_ipv6 $v2ray_index 0
config_t_set servers server_port $v2ray_index $server_port
config_t_set servers v2ray_security $v2ray_index 'auto'
config_t_set servers v2ray_VMess_id $v2ray_index $id
config_t_set servers v2ray_VMess_alterId $v2ray_index $aid
config_t_set servers v2ray_VMess_level $v2ray_index $v
config_t_set servers v2ray_transport $v2ray_index $net
config_t_set servers v2ray_stream_security $v2ray_index $tls
config_t_set servers v2ray_tcp_guise $v2ray_index $type
config_t_set servers v2ray_ws_host $v2ray_index $ws_host
config_t_set servers v2ray_ws_path $v2ray_index $ws_path
uci commit $CONFIG
}
update_config(){
isadded_server=$(uci show $CONFIG | grep -c "server='$server'")
if [ "$isadded_server" -eq 0 ]; then
add_servers
let addnum+=1
else
index=$(uci show $CONFIG | grep -w "server='$server'" | cut -d '[' -f2|cut -d ']' -f1)
local_server_port=$(config_t_get servers server_port $index)
local_vmess_id=$(config_t_get servers v2ray_VMess_id $index)
fi
}
del_config(){
# 删除订阅服务器已经不存在的节点
for localserver in $(cat /usr/share/$CONFIG/serverconfig_v2ray/all_localservers)
do
[ "`cat /usr/share/$CONFIG/serverconfig_v2ray/all_onlineservers |grep -c "$localserver"`" -eq 0 ] && {
for localindex in $(uci show $CONFIG|grep -w "$localserver" |grep -w "server=" |cut -d '[' -f2|cut -d ']' -f1)
do
uci delete $CONFIG.@servers[$localindex]
uci commit $CONFIG
let delnum+=1 #删除该节点
done
}
done
}
del_all_config(){
get_server_index
[ "`uci show $CONFIG | grep -c 'AutoSuB_V2ray'`" -eq 0 ] && exit 0
current_tcp_redir_server=$(config_t_get global tcp_redir_server)
is_sub_server=`uci -q get $CONFIG.$current_tcp_redir_server.group`
for i in `seq $v2ray_index -1 1`
do
[ "$(uci show $CONFIG.@servers[$(($i-1))] | grep -c 'AutoSuB_V2ray')" -eq 1 ] && uci delete $CONFIG.@servers[$(($i-1))] && uci commit $CONFIG
done
[ -n "$is_sub_server" ] && {
config_t_set global tcp_redir_server 0 'nil'
uci commit $CONFIG && /etc/init.d/$CONFIG stop
}
}
add() {
V2RAY_LINKS=$(cat /tmp/v2ray_links.conf 2>/dev/null)
[ -n "$V2RAY_LINKS" ] && {
[ -f "$LOCK_FILE" ] && return 3
touch "$LOCK_FILE"
mkdir -p /usr/share/$CONFIG/serverconfig_v2ray
rm -f /usr/share/$CONFIG/serverconfig_v2ray/*
for v2ray_link in $V2RAY_LINKS
do
if [ -n "`echo -n "$v2ray_link" | grep 'vmess://'`" ]; then
new_v2ray_link=`echo -n "$v2ray_link" | sed 's/vmess:\/\///g'`
decode_v2ray_link=$(decode_url_link $new_v2ray_link 1)
get_remote_config "$decode_v2ray_link"
is_added=$(uci show $CONFIG | grep -v "AutoSuB_V2ray" | grep -c "server='$server'")
[ "$is_added" -gt 0 ] && continue
add_servers 1
fi
done
[ -f "/usr/share/$CONFIG/serverconfig_v2ray/all_onlineservers" ] && rm -f /usr/share/$CONFIG/serverconfig_v2ray/all_onlineservers
}
rm -f /tmp/v2ray_links.conf
rm -f "$LOCK_FILE"
exit 0
}
start() {
#防止并发开启服务
[ -f "$LOCK_FILE" ] && return 3
touch "$LOCK_FILE"
addnum=0
updatenum=0
delnum=0
baseurl_v2ray=$(uci get $CONFIG.@global_subscribe[0].baseurl_v2ray) ##V2ray订阅地址
[ -z "$baseurl_v2ray" ] && echo "$Date: V2ray订阅地址为空跳过" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0
echo "$Date: 开始订阅V2ray..." >> $LOG_FILE
[ ! -d "/usr/share/$CONFIG/onlineurl_v2ray" ] && mkdir -p /usr/share/$CONFIG/onlineurl_v2ray
[ ! -d "/usr/share/$CONFIG/serverconfig_v2ray" ] && mkdir -p /usr/share/$CONFIG/serverconfig_v2ray
rm -f /usr/share/$CONFIG/onlineurl_v2ray/*
/usr/bin/wget --no-check-certificate --timeout=8 -t 2 $baseurl_v2ray -P /usr/share/$CONFIG/onlineurl_v2ray
[ ! -d "/usr/share/$CONFIG/onlineurl_v2ray" ] || [ "$(ls /usr/share/$CONFIG/onlineurl_v2ray |wc -l)" -eq 0 ] && echo "$Date: 订阅链接下载失败,请重试!" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0
rm -f /usr/share/$CONFIG/serverconfig_v2ray/*
get_local_servers
for file in /usr/share/$CONFIG/onlineurl_v2ray/*
do
[ -z "$(du -sh $file 2> /dev/null)" ] && echo "$Date: 订阅链接下载 $file 失败,请重试!" >> $LOG_FILE && continue
maxnum=$(cat "$file" | /usr/bin/base64 -d 2> /dev/null| grep "MAX=" |awk -F"=" '{print $2}')
if [ -n "$maxnum" ]; then
urllinks=$(cat "$file" | /usr/bin/base64 -d 2> /dev/null| sed '/MAX=/d' | shuf -n${maxnum} | sed 's/vmess:\/\///g')
else
urllinks=$(cat "$file" | /usr/bin/base64 -d 2> /dev/null| sed 's/vmess:\/\///g')
fi
[ -z "$urllinks" ] && continue
for link in $urllinks
do
decode_link=$(decode_url_link $link 1)
get_remote_config "$decode_link"
update_config
done
done
[ -f "/usr/share/$CONFIG/serverconfig_v2ray/all_localservers" ] && del_config
echo "$Date: 本次更新V2ray新增服务器节点 $addnum 个,修改 $updatenum 个,删除 $delnum 个。" >> $LOG_FILE
rm -f "$LOCK_FILE"
exit 0
}
stop() {
[ "`uci show $CONFIG | grep -c 'AutoSuB_V2ray'`" -gt 0 ] && {
echo "$Date: 在线订阅V2ray节点已全部删除" >> $LOG_FILE
del_all_config
}
rm -rf /usr/share/$CONFIG/onlineurl_v2ray
rm -rf /usr/share/$CONFIG/serverconfig_v2ray
rm -f "$LOCK_FILE"
exit 0
}
case $1 in
stop)
stop
;;
add)
add
;;
*)
start
;;
esac

View File

@ -0,0 +1,132 @@
#!/bin/sh
CONFIG=passwall
LOCK_FILE=/var/lock/passwall_test.lock
get_date(){
echo "$(date "+%Y-%m-%d %H:%M:%S")"
}
test_url(){
status=$(curl -I -o /dev/null -s --connect-timeout 5 -w %{http_code} "$1" |grep 200)
echo $status
}
test_proxy(){
result=0
status=$(test_url "https://www.google.com")
if [ "$status" = "200" ];then
result=0
else
status2=$(test_url "https://www.baidu.com")
if [ "$status2" = "200" ];then
result=1
else
result=2
fi
fi
echo $result
}
test_auto_switch(){
if [ -f "/var/etc/passwall/tcp_server_id" ];then
TCP_REDIR_SERVER=`cat /var/etc/passwall/tcp_server_id`
else
rm -f $LOCK_FILE
exit 1
fi
failcount=1
while [ "$failcount" -lt "6" ]
do
status=$(test_proxy)
if [ "$status" == 2 ];then
echo "$(get_date): 自动切换检测:无法连接到网络,请检查网络是否正常!" >> /var/log/passwall.log
break
elif [ "$status" == 1 ];then
echo "$(get_date): 自动切换检测:第$failcount次检测异常" >> /var/log/passwall.log
let "failcount++"
[ "$failcount" -ge 6 ] && {
echo "$(get_date): 自动切换检测:检测异常,切换节点" >> /var/log/passwall.log
TCP_REDIR_SERVERS=`uci get passwall.@auto_switch[0].tcp_redir_server`
has_backup_server=`echo $TCP_REDIR_SERVERS | grep $TCP_REDIR_SERVER`
setserver=
if [ -z "$has_backup_server" ];then
setserver=`echo $TCP_REDIR_SERVERS | awk -F ' ' '{print $1}'`
else
setserver=$TCP_REDIR_SERVER
flag=0
for server in $has_backup_server
do
if [ "$flag" == 0 ];then
if [ "$TCP_REDIR_SERVER" == "$server" ];then
flag=1
continue
fi
fi
if [ "$flag" == 1 ];then
flag=2
continue
fi
if [ "$flag" == 2 ];then
setserver=$server
break
fi
done
fi
rm -f $LOCK_FILE
uci set passwall.@global[0].tcp_redir_server=$setserver
uci commit passwall
/etc/init.d/passwall restart
exit 1
}
sleep 5s
elif [ "$status" == 0 ];then
echo "$(get_date): 自动切换检测:检测正常" >> /var/log/passwall.log
break
fi
done
}
test_reconnection(){
failcount=1
while [ "$failcount" -lt "6" ]
do
status=$(test_proxy)
if [ "$status" == 2 ];then
echo "$(get_date): 掉线重连检测:无法连接到网络,请检查网络是否正常!" >> /var/log/passwall.log
break
elif [ "$status" == 1 ];then
echo "$(get_date): 掉线重连检测:第$failcount次检测异常" >> /var/log/passwall.log
let "failcount++"
[ "$failcount" -ge 6 ] && {
echo "$(get_date): 掉线重连检测:检测异常,重启服务" >> /var/log/passwall.log
rm -f $LOCK_FILE
/etc/init.d/passwall restart
exit 1
}
sleep 5s
elif [ "$status" == 0 ];then
echo "$(get_date): 掉线重连检测:检测正常" >> /var/log/passwall.log
break
fi
done
}
#防止并发执行
if [ -f "$LOCK_FILE" ];then
exit 1
else
touch $LOCK_FILE
fi
is_auto_switch=`uci show $CONFIG.@auto_switch[0] | grep "tcp_redir_server"`
if [ -z "$is_auto_switch" ];then
test_reconnection
else
test_auto_switch
fi
rm -f $LOCK_FILE
exit