- NEW: 增加V2ray的VLESS支持。
- NEW: 增加V2ray的XTLS支持。
- NEW: 增加Xray的支持(可选择使用Xray代替V2ray执行)。
- NEW: 增加订阅时可手动添加机场名称(主要用于v2ray订阅)。
- NEW: 增加订阅节点过滤。
- UPDATE: 更新IP地址库。
This commit is contained in:
jerrykuku 2020-12-04 18:01:46 +08:00
parent f58834aa25
commit 677ba6d5e1
13 changed files with 233 additions and 59 deletions

View File

@ -1,8 +1,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-vssr
PKG_VERSION:=1.17-1
PKG_RELEASE:=20200830
PKG_VERSION:=1.18
PKG_RELEASE:=20201204
include $(INCLUDE_DIR)/package.mk

View File

@ -13,11 +13,16 @@ A new SSR SS V2ray Trojan luci app bese luci-app-ssr-plus
稳定性的差异来自于你固件的内核还有ss ssr v2ray 这几个核心插件的稳定性,当然你的节点才是影响稳定性的最大因素。
Luci 能决定的只有操作起来是否便利、顺手,还有对几个核心应用功能的适配挖掘而已。
### Update Log 2020-08-30 v1.17-1
### Update Log 2020-12-04 v1.18
#### Updates
- FIX: 修复台台湾视频分流不起作用的问题。
- NEW: 增加V2ray的VLESS支持。
- NEW: 增加V2ray的XTLS支持。
- NEW: 增加Xray的支持可选择使用Xray代替V2ray执行
- NEW: 增加订阅时可手动添加机场名称主要用于v2ray订阅
- NEW: 增加订阅节点过滤。
- UPDATE: 更新IP地址库。
详情见[具体日志](./relnotes.txt)。

View File

@ -51,11 +51,13 @@ function get_subscribe()
local auto_update_time = luci.http.formvalue('auto_update_time')
local proxy = luci.http.formvalue('proxy')
local subscribe_url = luci.http.formvalue('subscribe_url')
local filter_words = luci.http.formvalue('filter_words')
if subscribe_url ~= '[]' then
uci:delete(name, '@server_subscribe[0]', subscribe_url)
uci:set(name, '@server_subscribe[0]', 'auto_update', auto_update)
uci:set(name, '@server_subscribe[0]', 'auto_update_time', auto_update_time)
uci:set(name, '@server_subscribe[0]', 'proxy', proxy)
uci:set(name, '@server_subscribe[0]', 'filter_words', filter_words)
uci:set_list(name, '@server_subscribe[0]', 'subscribe_url', cjson.parse(subscribe_url))
uci:commit(name)
luci.sys.exec('nohup /usr/bin/lua /usr/share/vssr/subscribe.lua >/www/check_update.htm 2>/dev/null &')

View File

@ -79,6 +79,11 @@ o.rmempty = false
o = s:option(DynamicList, 'subscribe_url', translate('Subscribe URL'))
o.rmempty = true
o.description = translate('You can manually add group names in front of the URL, splited by ,')
o = s:option(Value, "filter_words", translate("Subscribe Filter Words"))
o.rmempty = true
o.description = translate("Filter Words splited by /")
o = s:option(Flag, 'proxy', translate('Through proxy update'))
o.rmempty = false

View File

