From f98163343339e00af0003154bb2f2ff76e148403 Mon Sep 17 00:00:00 2001 From: CN_SZTL Date: Sat, 15 Feb 2020 22:07:00 +0800 Subject: [PATCH] luci-app-passwall: sync with upstream source --- package/lienol/luci-app-passwall/Makefile | 4 +- .../luasrc/controller/passwall.lua | 24 +- .../api/gen_v2ray_client_config_file.lua | 19 +- .../luasrc/model/cbi/passwall/rule.lua | 7 +- .../luasrc/view/passwall/global/status.htm | 22 +- .../luasrc/view/passwall/global/status2.htm | 22 +- .../luci-app-passwall/po/zh-cn/passwall.po | 18 +- .../root/usr/share/passwall/app.sh | 226 +++---- .../root/usr/share/passwall/monitor.sh | 11 +- .../root/usr/share/passwall/subscribe.lua | 463 ++++++++++++++ .../root/usr/share/passwall/subscription.sh | 597 ------------------ 11 files changed, 650 insertions(+), 763 deletions(-) create mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua delete mode 100755 package/lienol/luci-app-passwall/root/usr/share/passwall/subscription.sh diff --git a/package/lienol/luci-app-passwall/Makefile b/package/lienol/luci-app-passwall/Makefile index 3fe1d9daee..bd30b01d78 100644 --- a/package/lienol/luci-app-passwall/Makefile +++ b/package/lienol/luci-app-passwall/Makefile @@ -6,8 +6,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall -PKG_VERSION:=3.5.6 -PKG_RELEASE:=20200213 +PKG_VERSION:=3.5.8 +PKG_RELEASE:=20200215 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) diff --git a/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua b/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua index 314b76fdaa..1ecd69f774 100644 --- a/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua +++ b/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua @@ -9,7 +9,8 @@ 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", "reset_config"}, call("reset_config")).leaf = true + entry({"admin", "vpn", "passwall", "reset_config"}, call("reset_config")).leaf = + true 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 @@ -81,7 +82,8 @@ local function http_write_json(content) end function reset_config() - luci.sys.call('[ -f "/usr/share/passwall/config.default" ] && cp -f /usr/share/passwall/config.default /etc/config/passwall && /etc/init.d/passwall reload') + luci.sys.call( + '[ -f "/usr/share/passwall/config.default" ] && cp -f /usr/share/passwall/config.default /etc/config/passwall && /etc/init.d/passwall reload') luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall")) end @@ -99,7 +101,7 @@ function link_add_node() local link = luci.http.formvalue("link") luci.sys.call('rm -f /tmp/links.conf && echo "' .. link .. '" >> /tmp/links.conf') - luci.sys.call("/usr/share/passwall/subscription.sh add >/dev/null") + luci.sys.call("lua /usr/share/passwall/subscribe.lua add >> /var/log/passwall.log") end function get_log() @@ -115,9 +117,9 @@ function status() local e = {} 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.haproxy_status = luci.sys.call(string.format( + "ps -w | grep -v grep | grep '%s/bin/' | grep haproxy >/dev/null", + appname)) == 0 e.kcptun_status = luci.sys.call( "ps -w | grep -v grep | grep -i 'log /var/etc/" .. appname .. "/kcptun' >/dev/null") == 0 @@ -132,7 +134,7 @@ function status() i, i)) e["tcp_node%s_status" % i] = luci.sys.call( string.format( - "ps -w | grep -v grep | grep -i -E '%s/TCP_%s|brook tproxy -l 0.0.0.0:%s|ipt2socks -T -l %s' >/dev/null", + "ps -w | grep -v grep | grep '%s/bin/' | grep -i -E 'TCP_%s|brook tproxy -l 0.0.0.0:%s|ipt2socks -T -l %s' >/dev/null", appname, i, listen_port, listen_port)) == 0 end @@ -147,7 +149,7 @@ function status() i, i)) e["udp_node%s_status" % i] = luci.sys.call( string.format( - "ps -w | grep -v grep | grep -i -E '%s/UDP_%s|brook tproxy -l 0.0.0.0:%s|ipt2socks -U -l %s' >/dev/null", + "ps -w | grep -v grep | grep '%s/bin/' | grep -i -E 'UDP_%s|brook tproxy -l 0.0.0.0:%s|ipt2socks -U -l %s' >/dev/null", appname, i, listen_port, listen_port)) == 0 end @@ -162,7 +164,7 @@ function status() i, i)) e["socks5_node%s_status" % i] = luci.sys.call( string.format( - "ps -w | grep -v grep | grep -i -E '%s/SOCKS5_%s|brook client -l 0.0.0.0:%s' >/dev/null", + "ps -w | grep -v grep | grep '%s/bin/' | grep -i -E 'SOCKS5_%s|brook client -l 0.0.0.0:%s' >/dev/null", appname, i, listen_port)) == 0 end luci.http.prepare_content("application/json") @@ -170,7 +172,9 @@ function status() end function connect_status() + local os = require "os" local e = {} + 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") == @@ -180,6 +184,8 @@ function connect_status() "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) + e.use_time = use_time luci.http.prepare_content("application/json") luci.http.write_json(e) end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_client_config_file.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_client_config_file.lua index 2aae45636f..791db52ee8 100755 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_client_config_file.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_client_config_file.lua @@ -56,8 +56,10 @@ if node.v2ray_balancing_node then users = { { id = api.uci_get_type_id(id, "v2ray_VMess_id"), - alterId = tonumber(api.uci_get_type_id(id, "v2ray_VMess_alterId")), - level = tonumber(api.uci_get_type_id(id, "v2ray_VMess_level")), + alterId = tonumber(api.uci_get_type_id(id, + "v2ray_VMess_alterId")), + level = tonumber( + api.uci_get_type_id(id, "v2ray_VMess_level")), security = api.uci_get_type_id(id, "v2ray_security") } } @@ -106,6 +108,17 @@ local v2ray = { allowInsecure = (node.tls_allowInsecure == "1") and true or false } or nil, + tcpSettings = (node.v2ray_transport == "tcp") and { + header = { + type = node.v2ray_tcp_guise, + request = { + path = node.v2ray_tcp_guise_http_path or {"/"}, + headers = { + Host = node.v2ray_tcp_guise_http_host or {} + } + } or {} + } + } or nil, kcpSettings = (node.v2ray_transport == "mkcp") and { mtu = tonumber(node.v2ray_mkcp_mtu), tti = tonumber(node.v2ray_mkcp_tti), @@ -118,7 +131,7 @@ local v2ray = { header = {type = node.v2ray_mkcp_guise} } or nil, wsSettings = (node.v2ray_transport == "ws") and { - path = node.v2ray_ws_path, + path = node.v2ray_ws_path or "", headers = (node.v2ray_ws_host ~= nil) and {Host = node.v2ray_ws_host} or nil } or nil, diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/rule.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/rule.lua index 7d19957eab..4cc2acb5c0 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/rule.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/rule.lua @@ -62,8 +62,8 @@ o:depends("auto_update_subscribe", 1) o = s:option(Button, "_update", translate("Manual subscription")) o.inputstyle = "apply" function o.write(e, e) - luci.sys - .call("nohup /usr/share/passwall/subscription.sh > /dev/null 2>&1 &") + luci.sys.call( + "lua /usr/share/passwall/subscribe.lua start >> /var/log/passwall.log 2>&1 &") luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall", "log")) end @@ -72,7 +72,8 @@ end o = s:option(Button, "_stop", translate("Delete All Subscribe Node")) o.inputstyle = "remove" function o.write(e, e) - luci.sys.call("/usr/share/passwall/subscription.sh stop") + luci.sys.call( + "lua /usr/share/passwall/subscribe.lua truncate >> /var/log/passwall.log 2>&1 &") luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall", "log")) end diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm index e27e2486e2..6c45e32cd1 100644 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm +++ b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm @@ -365,23 +365,23 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md }, function(x, rv) { if (rv.status) { - var time = ((new Date()).getTime() - sendDate) / 1000; + var use_time = rv.use_time; var speed = ""; - if (time < 0.5) { + if (use_time < 1) { s.className="green"; - speed = "<%:very good%>"; - } else if (time < 0.8) { + speed = "<%:Very Fast%>"; + } else if (use_time < 2) { s.className="green"; - speed = "<%:good%>"; - } else if (time < 1.5) { + speed = "<%:Fast%>"; + } else if (use_time < 3) { s.className="yellow"; - speed = "<%:general%>"; - } else if (time < 3) { + speed = "<%:General%>"; + } else if (use_time < 4) { s.className="red"; - speed = "<%:bad%>"; - } else if (time >= 3) { + speed = "<%:Slow%>"; + } else if (use_time >= 4) { s.className="red"; - speed = "<%:very bad%>"; + speed = "<%:Very Slow%>"; } s.innerHTML = speed; } diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm index 788a425fcd..159919befa 100644 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm +++ b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm @@ -223,24 +223,24 @@ local status_show_ip111 = api.uci_get_type("global_other", "status_show_ip111", var s = document.getElementById('_' + type + '_status'); if(s) { if(rv.status) { - var time = ((new Date()).getTime() - sendDate) / 1000; + var use_time = rv.use_time; var speed = ""; var color="red"; - if (time < 0.5) { + if (use_time < 1) { color = "green"; - speed = "<%:very good%>"; - } else if (time < 0.8) { + speed = "<%:Very Fast%>"; + } else if (use_time < 2) { color = "green"; - speed = "<%:good%>"; - } else if (time < 1.5) { + speed = "<%:Fast%>"; + } else if (use_time < 3) { color = "#b9b90b"; - speed = "<%:general%>"; - } else if (time < 3) { + speed = "<%:General%>"; + } else if (use_time < 4) { color = "red"; - speed = "<%:bad%>"; - } else if (time >= 3) { + speed = "<%:Slow%>"; + } else if (use_time >= 4) { color = "red"; - speed = "<%:very bad%>"; + speed = "<%:Very Slow%>"; } //s.setAttribute("color", color); btn.setAttribute("style","background-color: " + color + " !important; border-color: " + color + " !important;"); diff --git a/package/lienol/luci-app-passwall/po/zh-cn/passwall.po b/package/lienol/luci-app-passwall/po/zh-cn/passwall.po index b852a35f4c..559f91a0ed 100644 --- a/package/lienol/luci-app-passwall/po/zh-cn/passwall.po +++ b/package/lienol/luci-app-passwall/po/zh-cn/passwall.po @@ -16,20 +16,20 @@ msgstr "连接正常" msgid "Problem detected!" msgstr "连接失败" -msgid "very good" -msgstr "非常好" +msgid "Very Fast" +msgstr "非常快" -msgid "good" -msgstr "好" +msgid "Fast" +msgstr "很快" -msgid "general" +msgid "General" msgstr "一般般" -msgid "bad" -msgstr "差" +msgid "Slow" +msgstr "很慢" -msgid "very bad" -msgstr "非常差" +msgid "Very Slow" +msgstr "非常慢" msgid "Touch Check" msgstr "点我检测" diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/app.sh b/package/lienol/luci-app-passwall/root/usr/share/passwall/app.sh index 2e696da29f..eda9e0ab40 100755 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/package/lienol/luci-app-passwall/root/usr/share/passwall/app.sh @@ -6,6 +6,7 @@ CONFIG=passwall CONFIG_PATH=/var/etc/$CONFIG +RUN_BIN_PATH=$CONFIG_PATH/bin RUN_PID_PATH=$CONFIG_PATH/pid RUN_ID_PATH=$CONFIG_PATH/id RUN_IP_PATH=$CONFIG_PATH/ip @@ -41,7 +42,6 @@ find_bin() { result=$(find /usr/*bin -iname "$bin_name" -type f) if [ -z "$result" ]; then echo "" - echolog "找不到$bin_name主程序,无法启动!" else echo "$result" fi @@ -201,6 +201,7 @@ load_config() { echolog "没有选择节点!" return 1 } + DNS_MODE=$(config_t_get global dns_mode pdnsd) DNS_FORWARD=$(config_t_get global dns_forward 8.8.4.4) use_tcp_node_resolve_dns=$(config_t_get global use_tcp_node_resolve_dns 0) @@ -236,7 +237,38 @@ load_config() { SOCKS5_PROXY_PORT2=$(expr $SOCKS5_PROXY_PORT1 + 1) SOCKS5_PROXY_PORT3=$(expr $SOCKS5_PROXY_PORT2 + 1) PROXY_IPV6=$(config_t_get global_forwarding proxy_ipv6 0) - mkdir -p /var/etc $CONFIG_PATH $RUN_PID_PATH $RUN_ID_PATH $RUN_IP_PATH $RUN_PORT_PATH + mkdir -p /var/etc $CONFIG_PATH $RUN_BIN_PATH $RUN_PID_PATH $RUN_ID_PATH $RUN_IP_PATH $RUN_PORT_PATH + + #配置环境 + ss_redir_bin=$(find_bin ss-redir) + [ -n "$ss_redir_bin" -a -f "$ss_redir_bin" ] && ln -s $ss_redir_bin ${RUN_BIN_PATH}/ss-redir && ss_redir_bin=${RUN_BIN_PATH}/ss-redir + ss_local_bin=$(find_bin ss-local) + [ -n "$ss_local_bin" -a -f "$ss_local_bin" ] && ln -s $ss_local_bin ${RUN_BIN_PATH}/ss-local && ss_local_bin=${RUN_BIN_PATH}/ss-local + ssr_redir_bin=$(find_bin ssr-redir) + [ -n "$ssr_redir_bin" -a -f "$ssr_redir_bin" ] && ln -s $ssr_redir_bin ${RUN_BIN_PATH}/ssr-redir && ssr_redir_bin=${RUN_BIN_PATH}/ssr-redir + ssr_local_bin=$(find_bin ssr-local) + [ -n "$ssr_local_bin" -a -f "$ssr_local_bin" ] && ln -s $ssr_local_bin ${RUN_BIN_PATH}/ssr-local && ssr_local_bin=${RUN_BIN_PATH}/ssr-local + trojan_bin=$(find_bin trojan) + [ -n "$trojan_bin" -a -f "$trojan_bin" ] && ln -s $trojan_bin ${RUN_BIN_PATH}/trojan && trojan_bin=${RUN_BIN_PATH}/trojan + v2ray_path=$(config_t_get global_app v2ray_file $(find_bin v2ray)) + [ -n "$v2ray_path" -a -f "${v2ray_path}/v2ray" ]&& ln -s ${v2ray_path}/v2ray ${RUN_BIN_PATH}/v2ray && v2ray_bin=${RUN_BIN_PATH}/v2ray + brook_bin=$(config_t_get global_app brook_file $(find_bin brook)) + [ -n "$brook_bin" -a -f "$brook_bin" ] && ln -s $brook_bin ${RUN_BIN_PATH}/brook && brook_bin=${RUN_BIN_PATH}/brook + kcptun_bin=$(config_t_get global_app kcptun_client_file $(find_bin kcptun-client)) + [ -n "$kcptun_bin" -a -f "$kcptun_bin" ] && ln -s $kcptun_bin ${RUN_BIN_PATH}/kcptun-client && kcptun_bin=${RUN_BIN_PATH}/kcptun-client + redsocks2_bin=$(find_bin redsocks2) + [ -n "$redsocks2_bin" -a -f "$redsocks2_bin" ] && ln -s $redsocks2_bin ${RUN_BIN_PATH}/redsocks2 && redsocks2_bin=${RUN_BIN_PATH}/redsocks2 + ipt2socks_bin=$(find_bin ipt2socks) + [ -n "$ipt2socks_bin" -a -f "$ipt2socks_bin" ] && ln -s $ipt2socks_bin ${RUN_BIN_PATH}/ipt2socks && ipt2socks_bin=${RUN_BIN_PATH}/ipt2socks + dns2socks_bin=$(find_bin dns2socks) + [ -n "$dns2socks_bin" -a -f "$dns2socks_bin" ] && ln -s $dns2socks_bin ${RUN_BIN_PATH}/dns2socks && dns2socks_bin=${RUN_BIN_PATH}/dns2socks + pdnsd_bin=$(find_bin pdnsd) + [ -n "$pdnsd_bin" -a -f "$pdnsd_bin" ] && ln -s $pdnsd_bin ${RUN_BIN_PATH}/pdnsd && pdnsd_bin=${RUN_BIN_PATH}/pdnsd + chinadns_ng_bin=$(find_bin chinadns-ng) + [ -n "$chinadns_ng_bin" -a -f "$chinadns_ng_bin" ] && ln -s $chinadns_ng_bin ${RUN_BIN_PATH}/chinadns-ng && chinadns_ng_bin=${RUN_BIN_PATH}/chinadns-ng + haproxy_bin=$(find_bin haproxy) + [ -n "$haproxy_bin" -a -f "$haproxy_bin" ] && ln -s $haproxy_bin ${RUN_BIN_PATH}/haproxy && haproxy_bin=${RUN_BIN_PATH}/haproxy + config_load $CONFIG return 0 } @@ -259,23 +291,23 @@ gen_ss_ssr_config_file() { } cat <<-EOF >$configfile { - "_comment": "$server_ip", - "server": "$server_host", - "server_port": $port, - "local_address": "0.0.0.0", - "local_port": $local_port, - "password": "$(config_n_get $node password)", - "timeout": $(config_n_get $node timeout), - "method": "$encrypt_method", - "fast_open": $(config_n_get $node tcp_fast_open false), - "reuse_port": true, + "_comment": "$server_ip", + "server": "$server_host", + "server_port": $port, + "local_address": "0.0.0.0", + "local_port": $local_port, + "password": "$(config_n_get $node password)", + "timeout": $(config_n_get $node timeout), + "method": "$encrypt_method", + "fast_open": $(config_n_get $node tcp_fast_open false), + "reuse_port": true, EOF [ "$1" == "ssr" ] && { cat <<-EOF >>$configfile - "protocol": "$(config_n_get $node protocol)", - "protocol_param": "$(config_n_get $node protocol_param)", - "obfs": "$(config_n_get $node obfs)", - "obfs_param": "$(config_n_get $node obfs_param)" + "protocol": "$(config_n_get $node protocol)", + "protocol_param": "$(config_n_get $node protocol_param)", + "obfs": "$(config_n_get $node obfs)", + "obfs_param": "$(config_n_get $node obfs_param)" EOF } echo -e "}" >>$configfile @@ -310,9 +342,8 @@ gen_start_config() { echolog "Socks5节点不能使用Socks5代理节点!" elif [ "$type" == "v2ray" ]; then lua $API_GEN_V2RAY $node nil nil $local_port >$config_file - v2ray_path=$(config_t_get global_app v2ray_file $(find_bin v2ray)) - if [ -f "${v2ray_path}/v2ray" ]; then - ${v2ray_path}/v2ray -config=$config_file >/dev/null & + if [ -f "$v2ray_bin" ]; then + $v2ray_bin -config=$config_file >/dev/null & else echolog "找不到V2ray客户端主程序,无法启用!" fi @@ -332,19 +363,16 @@ gen_start_config() { balancing_node_address="$temp" done lua $API_GEN_V2RAY $node nil nil $local_port >$config_file - v2ray_path=$(config_t_get global_app v2ray_file $(find_bin v2ray)) - if [ -f "${v2ray_path}/v2ray" ]; then - ${v2ray_path}/v2ray -config=$config_file >/dev/null & + if [ -f "$v2ray_bin" ]; then + $v2ray_bin -config=$config_file >/dev/null & else echolog "找不到V2ray客户端主程序,无法启用!" fi elif [ "$type" == "trojan" ]; then lua $API_GEN_TROJAN $node client "0.0.0.0" $local_port >$config_file - trojan_bin=$(find_bin trojan) [ -f "$trojan_bin" ] && $trojan_bin -c $config_file >/dev/null 2>&1 & elif [ "$type" == "brook" ]; then BROOK_SOCKS5_CMD="client -l 0.0.0.0:$local_port -i 0.0.0.0 -s $server_ip:$port -p $(config_n_get $node password)" - brook_bin=$(config_t_get global_app brook_file $(find_bin brook)) if [ -f "$brook_bin" ]; then $brook_bin $BROOK_SOCKS5_CMD &>/dev/null & else @@ -352,12 +380,10 @@ gen_start_config() { fi elif [ "$type" == "ssr" ]; then gen_ss_ssr_config_file ssr $local_port 0 $node $config_file - ssr_bin=$(find_bin ssr-local) - [ -n "$ssr_bin" ] && $ssr_bin -c $config_file -b 0.0.0.0 -u >/dev/null 2>&1 & + [ -f "$ssr_local_bin" ] && $ssr_local_bin -c $config_file -b 0.0.0.0 -u >/dev/null 2>&1 & elif [ "$type" == "ss" ]; then gen_ss_ssr_config_file ss $local_port 0 $node $config_file - ss_bin=$(find_bin ss-local) - [ -n "$ss_bin" ] && { + [ -n "$ss_local_bin" ] && { local plugin_params="" local plugin=$(config_n_get $node ss_plugin) if [ "$plugin" != "none" ]; then @@ -366,7 +392,7 @@ gen_start_config() { plugin_params="--plugin $plugin --plugin-opts $opts" } fi - $ss_bin -c $config_file -b 0.0.0.0 -u $plugin_params >/dev/null 2>&1 & + $ss_local_bin -c $config_file -b 0.0.0.0 -u $plugin_params >/dev/null 2>&1 & } fi fi @@ -385,20 +411,17 @@ gen_start_config() { local server_username=$(config_n_get $node username) local server_password=$(config_n_get $node password) eval port=\$UDP_REDIR_PORT$5 - ipt2socks_bin=$(find_bin ipt2socks) [ -f "$ipt2socks_bin" ] && $ipt2socks_bin -U -l $port -b 0.0.0.0 -s $node_address -p $node_port -R >/dev/null & - #redsocks_bin=$(find_bin redsocks2) - #[ -n "$redsocks_bin" ] && { + #[ -f "$redsocks2_bin" ] && { # local redsocks_config_file=$CONFIG_PATH/UDP_$i.conf # gen_redsocks_config $redsocks_config_file udp $port $node_address $node_port $server_username $server_password - # $redsocks_bin -c $redsocks_config_file >/dev/null & + # $redsocks2_bin -c $redsocks_config_file >/dev/null & #} elif [ "$type" == "v2ray" ]; then lua $API_GEN_V2RAY $node udp $local_port nil >$config_file - v2ray_path=$(config_t_get global_app v2ray_file $(find_bin v2ray)) - if [ -f "${v2ray_path}/v2ray" ]; then - ${v2ray_path}/v2ray -config=$config_file >/dev/null & + if [ -f "$v2ray_bin" ]; then + $v2ray_bin -config=$config_file >/dev/null & else echolog "找不到V2ray客户端主程序,无法启用!" fi @@ -418,9 +441,8 @@ gen_start_config() { balancing_node_address="$temp" done lua $API_GEN_V2RAY $node udp $local_port nil >$config_file - v2ray_path=$(config_t_get global_app v2ray_file $(find_bin v2ray)) - if [ -f "${v2ray_path}/v2ray" ]; then - ${v2ray_path}/v2ray -config=$config_file >/dev/null & + if [ -f "$v2ray_bin" ]; then + $v2ray_bin -config=$config_file >/dev/null & else echolog "找不到V2ray客户端主程序,无法启用!" fi @@ -429,7 +451,6 @@ gen_start_config() { local_port=$(get_not_exists_port_after $SOCKS5_PROXY_PORT4 tcp) socks5_port=$local_port lua $API_GEN_TROJAN $node client "127.0.0.1" $socks5_port >$config_file - trojan_bin=$(find_bin trojan) [ -f "$trojan_bin" ] && $trojan_bin -c $config_file >/dev/null 2>&1 & local node_address=$(config_n_get $node address) @@ -437,18 +458,15 @@ gen_start_config() { local server_username=$(config_n_get $node username) local server_password=$(config_n_get $node password) eval port=\$UDP_REDIR_PORT$5 - ipt2socks_bin=$(find_bin ipt2socks) [ -f "$ipt2socks_bin" ] && $ipt2socks_bin -U -l $port -b 0.0.0.0 -s 127.0.0.1 -p $socks5_port -R >/dev/null & - #redsocks_bin=$(find_bin redsocks2) - #[ -n "$redsocks_bin" ] && { + #[ -f "$redsocks2_bin" ] && { # local redsocks_config_file=$CONFIG_PATH/redsocks_UDP_$i.conf # gen_redsocks_config $redsocks_config_file udp $port "127.0.0.1" $socks5_port - # $redsocks_bin -c $redsocks_config_file >/dev/null & + # $redsocks2_bin -c $redsocks_config_file >/dev/null & #} elif [ "$type" == "brook" ]; then BROOK_UDP_CMD="tproxy -l 0.0.0.0:$local_port -s $server_ip:$port -p $(config_n_get $node password)" - brook_bin=$(config_t_get global_app brook_file $(find_bin brook)) if [ -f "$brook_bin" ]; then $brook_bin $BROOK_UDP_CMD &>/dev/null & else @@ -456,16 +474,14 @@ gen_start_config() { fi elif [ "$type" == "ssr" ]; then gen_ss_ssr_config_file ssr $local_port 0 $node $config_file - ssr_bin=$(find_bin ssr-redir) - if [ -f "$ssr_bin" ]; then - $ssr_bin -c $config_file -f $RUN_PID_PATH/udp_ssr_1_$5 -U >/dev/null 2>&1 & + if [ -f "$ssr_redir_bin" ]; then + $ssr_redir_bin -c $config_file -f $RUN_PID_PATH/udp_ssr_1_$5 -U >/dev/null 2>&1 & else echolog "找不到ssr客户端主程序,无法启用!" fi elif [ "$type" == "ss" ]; then gen_ss_ssr_config_file ss $local_port 0 $node $config_file - ss_bin=$(find_bin ss-redir) - [ -f "$ss_bin" ] && { + [ -f "$ss_redir_bin" ] && { local plugin_params="" local plugin=$(config_n_get $node ss_plugin) if [ "$plugin" != "none" ]; then @@ -474,7 +490,7 @@ gen_start_config() { plugin_params="--plugin $plugin --plugin-opts $opts" } fi - $ss_bin -c $config_file -f $RUN_PID_PATH/udp_ss_1_$5 -U $plugin_params >/dev/null 2>&1 & + $ss_redir_bin -c $config_file -f $RUN_PID_PATH/udp_ss_1_$5 -U $plugin_params >/dev/null 2>&1 & } fi fi @@ -493,20 +509,17 @@ gen_start_config() { local server_username=$(config_n_get $node username) local server_password=$(config_n_get $node password) eval port=\$TCP_REDIR_PORT$5 - ipt2socks_bin=$(find_bin ipt2socks) [ -f "$ipt2socks_bin" ] && $ipt2socks_bin -l $port -b 0.0.0.0 -s $node_address -p $socks5_port -R >/dev/null & - #redsocks_bin=$(find_bin redsocks2) - #[ -n "$redsocks_bin" ] && { + #[ -f "$redsocks2_bin" ] && { # local redsocks_config_file=$CONFIG_PATH/TCP_$i.conf # gen_redsocks_config $redsocks_config_file tcp $port $node_address $socks5_port $server_username $server_password - # $redsocks_bin -c $redsocks_config_file >/dev/null & + # $redsocks2_bin -c $redsocks_config_file >/dev/null & #} elif [ "$type" == "v2ray" ]; then lua $API_GEN_V2RAY $node tcp $local_port nil >$config_file - v2ray_path=$(config_t_get global_app v2ray_file $(find_bin v2ray)) - if [ -f "${v2ray_path}/v2ray" ]; then - ${v2ray_path}/v2ray -config=$config_file >/dev/null & + if [ -f "$v2ray_bin" ]; then + $v2ray_bin -config=$config_file >/dev/null & else echolog "找不到V2ray客户端主程序,无法启用!" fi @@ -526,59 +539,54 @@ gen_start_config() { balancing_node_address="$temp" done lua $API_GEN_V2RAY $node tcp $local_port nil >$config_file - v2ray_path=$(config_t_get global_app v2ray_file $(find_bin v2ray)) - if [ -f "${v2ray_path}/v2ray" ]; then - ${v2ray_path}/v2ray -config=$config_file >/dev/null & + if [ -f "$v2ray_bin" ]; then + $v2ray_bin -config=$config_file >/dev/null & else echolog "找不到V2ray客户端主程序,无法启用!" fi elif [ "$type" == "trojan" ]; then lua $API_GEN_TROJAN $node nat "0.0.0.0" $local_port >$config_file - trojan_bin=$(find_bin trojan) [ -f "$trojan_bin" ] && $trojan_bin -c $config_file >/dev/null 2>&1 & else - local kcptun_use kcptun_server_host kcptun_port kcptun_config - kcptun_use=$(config_n_get $node use_kcp 0) - kcptun_server_host=$(config_n_get $node kcp_server) - kcptun_port=$(config_n_get $node kcp_port) - kcptun_config="$(config_n_get $node kcp_opts)" - kcptun_bin=$(config_t_get global_app kcptun_client_file $(find_bin kcptun-client)) - lbenabled=$(config_t_get global_haproxy balancing_enable 0) - if [ -z "$kcptun_bin" ]; then - echolog "【未安装Kcptun主程序,请到自动更新下载Kcptun】,跳过~" - force_stop - fi - if [ "$kcptun_use" == "1" ] && ([ -z "$kcptun_port" ] || [ -z "$kcptun_config" ]); then - echolog "【未配置Kcptun参数】,跳过~" - force_stop - fi - if [ "$kcptun_use" == "1" -a -n "$kcptun_port" -a -n "$kcptun_config" -a "$lbenabled" == "0" -a -f "$kcptun_bin" ]; then - local run_kcptun_ip=$server_ip - if [ -n "$kcptun_server_host" ]; then - kcptun_use_ipv6=$(config_n_get $node kcp_use_ipv6) - network_type="ipv4" - [ "$kcptun_use_ipv6" == "1" ] && network_type="ipv6" - kcptun_server_ip=$(get_host_ip $network_type $kcptun_server_host) - eval TCP_NODE${5}_IP=$kcptun_server_ip - run_kcptun_ip=$kcptun_server_ip - echolog "Kcptun节点IP地址:$kcptun_server_ip" + local kcptun_use=$(config_n_get $node use_kcp 0) + if [ "$kcptun_use" == "1" ]; then + local kcptun_server_host=$(config_n_get $node kcp_server) + local kcptun_port=$(config_n_get $node kcp_port) + local kcptun_config="$(config_n_get $node kcp_opts)" + local lbenabled=$(config_t_get global_haproxy balancing_enable 0) + if [ ! -f "$kcptun_bin" ]; then + echolog "【未安装Kcptun主程序,请到自动更新下载Kcptun】,跳过~" + force_stop + fi + if [ -z "$kcptun_port" -o -z "$kcptun_config" ]; then + echolog "【未配置Kcptun参数】,跳过~" + force_stop + fi + if [ -n "$kcptun_port" -a -n "$kcptun_config" -a "$lbenabled" == "0" -a -f "$kcptun_bin" ]; then + local run_kcptun_ip=$server_ip + if [ -n "$kcptun_server_host" ]; then + kcptun_use_ipv6=$(config_n_get $node kcp_use_ipv6) + network_type="ipv4" + [ "$kcptun_use_ipv6" == "1" ] && network_type="ipv6" + kcptun_server_ip=$(get_host_ip $network_type $kcptun_server_host) + eval TCP_NODE${5}_IP=$kcptun_server_ip + run_kcptun_ip=$kcptun_server_ip + echolog "Kcptun节点IP地址:$kcptun_server_ip" + fi + KCPTUN_REDIR_PORT=$(get_not_exists_port_after $KCPTUN_REDIR_PORT udp) + $kcptun_bin --log $CONFIG_PATH/kcptun_${5}.log -l 0.0.0.0:$KCPTUN_REDIR_PORT -r $run_kcptun_ip:$kcptun_port $kcptun_config >/dev/null 2>&1 & fi - KCPTUN_REDIR_PORT=$(get_not_exists_port_after $KCPTUN_REDIR_PORT udp) - $kcptun_bin --log $CONFIG_PATH/kcptun_${5}.log -l 0.0.0.0:$KCPTUN_REDIR_PORT -r $run_kcptun_ip:$kcptun_port $kcptun_config >/dev/null 2>&1 & fi - if [ "$type" == "ssr" ]; then gen_ss_ssr_config_file ssr $local_port $kcptun_use $node $config_file - ssr_bin=$(find_bin ssr-redir) - [ -f "$ssr_bin" ] && { + [ -f "$ssr_redir_bin" ] && { for k in $(seq 1 $process); do - $ssr_bin -c $config_file -f $RUN_PID_PATH/tcp_ssr_${k}_${5} >/dev/null 2>&1 & + $ssr_redir_bin -c $config_file -f $RUN_PID_PATH/tcp_ssr_${k}_${5} >/dev/null 2>&1 & done } elif [ "$type" == "ss" ]; then gen_ss_ssr_config_file ss $local_port $kcptun_use $node $config_file - ss_bin=$(find_bin ${type}-redir) - [ -f "$ss_bin" ] && { + [ -f "$ss_redir_bin" ] && { local plugin_params="" local plugin=$(config_n_get $node ss_plugin) if [ "$plugin" != "none" ]; then @@ -588,7 +596,7 @@ gen_start_config() { } fi for k in $(seq 1 $process); do - $ss_bin -c $config_file -f $RUN_PID_PATH/tcp_ss_${k}_${5} $plugin_params >/dev/null 2>&1 & + $ss_redir_bin -c $config_file -f $RUN_PID_PATH/tcp_ss_${k}_${5} $plugin_params >/dev/null 2>&1 & done } elif [ "$type" == "brook" ]; then @@ -597,7 +605,6 @@ gen_start_config() { port=$KCPTUN_REDIR_PORT } BROOK_TCP_CMD="tproxy -l 0.0.0.0:$local_port -s $server_ip:$port -p $(config_n_get $node password)" - brook_bin=$(config_t_get global_app brook_file $(find_bin brook)) if [ -f "$brook_bin" ]; then $brook_bin $BROOK_TCP_CMD &>/dev/null & else @@ -692,10 +699,10 @@ start_crontab() { if [ "$autoupdatesubscribe" = "1" ]; then if [ "$weekupdatesubscribe" = "7" ]; then - echo "0 $dayupdatesubscribe * * * $APP_PATH/subscription.sh" >>/etc/crontabs/root + echo "0 $dayupdatesubscribe * * * lua $APP_PATH/subscribe.lua >> /var/log/passwall.log" >>/etc/crontabs/root echolog "设置节点订阅自动更新规则在每天 $dayupdatesubscribe 点。" else - echo "0 $dayupdatesubscribe * * $weekupdate $APP_PATH/subscription.sh" >>/etc/crontabs/root + echo "0 $dayupdatesubscribe * * $weekupdate lua $APP_PATH/subscribe.lua >> /var/log/passwall.log" >>/etc/crontabs/root echolog "设置节点订阅自动更新规则在星期 $weekupdate 的 $dayupdatesubscribe 点。" fi else @@ -723,8 +730,7 @@ start_dns() { ;; dns2socks) if [ -n "$SOCKS5_NODE1" -a "$SOCKS5_NODE1" != "nil" ]; then - dns2socks_bin=$(find_bin dns2socks) - [ -n "$dns2socks_bin" ] && { + [ -f "$dns2socks_bin" ] && { DNS2SOCKS_FORWARD=$(config_t_get global dns2socks_forward 8.8.4.4) nohup $dns2socks_bin 127.0.0.1:$SOCKS5_PROXY_PORT1 $DNS2SOCKS_FORWARD 127.0.0.1:$DNS_PORT >/dev/null 2>&1 & echolog "DNS:dns2socks..." @@ -735,8 +741,7 @@ start_dns() { fi ;; pdnsd) - pdnsd_bin=$(find_bin pdnsd) - [ -n "$pdnsd_bin" ] && { + [ -f "$pdnsd_bin" ] && { use_tcp_node_resolve_dns=1 gen_pdnsd_config $DNS_PORT 10240 DNS_FORWARD=$(echo $DNS_FORWARD | sed 's/,/ /g') @@ -745,8 +750,7 @@ start_dns() { } ;; chinadns-ng) - chinadns_ng_bin=$(find_bin chinadns-ng) - [ -n "$chinadns_ng_bin" ] && { + [ -f "$chinadns_ng_bin" ] && { other_port=$(expr $DNS_PORT + 1) cat $RULE_PATH/gfwlist.conf | sort | uniq | sed -e '/127.0.0.1/d' | sed 's/ipset=\/.//g' | sed 's/\/gfwlist//g' > $CONFIG_PATH/gfwlist.txt [ -f "$CONFIG_PATH/gfwlist.txt" ] && local gfwlist_param="-g $CONFIG_PATH/gfwlist.txt" @@ -760,8 +764,7 @@ start_dns() { else use_tcp_node_resolve_dns=1 gen_pdnsd_config $other_port 0 - pdnsd_bin=$(find_bin pdnsd) - [ -n "$pdnsd_bin" ] && { + [ -f "$pdnsd_bin" ] && { DNS_FORWARD=$(echo $DNS_FORWARD | sed 's/,/ /g') nohup $pdnsd_bin --daemon -c $pdnsd_dir/pdnsd.conf -d >/dev/null 2>&1 & nohup $chinadns_ng_bin -l $DNS_PORT -c $UP_CHINA_DNS -t 127.0.0.1#$other_port $gfwlist_param $chnlist_param >/dev/null 2>&1 & @@ -770,8 +773,7 @@ start_dns() { fi elif [ "$up_trust_chinadns_ng_dns" == "dns2socks" ]; then if [ -n "$SOCKS5_NODE1" -a "$SOCKS5_NODE1" != "nil" ]; then - dns2socks_bin=$(find_bin dns2socks) - [ -n "$dns2socks_bin" ] && { + [ -f "$dns2socks_bin" ] && { DNS2SOCKS_FORWARD=$(config_t_get global dns2socks_forward 8.8.4.4) nohup $dns2socks_bin 127.0.0.1:$SOCKS5_PROXY_PORT1 $DNS2SOCKS_FORWARD 127.0.0.1:$other_port >/dev/null 2>&1 & nohup $chinadns_ng_bin -l $DNS_PORT -c $UP_CHINA_DNS -t 127.0.0.1#$other_port $gfwlist_param $chnlist_param >/dev/null 2>&1 & @@ -978,8 +980,7 @@ stop_dnsmasq() { start_haproxy() { enabled=$(config_t_get global_haproxy balancing_enable 0) [ "$enabled" = "1" ] && { - haproxy_bin=$(find_bin haproxy) - [ -n "$haproxy_bin" ] && { + [ -f "$haproxy_bin" ] && { bport=$(config_t_get global_haproxy haproxy_port) cat <<-EOF >$HAPROXY_FILE global @@ -1133,8 +1134,7 @@ stop() { done clean_log source $APP_PATH/iptables.sh stop - kill_all brook dns2socks haproxy chinadns-ng ipt2socks v2ray-plugin obfs-local - 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 & + kill_all v2ray-plugin obfs-local ps -w | grep -E "$CONFIG_PATH" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & rm -rf $TMP_DNSMASQ_PATH $CONFIG_PATH stop_dnsmasq diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh b/package/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh index 7f14992734..97f254aa90 100755 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh +++ b/package/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh @@ -2,6 +2,7 @@ CONFIG=passwall CONFIG_PATH=/var/etc/$CONFIG +RUN_BIN_PATH=$CONFIG_PATH/bin config_n_get() { local ret=$(uci -q get $CONFIG.$1.$2 2>/dev/null) @@ -40,14 +41,14 @@ for i in $(seq 1 $TCP_NODE_NUM); do #kcptun use_kcp=$(config_n_get $tmp_node use_kcp 0) if [ $use_kcp -gt 0 ]; then - icount=$(ps -w | grep kcptun-client | grep $CONFIG_PATH/kcptun_${i} | grep -v grep | wc -l) + icount=$(ps -w | grep -v grep | grep $RUN_BIN_PATH | grep kcptun-client | grep kcptun_${i} | wc -l) if [ $icount = 0 ]; then /etc/init.d/passwall restart exit 0 fi fi [ -f "/var/etc/passwall/port/TCP_$i" ] && listen_port=$(echo -n `cat /var/etc/passwall/port/TCP_$i`) - icount=$(ps -w | grep -v grep | grep -i -E "${CONFIG}/TCP_${i}|brook tproxy -l 0.0.0.0:${listen_port}|ipt2socks -T -l ${listen_port}" | wc -l) + icount=$(ps -w | grep -v grep | grep $RUN_BIN_PATH | grep -i -E "TCP_${i}|brook tproxy -l 0.0.0.0:${listen_port}|ipt2socks -T -l ${listen_port}" | wc -l) if [ $icount = 0 ]; then /etc/init.d/passwall restart exit 0 @@ -62,7 +63,7 @@ for i in $(seq 1 $UDP_NODE_NUM); do if [ "$tmp_node" != "nil" ]; then [ "$tmp_node" == "default" ] && tmp_node=$TCP_NODE1 [ -f "/var/etc/passwall/port/UDP_$i" ] && listen_port=$(echo -n `cat /var/etc/passwall/port/UDP_$i`) - icount=$(ps -w | grep -v grep | grep -i -E "${CONFIG}/UDP_${i}|brook tproxy -l 0.0.0.0:${listen_port}|ipt2socks -U -l ${listen_port}" | wc -l) + icount=$(ps -w | grep -v grep | grep $RUN_BIN_PATH | grep -i -E "UDP_${i}|brook tproxy -l 0.0.0.0:${listen_port}|ipt2socks -U -l ${listen_port}" | wc -l) if [ $icount = 0 ]; then /etc/init.d/passwall restart exit 0 @@ -75,7 +76,7 @@ for i in $(seq 1 $SOCKS5_NODE_NUM); do eval tmp_node=\$SOCKS5_NODE$i if [ "$tmp_node" != "nil" ]; then [ -f "/var/etc/passwall/port/SOCKS5_$i" ] && listen_port=$(echo -n `cat /var/etc/passwall/port/SOCKS5_$i`) - icount=$(ps -w | grep -v grep | grep -i -E "${CONFIG}/SOCKS5_${i}|brook client -l 0.0.0.0:${listen_port}" | wc -l) + icount=$(ps -w | grep -v grep | grep $RUN_BIN_PATH | grep -i -E "SOCKS5_${i}|brook client -l 0.0.0.0:${listen_port}" | wc -l) if [ $icount = 0 ]; then /etc/init.d/passwall restart exit 0 @@ -94,7 +95,7 @@ fi #haproxy if [ $use_haproxy -gt 0 ]; then - icount=$(ps -w | grep haproxy | grep $CONFIG_PATH/haproxy.cfg | grep -v grep | wc -l) + icount=$(ps -w | grep -v grep | grep $RUN_BIN_PATH | grep haproxy | wc -l) if [ $icount = 0 ]; then /etc/init.d/passwall restart exit 0 diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/package/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua new file mode 100644 index 0000000000..04b3b757ea --- /dev/null +++ b/package/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -0,0 +1,463 @@ +#!/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 +-- @author William Chan +------------------------------------------------ +require 'nixio' +require 'luci.util' +require 'luci.jsonc' +require 'luci.sys' + +local params = arg[1] + +-- these global functions are accessed all the time by the event handler +-- so caching them is worth the effort +local luci = luci +local tinsert = table.insert +local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string.char, string.byte, string.format, string.gsub +local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify +local b64decode = nixio.bin.b64decode +local cache = {} +local nodeResult = setmetatable({}, { __index = cache }) -- update result +local name = 'passwall' +local uciType = 'nodes' +local ucic = luci.model.uci.cursor() +local api = require "luci.model.cbi.passwall.api.api" + +local log = function(...) + print(os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({ ... }, " ")) +end + +-- 分割字符串 +local function split(full, sep) + full = full:gsub("%z", "") -- 这里不是很清楚 有时候结尾带个\0 + local off, result = 1, {} + while true do + local nEnd = full:find(sep, off) + if not nEnd then + local res = ssub(full, off, slen(full)) + if #res > 0 then -- 过滤掉 \0 + tinsert(result, res) + end + break + else + tinsert(result, ssub(full, off, nEnd - 1)) + off = nEnd + slen(sep) + end + end + return result +end +-- urlencode +local function get_urlencode(c) + return sformat("%%%02X", sbyte(c)) +end + +local function urlEncode(szText) + local str = szText:gsub("([^0-9a-zA-Z ])", get_urlencode) + str = str:gsub(" ", "+") + return str +end + +local function get_urldecode(h) + return schar(tonumber(h, 16)) +end +local function UrlDecode(szText) + return szText:gsub("+", " "):gsub("%%(%x%x)", get_urldecode) +end + +-- trim +local function trim(text) + if not text or text == "" then + return "" + end + return (sgsub(text, "^%s*(.-)%s*$", "%1")) +end +-- md5 +local function md5(content) + local stdout = luci.sys.exec('echo \"' .. urlEncode(content) .. '\" | md5sum | cut -d \" \" -f1') + -- assert(nixio.errno() == 0) + return trim(stdout) +end +-- base64 +local function base64Decode(text) + local raw = text + if not text then return '' end + text = text:gsub("%z", "") + text = text:gsub("_", "/") + text = text:gsub("-", "+") + local mod4 = #text % 4 + text = text .. string.sub('====', mod4 + 1) + local result = b64decode(text) + if result then + return result:gsub("%z", "") + else + return raw + end +end +-- 处理数据 +local function processData(szType, content, add_mode) + local result = { + timeout = 60, + add_mode = add_mode, + is_sub = (add_mode and add_mode == "导入") and 0 or 1 + } + result.hashkey = type(content) == 'string' and md5(content) or md5(jsonStringify(content)) + if szType == 'ssr' then + local dat = split(content, "/\\?") + local hostInfo = split(dat[1], ':') + result.type = "SSR" + result.address = hostInfo[1] + result.port = hostInfo[2] + result.protocol = hostInfo[3] + result.ssr_encrypt_method = hostInfo[4] + result.obfs = hostInfo[5] + result.password = base64Decode(hostInfo[6]) + local params = {} + for _, v in pairs(split(dat[2], '&')) do + local t = split(v, '=') + params[t[1]] = t[2] + end + result.obfs_param = base64Decode(params.bfsparam) + result.protocol_param = base64Decode(params.protoparam) + local group = base64Decode(params.group) + if group then + result.group = group + end + result.remarks = base64Decode(params.remarks) + elseif szType == 'vmess' then + local info = jsonParse(content) + result.type = 'V2ray' + result.address = info.add + result.port = info.port + result.v2ray_transport = info.net + result.v2ray_VMess_alterId = info.aid + result.v2ray_VMess_id = info.id + result.remarks = info.ps + result.v2ray_mux = 1 + result.v2ray_mux_concurrency = 8 + if info.net == 'ws' then + result.v2ray_ws_host = info.host + result.v2ray_ws_path = info.path + end + if info.net == 'h2' then + result.v2ray_h2_host = info.host + result.v2ray_h2_path = info.path + end + if info.net == 'tcp' then + result.v2ray_tcp_guise = info.type + result.v2ray_tcp_guise_http_host = info.host + result.v2ray_tcp_guise_http_path = info.path + end + if info.net == 'kcp' then + result.v2ray_mkcp_guise = info.type + result.v2ray_mkcp_mtu = 1350 + result.v2ray_mkcp_tti = 50 + result.v2ray_mkcp_uplinkCapacity = 5 + result.v2ray_mkcp_downlinkCapacity = 20 + result.v2ray_mkcp_readBufferSize = 2 + result.v2ray_mkcp_writeBufferSize = 2 + end + if info.net == 'quic' then + result.v2ray_quic_guise = info.type + result.v2ray_quic_key = info.key + result.v2ray_quic_security = info.securty + 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 + else + result.v2ray_stream_security = "none" + end + elseif szType == "ss" then + local idx_sp = 0 + local alias = "" + if content:find("#") then + idx_sp = content:find("#") + alias = content:sub(idx_sp + 1, -1) + end + local info = content:sub(1, idx_sp - 1) + local hostInfo = split(base64Decode(info), "@") + local host = split(hostInfo[2], ":") + local userinfo = base64Decode(hostInfo[1]) + local method = userinfo:sub(1, userinfo:find(":") - 1) + local password = userinfo:sub(userinfo:find(":") + 1, #userinfo) + result.remarks = UrlDecode(alias) + result.type = "SS" + result.address = host[1] + if host[2]:find("/\\?") then + local query = split(host[2], "/\\?") + result.port = query[1] + local params = {} + for _, v in pairs(split(query[2], '&')) do + local t = split(v, '=') + params[t[1]] = t[2] + end + if params.lugin then + local plugin_info = UrlDecode(params.lugin) + 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) + else + result.ss_plugin = plugin_info + end + end + else + result.port = host[2] + end + result.ss_encrypt_method = method + result.password = password + elseif szType == "ssd" then + result.type = "SS" + result.address = content.server + result.port = content.port + result.password = content.password + result.ss_encrypt_method = content.encryption + result.ss_plugin = content.plugin + result.ss_plugin_opts = content.plugin_options + result.group = content.airport + result.remarks = content.remarks + end + if not result.remarks then + result.remarks = result.address .. ':' .. result.port + end + return result +end +-- wget +local function wget(url) + local stdout = luci.sys.exec('/usr/bin/wget --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36" --no-check-certificate -t 3 -T 10 -O- "' .. url .. '"') + return trim(stdout) +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 = api.uci_get_type_id(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") + end + end + end + + 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 = api.uci_get_type_id(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 = api.uci_get_type_id(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) + if old.is_sub and old.is_sub == "1" then + ucic:delete(name, old['.name']) + end + end) + ucic:commit(name) + + if is_stop == 1 then + luci.sys.call("/etc/init.d/" .. name .. " restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早 + end + log('在线订阅节点已全部删除') +end + +local function update_node(manual) + assert(next(nodeResult), "node result is empty") + 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 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 + end + else + --log('忽略手动添加的节点: ' .. old.remarks) + 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 + + end + end + 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 + log('新增节点数量: ' ..add, '删除节点数量: ' .. del) +end + +local function parse_link(raw, md5_str, 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 + -- SSD 似乎是这种格式 ssd:// 开头的 + if raw:find('ssd://') then + szType = 'ssd' + local nEnd = select(2, raw:find('ssd://')) + nodes = base64Decode(raw:sub(nEnd + 1, #raw)) + nodes = jsonParse(nodes) + local extra = { + airport = nodes.airport, + port = nodes.port, + encryption = nodes.encryption, + password = nodes.password + } + local servers = {} + -- SS里面包着 干脆直接这样 + for _, server in ipairs(nodes.servers) do + tinsert(servers, setmetatable(server, { __index = extra })) + end + nodes = servers + else + -- ssd 外的格式 + if manual then + nodes = split(raw:gsub(" ", "\n"), "\n") + add_mode = '导入' + else + nodes = split(base64Decode(raw):gsub(" ", "\n"), "\n") + end + end + + for _, v in ipairs(nodes) do + if v then + local result + if szType == 'ssd' then + result = processData(szType, v, add_mode) + elseif not szType then + local node = trim(v) + local dat = split(node, "://") + if dat and dat[1] and dat[2] then + if dat[1] == 'ss' then + result = processData(dat[1], dat[2], add_mode) + else + result = processData(dat[1], base64Decode(dat[2]), add_mode) + end + end + else + log('跳过未知类型: ' .. szType) + end + -- log(result) + if result then + if result.remarks:find("过期时间") or + result.remarks:find("剩余流量") or + result.remarks:find("QQ群") or + result.remarks:find("官网") or + not result.address + then + 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]] + end + end + end + end + log('成功解析节点数量: ' ..#nodes) + end +end + +local execute = function() + -- exec + do + ucic:foreach(name, "subscribe_list", function(obj) + local enabled = obj.enabled or nil + if enabled and enabled == "1" then + local remark = obj.remark + local url = obj.url + local md5_str = md5(url) + local raw = wget(url) + parse_link(raw, md5_str) + end + end) + end + -- diff + do + update_node(0) + 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'\")") + if count and tonumber(count) > 0 then + log('开始订阅...') + xpcall(execute, function(e) + log(e) + log(debug.traceback()) + log('发生错误, 正在恢复服务') + end) + log('订阅完毕...') + end + elseif arg[1] == "add" then + 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, md5_str, 1) + end + update_node(1) + elseif arg[1] == "truncate" then + truncate_nodes() + end +end \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/subscription.sh b/package/lienol/luci-app-passwall/root/usr/share/passwall/subscription.sh deleted file mode 100755 index 0d2288ae48..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/subscription.sh +++ /dev/null @@ -1,597 +0,0 @@ -#!/bin/bash - -. $IPKG_INSTROOT/lib/functions.sh -. /usr/share/libubox/jshn.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 -q get $CONFIG.@$1[$index].$2 2>/dev/null) - #echo ${ret:=$3} - echo $ret -} - -urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; } - -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' | base64 -d -i 2> /dev/null - else - echo -n "$link" | sed 's/-/+/g; s/_/\//g' | base64 -d -i 2> /dev/null - fi -} - -start_subscribe() { - local enabled - local url - config_get enabled $1 enabled - config_get url $1 url - [ "$enabled" == "1" ] && { - [ -n "$url" -a "$url" != "" ] && { - local addnum_ss=0 - local updatenum_ss=0 - local delnum_ss=0 - local addnum_ssr=0 - local updatenum_ssr=0 - local delnum_ssr=0 - local addnum_v2ray=0 - local updatenum_v2ray=0 - local delnum_v2ray=0 - local addnum_trojan=0 - local updatenum_trojan=0 - local delnum_trojan=0 - config_get subscrib_remark $1 remark - let index+=1 - echo "$Date: 正在订阅:$url" >> $LOG_FILE - result=$(/usr/bin/curl --connect-timeout 5 --retry 1 -sL $url) - [ "$?" != 0 ] || [ -z "$result" ] && { - result=$(/usr/bin/wget --no-check-certificate --timeout=5 -t 1 -O- $url) - [ "$?" != 0 ] || [ -z "$result" ] && echo "$Date: 订阅失败:$url,请检测订阅链接是否正常或使用代理尝试!" >> $LOG_FILE && continue - } - file="/var/${CONFIG}_sub/$index" - echo "$result" > $file - - get_local_nodes - - if [ $(expr "$result" : "ssd://") == 0 ];then - [ -z "$(du -sh $file 2> /dev/null)" ] && echo "$Date: 订阅失败:$url,解密失败!" >> $LOG_FILE && continue - decode_link=$(cat "$file" | base64 -d 2> /dev/null) - maxnum=$(echo -n "$decode_link" | grep "MAX=" | awk -F"=" '{print $2}') - if [ -n "$maxnum" ]; then - decode_link=$(echo -n "$decode_link" | sed '/MAX=/d' | shuf -n${maxnum}) - else - decode_link=$(echo -n "$decode_link") - fi - - [ -z "$decode_link" ] && continue - for link in $decode_link - do - if expr "$link" : "ss://";then - link_type="ss" - new_link=$(echo -n "$link" | sed 's/ss:\/\///g') - elif expr "$link" : "ssr://";then - link_type="ssr" - new_link=$(echo -n "$link" | sed 's/ssr:\/\///g') - elif expr "$link" : "vmess://";then - link_type="v2ray" - new_link=$(echo -n "$link" | sed 's/vmess:\/\///g') - elif expr "$link" : "trojan://";then - link_type="trojan" - new_link=$(echo -n "$link" | sed 's/trojan:\/\///g') - fi - [ -z "$link_type" ] && continue - get_remote_config "$link_type" "$new_link" - done - else - link=$result - link_type="ssd" - new_link=$(echo -n "$link" | sed 's/ssd:\/\///g') - [ -z "$link_type" ] && continue - get_remote_config "$link_type" "$new_link" - fi - [ "$addnum_ss" -gt 0 ] || [ "$updatenum_ss" -gt 0 ] || [ "$delnum_ss" -gt 0 ] && echo "$Date: $subscrib_remark: SS节点新增 $addnum_ss 个,修改 $updatenum_ss 个,删除 $delnum_ss 个。" >> $LOG_FILE - [ "$addnum_ssr" -gt 0 ] || [ "$updatenum_ssr" -gt 0 ] || [ "$delnum_ssr" -gt 0 ] && echo "$Date: $subscrib_remark: SSR节点新增 $addnum_ssr 个,修改 $updatenum_ssr 个,删除 $delnum_ssr 个。" >> $LOG_FILE - [ "$addnum_v2ray" -gt 0 ] || [ "$updatenum_v2ray" -gt 0 ] || [ "$delnum_v2ray" -gt 0 ] && echo "$Date: $subscrib_remark: V2ray节点新增 $addnum_v2ray 个,修改 $updatenum_v2ray 个,删除 $delnum_v2ray 个。" >> $LOG_FILE - [ "$addnum_trojan" -gt 0 ] || [ "$updatenum_trojan" -gt 0 ] || [ "$delnum_trojan" -gt 0 ] && echo "$Date: $subscrib_remark: Trojan节点新增 $addnum_trojan 个,修改 $updatenum_trojan 个,删除 $delnum_trojan 个。" >> $LOG_FILE - } - } -} - -ss_decode() { - temp_link=$1 - if [[ "$(echo $temp_link | grep "@")" != "" ]]; then - link1=$(decode_url_link $(echo -n "$temp_link" | awk -F '@' '{print $1}') 1) - link2=$(echo -n "$temp_link" | awk -F '@' '{print $2}') - echo -n "${link1}@${link2}" - elif [[ "$(echo $temp_link | grep "#")" != "" ]]; then - link1=$(decode_url_link $(echo -n "$temp_link" | awk -F '#' '{print $1}') 1) - link2=$(echo -n "$temp_link" | awk -F '#' '{print $2}') - echo -n "${link1}#${link2}" - else - link1=$(decode_url_link $(echo -n "$temp_link" ) 1) - echo -n "$link1" - fi -} - -get_node_index(){ - [ -f "/etc/config/$CONFIG" ] && { - nodes_index=$(uci show $CONFIG | grep -c "=nodes") - } -} - -get_local_nodes(){ - [ -f "/etc/config/$CONFIG" ] && [ "`uci show $CONFIG | grep -c 'is_sub'`" -gt 0 ] && { - get_node_index - for i in `seq $nodes_index -1 1` - do - [ "$(uci show $CONFIG.@nodes[$(($i-1))]|grep -c "is_sub")" -eq 1 ] && { - if [ ! -f "/usr/share/${CONFIG}/sub/all_localnodes" ]; then - echo $(config_t_get nodes address $(($i-1))) > /usr/share/${CONFIG}/sub/all_localnodes - else - echo $(config_t_get nodes address $(($i-1))) >> /usr/share/${CONFIG}/sub/all_localnodes - fi - } - done - } -} - -get_remote_config(){ - add_mode="$subscrib_remark" - [ -n "$3" ] && add_mode="导入" - new_node_type=$(echo $1 | tr '[a-z]' '[A-Z]') - if [ "$1" == "ss" ]; then - decode_link=$(ss_decode $2) - ss_encrypt_method=$(echo "$decode_link" | awk -F ':' '{print $1}') - password=$(echo "$decode_link" | awk -F ':' '{print $2}' | awk -F '@' '{print $1}') - node_address=$(echo "$decode_link" | awk -F ':' '{print $2}' | awk -F '@' '{print $2}') - - plugin_tmp=$(echo "$decode_link" | awk -F '\\/\\?' '{print $2}' | awk -F '#' '{print $1}') - if [ "$plugin_tmp" != "" ]; then - plugin_tmp=$(urldecode $plugin_tmp) - plugin=$(echo "$plugin_tmp" | awk -F 'plugin=' '{print $2}' | awk -F ';' '{print $1}') - plugin_options=$(echo "$plugin_tmp" | awk -F "$plugin;" '{print $2}' | awk -F '&' '{print $1}') - node_port=$(echo "$decode_link" | awk -F '@' '{print $2}' | awk -F '\\/\\?' '{print $1}' | awk -F ':' '{print $2}') - else - node_port=$(echo "$decode_link" | awk -F '@' '{print $2}' | awk -F '#' '{print $1}' | awk -F ':' '{print $2}') - fi - - [ -n "$plugin" -a "$plugin" == "simple-obfs" ] && plugin=obfs-local - remarks=$(urldecode $(echo "$decode_link" | awk -F '#' '{print $2}')) - elif [ "$1" == "ssr" ]; then - decode_link=$(decode_url_link $2 1) - node_address=$(echo "$decode_link" | awk -F ':' '{print $1}') - node_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)" - group_temp=$(echo "$decode_link" |grep -Eo "group.+" |sed 's/group=//g'|awk -F'&' '{print $1}') - [ -n "$group_temp" ] && group="$(decode_url_link $group_temp 0)" - elif [ "$1" == "v2ray" ]; then - decode_link=$(decode_url_link $2 1) - json_load "$decode_link" - json_get_var json_v v - json_get_var json_ps ps - json_get_var json_node_address add - json_get_var json_node_port port - json_get_var json_id id - json_get_var json_aid aid - json_get_var json_security security - json_get_var json_net net - json_get_var json_type type - json_get_var json_transport net - json_get_var json_tls tls - json_get_var json_host host - json_get_var json_path path - - if [ "$json_tls" == "tls" -o "$json_tls" == "1" ]; then - json_tls="tls" - else - json_tls="none" - fi - - remarks="${json_ps}" - node_address=$json_node_address - node_port=$json_node_port - elif [ "$1" == "trojan" ]; then - link="$2" - node_password=$(echo "$link" | sed 's/trojan:\/\///g' | awk -F '@' '{print $1}') - node_address=$(echo "$link" | sed 's/trojan:\/\///g' | awk -F '@' '{print $2}' | awk -F ':' '{print $1}') - node_port=$(echo "$link" | sed 's/trojan:\/\///g' | awk -F '@' '{print $2}' | awk -F ':' '{print $2}') - remarks="${node_address}:${node_port}" - elif [ "$1" == "ssd" ]; then - link_type="ss" - new_node_type=$(echo $link_type | tr '[a-z]' '[A-Z]') - decode_link=$(decode_url_link $2 1) - json_load "$decode_link" - json_get_var json_airport airport - json_get_var json_port port - json_get_var json_encryption encryption - json_get_var json_password password - json_get_var json_traffic_used traffic_used - json_get_var json_traffic_total traffic_total - json_get_var json_expiry expiry - json_get_var json_url url - json_get_var json_plugin plugin - json_get_var json_plugin_options plugin_options - - ss_encrypt_method=$json_encryption - password=$json_password - plugin=$json_plugin - plugin_options=$json_plugin_options - - [ -n "$plugin" -a "$plugin" == "simple-obfs" ] && plugin=obfs-local - - if json_get_type Type servers && [ "$Type" == array ] - then - json_select servers - idx=1 - while json_get_type Type "$idx" && [ "$Type" == object ] - do - json_select $idx - json_get_var json_server server - json_get_var json_server_id id - json_get_var json_server_ratio ratio - json_get_var json_server_remarks remarks - - remarks="${json_server_remarks}" - node_address=$json_server - node_port=$json_port - - idx=$(expr $idx + 1) - json_select .. - - node_address=$(echo -n $node_address | awk '{print gensub(/[^!-~]/,"","g",$0)}') - node_address=$(echo -n $node_address | grep -F ".") - [ -z "$node_address" -o "$node_address" == "" ] && return - - [ -z "$remarks" -o "$remarks" == "" ] && remarks="${node_address}:${node_port}" - tmp=$(echo $remarks | grep -E "过期时间|剩余流量|QQ群|官网") - [ -n "$tmp" ] && { - echo "$Date: 丢弃无用节点:$tmp" >> $LOG_FILE - return - } - - # 把全部节点节点写入文件 /usr/share/${CONFIG}/sub/all_onlinenodes - if [ ! -f "/usr/share/${CONFIG}/sub/all_onlinenodes" ]; then - echo $node_address > /usr/share/${CONFIG}/sub/all_onlinenodes - else - echo $node_address >> /usr/share/${CONFIG}/sub/all_onlinenodes - fi - - update_config - done - return - fi - fi - - node_address=$(echo -n $node_address | awk '{print gensub(/[^!-~]/,"","g",$0)}') - node_address=$(echo -n $node_address | grep -F ".") - [ -z "$node_address" -o "$node_address" == "" ] && return - - [ -z "$remarks" -o "$remarks" == "" ] && remarks="${node_address}:${node_port}" - tmp=$(echo $remarks | grep -E "过期时间|剩余流量|QQ群|官网") - [ -n "$tmp" ] && { - echo "$Date: 丢弃无用节点:$tmp" >> $LOG_FILE - return - } - - # 把全部节点节点写入文件 /usr/share/${CONFIG}/sub/all_onlinenodes - if [ ! -f "/usr/share/${CONFIG}/sub/all_onlinenodes" ]; then - echo $node_address > /usr/share/${CONFIG}/sub/all_onlinenodes - else - echo $node_address >> /usr/share/${CONFIG}/sub/all_onlinenodes - fi - - update_config -} - -add_nodes(){ - if [ "$1" == "add" ]; then - get_node_index - uci add $CONFIG nodes - elif [ "$1" == "update" ]; then - nodes_index=$update_index - fi - uci_set="uci set $CONFIG.@nodes[$nodes_index]." - [ "$add_mode" != "导入" ] && ${uci_set}is_sub="is_sub" - if [ "$2" == "ss" ]; then - ${uci_set}add_mode="$add_mode" - ${uci_set}remarks="$remarks" - ${uci_set}type="SS" - ${uci_set}address="$node_address" - ${uci_set}use_ipv6=0 - ${uci_set}port="$node_port" - ${uci_set}password="$password" - ${uci_set}ss_encrypt_method="$ss_encrypt_method" - ${uci_set}timeout=300 - ${uci_set}tcp_fast_open=false - [ -n "$plugin" ] && ${uci_set}ss_plugin="$plugin" - [ -n "$plugin_options" ] && ${uci_set}ss_plugin_opts="$plugin_options" - - if [ "$1" == "add" ]; then - let addnum_ss+=1 - elif [ "$1" == "update" ]; then - let updatenum_ss+=1 - fi - - elif [ "$2" == "ssr" ]; then - ${uci_set}add_mode="$add_mode" - ${uci_set}remarks="$remarks" - ${uci_set}type="SSR" - ${uci_set}address="$node_address" - ${uci_set}use_ipv6=0 - ${uci_set}port="$node_port" - ${uci_set}password="$password" - ${uci_set}ssr_encrypt_method="$ssr_encrypt_method" - ${uci_set}protocol="$protocol" - ${uci_set}protocol_param="$protoparam" - ${uci_set}obfs="$obfs" - ${uci_set}obfs_param="$obfsparam" - ${uci_set}timeout=300 - ${uci_set}tcp_fast_open=false - ${uci_set}group="$group" - - if [ "$1" == "add" ]; then - let addnum_ssr+=1 - elif [ "$1" == "update" ]; then - let updatenum_ssr+=1 - fi - - elif [ "$2" == "v2ray" ]; then - ${uci_set}add_mode="$add_mode" - ${uci_set}remarks="$remarks" - ${uci_set}type="V2ray" - ${uci_set}v2ray_protocol="vmess" - ${uci_set}address="$node_address" - ${uci_set}use_ipv6=0 - ${uci_set}port="$json_node_port" - ${uci_set}v2ray_security="auto" - ${uci_set}v2ray_VMess_id="$json_id" - ${uci_set}v2ray_VMess_alterId="$json_aid" - ${uci_set}v2ray_VMess_level="$json_v" - ${uci_set}v2ray_transport="$json_net" - ${uci_set}v2ray_stream_security="$json_tls" - ${uci_set}v2ray_tcp_guise="$json_type" - ${uci_set}v2ray_ws_host="$json_host" - ${uci_set}v2ray_ws_path="$json_path" - ${uci_set}v2ray_h2_host="$json_host" - ${uci_set}v2ray_h2_path="$json_path" - ${uci_set}tls_allowInsecure=1 - - if [ "$1" == "add" ]; then - let addnum_v2ray+=1 - elif [ "$1" == "update" ]; then - let updatenum_v2ray+=1 - fi - - elif [ "$2" == "trojan" ]; then - ${uci_set}add_mode="$add_mode" - ${uci_set}remarks="$remarks" - ${uci_set}type="Trojan" - ${uci_set}address="$node_address" - ${uci_set}port="$node_port" - ${uci_set}password="$node_password" - - if [ "$1" == "add" ]; then - let addnum_trojan+=1 - elif [ "$1" == "update" ]; then - let updatenum_trojan+=1 - fi - - fi - uci commit $CONFIG -} - -update_config(){ - [ -z "$remarks" -o "$remarks" == "" ] && return - indexs=$(uci show $CONFIG | grep "@nodes" | grep "remarks=" | grep -F "$remarks" | cut -d '[' -f2|cut -d ']' -f1) - if [ -z "$indexs" ]; then - add_nodes add "$link_type" - else - action="add" - for index in $indexs - do - local is_sub=$(uci -q get $CONFIG.@nodes[$index].is_sub) - [ -z "$is_sub" -o "$is_sub" == "" ] && return - local old_node_type=$(uci -q get $CONFIG.@nodes[$index].type | tr '[a-z]' '[A-Z]') - if [ -n "$old_node_type" -a "$old_node_type" == "$new_node_type" ]; then - action="update" - update_index=$index - break - fi - done - if [ "$action" == "add" ]; then - add_nodes add "$link_type" - elif [ "$action" == "update" ]; then - add_nodes update "$link_type" - fi - fi -} - -del_config(){ - # 删除订阅节点已经不存在的节点 - for localaddress in $(cat /usr/share/${CONFIG}/sub/all_localnodes) - do - [ "`cat /usr/share/${CONFIG}/sub/all_onlinenodes |grep -c "$localaddress"`" -eq 0 ] && { - for localindex in $(uci show $CONFIG | grep -w "$localaddress" | grep -w "address=" |cut -d '[' -f2|cut -d ']' -f1) - do - del_type=$(uci -q get $CONFIG.@nodes[$localindex].type) - uci delete $CONFIG.@nodes[$localindex] - uci commit $CONFIG - if [ "$del_type" == "SS" ]; then - let delnum_ss+=1 #删除该节点 - elif [ "$del_type" == "SSR" ]; then - let delnum_ssr+=1 #删除该节点 - elif [ "$del_type" == "V2ray" ]; then - let delnum_v2ray+=1 #删除该节点 - elif [ "$del_type" == "Trojan" ]; then - let delnum_trojan=1 #删除该节点 - fi - - done - } - done -} - -del_all_config(){ - get_node_index - [ "`uci show $CONFIG | grep -c 'is_sub'`" -eq 0 ] && exit 0 - TCP_NODE_NUM=$(uci -q get $CONFIG.@global_other[0].tcp_node_num) - [ -z "$TCP_NODE_NUM" ] && TCP_NODE_NUM=1 - for i in $(seq 1 $TCP_NODE_NUM); do - eval TCP_NODE$i=$(config_t_get global tcp_node$i) - done - - UDP_NODE_NUM=$(uci -q get $CONFIG.@global_other[0].udp_node_num) - [ -z "$UDP_NODE_NUM" ] && UDP_NODE_NUM=1 - for i in $(seq 1 $UDP_NODE_NUM); do - eval UDP_NODE$i=$(config_t_get global udp_node$i) - done - - SOCKS5_NODE_NUM=$(uci -q get $CONFIG.@global_other[0].socks5_node_num) - [ -z "$SOCKS5_NODE_NUM" ] && SOCKS5_NODE_NUM=1 - for i in $(seq 1 $SOCKS5_NODE_NUM); do - eval SOCKS5_NODE$i=$(config_t_get global socks5_node$i) - done - - [ "$UDP_NODE1" == "default" ] && UDP_NODE1=$TCP_NODE1 - - is_stop=0 - - for i in $(seq 1 $TCP_NODE_NUM); do - eval node=\$TCP_NODE$i - [ -n "$node" -a "$node" != "nil" ] && { - is_sub_node=`uci -q get $CONFIG.$node.is_sub` - [ -n "$is_sub_node" ] && { - is_stop=1 - uci set $CONFIG.@global[0].tcp_node$i="nil" && uci commit $CONFIG - } - } - done - - for i in $(seq 1 $UDP_NODE_NUM); do - eval node=\$UDP_NODE$i - [ "$node" != "nil" ] && { - is_sub_node=`uci -q get $CONFIG.$node.is_sub` - [ -n "$is_sub_node" ] && { - is_stop=1 - uci set $CONFIG.@global[0].udp_node$i="nil" && uci commit $CONFIG - } - } - done - - for i in $(seq 1 $SOCKS5_NODE_NUM); do - eval node=\$SOCKS5_NODE$i - [ "$node" != "nil" ] && { - is_sub_node=`uci -q get $CONFIG.$node.is_sub` - [ -n "$is_sub_node" ] && { - is_stop=1 - uci set $CONFIG.@global[0].socks5_node$i="nil" && uci commit $CONFIG - } - } - done - - for i in `seq $nodes_index -1 1` - do - [ "$(uci show $CONFIG.@nodes[$(($i-1))] | grep -c 'is_sub')" -eq 1 ] && uci delete $CONFIG.@nodes[$(($i-1))] && uci commit $CONFIG - done - - [ "$is_stop" == 1 ] && /etc/init.d/$CONFIG restart -} - -add() { - base64=$(command -v base64) - [ -z "$base64" ] && echo "$Date: 找不到Base64程序,请安装后重试!" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0 - LINKS=$(cat /tmp/links.conf 2>/dev/null) - [ -n "$LINKS" ] && { - [ -f "$LOCK_FILE" ] && return 3 - touch "$LOCK_FILE" - mkdir -p /usr/share/${CONFIG}/sub && rm -f /usr/share/${CONFIG}/sub/* - for link in $LINKS - do - if expr "$link" : "ss://";then - link_type="ss" - new_link=$(echo -n "$link" | sed 's/ss:\/\///g') - elif expr "$link" : "ssr://";then - link_type="ssr" - new_link=$(echo -n "$link" | sed 's/ssr:\/\///g') - elif expr "$link" : "vmess://";then - link_type="v2ray" - new_link=$(echo -n "$link" | sed 's/vmess:\/\///g') - elif expr "$link" : "trojan://";then - link_type="trojan" - new_link=$(echo -n "$link" | sed 's/trojan:\/\///g') - fi - [ -z "$link_type" ] && continue - get_remote_config "$link_type" "$new_link" 1 - done - [ -f "/usr/share/${CONFIG}/sub/all_onlinenodes" ] && rm -f /usr/share/${CONFIG}/sub/all_onlinenodes - } - rm -f /tmp/links.conf - rm -f "$LOCK_FILE" - exit 0 -} - -start() { - # 防止并发开启服务 - [ -f "$LOCK_FILE" ] && return 3 - touch "$LOCK_FILE" - base64=$(command -v base64) - [ -z "$base64" ] && echo "$Date: 找不到Base64程序,请安装后重试!" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0 - has_subscribe=$(uci show $CONFIG | grep @subscribe_list | grep enabled=\'1\') - [ -z "$has_subscribe" -o "$has_subscribe" = "" ] && echo "$Date: 没有订阅地址或没启用!" >> $LOG_FILE && rm -f "$LOCK_FILE" && exit 0 - - echo "$Date: 开始订阅..." >> $LOG_FILE - mkdir -p /var/${CONFIG}_sub && rm -f /var/${CONFIG}_sub/* - mkdir -p /usr/share/${CONFIG}/sub && rm -f /usr/share/${CONFIG}/sub/* - index=0 - config_load $CONFIG - config_foreach start_subscribe "subscribe_list" - - [ -f "/usr/share/${CONFIG}/sub/all_localnodes" ] && del_config - echo "$Date: 订阅完毕..." >> $LOG_FILE - rm -f "$LOCK_FILE" - exit 0 -} - -stop() { - [ "`uci show $CONFIG | grep -c 'is_sub'`" -gt 0 ] && { - del_all_config - echo "$Date: 在线订阅节点已全部删除" >> $LOG_FILE - } - rm -rf /var/${CONFIG}_sub - rm -rf /usr/share/${CONFIG}/sub - rm -f "$LOCK_FILE" - exit 0 -} - -case $1 in -stop) - stop - ;; -add) - add - ;; -*) - start - ;; -esac