luci-app-passwall: sync with upstream source
This commit is contained in:
parent
146b56b822
commit
105f3763b0
@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=3.6
|
||||
PKG_RELEASE:=16
|
||||
PKG_DATE:=20200306
|
||||
PKG_RELEASE:=18
|
||||
PKG_DATE:=20200308
|
||||
|
||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
@ -85,7 +85,7 @@ define Package/$(PKG_NAME)
|
||||
SUBMENU:=3. Applications
|
||||
TITLE:=LuCI support for PassWall
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+libmbedtls +iptables-mod-tproxy +kmod-ipt-tproxy +iptables-mod-ipopt +kmod-ipt-ipopt +ip +ipset +coreutils +coreutils-base64 +coreutils-nohup +luci-lib-jsonc \
|
||||
DEPENDS:=+libmbedtls +iptables-mod-tproxy +ip +ipset +coreutils +coreutils-base64 +coreutils-nohup +luci-lib-jsonc \
|
||||
+wget +resolveip +unzip +dnsmasq-full +tcping \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_ipt2socks:ipt2socks \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks:shadowsocks-libev-ss-redir \
|
||||
|
||||
@ -33,8 +33,9 @@ function index()
|
||||
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", "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", "log"}, form("passwall/log"),
|
||||
@ -115,7 +116,7 @@ end
|
||||
function clear_log() luci.sys.call("echo '' > /var/log/passwall.log") end
|
||||
|
||||
function status()
|
||||
-- local dns_mode = luci.sys.exec("echo -n `uci -q get " .. appname .. ".@global[0].dns_mode`")
|
||||
-- local dns_mode = luci.sys.exec("echo -n $(uci -q get " .. appname .. ".@global[0].dns_mode)")
|
||||
local e = {}
|
||||
e.dns_mode_status = luci.sys.call("netstat -apn | grep 7913 >/dev/null") ==
|
||||
0
|
||||
@ -123,7 +124,7 @@ function status()
|
||||
"ps -w | grep -v grep | grep '%s/bin/' | grep haproxy >/dev/null",
|
||||
appname)) == 0
|
||||
local tcp_node_num = luci.sys.exec(
|
||||
"echo -n `uci -q get %s.@global_other[0].tcp_node_num`" %
|
||||
"echo -n $(uci -q get %s.@global_other[0].tcp_node_num)" %
|
||||
appname)
|
||||
for i = 1, tcp_node_num, 1 do
|
||||
e["kcptun_tcp_node%s_status" % i] =
|
||||
@ -137,7 +138,7 @@ function status()
|
||||
end
|
||||
|
||||
local udp_node_num = luci.sys.exec(
|
||||
"echo -n `uci -q get %s.@global_other[0].udp_node_num`" %
|
||||
"echo -n $(uci -q get %s.@global_other[0].udp_node_num)" %
|
||||
appname)
|
||||
for i = 1, udp_node_num, 1 do
|
||||
e["udp_node%s_status" % i] = luci.sys.call(
|
||||
@ -147,7 +148,7 @@ function status()
|
||||
end
|
||||
|
||||
local socks5_node_num = luci.sys.exec(
|
||||
"echo -n `uci -q get %s.@global_other[0].socks5_node_num`" %
|
||||
"echo -n $(uci -q get %s.@global_other[0].socks5_node_num)" %
|
||||
appname)
|
||||
for i = 1, socks5_node_num, 1 do
|
||||
e["kcptun_socks_node%s_status" % i] =
|
||||
@ -169,11 +170,11 @@ function connect_status()
|
||||
local start_time = os.time()
|
||||
if luci.http.formvalue("type") == "google" then
|
||||
e.status = luci.sys.call(
|
||||
"echo `/usr/share/passwall/test.sh test_url 'www.google.com'` | grep 200 >/dev/null") ==
|
||||
"echo $(/usr/share/passwall/test.sh test_url 'www.google.com') | grep 200 >/dev/null") ==
|
||||
0
|
||||
else
|
||||
e.status = luci.sys.call(
|
||||
"echo `/usr/share/passwall/test.sh test_url 'www.baidu.com'` | grep 200 >/dev/null") ==
|
||||
"echo $(/usr/share/passwall/test.sh test_url 'www.baidu.com') | grep 200 >/dev/null") ==
|
||||
0
|
||||
end
|
||||
local use_time = os.difftime(os.time(), start_time)
|
||||
@ -188,18 +189,18 @@ function ping_node()
|
||||
local port = luci.http.formvalue("port")
|
||||
local e = {}
|
||||
e.index = index
|
||||
if luci.sys.exec("echo -n `uci -q get %s.@global_other[0].use_tcping`" %
|
||||
if luci.sys.exec("echo -n $(uci -q get %s.@global_other[0].use_tcping)" %
|
||||
appname) == "1" and
|
||||
luci.sys.exec("echo -n $(command -v tcping)") ~= "" then
|
||||
luci.sys.call(string.format(
|
||||
"ps -w | grep 'tcping -q -c 1 -i 1 -p %s %s' | grep -v grep | awk '{print $1}' | xargs kill -9 > /dev/null",
|
||||
port, address))
|
||||
e.ping = luci.sys.exec(string.format(
|
||||
"echo -n $(tcping -q -c 1 -i 1 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print$2}')",
|
||||
"echo -n $(tcping -q -c 1 -i 1 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print$2}') 2>/dev/null",
|
||||
port, address))
|
||||
luci.sys.call(string.format(
|
||||
"ps -w | grep 'tcping -q -c 1 -i 1 -p %s %s' | grep -v grep | awk '{print $1}' | xargs kill -9 2>/dev/null",
|
||||
port, address))
|
||||
else
|
||||
e.ping = luci.sys.exec(
|
||||
"echo -n `ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print$2}'`" %
|
||||
"echo -n $(ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print$2}') 2>/dev/null" %
|
||||
address)
|
||||
end
|
||||
luci.http.prepare_content("application/json")
|
||||
@ -241,8 +242,8 @@ function check_port()
|
||||
(s.v2ray_transport and s.v2ray_transport == "mkcp" and s.port) then
|
||||
else
|
||||
local type = s.type
|
||||
if type and type ~= "V2ray_balancing" and s.address and s.port and
|
||||
s.remarks then
|
||||
if type and type ~= "V2ray_balancing" and type ~= "V2ray_shunt" and
|
||||
s.address and s.port and s.remarks then
|
||||
node_name = "%s:[%s] %s:%s" %
|
||||
{s.type, s.remarks, s.address, s.port}
|
||||
tcp_socket = nixio.socket("inet", "stream")
|
||||
@ -279,7 +280,8 @@ function luci_check()
|
||||
end
|
||||
|
||||
function luci_update()
|
||||
local json = passwall.update_luci(http.formvalue("url"), http.formvalue("save"))
|
||||
local json = passwall.update_luci(http.formvalue("url"),
|
||||
http.formvalue("save"))
|
||||
http_write_json(json)
|
||||
end
|
||||
|
||||
|
||||
@ -32,7 +32,9 @@ o = s:option(Value, "testing_time", translate("How often is a diagnosis made"),
|
||||
o.default = "3"
|
||||
|
||||
---- TCP Node
|
||||
local tcp_node_num = tonumber(api.uci_get_type("global_other", "tcp_node_num", 1))
|
||||
-- local tcp_node_num = tonumber(api.uci_get_type("global_other", "tcp_node_num", 1))
|
||||
-- 暂时只支持TCP1
|
||||
local tcp_node_num = 1
|
||||
for i = 1, tcp_node_num, 1 do
|
||||
o = s:option(DynamicList, "tcp_node" .. i,
|
||||
"TCP " .. i .. " " .. translate("List of backup nodes"),
|
||||
|
||||
@ -499,12 +499,6 @@ clean_log() {
|
||||
|
||||
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 "*/1 * * * * nohup $APP_PATH/monitor.sh > /dev/null 2>&1" >>/etc/crontabs/root
|
||||
echolog "已启动守护进程。"
|
||||
fi
|
||||
|
||||
auto_on=$(config_t_get global_delay auto_on 0)
|
||||
if [ "$auto_on" = "1" ]; then
|
||||
time_off=$(config_t_get global_delay time_off)
|
||||
@ -524,24 +518,15 @@ start_crontab() {
|
||||
}
|
||||
fi
|
||||
|
||||
AUTO_SWITCH_ENABLE=$(config_t_get auto_switch enable 0)
|
||||
[ "$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分钟执行自动切换检测脚本。"
|
||||
}
|
||||
}
|
||||
|
||||
autoupdate=$(config_t_get global_rules auto_update)
|
||||
weekupdate=$(config_t_get global_rules week_update)
|
||||
dayupdate=$(config_t_get global_rules time_update)
|
||||
#if [ "$autoupdate" = "1" ]; then
|
||||
# local t="0 $dayupdate * * $weekupdate"
|
||||
# [ "$weekupdate" = "7" ] && t="0 $dayupdate * * *"
|
||||
# echo "$t lua $APP_PATH/rule_update.lua nil log > /dev/null 2>&1 &" >>/etc/crontabs/root
|
||||
# echolog "配置定时任务:自动更新规则。"
|
||||
#fi
|
||||
if [ "$autoupdate" = "1" ]; then
|
||||
local t="0 $dayupdate * * $weekupdate"
|
||||
[ "$weekupdate" = "7" ] && t="0 $dayupdate * * *"
|
||||
echo "$t lua $APP_PATH/rule_update.lua nil log > /dev/null 2>&1 &" >>/etc/crontabs/root
|
||||
echolog "配置定时任务:自动更新规则。"
|
||||
fi
|
||||
|
||||
autoupdatesubscribe=$(config_t_get global_subscribe auto_update_subscribe)
|
||||
weekupdatesubscribe=$(config_t_get global_subscribe week_update_subscribe)
|
||||
@ -553,13 +538,18 @@ start_crontab() {
|
||||
echolog "配置定时任务:自动更新节点订阅。"
|
||||
fi
|
||||
|
||||
start_daemon=$(config_t_get global_delay start_daemon 0)
|
||||
[ "$start_daemon" = "1" ] && $APP_PATH/monitor.sh > /dev/null 2>&1 &
|
||||
|
||||
AUTO_SWITCH_ENABLE=$(config_t_get auto_switch enable 0)
|
||||
[ "$AUTO_SWITCH_ENABLE" = "1" ] && $APP_PATH/test.sh > /dev/null 2>&1 &
|
||||
|
||||
/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/${CONFIG}_test.lock >/dev/null 2>&1 &
|
||||
/etc/init.d/cron restart
|
||||
echolog "清除定时执行命令。"
|
||||
}
|
||||
@ -932,9 +922,9 @@ start() {
|
||||
add_dnsmasq
|
||||
source $APP_PATH/iptables.sh start
|
||||
gen_include
|
||||
start_crontab
|
||||
/etc/init.d/dnsmasq restart >/dev/null 2>&1 &
|
||||
echolog "运行完成!\n"
|
||||
start_crontab
|
||||
rm -f "$LOCK_FILE"
|
||||
return 0
|
||||
}
|
||||
@ -954,7 +944,9 @@ stop() {
|
||||
source $APP_PATH/iptables.sh stop
|
||||
flush_include
|
||||
kill_all v2ray-plugin obfs-local
|
||||
ps -w | grep -E "$TMP_PATH" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
|
||||
ps -w | grep -v "grep" | grep $CONFIG/test.sh | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
|
||||
ps -w | grep -v "grep" | grep $CONFIG/monitor.sh | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
|
||||
ps -w | grep -v "grep" | grep -E "$TMP_PATH" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
|
||||
rm -rf $TMP_DNSMASQ_PATH $TMP_PATH
|
||||
stop_dnsmasq
|
||||
stop_crontab
|
||||
|
||||
@ -15,8 +15,17 @@ config_t_get() {
|
||||
echo ${ret:=$3}
|
||||
}
|
||||
|
||||
if [ "$(ps -w | grep -v grep | grep $CONFIG/monitor.sh | wc -l)" -gt 2 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ENABLED=$(config_t_get global enabled 0)
|
||||
[ "$ENABLED" == "1" ] && {
|
||||
[ "$ENABLED" != 1 ] && return 1
|
||||
ENABLED=$(config_t_get global_delay start_daemon 0)
|
||||
[ "$ENABLED" != 1 ] && return 1
|
||||
sleep 1m
|
||||
while [ "$ENABLED" -eq 1 ]
|
||||
do
|
||||
TCP_NODE_NUM=$(config_t_get global_other tcp_node_num 1)
|
||||
for i in $(seq 1 $TCP_NODE_NUM); do
|
||||
eval TCP_NODE$i=$(config_t_get global tcp_node$i nil)
|
||||
@ -56,7 +65,6 @@ ENABLED=$(config_t_get global enabled 0)
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
#udp
|
||||
for i in $(seq 1 $UDP_NODE_NUM); do
|
||||
eval tmp_node=\$UDP_NODE$i
|
||||
@ -99,4 +107,6 @@ ENABLED=$(config_t_get global enabled 0)
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
sleep 1m
|
||||
done
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
------------------------------------------------
|
||||
-- This file from luci-app-ssr-plus transplant to luci-app-passwall
|
||||
-- This file is part of the luci-app-ssr-plus subscribe.lua
|
||||
@ -16,20 +17,19 @@ local tinsert = table.insert
|
||||
local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string.char, string.byte, string.format, string.gsub
|
||||
local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify
|
||||
local b64decode = nixio.bin.b64decode
|
||||
local cache = {}
|
||||
local nodeResult = setmetatable({}, { __index = cache }) -- update result
|
||||
local name = 'passwall'
|
||||
local nodeResult = {} -- update result
|
||||
local application = 'passwall'
|
||||
local uciType = 'nodes'
|
||||
local ucic = luci.model.uci.cursor()
|
||||
local arg2 = arg[2]
|
||||
|
||||
local log = function(...)
|
||||
if arg2 then
|
||||
local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({ ... }, " ")
|
||||
local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ")
|
||||
if arg2 == "log" then
|
||||
local f,err = io.open("/var/log/passwall.log","a")
|
||||
local f, err = io.open("/var/log/passwall.log", "a")
|
||||
if f and err == nil then
|
||||
f:write(result.."\n")
|
||||
f:write(result .. "\n")
|
||||
f:close()
|
||||
end
|
||||
elseif arg2 == "print" then
|
||||
@ -38,10 +38,50 @@ local log = function(...)
|
||||
end
|
||||
end
|
||||
|
||||
-- 获取各项动态配置的当前服务器,可以用 get 和 set, get必须要获取到节点表
|
||||
local CONFIG = {}
|
||||
do
|
||||
local function import_config(protocol)
|
||||
local node_num = ucic:get_first(application, "global_other", protocol .. "_node_num", 1)
|
||||
for i = 1, node_num, 1 do
|
||||
local name = string.upper(protocol)
|
||||
local option = protocol .. "_node" .. i
|
||||
local szType = "global"
|
||||
local json = {
|
||||
remarks = name .. "节点" .. i,
|
||||
type = szType,
|
||||
option = option,
|
||||
set = function(server)
|
||||
ucic:set(application, ucic:get_first(application, szType), option, server)
|
||||
end
|
||||
}
|
||||
CONFIG[name .. "_NODE" .. i] = json
|
||||
end
|
||||
end
|
||||
import_config("tcp")
|
||||
import_config("udp")
|
||||
import_config("socks5")
|
||||
|
||||
for k, v in pairs(CONFIG) do
|
||||
local currentNode
|
||||
if v.get then
|
||||
currentNode = v.get()
|
||||
else
|
||||
local cfgid = ucic:get_first(application, v.type, v.option)
|
||||
if cfgid then currentNode = ucic:get_all(application, cfgid) end
|
||||
end
|
||||
if currentNode then
|
||||
CONFIG[k].currentNode = currentNode
|
||||
else
|
||||
CONFIG[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 分割字符串
|
||||
local function split(full, sep)
|
||||
if full then
|
||||
full = full:gsub("%z", "") -- 这里不是很清楚 有时候结尾带个\0
|
||||
full = full:gsub("%z", "") -- 这里不是很清楚 有时候结尾带个\0
|
||||
local off, result = 1, {}
|
||||
while true do
|
||||
local nStart, nEnd = full:find(sep, off)
|
||||
@ -61,9 +101,7 @@ local function split(full, sep)
|
||||
return {}
|
||||
end
|
||||
-- urlencode
|
||||
local function get_urlencode(c)
|
||||
return sformat("%%%02X", sbyte(c))
|
||||
end
|
||||
local function get_urlencode(c) return sformat("%%%02X", sbyte(c)) end
|
||||
|
||||
local function urlEncode(szText)
|
||||
local str = szText:gsub("([^0-9a-zA-Z ])", get_urlencode)
|
||||
@ -71,26 +109,17 @@ local function urlEncode(szText)
|
||||
return str
|
||||
end
|
||||
|
||||
local function get_urldecode(h)
|
||||
return schar(tonumber(h, 16))
|
||||
end
|
||||
local function get_urldecode(h) return schar(tonumber(h, 16)) end
|
||||
local function UrlDecode(szText)
|
||||
return szText:gsub("+", " "):gsub("%%(%x%x)", get_urldecode)
|
||||
end
|
||||
|
||||
-- trim
|
||||
local function trim(text)
|
||||
if not text or text == "" then
|
||||
return ""
|
||||
end
|
||||
if not text or text == "" then return "" end
|
||||
return (sgsub(text, "^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
-- md5
|
||||
local function md5(content)
|
||||
local stdout = luci.sys.exec('echo \"' .. urlEncode(content) .. '\" | md5sum | cut -d \" \" -f1')
|
||||
-- assert(nixio.errno() == 0)
|
||||
return trim(stdout)
|
||||
end
|
||||
|
||||
-- base64
|
||||
local function base64Decode(text)
|
||||
local raw = text
|
||||
@ -112,7 +141,7 @@ local function processData(szType, content, add_mode)
|
||||
local result = {
|
||||
timeout = 60,
|
||||
add_mode = add_mode,
|
||||
is_sub = (add_mode and add_mode == "导入") and 0 or 1
|
||||
is_sub = add_mode == '导入' and 0 or 1
|
||||
}
|
||||
if szType == 'ssr' then
|
||||
local dat = split(content, "/%?")
|
||||
@ -132,9 +161,7 @@ local function processData(szType, content, add_mode)
|
||||
result.obfs_param = base64Decode(params.obfsparam)
|
||||
result.protocol_param = base64Decode(params.protoparam)
|
||||
local group = base64Decode(params.group)
|
||||
if group then
|
||||
result.group = group
|
||||
end
|
||||
if group then result.group = group end
|
||||
result.remarks = base64Decode(params.remarks)
|
||||
elseif szType == 'vmess' then
|
||||
local info = jsonParse(content)
|
||||
@ -175,9 +202,7 @@ local function processData(szType, content, add_mode)
|
||||
result.v2ray_quic_key = info.key
|
||||
result.v2ray_quic_security = info.securty
|
||||
end
|
||||
if not info.security then
|
||||
result.v2ray_security = "auto"
|
||||
end
|
||||
if not info.security then result.v2ray_security = "auto" end
|
||||
if info.tls == "tls" or info.tls == "1" then
|
||||
result.v2ray_stream_security = "tls"
|
||||
result.tls_serverName = info.host
|
||||
@ -214,7 +239,8 @@ local function processData(szType, content, add_mode)
|
||||
local idx_pn = plugin_info:find(";")
|
||||
if idx_pn then
|
||||
result.ss_plugin = plugin_info:sub(1, idx_pn - 1)
|
||||
result.ss_plugin_opts = plugin_info:sub(idx_pn + 1, #plugin_info)
|
||||
result.ss_plugin_opts =
|
||||
plugin_info:sub(idx_pn + 1, #plugin_info)
|
||||
else
|
||||
result.ss_plugin = plugin_info
|
||||
end
|
||||
@ -250,9 +276,7 @@ local function processData(szType, content, add_mode)
|
||||
if params.allowInsecure then
|
||||
allowInsecure = params.allowInsecure
|
||||
end
|
||||
if params.peer then
|
||||
peer = params.peer
|
||||
end
|
||||
if params.peer then peer = params.peer end
|
||||
end
|
||||
end
|
||||
result.type = "Trojan"
|
||||
@ -274,17 +298,13 @@ local function processData(szType, content, add_mode)
|
||||
result.group = content.airport
|
||||
result.remarks = content.remarks
|
||||
else
|
||||
log('暂时不支持' .. szType .. "类型的节点订阅,跳过此节点。")
|
||||
log('暂时不支持' .. szType ..
|
||||
"类型的节点订阅,跳过此节点。")
|
||||
return nil
|
||||
end
|
||||
if not result.remarks then
|
||||
result.remarks = result.address .. ':' .. result.port
|
||||
end
|
||||
-- remarks 不参与 hashkey 计算
|
||||
local remarks = result.remarks
|
||||
result.remarks = nil
|
||||
result.hashkey = md5(jsonStringify(result))
|
||||
result.remarks = remarks
|
||||
return result
|
||||
end
|
||||
-- wget
|
||||
@ -295,115 +315,132 @@ end
|
||||
|
||||
local function truncate_nodes()
|
||||
local is_stop = 0
|
||||
local tcp_node_num = ucic:get_first(name, "global_other", "tcp_node_num", 1)
|
||||
local udp_node_num = ucic:get_first(name, "global_other", "udp_node_num", 1)
|
||||
local socks5_node_num = ucic:get_first(name, "global_other", "socks5_node_num", 1)
|
||||
for i = 1, tcp_node_num, 1 do
|
||||
local node = ucic:get_first(name, "global", "tcp_node"..i, nil)
|
||||
if node and node ~= "nil" then
|
||||
local is_sub_node = ucic:get(name, node, "is_sub", "0")
|
||||
if is_sub_node == "1" then
|
||||
is_stop = 1
|
||||
ucic:set(name, ucic:get_first(name, 'global'), "tcp_node"..i, "nil")
|
||||
local function clear(type)
|
||||
local node_num =
|
||||
ucic:get_first(application, "global_other", type .. "_node_num", 1)
|
||||
for i = 1, node_num, 1 do
|
||||
local node = ucic:get_first(application, "global", type.."_node" .. i, nil)
|
||||
if node and node ~= "nil" then
|
||||
local is_sub_node = ucic:get(application, node, "is_sub", "0")
|
||||
if is_sub_node == "1" then
|
||||
is_stop = 1
|
||||
ucic:set(application, ucic:get_first(application, 'global'), type.."_node" .. i, "nil")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
clear("tcp")
|
||||
clear("udp")
|
||||
clear("socks5")
|
||||
|
||||
for i = 1, udp_node_num, 1 do
|
||||
local node = ucic:get_first(name, "global", "udp_node"..i, nil)
|
||||
if node and node ~= "nil" then
|
||||
local is_sub_node = ucic:get(name, node, "is_sub", "0")
|
||||
if is_sub_node == "1" then
|
||||
is_stop = 1
|
||||
ucic:set(name, ucic:get_first(name, 'global'), "udp_node"..i, "nil")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, socks5_node_num, 1 do
|
||||
local node = ucic:get_first(name, "global", "socks5_node"..i, nil)
|
||||
if node and node ~= "nil" then
|
||||
local is_sub_node = ucic:get(name, node, "is_sub", "0")
|
||||
if is_sub_node == "1" then
|
||||
is_stop = 1
|
||||
ucic:set(name, ucic:get_first(name, 'global'), "socks5_node"..i, "nil")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ucic:foreach(name, uciType, function(old)
|
||||
ucic:delete_all(application, uciType, function(old)
|
||||
if old.is_sub and old.is_sub == "1" then
|
||||
ucic:delete(name, old['.name'])
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end)
|
||||
ucic:commit(name)
|
||||
ucic:commit(application)
|
||||
|
||||
if is_stop == 1 then
|
||||
luci.sys.call("/etc/init.d/" .. name .. " restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
luci.sys.call("/etc/init.d/" .. application .. " restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
end
|
||||
log('在线订阅节点已全部删除')
|
||||
end
|
||||
|
||||
local function update_node(manual)
|
||||
if next(nodeResult) == nil then
|
||||
log("更新失败,没有可用的节点信息")
|
||||
return
|
||||
local function select_node(nodes, config)
|
||||
local server
|
||||
-- 第一优先级 IP + 端口
|
||||
for id, node in pairs(nodes) do
|
||||
if node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port then
|
||||
log('选择【' .. config.remarks .. '】第一匹配节点:' .. node.remarks)
|
||||
server = id
|
||||
break
|
||||
end
|
||||
end
|
||||
local add, del = 0, 0
|
||||
ucic:foreach(name, uciType, function(old)
|
||||
if old.grouphashkey or old.hashkey then -- 没有 hash 的不参与删除
|
||||
if manual == 0 and (old.is_sub and old.is_sub == "1") then
|
||||
if not nodeResult[old.grouphashkey] or not nodeResult[old.grouphashkey][old.hashkey] then
|
||||
ucic:delete(name, old['.name'])
|
||||
del = del + 1
|
||||
else
|
||||
local dat = nodeResult[old.grouphashkey][old.hashkey]
|
||||
ucic:tset(name, old['.name'], dat)
|
||||
-- 标记一下
|
||||
setmetatable(nodeResult[old.grouphashkey][old.hashkey], { __index = { _ignore = true } })
|
||||
end
|
||||
elseif manual == 1 and (old.add_mode and old.add_mode == "导入") then
|
||||
if nodeResult[old.grouphashkey] and nodeResult[old.grouphashkey][old.hashkey] then
|
||||
ucic:delete(name, old['.name'])
|
||||
end
|
||||
-- 第二优先级 IP
|
||||
if not server then
|
||||
for id, node in pairs(nodes) do
|
||||
if node.address == config.currentNode.address then
|
||||
log('选择【' .. config.remarks .. '】第二匹配节点:' .. node.remarks)
|
||||
server = id
|
||||
break
|
||||
end
|
||||
else
|
||||
--log('忽略手动添加的节点: ' .. old.remarks)
|
||||
end
|
||||
end
|
||||
-- 第三优先级备注
|
||||
if not server then
|
||||
for id, node in pairs(nodes) do
|
||||
if node.remarks == config.currentNode.remarks then
|
||||
log('选择【' .. config.remarks .. '】第三匹配节点:' .. node.remarks)
|
||||
server = id
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- 第四 cfgid
|
||||
if not server then
|
||||
for id, node in pairs(nodes) do
|
||||
if id == config.currentNode['.name'] then
|
||||
log('选择【' .. config.remarks .. '】第四匹配节点:' .. node.remarks)
|
||||
server = id
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- 还不行 随便找一个
|
||||
if not server then
|
||||
server = ucic:get_first(application, uciType)
|
||||
if server then
|
||||
log('无法找到最匹配的节点,当前已更换为' .. ucic:get_all(application, server).remarks)
|
||||
end
|
||||
end
|
||||
if server then
|
||||
config.set(server)
|
||||
end
|
||||
end
|
||||
|
||||
local function update_node()
|
||||
if next(nodeResult) == nil then
|
||||
log("更新失败,没有可用的节点信息")
|
||||
return
|
||||
end
|
||||
-- delet all for subscribe nodes
|
||||
ucic:foreach(application, uciType, function(node)
|
||||
if (node.is_sub or node.hashkey) and node.add_mode ~= '导入' then
|
||||
ucic:delete(application, node['.name'])
|
||||
end
|
||||
end)
|
||||
for k, v in ipairs(nodeResult) do
|
||||
for kk, vv in ipairs(v) do
|
||||
if not vv._ignore then
|
||||
local section = ucic:add(name, uciType)
|
||||
ucic:tset(name, section, vv)
|
||||
add = add + 1
|
||||
end
|
||||
local section = ucic:add(application, uciType)
|
||||
ucic:tset(application, section, vv)
|
||||
end
|
||||
end
|
||||
ucic:commit(application)
|
||||
|
||||
if next(CONFIG) then
|
||||
local nodes = {}
|
||||
ucic:foreach(application, uciType, function(node)
|
||||
if node.port and node.address and node.remarks then
|
||||
nodes[node['.name']] = node
|
||||
end
|
||||
end)
|
||||
for _, config in pairs(CONFIG) do
|
||||
select_node(nodes, config)
|
||||
end
|
||||
ucic:commit(application)
|
||||
luci.sys.call("/etc/init.d/" .. application .. " restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
end
|
||||
log('新增节点数量: ' ..add, '删除节点数量: ' .. del)
|
||||
ucic:commit(name)
|
||||
-- 如果节点已经不见了把帮换一个
|
||||
local globalServer = ucic:get_first(name, 'global', 'tcp_node1', '')
|
||||
local firstServer = ucic:get_first(name, uciType)
|
||||
if not ucic:get(name, globalServer) then
|
||||
if firstServer then
|
||||
ucic:set(name, ucic:get_first(name, 'global'), 'tcp_node1', firstServer)
|
||||
ucic:commit(name)
|
||||
log('当前主服务器已更新,正在自动更换。')
|
||||
end
|
||||
luci.sys.call("/etc/init.d/" .. name .. " restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function parse_link(raw, remark, md5_str, manual)
|
||||
local function parse_link(raw, remark, manual)
|
||||
if raw and #raw > 0 then
|
||||
local add_mode
|
||||
local nodes, szType
|
||||
local groupHash = md5_str or md5(raw)
|
||||
cache[groupHash] = {}
|
||||
tinsert(nodeResult, {})
|
||||
local index = #nodeResult
|
||||
local all_nodes = {}
|
||||
tinsert(nodeResult, all_nodes)
|
||||
-- SSD 似乎是这种格式 ssd:// 开头的
|
||||
if raw:find('ssd://') then
|
||||
szType = 'ssd'
|
||||
@ -420,7 +457,7 @@ local function parse_link(raw, remark, md5_str, manual)
|
||||
local servers = {}
|
||||
-- SS里面包着 干脆直接这样
|
||||
for _, server in ipairs(nodes.servers) do
|
||||
tinsert(servers, setmetatable(server, { __index = extra }))
|
||||
tinsert(servers, setmetatable(server, {__index = extra}))
|
||||
end
|
||||
nodes = servers
|
||||
else
|
||||
@ -457,23 +494,19 @@ local function parse_link(raw, remark, md5_str, manual)
|
||||
if result.remarks:find("过期时间") or
|
||||
result.remarks:find("剩余流量") or
|
||||
result.remarks:find("QQ群") or
|
||||
result.remarks:find("官网") or
|
||||
not result.address or
|
||||
result.remarks:find("官网") or not result.address or
|
||||
result.address:match("[^0-9a-zA-Z%-%_%.%s]") or -- 中文做地址的 也没有人拿中文域名搞,就算中文域也有Puny Code SB 机场
|
||||
not result.address:find("%.") or -- 虽然没有.也算域,不过应该没有人会这样干吧
|
||||
result.address:sub(#result.address) == "." -- 结尾是.
|
||||
then
|
||||
log('丢弃无效节点: ' .. result.type ..' 节点, ' .. result.remarks)
|
||||
log('丢弃无效节点: ' .. result.type .. ' 节点, ' .. result.remarks)
|
||||
else
|
||||
--log('成功解析: ' .. result.type ..' 节点, ' .. result.remarks)
|
||||
result.grouphashkey = groupHash
|
||||
tinsert(nodeResult[index], result)
|
||||
cache[groupHash][result.hashkey] = nodeResult[index][#nodeResult[index]]
|
||||
tinsert(all_nodes, result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
log('成功解析节点数量: ' ..#nodes)
|
||||
log('成功解析节点数量: ' .. #nodes)
|
||||
else
|
||||
if not manual then
|
||||
log('获取到的节点内容为空...')
|
||||
@ -484,27 +517,24 @@ end
|
||||
local execute = function()
|
||||
-- exec
|
||||
do
|
||||
ucic:foreach(name, "subscribe_list", function(obj)
|
||||
ucic:foreach(application, "subscribe_list", function(obj)
|
||||
local enabled = obj.enabled or nil
|
||||
if enabled and enabled == "1" then
|
||||
local remark = obj.remark
|
||||
local url = obj.url
|
||||
log('正在订阅: ' .. url)
|
||||
local md5_str = md5(url)
|
||||
local raw = wget(url)
|
||||
parse_link(raw, remark, md5_str)
|
||||
parse_link(raw, remark)
|
||||
end
|
||||
end)
|
||||
end
|
||||
-- diff
|
||||
do
|
||||
update_node(0)
|
||||
-- diff
|
||||
update_node()
|
||||
end
|
||||
end
|
||||
|
||||
if arg[1] then
|
||||
if arg[1] == "start" then
|
||||
count = luci.sys.exec("echo -n $(uci show " .. name .." | grep @subscribe_list | grep -c \"enabled='1'\")")
|
||||
local count = luci.sys.exec("echo -n $(uci show " .. application .. " | grep @subscribe_list | grep -c \"enabled='1'\")")
|
||||
if count and tonumber(count) > 0 then
|
||||
log('开始订阅...')
|
||||
xpcall(execute, function(e)
|
||||
@ -517,16 +547,20 @@ if arg[1] then
|
||||
log('未设置或启用订阅, 请检查设置...')
|
||||
end
|
||||
elseif arg[1] == "add" then
|
||||
local f = assert(io.open("/tmp/links.conf",'r'))
|
||||
local f = assert(io.open("/tmp/links.conf", 'r'))
|
||||
local content = f:read('*all')
|
||||
f:close()
|
||||
local nodes = split(content:gsub(" ", "\n"), "\n")
|
||||
for _, raw in ipairs(nodes) do
|
||||
local md5_str = md5(raw)
|
||||
parse_link(raw, nil, md5_str, 1)
|
||||
parse_link(raw, nil, 1)
|
||||
end
|
||||
update_node(1)
|
||||
update_node()
|
||||
elseif arg[1] == "truncate" then
|
||||
truncate_nodes()
|
||||
elseif arg[1] == "test" then
|
||||
for k, v in pairs(CONFIG) do
|
||||
print(k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
CONFIG=passwall
|
||||
LOCK_FILE=/var/lock/${CONFIG}_test.lock
|
||||
LOG_FILE=/var/log/$CONFIG.log
|
||||
|
||||
echolog() {
|
||||
@ -22,7 +21,7 @@ test_url() {
|
||||
[ -n "$2" ] && try=$2
|
||||
local timeout=2
|
||||
[ -n "$3" ] && timeout=$3
|
||||
status=$(/usr/bin/wget --no-check-certificate --spider --timeout=$timeout --tries $try "$url")
|
||||
status=$(/usr/bin/wget --no-check-certificate --spider --timeout=$timeout --tries $try "$url" 2>/dev/null)
|
||||
[ "$?" == 0 ] && status=200
|
||||
echo $status
|
||||
}
|
||||
@ -87,28 +86,31 @@ test_auto_switch() {
|
||||
}
|
||||
|
||||
start() {
|
||||
#防止并发执行
|
||||
if [ -f "$LOCK_FILE" ]; then
|
||||
if [ "$(ps -w | grep -v grep | grep $CONFIG/test.sh | wc -l)" -gt 2 ]; then
|
||||
exit 1
|
||||
else
|
||||
touch $LOCK_FILE
|
||||
fi
|
||||
|
||||
ENABLED=$(config_t_get global enabled 0)
|
||||
[ "$ENABLED" != 1 ] && return 1
|
||||
ENABLED=$(config_t_get auto_switch enable 0)
|
||||
[ "$ENABLED" != 1 ] && return 1
|
||||
TCP_NODE_NUM=$(config_t_get global_other tcp_node_num 1)
|
||||
for i in $(seq 1 $TCP_NODE_NUM); do
|
||||
eval TCP_NODE$i=\"$(config_t_get auto_switch tcp_node$i nil)\"
|
||||
eval tmp=\$TCP_NODE$i
|
||||
[ -n "$tmp" ] && {
|
||||
test_auto_switch TCP REDIR tcp $i "$tmp"
|
||||
}
|
||||
delay=$(config_t_get auto_switch testing_time 1)
|
||||
sleep ${delay}m
|
||||
while [ "$ENABLED" -eq 1 ]
|
||||
do
|
||||
# TCP_NODE_NUM=$(config_t_get global_other tcp_node_num 1)
|
||||
# 暂时只能检测TCP1
|
||||
TCP_NODE_NUM=1
|
||||
for i in $(seq 1 $TCP_NODE_NUM); do
|
||||
eval TCP_NODE$i=\"$(config_t_get auto_switch tcp_node$i nil)\"
|
||||
eval tmp=\$TCP_NODE$i
|
||||
[ -n "$tmp" -a "$tmp" != "nil" ] && {
|
||||
test_auto_switch TCP REDIR tcp $i "$tmp"
|
||||
}
|
||||
done
|
||||
delay=$(config_t_get auto_switch testing_time 1)
|
||||
sleep ${delay}m
|
||||
done
|
||||
|
||||
rm -f $LOCK_FILE
|
||||
exit
|
||||
}
|
||||
|
||||
case $1 in
|
||||
|
||||
Loading…
Reference in New Issue
Block a user