@ -93,6 +93,13 @@ obfs = {
}
local securitys = {'auto', 'none', 'aes-128-gcm', 'chacha20-poly1305'}
local flows = {
'xtls-rprx-origin',
'xtls-rprx-origin-udp443',
'xtls-rprx-direct',
'xtls-rprx-direct-udp443'
}
m = Map(vssr, translate('Edit vssr Server'))
m.redirect = luci.dispatcher.build_url('admin/services/vssr/servers')
if m.uci:get(vssr, sid) ~= 'servers' then
@ -112,10 +119,12 @@ o.value = sid
o = s:option(ListValue, 'type', translate('Server Node Type'))
o:value('ssr', translate('ShadowsocksR'))
if nixio.fs.access('/usr/bin/v2ray/v2ray') or nixio.fs.access('/usr/bin/v2ray') then
if nixio.fs.access('/usr/bin/ss-redir') then
o:value('ss', translate('Shadowsocks New Version'))
end
if nixio.fs.access('/usr/bin/v2ray/v2ray') or nixio.fs.access('/usr/bin/v2ray') then
o:value('v2ray', translate('V2Ray'))
o:value('vless', translate('VLESS'))
end
if nixio.fs.access('/usr/sbin/trojan') then
@ -138,11 +147,6 @@ o = s:option(Value, 'server_port', translate('Server Port'))
o.datatype = 'port'
o.rmempty = false
-- o = s:option(Value, "timeout", translate("Connection Timeout"))
-- o.datatype = "uinteger"
-- o.default = 60
-- o.rmempty = false
o = s:option(Value, 'password', translate('Password'))
o.password = true
o.rmempty = true
@ -206,10 +210,19 @@ o.rmempty = true
o:depends('type', 'v2ray')
-- VmessId
o = s:option(Value, 'vmess_id', translate('VmessId (UUID)'))
o = s:option(Value, 'vmess_id', translate('VMESS/VLESS ID (UUID)'))
o.rmempty = true
o.default = uuid
o:depends('type', 'v2ray')
o:depends('type', 'vless')
o:depends('type', 'xray')
-- VLESS 加密方式
o = s:option(Value, 'vless_encryption', translate('VLESS Encryption'))
o.rmempty = true
o.default = 'none'
o:depends('type', 'vless')
o:depends('type', 'xray')
-- 加密方式
o = s:option(ListValue, 'security', translate('Encrypt Method'))
@ -228,6 +241,8 @@ o:value('h2', 'HTTP/2')
o:value('quic', 'QUIC')
o.rmempty = true
o:depends('type', 'v2ray')
o:depends('type', 'vless')
o:depends('type', 'xray')
-- [[ TCP部分 ]]--
@ -353,9 +368,11 @@ o.rmempty = true
-- [[ allowInsecure ]]--
o = s:option(Flag, 'insecure', translate('allowInsecure'))
o.rmempty = true
o.rmempty = false
o:depends('type', 'v2ray')
o:depends('type', 'trojan')
o:depends('type', 'vless')
o:depends('type', 'xray')
-- [[ TLS ]]--
o = s:option(Flag, 'tls', translate('TLS'))
@ -363,18 +380,45 @@ o.rmempty = true
o.default = '0'
o:depends('type', 'v2ray')
o:depends('type', 'trojan')
o:depends('type', 'vless')
o:depends('type', 'xray')
o = s:option(Value, 'tls_host', translate('TLS Host'))
--o:depends("type", "trojan")
o:depends('tls', '1')
o.rmempty = true
-- XTLS
o = s:option(Flag, 'xtls', translate('XTLS'))
o.rmempty = true
o.default = '0'
o:depends({type = 'vless', tls = '1'})
o:depends({type = 'xray', tls = '1'})
-- Flow
o = s:option(Value, 'vless_flow', translate('Flow'))
for _, v in ipairs(flows) do
o:value(v, v)
end
o.rmempty = true
o.default = 'xtls-rprx-origin'
o:depends('xtls', '1')
-- [[ Mux ]]--
o = s:option(Flag, 'mux', translate('Mux'))
o.rmempty = true
o.default = '0'
o:depends('type', 'v2ray')
o:depends('type', 'vless')
o = s:option(Value, 'concurrency', translate('Concurrency'))
o.datatype = 'uinteger'
o.rmempty = true
o.default = '8'
o:depends('mux', '1')
-- [[NO self cert]]
o = s:option(Flag, 'fast_open', translate('TCP Fast Open'))
o.rmempty = true
o.default = '0'

View File

