luci-app-vssr: sync with upstream source

This commit is contained in:
CN_SZTL 2020-03-04 12:20:17 +08:00
parent 1fb7b958aa
commit 8782ce26c8
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
12 changed files with 588 additions and 21 deletions

View File

@ -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 \

View File

@ -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

View File

@ -0,0 +1,48 @@
-- Copyright 2009 Steven Barth <steven@midlink.org>
-- 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

View File

@ -1,7 +1,7 @@
-- Copyright (C) 2017 yushi studio <ywb94@qq.com>
-- 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 ][<N ]) +(%d+.?) +(%d+%%) +(%d+%%) +(.+)"
)
if cmd then
local idx = tonumber(pid)
local bin, param, cfg = cmd:match("^.*\/([^ ]*) *([^ ]*) *\/var\/etc\/([^ ]*).*")
if idx and cfg then
local listen = "NONE"
if netf[idx] and netf[idx]['listen'] then
listen = netf[idx]['listen']
end
data[idx] = {
['PID'] = pid,
['COMMAND'] = bin,
['LISTEN'] = listen,
['CONFIG'] = cfg,
['%MEM'] = mem,
['%CPU'] = cpu,
}
end
end
end
return data
end
function printstat(status, form, name)
local tabs = {
["Global Client"] = "shadowsocksr.json",
["Game Mode UDP Relay"] = "shadowsocksr_u.json",
["PDNSD"] = "pdnsd.conf",
["DNS Forward"] = "shadowsocksr_d.json",
["SOCKS5 Proxy"] = "shadowsocksr_s.json",
["Global SSR Server"] = "shadowsocksr_0.json",
}
local stat = translate("Unknown")
local sname = stat
if tabs[name] and status then
stat = translate("Not Running")
for idx, cfg in pairs(status) do
if status[idx]['CONFIG'] and status[idx]['CONFIG'] == tabs[name] then
stat = font_blue .. bold_on .. translate("Running") .. bold_off .. " > " .. 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

View File

@ -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"))

View File

@ -0,0 +1,109 @@
<!-- ++ BEGIN ++ Auto Repeater ++ logsview.htm ++ -->
<%-
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%>
<select class="cbi-input-select" onchange="onclick_logview(this, false)"
<%=
attr("name", cbid) .. attr("id", cbid) .. attr("value", self.default) .. ifattr(self.size, "size")
%>
></select>
<script type="text/javascript">//<![CDATA[
(function() {
//var values = <%=serialize_json(values)%>;
var keylist = <%=serialize_json(self.keylist)%>;
var vallist = <%=serialize_json(self.vallist)%>;
var parent = document.getElementById("<%=cbid%>");
for (var j = 0; j < keylist.length; j++) {
var opt = document.createElement("option");
opt.value = keylist[j];
if (j == 0) {
opt.selected = "selected";
}
opt.appendChild(document.createTextNode(vallist[j]));
parent.appendChild(opt);
}
}());
//]]></script>
<script type="text/javascript">//<![CDATA[
function onclick_logview(id, bottom) {
// get elements
var txt = document.getElementById("<%=cbid%>.txt"); // TextArea
if ( !txt ) { return; } // security check
txt.value= "Reading: " + document.getElementById("<%=cbid%>").value
XHR.get('<%=luci.dispatcher.build_url("admin", "vpn", "vssr", "fileread")%>', {lfile: document.getElementById("<%=cbid%>").value} ,
function(x, ifc) {
if (! ifc) {txt.value = "XHR.get(<%=luci.dispatcher.build_url("admin", "vpn", "vssr", "fileread")%>) Failed!"; return;}
txt.value = ifc[0];
if (bottom)
txt.scrollTop = txt.scrollHeight;
else
txt.scrollTop = 0;
txt.scrollLeft = 0;
}
);
}
//]]></script>
<%
-- one button on top, one at the buttom
%>
<br /><br />
<input class="cbi-button cbi-input-button" style="align: center; width: 100%" type="button" onclick='onclick_logview(this, false)'
<%=
attr("name", section) .. attr("id", cbid .. ".btn1") .. attr("value", self.inputtitle)
%> />
<br /><br />
<%
-- 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
%>
<textarea style="width: <%if media == "/luci-static/openwrt.org" then%>98.7%<%else%>100%<%end%> ; min-height: 200px; border: 3px solid #cccccc; padding: 5px; font-family: monospace; resize: none;" wrap="off" readonly="readonly"
<%=
attr("name", cbid .. ".txt") .. attr("id", cbid .. ".txt") .. ifattr(self.rows, "rows")
%> >
<%-=pcdata(self:cfgvalue(section))-%>
</textarea>
<br /><br />
<%
-- one button on top, one at the buttom
%>
<input class="cbi-button cbi-input-button" style="align: center; width: 100%" type="button" onclick='onclick_logview(this, true)'
<%= attr("name", section) .. attr("id", cbid .. ".btn2") .. attr("value", self.inputtitle) %> />
<br /><br />
<%+cbi/valuefooter%>
<!-- ++ END ++ Auto Repeater ++ logsview.htm ++ -->

View File

@ -1,6 +1,6 @@
<%+cbi/valueheader%>
<link rel="stylesheet" href="/luci-static/vssr/css/vssr.css?v=72883">
<label class="cbi-value-title"><%= translate("Update") %></label>
<label class="cbi-value-title"><%= translate("Before subscribing please click below to delete all servers in the subscription") %></label>
<div class="cbi-value-field">
<input class="cbi-button cbi-button-reload" id="update_subscribe" type="button"
size="0" value="<%= translate("Save And Start Subscribe") %>">

View File

@ -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 "文件查看器"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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