diff --git a/package/ctcgfw/luci-app-vssr/Makefile b/package/ctcgfw/luci-app-vssr/Makefile index e2a84c9b4f..b61eaf8c74 100644 --- a/package/ctcgfw/luci-app-vssr/Makefile +++ b/package/ctcgfw/luci-app-vssr/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-vssr -PKG_VERSION:=1.16 -PKG_RELEASE:=20200301-4 +PKG_VERSION:=1.17 +PKG_RELEASE:=20200304-4 PKG_CONFIG_DEPENDS:= CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray \ diff --git a/package/ctcgfw/luci-app-vssr/luasrc/controller/vssr.lua b/package/ctcgfw/luci-app-vssr/luasrc/controller/vssr.lua index 73e1683790..5bc1ecb271 100644 --- a/package/ctcgfw/luci-app-vssr/luasrc/controller/vssr.lua +++ b/package/ctcgfw/luci-app-vssr/luasrc/controller/vssr.lua @@ -47,13 +47,15 @@ end _("SSR Server"), 20).leaf = true end entry({"admin", "vpn", "vssr", "status"},form("vssr/status"),_("Status"), 23).leaf = true - entry({"admin", "vpn", "vssr", "log"}, cbi("vssr/log"), _("Log"), 30).leaf = - true + +entry({"admin", "vpn", "vssr", "logview"}, cbi("vssr/logview", {hideapplybtn=true, hidesavebtn=true, hideresetbtn=true}), _("Log") ,80).leaf=true + entry({"admin", "vpn", "vssr", "refresh"}, call("refresh_data")) -- 更新白名单和GFWLIST entry({"admin", "vpn", "vssr", "checkport"}, call("check_port")) -- 检测单个端口并返回Ping entry({"admin", "vpn", "vssr", "checkports"}, call("check_ports")) entry({"admin", "vpn", "vssr", "ping"}, call("act_ping")).leaf=true + entry({"admin", "vpn", "vssr", "fileread"}, call("act_read"), nil).leaf=true entry({"admin", "vpn", "vssr", "run"}, call("act_status")) -- 检测全局服务器状态 entry({"admin", "vpn", "vssr", "change"}, call("change_node")) -- 切换节点 entry({"admin", "vpn", "vssr", "allserver"}, call("get_servers")) -- 获取所有节点Json @@ -534,3 +536,16 @@ function get_flag() luci.http.prepare_content("application/json") luci.http.write_json(e) end + +function act_read(lfile) + local NXFS = require "nixio.fs" + local HTTP = require "luci.http" + local lfile = HTTP.formvalue("lfile") + local ldata={} + ldata[#ldata+1] = NXFS.readfile(lfile) or "_nofile_" + if ldata[1] == "" then + ldata[1] = "_nodata_" + end + HTTP.prepare_content("application/json") + HTTP.write_json(ldata) +end diff --git a/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/logview.lua b/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/logview.lua new file mode 100644 index 0000000000..11586ff3a9 --- /dev/null +++ b/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/logview.lua @@ -0,0 +1,48 @@ +-- Copyright 2009 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local NXFS = require "nixio.fs" +local DISP = require "luci.dispatcher" +local HTTP = require "luci.http" +local UCI = luci.model.uci.cursor() + +m = Map("vssr") + +-- log directory +log_dir = UCI:get_first(m.config, "global", "log_dir") or "/tmp" +run_dir = UCI:get_first(m.config, "global", "run_dir") or "/var/etc" +local logfile_list = {} + +for path in (NXFS.glob("%s/vssr*" % log_dir) or function() end) do + logfile_list[#logfile_list+1] = path +end +for path in (NXFS.glob("%s/*.*" % run_dir) or function() end) do + logfile_list[#logfile_list+1] = path +end + +ns = m:section(TypedSection, "_dummy", translate("File Viewer")) +ns.addremove = false +ns.anonymous = true +function ns.cfgsections() + return{"_exrules"} +end + +lv = ns:option(DynamicList, "logfiles") +lv.template = "vssr/logview" +lv.inputtitle = translate("Read / Reread log file") +lv.rows = 25 +lv.default = "" +for _, lfile in ipairs(logfile_list) do lv:value(lfile, lfile) end +function lv.cfgvalue(self, section) + if logfile_list[1] then + local lfile=logfile_list[1] + if NXFS.access(lfile) then + return lfile .. "\n" .. translate("Please press [Read] button") + end + return lfile .. "\n" .. translate("File not found or empty") + else + return log_dir .. "\/\n" .. translate("No files found") + end +end + +return m diff --git a/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/status.lua b/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/status.lua index d4fa53bc88..b8350025a4 100644 --- a/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/status.lua +++ b/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/status.lua @@ -1,7 +1,7 @@ -- Copyright (C) 2017 yushi studio -- Licensed to the public under the GNU General Public License v3. -local IPK_Version="20200301.1.16" +local IPK_Version="20200304.1.17" local m, s, o local redir_run=0 local reudp_run=0 @@ -96,7 +96,88 @@ if nixio.fs.access("/etc/china_ssr.txt") then ip_count = sys.exec("cat /etc/china_ssr.txt | wc -l") end +function processlist() + local data = {} + local netf = {} + local k + local ps = luci.util.execi("/bin/busybox top -bn1 | egrep -v dnsmasq") + local nets = luci.util.execi("netstat -netupl | egrep -v dnsmasq | awk '{print $1,$4,_,$6,$7}'") + if not ps or not nets then + return + end + + for line in nets do +-- tcp 0 0 127.0.0.1:1234 0.0.0.0:* LISTEN 5103/v2ray +-- udp 0 0 127.0.0.1:1234 0.0.0.0:* 5147/v2ray +-- local proto, ip, port, nid = line:match("([^%s]+) +.* +([^ ]*):(%d+) +.* +(%d+)\/.*") + local proto, ip, port, nid = line:match("([^%s]+) (.*):(%d+)[^%d]+(%d+)\/.*") + local idx = tonumber(nid) + if idx and ip then + local newstr = "://" .. ip .. ":" .. port + local isnew = (netf[idx] and netf[idx]['listen']) and netf[idx]['listen']:match(proto .. newstr) or false + netf[idx] = { + ['listen'] = ((netf[idx] and netf[idx]['listen']) and (not isnew) and (netf[idx]['listen'] .. "\n" .. proto) or proto) .. newstr, + } + end + end +-- 5103 1 root S 661m 543% 0% /usr/bin/v2ray/v2ray -config /var/etc/shadowsocksr.json + for line in ps do + local pid, ppid, user, stat, vsz, mem, cpu, cmd = line:match( + "^ *(%d+) +(%d+) +(%S.-%S) +([RSDZTW][W ][ " .. status[idx]['COMMAND'] .. " -c " .. status[idx]['CONFIG'] .. font_off + sname = translate(status[idx]['COMMAND']) + break + end + end + end + local section = form:field(DummyValue,name,translate(name) .. ": " .. sname) + section.rawhtml = true + section.value = stat + return section +end + +procs=processlist() local icount=sys.exec("ps -w | grep ssr-reudp |grep -v grep| wc -l") @@ -187,7 +268,12 @@ m = SimpleForm("Version") m.reset = false m.submit = false - +t = m:section(Table, procs, translate("Running Details: ") .. "(/var/etc)") +t:option(DummyValue, "PID", translate("PID")) +t:option(DummyValue, "COMMAND", translate("CMD")) +t:option(DummyValue, "LISTEN", translate("LISTEN")) +t:option(DummyValue, "%CPU", translate("CPU")) +t:option(DummyValue, "%MEM", translate("MEM")) s=m:field(DummyValue,"redir_run",translate("Global Client")) s.rawhtml = true diff --git a/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/subscription.lua b/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/subscription.lua index 8cd69113ef..be946b7078 100644 --- a/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/subscription.lua +++ b/package/ctcgfw/luci-app-vssr/luasrc/model/cbi/vssr/subscription.lua @@ -46,8 +46,7 @@ end o.default=2 o.rmempty = false -o = s:option(DynamicList, "subscribe_url", translate("Subscribe URL"), - translate("Before subscribing please click below to delete all servers in the subscription")) +o = s:option(DynamicList, "subscribe_url", translate("Subscribe URL")) o.rmempty = true o = s:option(Flag, "proxy", translate("Through proxy update")) @@ -59,6 +58,12 @@ o = s:option(DummyValue, "", "") o.rawhtml = true o.template = "vssr/update_subscribe" +o = s:option(Button,"update",translate("Update All Subscribe Severs"),translate("No special needs, please click here to subscribe to update")) +o.inputstyle = "reload" +o.write = function() + luci.sys.call("bash /usr/share/vssr/subscribe.sh >>/tmp/vssr.log 2>&1") + luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "vssr", "servers")) +end o = s:option(Button,"delete",translate("Delete All Subscribe Severs")) diff --git a/package/ctcgfw/luci-app-vssr/luasrc/view/vssr/logview.htm b/package/ctcgfw/luci-app-vssr/luasrc/view/vssr/logview.htm new file mode 100644 index 0000000000..3ed55bdcaf --- /dev/null +++ b/package/ctcgfw/luci-app-vssr/luasrc/view/vssr/logview.htm @@ -0,0 +1,109 @@ + +<%- + local values = self:formvalue(section) + if not values then + values = self:cfgvalue(section) or {self.default} + end + + local function serialize_json(x, cb) + local rv, push = nil, cb + if not push then + rv = { } + push = function(tok) rv[#rv+1] = tok end + end + + if x == nil then + push("null") + elseif type(x) == "table" then + push("[") + for k = 1, #x do + if k > 1 then + push(",") + end + serialize_json(x[k], push) + end + push("]") + else + push('"%s"' % tostring(x):gsub('["%z\1-\31\\]', + function(c) return '\\u%04x' % c:byte(1) end)) + end + + if not cb then + return table.concat(rv, "") + end + end +-%> +<%+cbi/valueheader%> + + + + +<% +-- one button on top, one at the buttom +%> +

+ /> + +

+ +<% +-- set a readable style taken from openwrt theme for textarea#syslog +-- in openwrt theme there are problems with a width of 100 so we check for theme and set to lower value +%> + +

+ +<% +-- one button on top, one at the buttom +%> + /> +

+<%+cbi/valuefooter%> + diff --git a/package/ctcgfw/luci-app-vssr/luasrc/view/vssr/update_subscribe.htm b/package/ctcgfw/luci-app-vssr/luasrc/view/vssr/update_subscribe.htm index 59a2493769..15932c2ff7 100644 --- a/package/ctcgfw/luci-app-vssr/luasrc/view/vssr/update_subscribe.htm +++ b/package/ctcgfw/luci-app-vssr/luasrc/view/vssr/update_subscribe.htm @@ -1,6 +1,6 @@ <%+cbi/valueheader%> - +
"> diff --git a/package/ctcgfw/luci-app-vssr/po/zh_Hans/vssr.po b/package/ctcgfw/luci-app-vssr/po/zh_Hans/vssr.po index 06a1cd4608..004e465fb8 100644 --- a/package/ctcgfw/luci-app-vssr/po/zh_Hans/vssr.po +++ b/package/ctcgfw/luci-app-vssr/po/zh_Hans/vssr.po @@ -800,7 +800,7 @@ msgid "Plugin Opts" msgstr "插件参数" msgid "Before subscribing please click below to delete all servers in the subscription" -msgstr "订阅前请点击下面的删除所有服务器在订阅" +msgstr "使用此订阅前请删除所有服务器在订阅" msgid "Chnroute Setting" msgstr "国内IP段数据库更新设置" @@ -854,4 +854,15 @@ msgstr "SS/SSR/V2RAY 服务端" msgid "Delete All Subscribe Severs" msgstr "删除所有订阅服务器节点" +msgid "Update All Subscribe Severs" +msgstr "更新所有订阅服务器节点" + +msgid "No special needs, please click here to subscribe to update" +msgstr "没有特殊需要,请点击这里订阅更新" + +msgid "Running Details:" +msgstr "进程详情:" + +msgid "File Viewer" +msgstr "文件查看器" diff --git a/package/ctcgfw/luci-app-vssr/root/etc/init.d/vssr b/package/ctcgfw/luci-app-vssr/root/etc/init.d/vssr index b4b98bc700..f719c9d6ce 100755 --- a/package/ctcgfw/luci-app-vssr/root/etc/init.d/vssr +++ b/package/ctcgfw/luci-app-vssr/root/etc/init.d/vssr @@ -54,8 +54,11 @@ uci_get_by_type() { add_cron() { sed -i '/vssr.log/d' $CRON_FILE echo '0 1 * * 0 echo "" > /tmp/vssr.log' >>$CRON_FILE - [ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/bin/lua /usr/share/vssr/subscribe.lua" >> $CRON_FILE +# [ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/bin/lua /usr/share/vssr/subscribe.lua" >> $CRON_FILE [ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/bin/lua /usr/share/vssr/update.lua" >> $CRON_FILE + [ -n "$(grep -w "/usr/share/vssr/subscribe.sh" $CRON_FILE)" ] && sed -i '/\/usr\/share\/vssr\/subscribe.sh/d' $CRON_FILE + [ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/share/vssr/subscribe.sh" >> $CRON_FILE + [ -z "$(grep -w "/usr/share/vssr/update.sh" $CRON_FILE)" ] && echo "0 5 * * 0 /usr/share/vssr/update.sh" >> $CRON_FILE crontab $CRON_FILE } @@ -614,6 +617,7 @@ start_redir() { sscmd="/usr/bin/v2ray/v2ray" elif [ "$stype" == "trojan" ] ;then sscmd="/usr/sbin/trojan" + fi local utype=$(uci_get_by_name $UDP_RELAY_SERVER type) if [ "$utype" == "ss" ] ;then @@ -624,6 +628,7 @@ start_redir() { ucmd="/usr/bin/v2ray/v2ray" elif [ "$utype" == "trojan" ] ;then ucmd="/usr/sbin/trojan" + fi if [ "$(uci_get_by_type global threads 0)" = "0" ] ;then threads=$(cat /proc/cpuinfo | grep 'processor' | wc -l) @@ -642,14 +647,16 @@ start_redir() { echo "$(date "+%Y-%m-%d %H:%M:%S") Shadowsocks/ShadowsocksR $threads 线程 已启动!" >> /tmp/vssr.log elif [ "$stype" == "v2ray" ] ;then + for i in $(seq 1 $threads); do $sscmd -config /var/etc/v2-ssr-retcp.json >/dev/null 2>&1 & - echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd -version | head -1) 已启动!" >> /tmp/vssr.log + done + echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd -version | head -1) $threads 线程 已启动!" >> /tmp/vssr.log elif [ "$stype" == "trojan" ] ;then for i in $(seq 1 $threads); do $sscmd --config /var/etc/trojan-ssr-retcp.json >/dev/null 2>&1 & done - echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd --version 2>&1 | head -1) 已启动!" >> /tmp/vssr.log + echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd --version 2>&1 | head -1) $threads 线程 已启动!" >> /tmp/vssr.log fi @@ -896,6 +903,7 @@ start_server() { gen_serv_include return 0 } + start_local() { local local_server=$(uci_get_by_type socks5_proxy server) local http_enable=$(uci_get_by_type socks5_proxy http_enable) @@ -1051,7 +1059,7 @@ stop() { killall -q -9 vssr-monitor killall -q -9 ss-redir killall -q -9 ssr-redir - killall -q -9 trojan + killall -q -9 trojan killall -q -9 v2ray killall -q -9 ssr-server killall -q -9 ss-server @@ -1066,8 +1074,8 @@ stop() { killall -q -9 obfs-local killall -q -9 obfs-server killall -q -9 chinadns - killall -q -9 udp2raw - killall -q -9 udpspeeder + killall -q -9 udp2raw + killall -q -9 udpspeeder /usr/bin/udp2raw --clear >/dev/null if [ -f /var/run/pdnsd.pid ] ;then kill $(cat /var/run/pdnsd.pid) >/dev/null 2>&1 diff --git a/package/ctcgfw/luci-app-vssr/root/usr/bin/vssr-rules b/package/ctcgfw/luci-app-vssr/root/usr/bin/vssr-rules index 93ad883707..44c23c12b4 100755 --- a/package/ctcgfw/luci-app-vssr/root/usr/bin/vssr-rules +++ b/package/ctcgfw/luci-app-vssr/root/usr/bin/vssr-rules @@ -84,7 +84,7 @@ ipset_r() { EOF ipset -N gfwlist hash:net 2>/dev/null $IPT -N SS_SPEC_WAN_AC - $IPT -I SS_SPEC_WAN_AC -d $server -j RETURN + $IPT -I SS_SPEC_WAN_AC -p tcp ! --dport 53 -d $server -j RETURN $IPT -A SS_SPEC_WAN_AC -m set --match-set ss_spec_wan_ac dst -j RETURN $IPT -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW @@ -94,7 +94,7 @@ EOF $IPT -A SS_SPEC_WAN_AC -m set --match-set gfwlist dst -j SS_SPEC_WAN_FW $IPT -A SS_SPEC_WAN_AC -m set --match-set gmlan src -m set ! --match-set china dst -j SS_SPEC_WAN_FW $IPT -A SS_SPEC_WAN_AC -m set --match-set china dst -j RETURN - $IPT -I SS_SPEC_WAN_AC -d $server -j RETURN + $IPT -I SS_SPEC_WAN_AC -p tcp ! --dport 53 -d $server -j RETURN elif [ "$RUNMODE" = "oversea" ] ;then ipset -N oversea hash:net 2>/dev/null @@ -102,12 +102,12 @@ EOF ipset -N gmlan hash:net 2>/dev/null for ip in $LAN_GM_IP; do ipset -! add gmlan $ip ; done $IPT -A SS_SPEC_WAN_AC -m set --match-set china dst -j SS_SPEC_WAN_FW - $IPT -I SS_SPEC_WAN_AC -d $server -j RETURN + $IPT -I SS_SPEC_WAN_AC -p tcp ! --dport 53 -d $server -j RETURN elif [ "$RUNMODE" = "all" ] ;then $IPT -N SS_SPEC_WAN_AC $IPT -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW - $IPT -I SS_SPEC_WAN_AC -d $server -j RETURN + $IPT -I SS_SPEC_WAN_AC -p tcp ! --dport 53 -d $server -j RETURN fi @@ -199,7 +199,7 @@ tp_rule() { $ipt -A SS_SPEC_TPROXY -p udp -d 192.168.0.0/16 -j RETURN $ipt -A SS_SPEC_TPROXY -p udp -d 224.0.0.0/4 -j RETURN $ipt -A SS_SPEC_TPROXY -p udp -d 240.0.0.0/4 -j RETURN - $ipt -A SS_SPEC_TPROXY -p udp -d $SERVER -j RETURN + $ipt -A SS_SPEC_TPROXY -p udp ! --dport 53 -d $server -j RETURN $ipt -A SS_SPEC_TPROXY -p udp -m set --match-set bplan src -j RETURN $ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set fplan src \ -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01 diff --git a/package/ctcgfw/luci-app-vssr/root/usr/share/vssr/subscribe.sh b/package/ctcgfw/luci-app-vssr/root/usr/share/vssr/subscribe.sh new file mode 100644 index 0000000000..a67fb69615 --- /dev/null +++ b/package/ctcgfw/luci-app-vssr/root/usr/share/vssr/subscribe.sh @@ -0,0 +1,260 @@ +#!/bin/bash +# Copyright (C) 2017 XiaoShan https://www.mivm.cn + +. /usr/share/libubox/jshn.sh + +urlsafe_b64decode() { + local d="====" data=$(echo $1 | sed 's/_/\//g; s/-/+/g') + local mod4=$((${#data}%4)) + [ $mod4 -gt 0 ] && data=${data}${d:mod4} + echo $data | base64 -d +} + +urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; } + +echo_date(){ + echo $(TZ=UTC-8 date -R +%Y-%m-%d\ %X):$1 +} + +Server_Update() { + local uci_set="uci -q set $name.$1." + ${uci_set}grouphashkey="$ssr_grouphashkey" + ${uci_set}hashkey="$ssr_hashkey" + ${uci_set}alias="[$ssr_group] $ssr_remarks" + ${uci_set}auth_enable="0" + ${uci_set}switch_enable="1" + ${uci_set}type="$ssr_type" + ${uci_set}server="$ssr_host" + ${uci_set}server_port="$ssr_port" + ${uci_set}local_port="1234" + uci -q get $name.@servers[$1].timeout >/dev/null || ${uci_set}timeout="60" + ${uci_set}password="$ssr_passwd" + ${uci_set}encrypt_method="$ssr_method" + ${uci_set}protocol="$ssr_protocol" + ${uci_set}protocol_param="$ssr_protoparam" + ${uci_set}obfs="$ssr_obfs" + ${uci_set}obfs_param="$ssr_obfsparam" + ${uci_set}fast_open="0" + ${uci_set}kcp_enable="0" + ${uci_set}kcp_port="0" + ${uci_set}kcp_param="--nocomp" + + if [ "$ssr_type" = "v2ray" ]; then + #v2ray + ${uci_set}alter_id="$ssr_alter_id" + ${uci_set}vmess_id="$ssr_vmess_id" + ${uci_set}transport="$ssr_transport" + ${uci_set}tcp_guise="$ssr_tcp_guise" + ${uci_set}ws_host="$ssr_ws_host" + ${uci_set}ws_path="$ssr_ws_path" + ${uci_set}h2_host="$ssr_h2_host" + ${uci_set}h2_path="$ssr_h2_path" + ${uci_set}tls="$ssr_tls" + ${uci_set}security=$ssr_security + ${uci_set}alias="$ssr_remarks" + fi + + if [ "$ssr_type" = "ss" ]; then + ${uci_set}encrypt_method_ss="$ss_method" + ${uci_set}alias="$ssr_remarks" + fi + +} + +name=vssr +subscribe_url=($(uci get $name.@server_subscribe[0].subscribe_url)) #订阅服务器地址 +[ ${#subscribe_url[@]} -eq 0 ] && exit 1 +[ $(uci -q get $name.@server_subscribe[0].proxy || echo 0) -eq 0 ] && /etc/init.d/$name stop >/dev/null 2>&1 +log_name=${name}_subscribe +for ((o=0;o<${#subscribe_url[@]};o++)) +do + echo_date "从 ${subscribe_url[o]} 获取订阅" + echo_date "开始更新在线订阅列表..." + echo_date "尝试下载订阅链接到本地临时文件,请稍等..." + subscribe_data=$(wget-ssl --no-check-certificate -t 3 -T 30 -O- ${subscribe_url[o]}) + curl_code=$? + # 计算group的hashkey + ssr_grouphashkey=$(echo "${subscribe_url[o]}" | md5sum | cut -d ' ' -f1) + if [ ! $curl_code -eq 0 ];then + echo_date "下载订阅失败,自动重试中..." + subscribe_data=$(wget-ssl --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 30 -O- ${subscribe_url[o]}) + curl_code=$? + fi + if [ $curl_code -eq 0 ];then + echo_date "下载订阅成功,开始解析节点信息..." + ssr_url=($(echo $subscribe_data | base64 -d | sed 's/\r//g')) # 解码数据并删除 \r 换行符 + subscribe_max=$(echo ${ssr_url[0]} | grep -i MAX= | awk -F = '{print $2}') + subscribe_max_x=() + if [ -n "$subscribe_max" ]; then + while [ ${#subscribe_max_x[@]} -ne $subscribe_max ] + do + if [ ${#ssr_url[@]} -ge 10 ]; then + if [ $((${RANDOM:0:2}%2)) -eq 0 ]; then + temp_x=${RANDOM:0:1} + else + temp_x=${RANDOM:0:2} + fi + else + temp_x=${RANDOM:0:1} + fi + [ $temp_x -lt ${#ssr_url[@]} -a -z "$(echo "${subscribe_max_x[*]}" | grep -w $temp_x)" ] && subscribe_max_x[${#subscribe_max_x[@]}]="$temp_x" + done + else + subscribe_max=${#ssr_url[@]} + fi + echo_date "共计$subscribe_max个节点" + + ssr_group=$(urlsafe_b64decode $(urlsafe_b64decode ${ssr_url[$((${#ssr_url[@]} - 1))]//ssr:\/\//} | sed 's/&/\n/g' | grep group= | awk -F = '{print $2}')) + if [ -z "$ssr_group" ]; then + ssr_group="default" + fi + if [ -n "$ssr_group" ]; then + subscribe_i=0 + subscribe_n=0 + subscribe_o=0 + subscribe_x="" + temp_host_o=() + curr_ssr=$(uci show $name | grep @servers | grep -c server=) + for ((x=0;x<$curr_ssr;x++)) # 循环已有服务器信息,匹配当前订阅群组 + do + temp_alias=$(uci -q get $name.@servers[$x].grouphashkey | grep "$ssr_grouphashkey") + [ -n "$temp_alias" ] && temp_host_o[${#temp_host_o[@]}]=$(uci get $name.@servers[$x].hashkey) + done + + for ((x=0;x<$subscribe_max;x++)) # 循环链接 + do + [ ${#subscribe_max_x[@]} -eq 0 ] && temp_x=$x || temp_x=${subscribe_max_x[x]} + result=$(echo ${ssr_url[temp_x]} | grep "ss") + subscribe_url_type=$(echo "$ssr_url" | awk -F ':' '{print $1}') + + if [ "$subscribe_url_type" = "ss" ]; then + temp_info=${ssr_url[temp_x]//ss:\/\//} # 解码 SS 链接 + # 计算hashkey + ssr_hashkey=$(echo "$temp_info" | md5sum | cut -d ' ' -f1) + + info=$(urlsafe_b64decode $(echo "$temp_info" | awk -F '@' '{print $1}')) + temp_info_array=(${info//:/ }) + ssr_type="ss" + ss_method=${temp_info_array[0]} + ssr_passwd=${temp_info_array[1]} + info=$(echo "$temp_info" | awk -F '@' '{print $2}' | awk -F '#' '{print $1}') + temp_info_array=(${info//:/ }) + ssr_host=${temp_info_array[0]} + ssr_port=${temp_info_array[1]} + ssr_remarks=$(urldecode $(echo "$temp_info" | awk -F '#' '{print $2}')) + fi + + if [ "$subscribe_url_type" = "ssr" ]; then + temp_info=$(urlsafe_b64decode ${ssr_url[temp_x]//ssr:\/\//}) # 解码 SSR 链接 + # 计算hashkey + ssr_hashkey=$(echo "$temp_info" | md5sum | cut -d ' ' -f1) + + info=${temp_info///?*/} + temp_info_array=(${info//:/ }) + ssr_type="ssr" + ssr_host=${temp_info_array[0]} + ssr_port=${temp_info_array[1]} + ssr_protocol=${temp_info_array[2]} + ssr_method=${temp_info_array[3]} + ssr_obfs=${temp_info_array[4]} + ssr_passwd=$(urlsafe_b64decode ${temp_info_array[5]}) + info=${temp_info:$((${#info} + 2))} + info=(${info//&/ }) + ssr_protoparam="" + ssr_obfsparam="" + ssr_remarks="$temp_x" + for ((i=0;i<${#info[@]};i++)) # 循环扩展信息 + do + temp_info=($(echo ${info[i]} | sed 's/=/ /g')) + case "${temp_info[0]}" in + protoparam) + ssr_protoparam=$(urlsafe_b64decode ${temp_info[1]});; + obfsparam) + ssr_obfsparam=$(urlsafe_b64decode ${temp_info[1]});; + remarks) + ssr_remarks=$(urlsafe_b64decode ${temp_info[1]});; + esac + done + fi + + if [ "$subscribe_url_type" = "vmess" ]; then + temp_info=$(urlsafe_b64decode ${ssr_url[temp_x]//vmess:\/\//}) # 解码 Vmess 链接 + # 计算hashkey + ssr_hashkey=$(echo "$temp_info" | md5sum | cut -d ' ' -f1) + + ssr_type="v2ray" + json_load "$temp_info" + json_get_var ssr_host add + json_get_var ssr_port port + json_get_var ssr_alter_id aid + json_get_var ssr_vmess_id id + json_get_var ssr_security security + if [ "$ssr_security" == "" ]; then + ssr_security="auto" + fi + json_get_var ssr_transport net + json_get_var ssr_remarks ps + ssr_tcp_guise="none" + json_get_var ssr_ws_host host + json_get_var ssr_ws_path path + json_get_var ssr_h2_host host + json_get_var ssr_h2_path path + json_get_var ssr_tls tls + if [ "$ssr_tls" == "tls" -o "$ssr_tls" == "1" ]; then + ssr_tls="1" + else + ssr_tls="0" + fi + fi + + if [ -z "ssr_remarks" ]; then # 没有备注的话则生成一个 + ssr_remarks="$ssr_host:$ssr_port"; + fi + + uci_name_tmp=$(uci show $name | grep -w "$ssr_hashkey" | awk -F . '{print $2}') + if [ -z "$uci_name_tmp" ]; then # 判断当前服务器信息是否存在 + uci_name_tmp=$(uci add $name servers) + subscribe_n=$(($subscribe_n + 1)) + fi + Server_Update $uci_name_tmp + subscribe_x=$subscribe_x$ssr_hashkey" " + ssrtype=$(echo $ssr_type | tr '[a-z]' '[A-Z]') + echo_date "$ssrtype节点:【$ssr_remarks】" + + # SSR + # echo "服务器地址: $ssr_host" + # echo "服务器端口 $ssr_port" + # echo "密码: $ssr_passwd" + # echo "SS加密: $ss_method" + # echo "加密: $ssr_method" + # echo "协议: $ssr_protocol" + # echo "协议参数: $ssr_protoparam" + # echo "混淆: $ssr_obfs" + # echo "混淆参数: $ssr_obfsparam" + # echo "备注: $ssr_remarks" + + done + for ((x=0;x<${#temp_host_o[@]};x++)) # 新旧服务器信息匹配,如果旧服务器信息不存在于新服务器信息则删除 + do + if [ -z "$(echo "$subscribe_x" | grep -w ${temp_host_o[x]})" ]; then + uci_name_tmp=$(uci show $name | grep ${temp_host_o[x]} | awk -F . '{print $2}') + uci delete $name.$uci_name_tmp + subscribe_o=$(($subscribe_o + 1)) + fi + done + echo_date "本次更新订阅来源 【$ssr_group】 服务器数量: ${#ssr_url[@]} 新增服务器: $subscribe_n 删除服务器: $subscribe_o" + echo_date "在线订阅列表更新完成!请等待网页自动刷新!" + subscribe_log="$ssr_group 服务器订阅更新成功 服务器数量: ${#ssr_url[@]} 新增服务器: $subscribe_n 删除服务器: $subscribe_o" + logger -st $log_name[$$] -p6 "$subscribe_log" + uci commit $name + else + echo_date "${subscribe_url[$o]} 订阅数据解析失败 无法获取 Group" + logger -st $log_name[$$] -p3 "${subscribe_url[$o]} 订阅数据解析失败 无法获取 Group" + fi + else + echo_date "${subscribe_url[$o]} 订阅数据获取失败 错误代码: $curl_code" + logger -st $log_name[$$] -p3 "${subscribe_url[$o]} 订阅数据获取失败 错误代码: $curl_code" + fi +done +echo "END SUBSCRIBE" +/etc/init.d/$name restart >/dev/null 2>&1 diff --git a/package/ctcgfw/luci-app-vssr/root/usr/share/vssr/update.sh b/package/ctcgfw/luci-app-vssr/root/usr/share/vssr/update.sh new file mode 100644 index 0000000000..be6dd981a1 --- /dev/null +++ b/package/ctcgfw/luci-app-vssr/root/usr/share/vssr/update.sh @@ -0,0 +1,25 @@ +#!/bin/sh +chnroute_data=$(wget -O- -t 3 -T 3 http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest) +[ $? -eq 0 ] && { + echo "$chnroute_data" | grep ipv4 | grep CN | awk -F\| '{ printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > /tmp/china_ssr.txt +} + +if [ -s "/tmp/china_ssr.txt" ];then + if ( ! cmp -s /tmp/china_ssr.txt /etc/china_ssr.txt );then + mv /tmp/china_ssr.txt /etc/china_ssr.txt + fi +fi + +/usr/share/vssr/chinaipset.sh + +wget-ssl --no-check-certificate https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt -O /tmp/gfw.b64 +/usr/bin/ssr-gfw + +if [ -s "/tmp/gfwnew.txt" ];then + if ( ! cmp -s /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf );then + mv /tmp/gfwnew.txt /etc/dnsmasq.ssr/gfw_list.conf + echo "copy" + fi +fi + +/etc/init.d/vssr restart