@ -102,7 +102,7 @@ local route_label = {
}
-- [[ Global Setting ]]--
s = m:section(TypedSection, 'global', translate('Basic Settings [SS|SSR|V2ray|Trojan]'))
s = m:section(TypedSection, 'global', translate('Basic Settings [SS|SSR|V2ray|Xray|Trojan]'))
s.anonymous = true
o = s:option(ListValue, 'global_server', translate('Main Server'))
@ -120,6 +120,9 @@ for _, key in pairs(key_table) do
o:value(key, server_table[key])
end
o = s:option(Flag, 'use_xray', translate('Use Xray instead of V2ray'))
o.rmempty = false
o = s:option(Flag, 'v2ray_flow', translate('Open v2ray route'))
o.rmempty = false
o.description = translate('When open v2ray routed,Apply may take more time.')

View File

@ -49,12 +49,13 @@
} else {
var proxy = "0";
}
var filter_words = $("[name='" + prefix + ".filter_words']").val();
var data = {
auto_update: auto_update,
auto_update_time: auto_update_time,
subscribe_url: JSON.stringify(subscribe_url),
proxy: proxy
proxy: proxy,
filter_words: filter_words
}
//console.log(data);
$.ajax({

View File

@ -386,8 +386,8 @@ msgstr "通过代理更新"
msgid "GFW List"
msgstr "GFW列表"
msgid "Basic Settings [SS|SSR|V2ray|Trojan]"
msgstr "基本设置 [SS|SSR|V2ray|Trojan]"
msgid "Basic Settings [SS|SSR|V2ray|Xray|Trojan]"
msgstr "基本设置 [SS|SSR|V2ray|Xray|Trojan]"
msgid "Main Server"
msgstr "主服务器"
@ -659,3 +659,18 @@ msgstr "许可"
msgid "Area"
msgstr "国家或地区"
msgid "Use Xray instead of V2ray"
msgstr "使用Xray替代V2ray"
msgid "Subscribe Filter Words"
msgstr "订阅过滤关键词"
msgid "Filter Words splited by /"
msgstr "使用 / 分隔关键词"
msgid "VLESS Encryption"
msgstr "VLESS 加密"
msgid "You can manually add group names in front of the URL, splited by ,"
msgstr "你可以在URL前面手动添加组名使用 , 分隔"

View File

@ -4,6 +4,23 @@
#
########################################################
########################################################
//
// 1.15 2020-12-04
// 新功能
//
########################################################
Updates
- NEW: 增加V2ray的VLESS支持。
- NEW: 增加V2ray的XTLS支持。
- NEW: 增加Xray的支持可选择使用Xray代替V2ray执行
- NEW: 增加订阅时可手动添加机场名称主要用于v2ray订阅
- NEW: 增加订阅节点过滤。
- UPDATE: 更新IP地址库。
########################################################
//
// 1.17 2020-08-27

View File

@ -72,7 +72,7 @@ count_shunt() {
}
count_shunt
run_mode=$(uci_get_by_type global run_mode)
is_xray=$(uci_get_by_type global use_xray)
gen_config_file() {
local hostip=$(uci_get_by_name $1 server)
@ -95,6 +95,9 @@ gen_config_file() {
local stype=$(uci_get_by_name $1 type)
local port=$(uci_get_by_name $1 local_port)
if [ "$stype" == "vless" ]; then
stype="v2ray"
fi
if [ "$stype" == "trojan" ]; then
if [ "$re_type" == "udp" ]; then
re_type="client"
@ -193,18 +196,18 @@ start_rules() {
fi
/usr/bin/vssr-rules \
-s "$server" \
-l "$local_port" \
-S "$udp_server" \
-L "$udp_local_port" \
-a "$ac_ips" \
-i "$(uci_get_by_type access_control wan_bp_list)" \
-b "$(uci_get_by_type access_control wan_bp_ips)" \
-w "$(uci_get_by_type access_control wan_fw_ips)" \
-p "$(uci_get_by_type access_control lan_fp_ips)" \
-G "$(uci_get_by_type access_control lan_gm_ips)" \
-D "$proxyport" \
$(get_arg_out) $gfwmode $ARG_UDP
-s "$server" \
-l "$local_port" \
-S "$udp_server" \
-L "$udp_local_port" \
-a "$ac_ips" \
-i "$(uci_get_by_type access_control wan_bp_list)" \
-b "$(uci_get_by_type access_control wan_bp_ips)" \
-w "$(uci_get_by_type access_control wan_fw_ips)" \
-p "$(uci_get_by_type access_control lan_fp_ips)" \
-G "$(uci_get_by_type access_control lan_gm_ips)" \
-D "$proxyport" \
$(get_arg_out) $gfwmode $ARG_UDP
return $?
}
@ -271,7 +274,18 @@ find_bin() {
ssr) ret="/usr/bin/ssr-redir" ;;
ssr-local) ret="/usr/bin/ssr-local" ;;
ssr-server) ret="/usr/bin/ssr-server" ;;
v2ray) ret="/usr/bin/v2ray/v2ray" && [ ! -f "$ret" ] && ret="/usr/bin/v2ray" ;;
v2ray)
ret="/usr/bin/v2ray/v2ray" && [ ! -f "$ret" ] && ret="/usr/bin/v2ray"
if [ $is_xray = "1" ]; then
ret="/usr/bin/xray"
fi
;;
vless)
ret="/usr/bin/v2ray/v2ray" && [ ! -f "$ret" ] && ret="/usr/bin/v2ray"
if [ $is_xray = "1" ]; then
ret="/usr/bin/xray"
fi
;;
trojan) ret="/usr/sbin/trojan" ;;
socks5 | tun) ret="/usr/sbin/redsocks2" ;;
esac
@ -284,6 +298,9 @@ start_shunt() {
local server_port=${shunt_port[i]}
local server_type=$(uci_get_by_name $server_index type)
local server_ip=$(uci_get_by_name $server_index server)
if ["$server_type" == "vless"]; then
server_type="v2ray"
fi
[ "$server_type" == "trojan" ] && re_type="client" || re_type="tcp"
if [ "$server_type" != "v2ray" -a "$server_type" != "" ]; then
local config_file=/var/etc/${NAME}_${shunt_type[i]}.json
@ -325,8 +342,8 @@ start_redir() {
local kcp_param=$(uci_get_by_name $GLOBAL_SERVER kcp_param)
[ "$password" != "" ] && password="--key "${password}
service_start /usr/bin/kcptun-client \
-r $kcp_server:$kcp_port \
-l :$server_port $password $kcp_param
-r $kcp_server:$kcp_port \
-l :$server_port $password $kcp_param
kcp_enable_flag=1
fi
@ -356,7 +373,7 @@ start_redir() {
done
echo "$(date "+%Y-%m-%d %H:%M:%S") $name $threads 线程 已启动!" >>/tmp/vssr.log
;;
v2ray)
v2ray | vless)
$sscmd -config $last_config_file >/dev/null 2>&1 &
echo $sscmd
echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd -version | head -1) 已启动!" >>/tmp/vssr.log
@ -397,7 +414,7 @@ start_redir() {
$ucmd -c $last_config_file $ARG_OTA -U -f /var/run/ssr-reudp.pid >/dev/null 2>&1
echo "$(date "+%Y-%m-%d %H:%M:%S") UDP TPROXY Relay: $name 已启动!" >>/tmp/vssr.log
;;
v2ray)
v2ray | vless)
$ucmd -config $last_config_file >/dev/null 2>&1 &
echo "$(date "+%Y-%m-%d %H:%M:%S") UDP TPROXY Relay: V2ray 已启动!" >>/tmp/vssr.log
;;
@ -598,7 +615,7 @@ stop() {
if [ $(uci_get_by_type global monitor_enable) = 1 ]; then
kill -9 $(busybox ps -w | grep vssr-monitor | grep -v grep | awk '{print $1}') >/dev/null 2>&1
fi
killall -q -9 ss-redir ss-local obfs-local ssr-redir ssr-local ssr-server v2ray v2ray-plugin trojan microsocks ipt2socks dns2socks redsocks2 pdnsd
killall -q -9 ss-redir ss-local obfs-local ssr-redir ssr-local ssr-server v2ray v2ray-plugin trojan microsocks ipt2socks dns2socks redsocks2 pdnsd xray
if [ -f "/tmp/dnsmasq.d/dnsmasq-ssr.conf" ]; then
rm -f /tmp/dnsmasq.d/dnsmasq-ssr.conf

View File

@ -7,6 +7,7 @@ local local_port = arg[3]
local outbounds_table = {}
local rules_table = {}
local v2ray_flow = ucursor:get_first(name, 'global', 'v2ray_flow', '0')
local proxy_domain_name = ucursor:get_list(name, '@access_control[0]', 'proxy_domain_name')
local flow_table = {
@ -145,13 +146,45 @@ local flow_table = {
}
}
local bt_rules = {
type = 'field',
outboundTag = 'bt',
protocol = {
'bittorrent'
}
}
local bt_rules1 = {
type = 'field',
outboundTag = 'bt',
domain = {
'torrent',
'peer_id=',
'info_hash',
'get_peers',
'find_node',
'BitTorrent',
'announce_peer',
'announce.php?passkey='
},
}
function gen_outbound(server_node, tags, local_ports)
local bound = {}
if server_node == nil or server_node == 'nil' then
bound = nil
else
local server = ucursor:get_all(name, server_node)
if server.type ~= 'v2ray' then
local outbound_security = "none"
if (server.xtls == '1') then
outbound_security = "xtls"
elseif (server.tls == '1') then
outbound_security = "tls"
elseif (server.tls == "0") then
outbound_security = "none"
end
local node_type = server.type == "vless" and "vless" or "vmess"
if server.type ~= 'v2ray' and server.type ~= 'vless' then
bound = {
tag = tags,
protocol = 'socks',
@ -164,7 +197,7 @@ function gen_outbound(server_node, tags, local_ports)
else
bound = {
tag = tags,
protocol = 'vmess',
protocol = node_type,
settings = {
vnext = {
{
@ -173,8 +206,10 @@ function gen_outbound(server_node, tags, local_ports)
users = {
{
id = server.vmess_id,
alterId = tonumber(server.alter_id),
security = server.security
alterId = server.type == "v2ray" and tonumber(server.alter_id) or nil,
security = server.type == "v2ray" and server.security or nil,
flow = (server.xtls == '1') and (server.vless_flow and server.vless_flow or "xtls-rprx-origin") or nil,
encryption = server.type == "vless" and server.vless_encryption or nil
}
}
}
@ -183,11 +218,9 @@ function gen_outbound(server_node, tags, local_ports)
-- 底层传输配置
streamSettings = {
network = server.transport,
security = (server.tls == '1') and 'tls' or 'none',
tlsSettings = {
allowInsecure = (server.insecure == '1') and true or false,
serverName = server.ws_host
},
security = outbound_security,
tlsSettings = (outbound_security == "tls") and {allowInsecure = (server.insecure ~= "0") and true or false,serverName=server.tls_host,} or nil,
xtlsSettings = (outbound_security == "xtls") and {allowInsecure = (server.insecure ~= "0") and true or false,serverName=server.tls_host,} or nil,
kcpSettings = (server.transport == 'kcp') and
{
mtu = tonumber(server.mtu),
@ -197,8 +230,7 @@ function gen_outbound(server_node, tags, local_ports)
congestion = (server.congestion == '1') and true or false,
readBufferSize = tonumber(server.read_buffer_size),
writeBufferSize = tonumber(server.write_buffer_size),
header = {type = server.kcp_guise},
seed = server.seed
header = {type = server.kcp_guise}
} or
nil,
wsSettings = (server.transport == 'ws') and (server.ws_path ~= nil or server.ws_host ~= nil) and
@ -226,6 +258,17 @@ function gen_outbound(server_node, tags, local_ports)
return bound
end
function gen_bt_outbounds()
local bound = {
tag = 'bt',
protocol = 'freedom',
settings = {
a = 1
}
}
return bound
end
if v2ray_flow == '1' then
table.insert(outbounds_table, gen_outbound(server_section, 'global', 2080))
for i, v in pairs(flow_table) do
@ -237,6 +280,10 @@ else
table.insert(outbounds_table, gen_outbound(server_section, 'main', local_port))
end
table.insert(outbounds_table, gen_bt_outbounds())
table.insert(rules_table, bt_rules)
table.insert(rules_table, bt_rules1)
local v2ray = {
log = {
-- error = "/var/vssrsss.log",

View File

@ -31,6 +31,7 @@ local ucic = luci.model.uci.cursor()
local proxy = ucic:get_first(name, 'server_subscribe', 'proxy', '0')
local switch = '0'
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url', {})
local filter_words = ucic:get_first(name, 'server_subscribe', 'filter_words', '过期时间/剩余流量')
local log = function(...)
print(os.date('%Y-%m-%d %H:%M:%S ') .. table.concat({...}, ' '))
@ -104,7 +105,7 @@ local function base64Decode(text)
end
end
-- 处理数据
local function processData(szType, content)
local function processData(szType, content, groupName)
local result = {
-- auth_enable = '0',
-- switch_enable = '1',
@ -145,7 +146,7 @@ local function processData(szType, content)
result.transport = info.net
result.alter_id = info.aid
result.vmess_id = info.id
result.alias = info.ps
result.alias = groupName .. info.ps
-- result.mux = 1
-- result.concurrency = 8
if info.net == 'ws' then
@ -197,7 +198,7 @@ local function processData(szType, content)
local userinfo = base64Decode(hostInfo[1])
local method = userinfo:sub(1, userinfo:find(':') - 1)
local password = userinfo:sub(userinfo:find(':') + 1, #userinfo)
result.alias = UrlDecode(alias)
result.alias = groupName .. UrlDecode(alias)
result.type = 'ss'
result.server = host[1]
if host[2]:find('/%?') then
@ -234,7 +235,7 @@ local function processData(szType, content)
local hostInfo = split(info, '@')
local host = split(hostInfo[2], ':')
local password = hostInfo[1]
result.alias = UrlDecode(alias)
result.alias = groupName .. UrlDecode(alias)
result.type = 'trojan'
result.server = host[1]
result.insecure = '0'
@ -293,6 +294,18 @@ local function wget(url)
return trim(stdout)
end
local function check_filer(result)
do
local filter_word = split(filter_words, "/")
for i, v in pairs(filter_word) do
if result.alias:find(v) then
log('订阅节点关键字过滤:“' .. v ..'” ,该节点被丢弃')
return true
end
end
end
end
local execute = function()
-- exec
do
@ -301,6 +314,10 @@ local execute = function()
luci.sys.init.stop(name)
end
for k, url in ipairs(subscribe_url) do
local groupName = ""
urlTable = split(url, ",")
groupName = table.getn(urlTable) > 1 and '[' .. urlTable[1] .. '] ' or ""
url = table.getn(urlTable) > 1 and urlTable[2] or url
local raw = wget(url)
if #raw > 0 then
local nodes, szType
@ -334,15 +351,15 @@ local execute = function()
if v then
local result
if szType == 'ssd' then
result = processData(szType, v)
result = processData(szType, v, groupName)
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])
result = processData(dat[1], dat[2], groupName)
else
result = processData(dat[1], base64Decode(dat[2]))
result = processData(dat[1], base64Decode(dat[2]), groupName)
end
end
else
@ -351,10 +368,11 @@ local execute = function()
-- log(result)
if result then
if
result.alias:find('过期时间') or result.alias:find('剩余流量') or result.alias:find('QQ群') or
result.alias:find('不支持') or
result.alias:find('官网') or
not result.server
not result.server or
not result.server_port or
result.alias == "NULL" or
check_filer(result) or
result.server:match("[^0-9a-zA-Z%-%.%s]") -- 中文做地址的 也没有人拿中文域名搞就算中文域也有Puny Code SB 机场
then
log('丢弃无效节点: ' .. result.type .. ' 节点, ' .. result.alias)
else