Merge Mainline

This commit is contained in:
CN_SZTL 2020-07-18 13:42:03 +08:00
commit efb6f74258
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
60 changed files with 2071 additions and 1143 deletions

View File

@ -7,8 +7,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-jd-dailybonus
LUCI_PKGARCH:=all
PKG_VERSION:=0.8
PKG_RELEASE:=20200715
PKG_VERSION:=0.8.1
PKG_RELEASE:=20200716
include $(INCLUDE_DIR)/package.mk

View File

@ -4,6 +4,18 @@
#
########################################################
########################################################
//
// 0.8.1 2020-07-16
//
//
########################################################
Updates
- UPDATE: 修正部分cookie无法更新到脚本的问题。
########################################################
//
// 0.8 2020-07-15

View File

@ -55,13 +55,19 @@ fill_cookie() {
cookie1=$(uci_get_by_type global cookie)
if [ ! "$cookie1" = "" ]; then
varb="var Key = '$cookie1';"
sed -i "s/^var Key =.*/$varb/g" $JD_SCRIPT
a=$(sed -n '/var Key =/=' $JD_SCRIPT)
b=$((a-1))
sed -i "${a}d" $JD_SCRIPT
sed -i "${b}a ${varb}" $JD_SCRIPT
fi
cookie2=$(uci_get_by_type global cookie2)
if [ ! "$cookie2" = "" ]; then
varb2="var DualKey = '$cookie2';"
sed -i "s/^var DualKey =.*/$varb2/g" $JD_SCRIPT
aa=$(sed -n '/var DualKey =/=' $JD_SCRIPT)
bb=$((aa-1))
sed -i "${aa}d" $JD_SCRIPT
sed -i "${bb}a ${varb2}" $JD_SCRIPT
fi
stop=$(uci_get_by_type global stop)

View File

@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=lzo
PKG_VERSION:=2.10
PKG_RELEASE:=3
PKG_RELEASE:=4
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://www.oberhumer.com/opensource/lzo/download/
@ -49,6 +49,8 @@ define Build/InstallDev
$(CP) $(PKG_INSTALL_DIR)/usr/include/lzo $(1)/usr/include/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/liblzo2.{a,so*} $(1)/usr/lib/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/lzo2.pc $(1)/usr/lib/pkgconfig
$(SED) 's,/usr/include,$$$${prefix}/include,g' $(1)/usr/lib/pkgconfig/lzo2.pc
$(SED) 's,/usr/lib,$$$${exec_prefix}/lib,g' $(1)/usr/lib/pkgconfig/lzo2.pc
endef
define Package/liblzo/install

View File

@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=3.9
PKG_RELEASE:=4
PKG_DATE:=20200705
PKG_RELEASE:=18
PKG_DATE:=20200717
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
@ -41,6 +41,10 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan
bool "Include Trojan"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO
bool "Include Trojan_GO"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Brook
bool "Include Brook"
default n
@ -90,8 +94,8 @@ define Package/$(PKG_NAME)
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR:shadowsocksr-libev-ssr-local \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-server \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:ipt2socks \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan-plus \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO:trojan-go \
+PACKAGE_$(PKG_NAME)_INCLUDE_Brook:brook \
+PACKAGE_$(PKG_NAME)_INCLUDE_kcptun:kcptun-client \
+PACKAGE_$(PKG_NAME)_INCLUDE_haproxy:haproxy \

View File

@ -6,181 +6,184 @@ local http = require "luci.http"
local kcptun = require "luci.model.cbi.passwall.api.kcptun"
local brook = require "luci.model.cbi.passwall.api.brook"
local v2ray = require "luci.model.cbi.passwall.api.v2ray"
local trojan_go = require "luci.model.cbi.passwall.api.trojan_go"
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", "show"}, call("show_menu")).leaf = true
entry({"admin", "vpn", "passwall", "hide"}, call("hide_menu")).leaf = true
if nixio.fs.access("/etc/config/passwall") and
nixio.fs.access("/etc/config/passwall_show") then
entry({"admin", "vpn", "passwall"}, alias("admin", "vpn", "passwall", "settings"), _("Pass Wall"), 1).dependent = true
end
entry({"admin", "vpn", "passwall", "settings"}, cbi("passwall/global"), _("Basic Settings"), 1).dependent = true
entry({"admin", "vpn", "passwall", "node_list"}, cbi("passwall/node_list"), _("Node List"), 2).dependent = true
entry({"admin", "vpn", "passwall", "auto_switch"}, cbi("passwall/auto_switch"), _("Auto Switch"), 3).leaf = true
entry({"admin", "vpn", "passwall", "other"}, cbi("passwall/other", {autoapply = true}), _("Other Settings"), 93).leaf = true
if nixio.fs.access("/usr/sbin/haproxy") then
entry({"admin", "vpn", "passwall", "haproxy"}, cbi("passwall/haproxy"), _("Load Balancing"), 94).leaf = true
end
entry({"admin", "vpn", "passwall", "node_subscribe"}, cbi("passwall/node_subscribe"), _("Node Subscribe"), 95).dependent = true
entry({"admin", "vpn", "passwall", "rule"}, cbi("passwall/rule"), _("Rule Update"), 96).leaf = true
entry({"admin", "vpn", "passwall", "node_config"}, cbi("passwall/node_config")).leaf = true
entry({"admin", "vpn", "passwall", "shunt_rules"}, cbi("passwall/shunt_rules")).leaf = true
entry({"admin", "vpn", "passwall", "acl"}, cbi("passwall/acl"), _("Access control"), 97).leaf = true
entry({"admin", "vpn", "passwall", "log"}, form("passwall/log"), _("Watch Logs"), 999).leaf = true
entry({"admin", "vpn", "passwall", "server"}, cbi("passwall/server/index"), _("Server-Side"), 99).leaf = true
entry({"admin", "vpn", "passwall", "server_user"}, cbi("passwall/server/user")).leaf = true
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", "show"}, call("show_menu")).leaf = true
entry({"admin", "vpn", "passwall", "hide"}, call("hide_menu")).leaf = true
if nixio.fs.access("/etc/config/passwall") and
nixio.fs.access("/etc/config/passwall_show") then
entry({"admin", "vpn", "passwall"}, alias("admin", "vpn", "passwall", "settings"), _("Pass Wall"), 1).dependent = true
end
entry({"admin", "vpn", "passwall", "settings"}, cbi("passwall/global"), _("Basic Settings"), 1).dependent = true
entry({"admin", "vpn", "passwall", "node_list"}, cbi("passwall/node_list"), _("Node List"), 2).dependent = true
entry({"admin", "vpn", "passwall", "auto_switch"}, cbi("passwall/auto_switch"), _("Auto Switch"), 3).leaf = true
entry({"admin", "vpn", "passwall", "other"}, cbi("passwall/other", {autoapply = true}), _("Other Settings"), 93).leaf = true
if nixio.fs.access("/usr/sbin/haproxy") then
entry({"admin", "vpn", "passwall", "haproxy"}, cbi("passwall/haproxy"), _("Load Balancing"), 94).leaf = true
end
entry({"admin", "vpn", "passwall", "node_subscribe"}, cbi("passwall/node_subscribe"), _("Node Subscribe"), 95).dependent = true
entry({"admin", "vpn", "passwall", "rule"}, cbi("passwall/rule"), _("Rule Update"), 96).leaf = true
entry({"admin", "vpn", "passwall", "node_config"}, cbi("passwall/node_config")).leaf = true
entry({"admin", "vpn", "passwall", "shunt_rules"}, cbi("passwall/shunt_rules")).leaf = true
entry({"admin", "vpn", "passwall", "acl"}, cbi("passwall/acl"), _("Access control"), 97).leaf = true
entry({"admin", "vpn", "passwall", "log"}, form("passwall/log"), _("Watch Logs"), 999).leaf = true
entry({"admin", "vpn", "passwall", "server"}, cbi("passwall/server/index"), _("Server-Side"), 99).leaf = true
entry({"admin", "vpn", "passwall", "server_user"}, cbi("passwall/server/user")).leaf = true
entry({"admin", "vpn", "passwall", "server_user_status"}, call("server_user_status")).leaf = true
entry({"admin", "vpn", "passwall", "server_get_log"}, call("server_get_log")).leaf = true
entry({"admin", "vpn", "passwall", "server_clear_log"}, call("server_clear_log")).leaf = true
entry({"admin", "vpn", "passwall", "link_add_node"}, call("link_add_node")).leaf = true
entry({"admin", "vpn", "passwall", "get_log"}, call("get_log")).leaf = true
entry({"admin", "vpn", "passwall", "clear_log"}, call("clear_log")).leaf = true
entry({"admin", "vpn", "passwall", "status"}, call("status")).leaf = true
entry({"admin", "vpn", "passwall", "socks_status"}, call("socks_status")).leaf = true
entry({"admin", "vpn", "passwall", "connect_status"}, call("connect_status")).leaf = true
entry({"admin", "vpn", "passwall", "check_port"}, call("check_port")).leaf = true
entry({"admin", "vpn", "passwall", "ping_node"}, call("ping_node")).leaf = true
entry({"admin", "vpn", "passwall", "set_node"}, call("set_node")).leaf = true
entry({"admin", "vpn", "passwall", "copy_node"}, call("copy_node")).leaf = true
entry({"admin", "vpn", "passwall", "clear_all_nodes"}, call("clear_all_nodes")).leaf = true
entry({"admin", "vpn", "passwall", "delete_select_nodes"}, call("delete_select_nodes")).leaf = true
entry({"admin", "vpn", "passwall", "update_rules"}, call("update_rules")).leaf = true
entry({"admin", "vpn", "passwall", "luci_check"}, call("luci_check")).leaf = true
entry({"admin", "vpn", "passwall", "luci_update"}, call("luci_update")).leaf = true
entry({"admin", "vpn", "passwall", "kcptun_check"}, call("kcptun_check")).leaf = true
entry({"admin", "vpn", "passwall", "kcptun_update"}, call("kcptun_update")).leaf = true
entry({"admin", "vpn", "passwall", "brook_check"}, call("brook_check")).leaf = true
entry({"admin", "vpn", "passwall", "brook_update"}, call("brook_update")).leaf = true
entry({"admin", "vpn", "passwall", "v2ray_check"}, call("v2ray_check")).leaf = true
entry({"admin", "vpn", "passwall", "v2ray_update"}, call("v2ray_update")).leaf = true
entry({"admin", "vpn", "passwall", "server_user_status"}, call("server_user_status")).leaf = true
entry({"admin", "vpn", "passwall", "server_get_log"}, call("server_get_log")).leaf = true
entry({"admin", "vpn", "passwall", "server_clear_log"}, call("server_clear_log")).leaf = true
entry({"admin", "vpn", "passwall", "link_add_node"}, call("link_add_node")).leaf = true
entry({"admin", "vpn", "passwall", "get_log"}, call("get_log")).leaf = true
entry({"admin", "vpn", "passwall", "clear_log"}, call("clear_log")).leaf = true
entry({"admin", "vpn", "passwall", "status"}, call("status")).leaf = true
entry({"admin", "vpn", "passwall", "socks_status"}, call("socks_status")).leaf = true
entry({"admin", "vpn", "passwall", "connect_status"}, call("connect_status")).leaf = true
entry({"admin", "vpn", "passwall", "check_port"}, call("check_port")).leaf = true
entry({"admin", "vpn", "passwall", "ping_node"}, call("ping_node")).leaf = true
entry({"admin", "vpn", "passwall", "set_node"}, call("set_node")).leaf = true
entry({"admin", "vpn", "passwall", "copy_node"}, call("copy_node")).leaf = true
entry({"admin", "vpn", "passwall", "clear_all_nodes"}, call("clear_all_nodes")).leaf = true
entry({"admin", "vpn", "passwall", "delete_select_nodes"}, call("delete_select_nodes")).leaf = true
entry({"admin", "vpn", "passwall", "update_rules"}, call("update_rules")).leaf = true
entry({"admin", "vpn", "passwall", "luci_check"}, call("luci_check")).leaf = true
entry({"admin", "vpn", "passwall", "luci_update"}, call("luci_update")).leaf = true
entry({"admin", "vpn", "passwall", "kcptun_check"}, call("kcptun_check")).leaf = true
entry({"admin", "vpn", "passwall", "kcptun_update"}, call("kcptun_update")).leaf = true
entry({"admin", "vpn", "passwall", "brook_check"}, call("brook_check")).leaf = true
entry({"admin", "vpn", "passwall", "brook_update"}, call("brook_update")).leaf = true
entry({"admin", "vpn", "passwall", "v2ray_check"}, call("v2ray_check")).leaf = true
entry({"admin", "vpn", "passwall", "v2ray_update"}, call("v2ray_update")).leaf = true
entry({"admin", "vpn", "passwall", "trojan_go_check"}, call("trojan_go_check")).leaf = true
entry({"admin", "vpn", "passwall", "trojan_go_update"}, call("trojan_go_update")).leaf = true
end
local function http_write_json(content)
http.prepare_content("application/json")
http.write_json(content or {code = 1})
http.prepare_content("application/json")
http.write_json(content or {code = 1})
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.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall"))
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
function show_menu()
luci.sys.call("touch /etc/config/passwall_show")
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall"))
luci.sys.call("touch /etc/config/passwall_show")
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall"))
end
function hide_menu()
luci.sys.call("rm -rf /etc/config/passwall_show")
luci.http.redirect(luci.dispatcher.build_url("admin", "status", "overview"))
luci.sys.call("rm -rf /etc/config/passwall_show")
luci.http.redirect(luci.dispatcher.build_url("admin", "status", "overview"))
end
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("lua /usr/share/passwall/subscribe.lua add log")
local link = luci.http.formvalue("link")
luci.sys.call('rm -f /tmp/links.conf && echo "' .. link .. '" >> /tmp/links.conf')
luci.sys.call("lua /usr/share/passwall/subscribe.lua add log")
end
function get_log()
-- luci.sys.exec("[ -f /var/log/passwall.log ] && sed '1!G;h;$!d' /var/log/passwall.log > /var/log/passwall_show.log")
luci.http.write(luci.sys.exec("[ -f '/var/log/passwall.log' ] && cat /var/log/passwall.log"))
-- luci.sys.exec("[ -f /var/log/passwall.log ] && sed '1!G;h;$!d' /var/log/passwall.log > /var/log/passwall_show.log")
luci.http.write(luci.sys.exec("[ -f '/var/log/passwall.log' ] && cat /var/log/passwall.log"))
end
function clear_log()
luci.sys.call("echo '' > /var/log/passwall.log")
luci.sys.call("echo '' > /var/log/passwall.log")
end
function status()
-- local dns_mode = ucic:get(appname, "@global[0]", "dns_mode")
local e = {}
e.dns_mode_status = luci.sys.call("netstat -apn | grep 7913 >/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
local tcp_node_num = ucic:get(appname, "@global_other[0]", "tcp_node_num") or 1
for i = 1, tcp_node_num, 1 do
e["kcptun_tcp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/kcptun' | grep -i 'tcp_%s' >/dev/null", appname, i)) == 0
e["tcp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v -E 'grep|kcptun' | grep '%s/bin/' | grep -i 'TCP_%s' >/dev/null", appname, i)) == 0
end
-- local dns_mode = ucic:get(appname, "@global[0]", "dns_mode")
local e = {}
e.dns_mode_status = luci.sys.call("netstat -apn | grep 7913 >/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
local tcp_node_num = ucic:get(appname, "@global_other[0]", "tcp_node_num") or 1
for i = 1, tcp_node_num, 1 do
e["kcptun_tcp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/kcptun' | grep -i 'tcp_%s' >/dev/null", appname, i)) == 0
e["tcp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v -E 'grep|kcptun' | grep '%s/bin/' | grep -i 'TCP_%s' >/dev/null", appname, i)) == 0
end
local udp_node_num = ucic:get(appname, "@global_other[0]", "udp_node_num") or 1
for i = 1, udp_node_num, 1 do
if (ucic:get(appname, "@global[0]", "udp_node" .. i) or "nil") == "tcp" then
e["udp_node%s_status" % i] = e["tcp_node%s_status" % i]
else
e["udp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep -i 'UDP_%s' >/dev/null", appname, i)) == 0
end
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
local udp_node_num = ucic:get(appname, "@global_other[0]", "udp_node_num") or 1
for i = 1, udp_node_num, 1 do
if (ucic:get(appname, "@global[0]", "udp_node" .. i) or "nil") == "tcp" then
e["udp_node%s_status" % i] = e["tcp_node%s_status" % i]
else
e["udp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep -i 'UDP_%s' >/dev/null", appname, i)) == 0
end
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function socks_status()
local e = {}
local index = luci.http.formvalue("index")
local id = luci.http.formvalue("id")
e.index = index
e.status = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep 'SOCKS_%s' > /dev/null", appname, id)) == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
local e = {}
local index = luci.http.formvalue("index")
local id = luci.http.formvalue("id")
e.index = index
e.status = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep 'SOCKS_%s' > /dev/null", appname, id)) == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function connect_status()
local e = {}
e.use_time = ""
local url = luci.http.formvalue("url")
local result = luci.sys.exec('curl --connect-timeout 5 -o /dev/null -I -skL -w "%{http_code}:%{time_total}" ' .. url)
local code = tonumber(luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $1}'") or "0")
if code ~= 0 then
local use_time = luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $2}'")
e.use_time = string.format("%.2f", use_time * 1000)
e.ping_type = "curl"
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
local e = {}
e.use_time = ""
local url = luci.http.formvalue("url")
local result = luci.sys.exec('curl --connect-timeout 5 -o /dev/null -I -skL -w "%{http_code}:%{time_starttransfer}" ' .. url)
local code = tonumber(luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $1}'") or "0")
if code ~= 0 then
local use_time = luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $2}'")
e.use_time = string.format("%.2f", use_time * 1000)
e.ping_type = "curl"
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function ping_node()
local index = luci.http.formvalue("index")
local address = luci.http.formvalue("address")
local port = luci.http.formvalue("port")
local e = {}
e.index = index
if (ucic:get(appname, "@global_other[0]", "use_tcping") or 1) == "1" and luci.sys.exec("echo -n $(command -v tcping)") ~= "" then
e.ping = luci.sys.exec(string.format("echo -n $(tcping -q -c 1 -i 1 -t 1 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null", port, address))
end
if e.ping == nil or tonumber(e.ping) == 0 then
e.ping = luci.sys.exec("echo -n $(ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null" % address)
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
local index = luci.http.formvalue("index")
local address = luci.http.formvalue("address")
local port = luci.http.formvalue("port")
local e = {}
e.index = index
if (ucic:get(appname, "@global_other[0]", "use_tcping") or 1) == "1" and luci.sys.exec("echo -n $(command -v tcping)") ~= "" then
e.ping = luci.sys.exec(string.format("echo -n $(tcping -q -c 1 -i 1 -t 2 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null", port, address))
end
if e.ping == nil or tonumber(e.ping) == 0 then
e.ping = luci.sys.exec("echo -n $(ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null" % address)
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function set_node()
local protocol = luci.http.formvalue("protocol")
local number = luci.http.formvalue("number")
local section = luci.http.formvalue("section")
ucic:set(appname, "@global[0]", protocol .. "_node" .. number, section)
ucic:commit(appname)
luci.sys.call("/etc/init.d/passwall restart > /dev/null 2>&1 &")
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall", "log"))
local protocol = luci.http.formvalue("protocol")
local number = luci.http.formvalue("number")
local section = luci.http.formvalue("section")
ucic:set(appname, "@global[0]", protocol .. "_node" .. number, section)
ucic:commit(appname)
luci.sys.call("/etc/init.d/passwall restart > /dev/null 2>&1 &")
luci.http.redirect(luci.dispatcher.build_url("admin", "vpn", "passwall", "log"))
end
function copy_node()
local e = {}
local section = luci.http.formvalue("section")
luci.http.prepare_content("application/json")
luci.http.write_json(e)
local e = {}
local section = luci.http.formvalue("section")
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function clear_all_nodes()
ucic:foreach(appname, "nodes", function(node)
ucic:foreach(appname, "nodes", function(node)
ucic:delete(appname, node['.name'])
end)
local function clear(type)
end)
local function clear(type)
local node_num = ucic:get(appname, "@global_other[0]", type .. "_node_num") or 1
for i = 1, node_num, 1 do
local node = ucic:get(appname, "@global[0]", type .. "_node" .. i)
@ -192,128 +195,144 @@ function clear_all_nodes()
clear("tcp")
clear("udp")
ucic:commit(appname)
luci.sys.call("/etc/init.d/" .. appname .. " restart")
ucic:commit(appname)
luci.sys.call("/etc/init.d/" .. appname .. " restart")
end
function delete_select_nodes()
local ids = luci.http.formvalue("ids")
string.gsub(ids, '[^' .. "," .. ']+', function(w)
ucic:delete(appname, w)
end)
ucic:commit(appname)
luci.sys.call("/etc/init.d/" .. appname .. " restart")
local ids = luci.http.formvalue("ids")
string.gsub(ids, '[^' .. "," .. ']+', function(w)
ucic:delete(appname, w)
end)
ucic:commit(appname)
luci.sys.call("/etc/init.d/" .. appname .. " restart")
end
function check_port()
local node_name = ""
local node_name = ""
local retstring = "<br />"
-- retstring = retstring .. "<font color='red'>暂时不支持UDP检测</font><br />"
local retstring = "<br />"
-- retstring = retstring .. "<font color='red'>暂时不支持UDP检测</font><br />"
retstring = retstring .. "<font color='green'>检测端口可用性</font><br />"
ucic:foreach("passwall", "nodes", function(s)
local ret = ""
local tcp_socket
if (s.use_kcp and s.use_kcp == "1" and s.kcp_port) or
(s.v2ray_transport and s.v2ray_transport == "mkcp" and s.port) then
else
local type = s.type
if type and type ~= "V2ray_balancing" and type ~= "V2ray_shunt" and
s.address and s.port and s.remarks then
node_name = "%s[%s] %s:%s" %
{s.type, s.remarks, s.address, s.port}
tcp_socket = nixio.socket("inet", "stream")
tcp_socket:setopt("socket", "rcvtimeo", 3)
tcp_socket:setopt("socket", "sndtimeo", 3)
ret = tcp_socket:connect(s.address, s.port)
if tostring(ret) == "true" then
retstring = retstring .. "<font color='green'>" .. node_name .. " OK.</font><br />"
else
retstring = retstring .. "<font color='red'>" .. node_name .. " Error.</font><br />"
end
ret = ""
end
end
if tcp_socket then tcp_socket:close() end
end)
luci.http.prepare_content("application/json")
luci.http.write_json({ret = retstring})
retstring = retstring .. "<font color='green'>检测端口可用性</font><br />"
ucic:foreach("passwall", "nodes", function(s)
local ret = ""
local tcp_socket
if (s.use_kcp and s.use_kcp == "1" and s.kcp_port) or
(s.v2ray_transport and s.v2ray_transport == "mkcp" and s.port) then
else
local type = s.type
if type and type ~= "V2ray_balancing" and type ~= "V2ray_shunt" and
s.address and s.port and s.remarks then
node_name = "%s[%s] %s:%s" % {s.type, s.remarks, s.address, s.port}
tcp_socket = nixio.socket("inet", "stream")
tcp_socket:setopt("socket", "rcvtimeo", 3)
tcp_socket:setopt("socket", "sndtimeo", 3)
ret = tcp_socket:connect(s.address, s.port)
if tostring(ret) == "true" then
retstring = retstring .. "<font color='green'>" .. node_name .. " OK.</font><br />"
else
retstring = retstring .. "<font color='red'>" .. node_name .. " Error.</font><br />"
end
ret = ""
end
end
if tcp_socket then tcp_socket:close() end
end)
luci.http.prepare_content("application/json")
luci.http.write_json({ret = retstring})
end
function update_rules()
local update = luci.http.formvalue("update")
luci.sys.call("lua /usr/share/passwall/rule_update.lua log '" .. update .. "' > /dev/null 2>&1 &")
local update = luci.http.formvalue("update")
luci.sys.call("lua /usr/share/passwall/rule_update.lua log '" .. update .. "' > /dev/null 2>&1 &")
end
function server_user_status()
local e = {}
e.index = luci.http.formvalue("index")
e.status = luci.sys.call(string.format("ps -w | grep -v 'grep' | grep '%s/bin/' | grep -i '%s' >/dev/null", appname .. "_server", luci.http.formvalue("id"))) == 0
http_write_json(e)
local e = {}
e.index = luci.http.formvalue("index")
e.status = luci.sys.call(string.format("ps -w | grep -v 'grep' | grep '%s/bin/' | grep -i '%s' >/dev/null", appname .. "_server", luci.http.formvalue("id"))) == 0
http_write_json(e)
end
function server_get_log()
luci.http.write(luci.sys.exec("[ -f '/var/log/passwall_server.log' ] && cat /var/log/passwall_server.log"))
luci.http.write(luci.sys.exec("[ -f '/var/log/passwall_server.log' ] && cat /var/log/passwall_server.log"))
end
function server_clear_log()
luci.sys.call("echo '' > /var/log/passwall_server.log")
luci.sys.call("echo '' > /var/log/passwall_server.log")
end
function kcptun_check()
local json = kcptun.to_check("")
http_write_json(json)
local json = kcptun.to_check("")
http_write_json(json)
end
function kcptun_update()
local json = nil
local task = http.formvalue("task")
if task == "extract" then
json = kcptun.to_extract(http.formvalue("file"),
http.formvalue("subfix"))
elseif task == "move" then
json = kcptun.to_move(http.formvalue("file"))
else
json = kcptun.to_download(http.formvalue("url"))
end
local json = nil
local task = http.formvalue("task")
if task == "extract" then
json = kcptun.to_extract(http.formvalue("file"), http.formvalue("subfix"))
elseif task == "move" then
json = kcptun.to_move(http.formvalue("file"))
else
json = kcptun.to_download(http.formvalue("url"))
end
http_write_json(json)
http_write_json(json)
end
function brook_check()
local json = brook.to_check("")
http_write_json(json)
local json = brook.to_check("")
http_write_json(json)
end
function brook_update()
local json = nil
local task = http.formvalue("task")
if task == "move" then
json = brook.to_move(http.formvalue("file"))
else
json = brook.to_download(http.formvalue("url"))
end
local json = nil
local task = http.formvalue("task")
if task == "move" then
json = brook.to_move(http.formvalue("file"))
else
json = brook.to_download(http.formvalue("url"))
end
http_write_json(json)
http_write_json(json)
end
function v2ray_check()
local json = v2ray.to_check("")
http_write_json(json)
local json = v2ray.to_check("")
http_write_json(json)
end
function v2ray_update()
local json = nil
local task = http.formvalue("task")
if task == "extract" then
json =
v2ray.to_extract(http.formvalue("file"), http.formvalue("subfix"))
elseif task == "move" then
json = v2ray.to_move(http.formvalue("file"))
else
json = v2ray.to_download(http.formvalue("url"))
end
local json = nil
local task = http.formvalue("task")
if task == "extract" then
json = v2ray.to_extract(http.formvalue("file"), http.formvalue("subfix"))
elseif task == "move" then
json = v2ray.to_move(http.formvalue("file"))
else
json = v2ray.to_download(http.formvalue("url"))
end
http_write_json(json)
http_write_json(json)
end
function trojan_go_check()
local json = trojan_go.to_check("")
http_write_json(json)
end
function trojan_go_update()
local json = nil
local task = http.formvalue("task")
if task == "extract" then
json = trojan_go.to_extract(http.formvalue("file"), http.formvalue("subfix"))
elseif task == "move" then
json = trojan_go.to_move(http.formvalue("file"))
else
json = trojan_go.to_download(http.formvalue("url"))
end
http_write_json(json)
end

View File

@ -20,7 +20,7 @@ function gen_uuid()
end
function uci_get_type(type, config, default)
local value = uci:get_first(appname, type, config, default) or sys.exec("echo -n `uci -q get " .. appname .. ".@" .. type .."[0]." .. config .. "`")
local value = uci:get_first(appname, type, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. ".@" .. type .."[0]." .. config .. ")")
if (value == nil or value == "") and (default and default ~= "") then
value = default
end
@ -28,22 +28,47 @@ function uci_get_type(type, config, default)
end
function uci_get_type_id(id, config, default)
local value = uci:get(appname, id, config, default) or sys.exec("echo -n `uci -q get " .. appname .. "." .. id .. "." .. config .. "`")
local value = uci:get(appname, id, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. "." .. id .. "." .. config .. ")")
if (value == nil or value == "") and (default and default ~= "") then
value = default
end
return value
end
function chmod_755(file)
if file and file ~= "" then
if not fs.access(file, "rwx", "rx", "rx") then
fs.chmod(file, 755)
end
end
end
function get_v2ray_path()
local path = uci_get_type("global_app", "v2ray_file")
return path .. "/v2ray"
end
function get_v2ray_version()
local path = get_v2ray_path()
local version = sys.exec("[ -f '" .. path .. "' ] && " .. path .. " -version | awk '{print $2}' | sed -n 1P")
return version
function get_v2ray_version(file)
if file == nil then file = get_v2ray_path() end
chmod_755(file)
if fs.access(file) then
return sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file)
end
return ""
end
function get_trojan_go_path()
local path = uci_get_type("global_app", "trojan_go_file")
return path
end
function get_trojan_go_version(file)
if file == nil then file = get_trojan_go_path() end
chmod_755(file)
if fs.access(file) then
return sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file)
end
return ""
end
function get_kcptun_path()
@ -51,10 +76,13 @@ function get_kcptun_path()
return path
end
function get_kcptun_version()
local path = get_kcptun_path()
local version = sys.exec("[ -f '" .. path .. "' ] && " .. path .. " -v | awk '{print $3}'")
return version
function get_kcptun_version(file)
if file == nil then file = get_kcptun_path() end
chmod_755(file)
if fs.access(file) then
return sys.exec("echo -n $(%s -v | awk '{print $3}')" % file)
end
return ""
end
function get_brook_path()
@ -62,10 +90,13 @@ function get_brook_path()
return path
end
function get_brook_version()
local path = get_brook_path()
local version = sys.exec("[ -f '" .. path .. "' ] && " .. path .. " -v | awk '{print $3}'")
return version
function get_brook_version(file)
if file == nil then file = get_brook_path() end
chmod_755(file)
if fs.access(file) then
return sys.exec("echo -n $(%s -v | awk '{print $3}')" % file)
end
return ""
end
function _unpack(t, i)
@ -144,12 +175,10 @@ end
function auto_get_arch()
local arch = nixio.uname().machine or ""
if fs.access("/usr/lib/os-release") then
LEDE_BOARD = sys.exec(
"echo -n `grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}'`")
LEDE_BOARD = sys.exec("echo -n `grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}'`")
end
if fs.access("/etc/openwrt_release") then
DISTRIB_TARGET = sys.exec(
"echo -n `grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}'`")
DISTRIB_TARGET = sys.exec("echo -n `grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}'`")
end
if arch == "mips" then
@ -157,15 +186,13 @@ function auto_get_arch()
if string.match(LEDE_BOARD, "ramips") == "ramips" then
arch = "ramips"
else
arch = sys.exec("echo '" .. LEDE_BOARD ..
"' | grep -oE 'ramips|ar71xx'")
arch = sys.exec("echo '" .. LEDE_BOARD .. "' | grep -oE 'ramips|ar71xx'")
end
elseif DISTRIB_TARGET and DISTRIB_TARGET ~= "" then
if string.match(DISTRIB_TARGET, "ramips") == "ramips" then
arch = "ramips"
else
arch = sys.exec("echo '" .. DISTRIB_TARGET ..
"' | grep -oE 'ramips|ar71xx'")
arch = sys.exec("echo '" .. DISTRIB_TARGET .. "' | grep -oE 'ramips|ar71xx'")
end
end
end
@ -204,7 +231,6 @@ end
function get_api_json(url)
local jsonc = require "luci.jsonc"
local json_content = luci.sys.exec(curl .. " " .. _unpack(curl_args) .. " " .. url)
if json_content == "" then return {} end
return jsonc.parse(json_content) or {}

View File

@ -5,31 +5,7 @@ local util = require "luci.util"
local i18n = require "luci.i18n"
local api = require "luci.model.cbi.passwall.api.api"
local brook_api =
"https://api.github.com/repos/txthinking/brook/releases/latest"
function get_brook_file_path()
return api.uci_get_type("global_app", "brook_file")
end
function get_brook_version(file)
if file == nil then file = get_brook_file_path() end
if file and file ~= "" then
if not fs.access(file, "rwx", "rx", "rx") then
fs.chmod(file, 755)
end
local info = util.trim(sys.exec("%s -v 2>/dev/null" % file))
if info ~= "" then
local tb = util.split(info, "%s+", nil, true)
return tb[1] == "Brook" and tb[3] or ""
end
end
return ""
end
local brook_api = "https://api.github.com/repos/txthinking/brook/releases/latest"
function to_check(arch)
if not arch or arch == "" then arch = api.auto_get_arch() end
@ -56,12 +32,9 @@ function to_check(arch)
}
end
local now_version = api.get_brook_version()
local remote_version = json.tag_name:match("[^v]+")
local client_file = get_brook_file_path()
local needs_update = api.compare_versions(get_brook_version(client_file),
"<", remote_version)
local needs_update = api.compare_versions(now_version, "<", remote_version)
local html_url, download_url
if needs_update then
@ -77,18 +50,17 @@ function to_check(arch)
if needs_update and not download_url then
return {
code = 1,
now_version = get_brook_version(client_file),
now_version = now_version,
version = remote_version,
html_url = html_url,
error = i18n.translate(
"New version found, but failed to get new version download url.")
error = i18n.translate("New version found, but failed to get new version download url.")
}
end
return {
code = 0,
update = needs_update,
now_version = get_brook_version(client_file),
now_version = now_version,
version = remote_version,
url = {html = html_url, download = download_url}
}
@ -122,17 +94,16 @@ function to_move(file)
return {code = 1, error = i18n.translate("Client file is required.")}
end
local version = get_brook_version(file)
local version = api.get_brook_version(file)
if version == "" then
sys.call("/bin/rm -rf /tmp/brook_download.*")
return {
code = 1,
error = i18n.translate(
"The client file is not suitable for current device.")
error = i18n.translate("The client file is not suitable for current device.")
}
end
local client_file = get_brook_file_path()
local client_file = api.get_brook_path()
local client_file_bak
if fs.access(client_file) then
@ -140,8 +111,7 @@ function to_move(file)
api.exec("/bin/mv", {"-f", client_file, client_file_bak})
end
local result = api.exec("/bin/mv", {"-f", file, client_file}, nil,
api.command_timeout) == 0
local result = api.exec("/bin/mv", {"-f", file, client_file}, nil, api.command_timeout) == 0
if not result or not fs.access(client_file) then
sys.call("/bin/rm -rf /tmp/brook_download.*")
@ -150,8 +120,7 @@ function to_move(file)
end
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s",
client_file)
error = i18n.translatef("Can't move new file to path: %s", client_file)
}
end

View File

@ -25,7 +25,7 @@ if node.type == "SS" then
end
elseif node.type == "SSR" then
config.method = node.ssr_encrypt_method
config.protocol = node.protocol
config.protocol = node.ssr_protocol
config.protocol_param = node.protocol_param
config.obfs = node.obfs
config.obfs_param = node.obfs_param

View File

@ -6,26 +6,34 @@ local local_addr = arg[3]
local local_port = arg[4]
local node = ucursor:get_all("passwall", node_section)
local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA"
local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"
local trojan = {
run_type = run_type,
local_addr = local_addr,
local_port = local_port,
local_port = tonumber(local_port),
remote_addr = node.address,
remote_port = tonumber(node.port),
password = {node.password},
log_level = 1,
ssl = {
verify = (node.trojan_verify_cert == "1") and true or false,
verify = (node.tls_allowInsecure ~= "1") and true or false,
verify_hostname = true,
cert = node.trojan_cert_path,
cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA",
cipher_tls13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384",
cipher = cipher,
cipher_tls13 = cipher13,
sni = node.tls_serverName,
alpn = {"h2", "http/1.1"},
reuse_session = true,
session_ticket = false,
session_ticket = (node.tls_sessionTicket == "1") and true or false,
curves = ""
},
udp_timeout = 60,
mux = (node.mux == "1") and {
enabled = true,
concurrency = tonumber(node.mux_concurrency),
idle_timeout = 60,
} or nil,
tcp = {
no_delay = true,
keep_alive = true,
@ -34,4 +42,29 @@ local trojan = {
fast_open_qlen = 20
}
}
if node.type == "Trojan-Go" then
trojan.ssl.cipher = node.fingerprint == nil and cipher or (node.fingerprint == "disable" and cipher13 .. ":" .. cipher or "")
trojan.ssl.cipher_tls13 = node.fingerprint == nil and cipher13 or nil
trojan.ssl.fingerprint = (node.fingerprint ~= nil and node.fingerprint ~= "disable" ) and node.fingerprint or ""
trojan.ssl.alpn = node.trojan_transport == 'ws' and {} or {"h2", "http/1.1"}
if node.stream_security ~= "tls" and node.trojan_transport == "original" then trojan.ssl = nil end
trojan.transport_plugin = node.stream_security == "none" and node.trojan_transport == "original" and {
enabled = node.plugin_type ~= nil,
type = node.plugin_type or "plaintext",
command = node.plugin_type ~= "plaintext" and node.plugin_cmd or nil,
plugin_option = node.plugin_type ~= "plaintext" and node.plugin_option or nil,
arg = node.plugin_type ~= "plaintext" and { node.plugin_arg } or nil,
env = {}
} or nil
trojan.websocket = node.trojan_transport and node.trojan_transport:find('ws') and {
enabled = true,
path = (node.ws_path ~= nil) and node.ws_path or "/",
host = (node.ws_host ~= nil) and node.ws_host or (node.tls_serverName ~= nil and node.tls_serverName or node.address)
} or nil
trojan.shadowsocks = (node.ss_aead == "1") and {
enabled = true,
method = (node.ss_aead_method ~= nil) and node.ss_aead_method or "aead_aes_128_gcm",
password = (node.ss_aead_pwd ~= nil) and node.ss_aead_pwd or ""
} or nil
end
print(json.stringify(trojan, 1))

View File

@ -21,8 +21,8 @@ local function gen_outbound(node, tag)
end
if node.type ~= "V2ray" then
if node.type == "Socks" then
node.v2ray_protocol = "socks"
node.v2ray_transport = "tcp"
node.protocol = "socks"
node.transport = "tcp"
else
local node_type = (proto and proto ~= "nil") and proto or "socks"
local new_port = sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port auto tcp)", appname))
@ -35,83 +35,87 @@ local function gen_outbound(node, tag)
string.format("/var/etc/%s/v2_%s_%s.json", appname, node_type, node_id),
"4")
)
node.v2ray_protocol = "socks"
node.v2ray_transport = "tcp"
node.protocol = "socks"
node.transport = "tcp"
node.address = "127.0.0.1"
end
end
result = {
tag = tag,
protocol = node.v2ray_protocol or "vmess",
protocol = node.protocol or "vmess",
mux = {
enabled = (node.v2ray_mux == "1") and true or false,
concurrency = (node.v2ray_mux_concurrency) and tonumber(node.v2ray_mux_concurrency) or 8
enabled = (node.mux == "1") and true or false,
concurrency = (node.mux_concurrency) and tonumber(node.mux_concurrency) or 8
},
-- 底层传输配置
streamSettings = (node.v2ray_protocol == "vmess") and {
network = node.v2ray_transport,
security = node.v2ray_stream_security,
tlsSettings = (node.v2ray_stream_security == "tls") and {
streamSettings = (node.protocol == "vmess") and {
network = node.transport,
security = node.stream_security,
tlsSettings = (node.stream_security == "tls") and {
disableSessionResumption = node.sessionTicket ~= "1" and true or false,
serverName = node.tls_serverName,
allowInsecure = (node.tls_allowInsecure == "1") and true or false
} or nil,
tcpSettings = (node.v2ray_transport == "tcp" and
node.v2ray_protocol ~= "socks") and {
tcpSettings = (node.transport == "tcp" and
node.protocol ~= "socks") and {
header = {
type = node.v2ray_tcp_guise,
type = node.tcp_guise,
request = {
path = node.v2ray_tcp_guise_http_path or {"/"},
path = node.tcp_guise_http_path or {"/"},
headers = {
Host = node.v2ray_tcp_guise_http_host or {}
Host = node.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),
uplinkCapacity = tonumber(node.v2ray_mkcp_uplinkCapacity),
downlinkCapacity = tonumber(node.v2ray_mkcp_downlinkCapacity),
congestion = (node.v2ray_mkcp_congestion == "1") and true or false,
readBufferSize = tonumber(node.v2ray_mkcp_readBufferSize),
writeBufferSize = tonumber(node.v2ray_mkcp_writeBufferSize),
header = {type = node.v2ray_mkcp_guise}
kcpSettings = (node.transport == "mkcp") and {
mtu = tonumber(node.mkcp_mtu),
tti = tonumber(node.mkcp_tti),
uplinkCapacity = tonumber(node.mkcp_uplinkCapacity),
downlinkCapacity = tonumber(node.mkcp_downlinkCapacity),
congestion = (node.mkcp_congestion == "1") and true or false,
readBufferSize = tonumber(node.mkcp_readBufferSize),
writeBufferSize = tonumber(node.mkcp_writeBufferSize),
header = {type = node.mkcp_guise}
} or nil,
wsSettings = (node.v2ray_transport == "ws") and {
path = node.v2ray_ws_path or "",
headers = (node.v2ray_ws_host ~= nil) and
{Host = node.v2ray_ws_host} or nil
wsSettings = (node.transport == "ws") and {
path = node.ws_path or "",
headers = (node.ws_host ~= nil) and
{Host = node.ws_host} or nil
} or nil,
httpSettings = (node.v2ray_transport == "h2") and
{path = node.v2ray_h2_path, host = node.v2ray_h2_host} or
httpSettings = (node.transport == "h2") and
{path = node.h2_path, host = node.h2_host} or
nil,
dsSettings = (node.v2ray_transport == "ds") and
{path = node.v2ray_ds_path} or nil,
quicSettings = (node.v2ray_transport == "quic") and {
security = node.v2ray_quic_security,
key = node.v2ray_quic_key,
header = {type = node.v2ray_quic_guise}
dsSettings = (node.transport == "ds") and
{path = node.ds_path} or nil,
quicSettings = (node.transport == "quic") and {
security = node.quic_security,
key = node.quic_key,
header = {type = node.quic_guise}
} or nil
} or nil,
settings = {
vnext = (node.v2ray_protocol == "vmess") and {
vnext = (node.protocol == "vmess") and {
{
address = node.address,
port = tonumber(node.port),
users = {
{
id = node.v2ray_VMess_id,
alterId = tonumber(node.v2ray_VMess_alterId),
level = tonumber(node.v2ray_VMess_level),
security = node.v2ray_security
id = node.vmess_id,
alterId = tonumber(node.alter_id),
level = tonumber(node.vmess_level),
security = node.security
}
}
}
} or nil,
servers = (node.v2ray_protocol == "socks") and {
servers = (node.protocol == "socks" or node.protocol == "http" or node.protocol == "shadowsocks") and {
{
address = node.address,
port = tonumber(node.port),
method = node.v_ss_encrypt_method or nil,
password = node.password or "",
ota = node.ss_ota == '1' and true or false,
users = (node.username and node.password) and
{{user = node.username, pass = node.password}} or nil
}
@ -139,17 +143,17 @@ if redir_port ~= "nil" then
settings = {network = proto, followRedirect = true},
sniffing = {enabled = true, destOverride = {"http", "tls"}}
})
if proto == "tcp" and node.v2ray_tcp_socks == "1" then
if proto == "tcp" and node.tcp_socks == "1" then
table.insert(inbounds, {
listen = "0.0.0.0",
port = tonumber(node.v2ray_tcp_socks_port),
port = tonumber(node.tcp_socks_port),
protocol = "socks",
settings = {
auth = node.v2ray_tcp_socks_auth,
accounts = (node.v2ray_tcp_socks_auth == "password") and {
auth = node.tcp_socks_auth,
accounts = (node.tcp_socks_auth == "password") and {
{
user = node.v2ray_tcp_socks_auth_username,
pass = node.v2ray_tcp_socks_auth_password
user = node.tcp_socks_auth_username,
pass = node.tcp_socks_auth_password
}
} or nil,
udp = true
@ -158,7 +162,7 @@ if redir_port ~= "nil" then
end
end
if node.v2ray_protocol == "_shunt" then
if node.protocol == "_shunt" then
local rules = {}
ucursor:foreach(appname, "shunt_rules", function(e)
@ -211,9 +215,9 @@ if node.v2ray_protocol == "_shunt" then
routing = {domainStrategy = "IPOnDemand", rules = rules}
elseif node.v2ray_protocol == "_balancing" then
if node.v2ray_balancing_node then
local nodes = node.v2ray_balancing_node
elseif node.protocol == "_balancing" then
if node.balancing_node then
local nodes = node.balancing_node
local length = #nodes
for i = 1, length do
local node = ucursor:get_all(appname, nodes[i])

View File

@ -0,0 +1,149 @@
module("luci.model.cbi.passwall.api.trojan_go", package.seeall)
local fs = require "nixio.fs"
local sys = require "luci.sys"
local util = require "luci.util"
local i18n = require "luci.i18n"
local ipkg = require("luci.model.ipkg")
local api = require "luci.model.cbi.passwall.api.api"
local trojan_go_api = api.uci_get_type("global_app", "trojan_go_latest", "https://api.github.com/repos/trojan-gfw/trojan-go/releases/latest")
function to_check(arch)
if not arch or arch == "" then arch = api.auto_get_arch() end
local file_tree, sub_version = api.get_file_info(arch)
if file_tree == "" then
return {
code = 1,
error = i18n.translate(
"Can't determine ARCH, or ARCH not supported.")
}
end
if file_tree == "mips" then file_tree = "mips%-hardfloat" end
if file_tree == "mipsle" then file_tree = "mipsle%-hardfloat" end
if file_tree == "arm64" then
file_tree = "armv8"
else
if sub_version and sub_version:match("^[5-8]$") then file_tree = file_tree .. "v" .. sub_version end
end
local json = api.get_api_json(trojan_go_api)
if json == nil or json.tag_name == nil then
return {
code = 1,
error = i18n.translate("Get remote version info failed.")
}
end
local now_version = api.get_trojan_go_version()
local remote_version = json.tag_name:match("[^v]+")
local needs_update = api.compare_versions(now_version, "<", remote_version)
local html_url, download_url
if needs_update then
html_url = json.html_url
for _, v in ipairs(json.assets) do
if v.name and v.name:match("linux%-" .. file_tree .. "%.zip") then
download_url = v.browser_download_url
break
end
end
end
if needs_update and not download_url then
return {
code = 1,
now_version = now_version,
version = remote_version,
html_url = html_url,
error = i18n.translate(
"New version found, but failed to get new version download url.") .. " [linux-" .. file_tree .. ".zip]"
}
end
return {
code = 0,
update = needs_update,
now_version = now_version,
version = remote_version,
url = {html = html_url, download = download_url}
}
end
function to_download(url)
if not url or url == "" then
return {code = 1, error = i18n.translate("Download url is required.")}
end
sys.call("/bin/rm -f /tmp/trojan-go_download.*")
local tmp_file = util.trim(util.exec("mktemp -u -t trojan-go_download.XXXXXX"))
local result = api.exec(api.curl, {api._unpack(api.curl_args), "-o", tmp_file, url}, nil, api.command_timeout) == 0
if not result then
api.exec("/bin/rm", {"-f", tmp_file})
return {
code = 1,
error = i18n.translatef("File download failed or timed out: %s", url)
}
end
return {code = 0, file = tmp_file}
end
function to_extract(file, subfix)
local isinstall_unzip = ipkg.installed("unzip")
if isinstall_unzip == nil then
ipkg.update()
ipkg.install("unzip")
end
if not file or file == "" or not fs.access(file) then
return {code = 1, error = i18n.translate("File path required.")}
end
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
local tmp_dir = util.trim(util.exec("mktemp -d -t trojan-go_extract.XXXXXX"))
local output = {}
api.exec("/usr/bin/unzip", {"-o", file, "-d", tmp_dir},
function(chunk) output[#output + 1] = chunk end)
local files = util.split(table.concat(output))
api.exec("/bin/rm", {"-f", file})
return {code = 0, file = tmp_dir}
end
function to_move(file)
if not file or file == "" then
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
return {code = 1, error = i18n.translate("Client file is required.")}
end
local client_file = api.get_trojan_go_path()
local client_file_bak
if fs.access(client_file) then
client_file_bak = client_file .. ".bak"
api.exec("/bin/mv", {"-f", client_file, client_file_bak})
end
local result = api.exec("/bin/mv", { "-f", file .. "/trojan-go", client_file }, nil, api.command_timeout) == 0
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
if not result or not fs.access(client_file) then
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s", client_file)
}
end
api.exec("/bin/chmod", {"-R", "755", client_file})
return {code = 0}
end

View File

@ -6,8 +6,7 @@ local i18n = require "luci.i18n"
local ipkg = require("luci.model.ipkg")
local api = require "luci.model.cbi.passwall.api.api"
local v2ray_api =
"https://api.github.com/repos/v2ray/v2ray-core/releases/latest"
local v2ray_api = "https://api.github.com/repos/v2fly/v2ray-core/releases/latest"
local is_armv7 = false
function get_v2ray_file_path()
@ -17,9 +16,7 @@ end
function get_v2ray_version()
if get_v2ray_file_path() and get_v2ray_file_path() ~= "" then
if fs.access(get_v2ray_file_path() .. "/v2ray") then
return sys.exec("echo -n `" .. get_v2ray_file_path() ..
"/v2ray -version | awk '{print $2}' | sed -n 1P" ..
"`")
return sys.exec("echo -n $(" .. get_v2ray_file_path() .. "/v2ray -version | awk '{print $2}' | sed -n 1P" .. ")")
end
end
return ""
@ -52,8 +49,7 @@ function to_check(arch)
end
local remote_version = json.tag_name:match("[^v]+")
local needs_update = api.compare_versions(get_v2ray_version(), "<",
remote_version)
local needs_update = api.compare_versions(get_v2ray_version(), "<", remote_version)
local html_url, download_url
if needs_update then
@ -160,8 +156,7 @@ function to_move(file)
if not result or not fs.access(client_file) then
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s",
client_file)
error = i18n.translatef("Can't move new file to path: %s", client_file)
}
end

View File

@ -5,8 +5,8 @@ local nodes_table = {}
uci:foreach(appname, "nodes", function(e)
if e.type and e.remarks then
local remarks = ""
if e.type == "V2ray" and (e.v2ray_protocol == "_balancing" or e.v2ray_protocol == "_shunt") then
remarks = "%s[%s] " % {translatef(e.type .. e.v2ray_protocol), e.remarks}
if e.type == "V2ray" and (e.protocol == "_balancing" or e.protocol == "_shunt") then
remarks = "%s[%s] " % {translatef(e.type .. e.protocol), e.remarks}
else
remarks = "%s[%s] %s:%s" % {e.type, e.remarks, e.address, e.port}
end

View File

@ -16,8 +16,8 @@ local nodes_table = {}
uci:foreach(appname, "nodes", function(e)
if e.type and e.remarks then
local remarks = ""
if e.type == "V2ray" and (e.v2ray_protocol == "_balancing" or e.v2ray_protocol == "_shunt") then
remarks = "%s[%s] " % {translatef(e.type .. e.v2ray_protocol), e.remarks}
if e.type == "V2ray" and (e.protocol == "_balancing" or e.protocol == "_shunt") then
remarks = "%s[%s] " % {translatef(e.type .. e.protocol), e.remarks}
else
if e.use_kcp and e.use_kcp == "1" then
remarks = "%s+%s[%s] %s" % {e.type, "Kcptun", e.remarks, e.address}

View File

@ -44,15 +44,27 @@ local ssr_obfs_list = {
"tls1.0_session_auth", "tls1.2_ticket_auth"
}
local v2ray_ss_encrypt_method_list = {
local v_ss_encrypt_method_list = {
"aes-128-cfb", "aes-256-cfb", "aes-128-gcm", "aes-256-gcm", "chacha20", "chacha20-ietf", "chacha20-poly1305", "chacha20-ietf-poly1305"
}
local v2ray_security_list = {"none", "auto", "aes-128-gcm", "chacha20-poly1305"}
local security_list = {"none", "auto", "aes-128-gcm", "chacha20-poly1305"}
local v2ray_header_type_list = {
local header_type_list = {
"none", "srtp", "utp", "wechat-video", "dtls", "wireguard"
}
local force_fp = {
"disable", "firefox", "chrome", "ios"
}
local encrypt_methods_ss_aead = {
"dummy",
"aead_chacha20_poly1305",
"aead_aes_128_gcm",
"aead_aes_256_gcm",
"chacha20-ietf-poly1305",
"aes-128-gcm",
"aes-256-gcm",
}
m = Map(appname, translate("Node Config"))
m.redirect = d.build_url("admin", "vpn", appname)
@ -82,18 +94,21 @@ end
if is_installed("brook") or is_finded("brook") then
type:value("Brook", translate("Brook"))
end
if is_installed("trojan") or is_finded("trojan") then
type:value("Trojan", translate("Trojan"))
if is_installed("trojan-plus") or is_finded("trojan-plus") then
type:value("Trojan", translate("Trojan-Plus"))
end
if is_installed("trojan-go") or is_finded("trojan-go") then
type:value("Trojan-Go", translate("Trojan-Go"))
end
v2ray_protocol = s:option(ListValue, "v2ray_protocol", translate("Protocol"))
v2ray_protocol:value("vmess", translate("Vmess"))
v2ray_protocol:value("http", translate("HTTP"))
v2ray_protocol:value("socks", translate("Socks"))
v2ray_protocol:value("shadowsocks", translate("Shadowsocks"))
v2ray_protocol:value("_balancing", translate("Balancing"))
v2ray_protocol:value("_shunt", translate("Shunt"))
v2ray_protocol:depends("type", "V2ray")
protocol = s:option(ListValue, "protocol", translate("Protocol"))
protocol:value("vmess", translate("Vmess"))
protocol:value("http", translate("HTTP"))
protocol:value("socks", translate("Socks"))
protocol:value("shadowsocks", translate("Shadowsocks"))
protocol:value("_balancing", translate("Balancing"))
protocol:value("_shunt", translate("Shunt"))
protocol:depends("type", "V2ray")
local nodes_table = {}
uci:foreach(appname, "nodes", function(e)
@ -108,26 +123,26 @@ uci:foreach(appname, "nodes", function(e)
end)
-- 负载均衡列表
v2ray_balancing_node = s:option(DynamicList, "v2ray_balancing_node", translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>"))
for k, v in pairs(nodes_table) do v2ray_balancing_node:value(v.id, v.remarks) end
v2ray_balancing_node:depends("v2ray_protocol", "_balancing")
balancing_node = s:option(DynamicList, "balancing_node", translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>"))
for k, v in pairs(nodes_table) do balancing_node:value(v.id, v.remarks) end
balancing_node:depends("protocol", "_balancing")
-- 分流
uci:foreach(appname, "shunt_rules", function(e)
o = s:option(ListValue, e[".name"], translate(e.remarks))
o:value("nil", translate("Close"))
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
o:depends("v2ray_protocol", "_shunt")
o:depends("protocol", "_shunt")
o = s:option(Flag, e[".name"] .. "_proxy", translate(e.remarks) .. translate("Preproxy"), translate("Use the default node for the transit."))
o.default = 0
o:depends("v2ray_protocol", "_shunt")
o:depends("protocol", "_shunt")
end)
default_node = s:option(ListValue, "default_node", translate("Default") .. " " .. translate("Node"))
default_node:value("nil", translate("Close"))
for k, v in pairs(nodes_table) do default_node:value(v.id, v.remarks) end
default_node:depends("v2ray_protocol", "_shunt")
default_node:depends("protocol", "_shunt")
-- Brook协议
brook_protocol = s:option(ListValue, "brook_protocol",
@ -144,12 +159,13 @@ address.rmempty = false
address:depends("type", "Socks")
address:depends("type", "SS")
address:depends("type", "SSR")
address:depends({ type = "V2ray", v2ray_protocol = "vmess" })
address:depends({ type = "V2ray", v2ray_protocol = "http" })
address:depends({ type = "V2ray", v2ray_protocol = "socks" })
address:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" })
address:depends({ type = "V2ray", protocol = "vmess" })
address:depends({ type = "V2ray", protocol = "http" })
address:depends({ type = "V2ray", protocol = "socks" })
address:depends({ type = "V2ray", protocol = "shadowsocks" })
address:depends("type", "Brook")
address:depends("type", "Trojan")
address:depends("type", "Trojan-Go")
--[[
use_ipv6 = s:option(Flag, "use_ipv6", translate("Use IPv6"))
@ -157,12 +173,13 @@ use_ipv6.default = 0
use_ipv6:depends("type", "Socks")
use_ipv6:depends("type", "SS")
use_ipv6:depends("type", "SSR")
use_ipv6:depends({ type = "V2ray", v2ray_protocol = "vmess" })
use_ipv6:depends({ type = "V2ray", v2ray_protocol = "http" })
use_ipv6:depends({ type = "V2ray", v2ray_protocol = "socks" })
use_ipv6:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" })
use_ipv6:depends({ type = "V2ray", protocol = "vmess" })
use_ipv6:depends({ type = "V2ray", protocol = "http" })
use_ipv6:depends({ type = "V2ray", protocol = "socks" })
use_ipv6:depends({ type = "V2ray", protocol = "shadowsocks" })
use_ipv6:depends("type", "Brook")
use_ipv6:depends("type", "Trojan")
use_ipv6:depends("type", "Trojan-Go")
--]]
port = s:option(Value, "port", translate("Port"))
@ -171,17 +188,18 @@ port.rmempty = false
port:depends("type", "Socks")
port:depends("type", "SS")
port:depends("type", "SSR")
port:depends({ type = "V2ray", v2ray_protocol = "vmess" })
port:depends({ type = "V2ray", v2ray_protocol = "http" })
port:depends({ type = "V2ray", v2ray_protocol = "socks" })
port:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" })
port:depends({ type = "V2ray", protocol = "vmess" })
port:depends({ type = "V2ray", protocol = "http" })
port:depends({ type = "V2ray", protocol = "socks" })
port:depends({ type = "V2ray", protocol = "shadowsocks" })
port:depends("type", "Brook")
port:depends("type", "Trojan")
port:depends("type", "Trojan-Go")
username = s:option(Value, "username", translate("Username"))
username:depends("type", "Socks")
username:depends("v2ray_protocol", "http")
username:depends("v2ray_protocol", "socks")
username:depends("protocol", "http")
username:depends("protocol", "socks")
password = s:option(Value, "password", translate("Password"))
password.password = true
@ -190,9 +208,10 @@ password:depends("type", "SS")
password:depends("type", "SSR")
password:depends("type", "Brook")
password:depends("type", "Trojan")
password:depends("v2ray_protocol", "http")
password:depends("v2ray_protocol", "socks")
password:depends("v2ray_protocol", "shadowsocks")
password:depends("type", "Trojan-Go")
password:depends("protocol", "http")
password:depends("protocol", "socks")
password:depends("protocol", "shadowsocks")
ss_encrypt_method = s:option(ListValue, "ss_encrypt_method",
translate("Encrypt Method"))
@ -204,24 +223,24 @@ ssr_encrypt_method = s:option(ListValue, "ssr_encrypt_method",
for a, t in ipairs(ssr_encrypt_method_list) do ssr_encrypt_method:value(t) end
ssr_encrypt_method:depends("type", "SSR")
v2ray_security = s:option(ListValue, "v2ray_security",
security = s:option(ListValue, "security",
translate("Encrypt Method"))
for a, t in ipairs(v2ray_security_list) do v2ray_security:value(t) end
v2ray_security:depends("v2ray_protocol", "vmess")
for a, t in ipairs(security_list) do security:value(t) end
security:depends("protocol", "vmess")
v2ray_ss_encrypt_method = s:option(ListValue, "v2ray_ss_encrypt_method",
v_ss_encrypt_method = s:option(ListValue, "v_ss_encrypt_method",
translate("Encrypt Method"))
for a, t in ipairs(v2ray_ss_encrypt_method_list) do v2ray_ss_encrypt_method:value(t) end
v2ray_ss_encrypt_method:depends("v2ray_protocol", "shadowsocks")
for a, t in ipairs(v_ss_encrypt_method_list) do v_ss_encrypt_method:value(t) end
v_ss_encrypt_method:depends("protocol", "shadowsocks")
v2ray_ss_ota = s:option(Flag, "v2ray_ss_ota", translate("OTA"), translate(
ss_ota = s:option(Flag, "ss_ota", translate("OTA"), translate(
"When OTA is enabled, V2Ray will reject connections that are not OTA enabled. This option is invalid when using AEAD encryption."))
v2ray_ss_ota.default = "0"
v2ray_ss_ota:depends("v2ray_protocol", "shadowsocks")
ss_ota.default = "0"
ss_ota:depends("protocol", "shadowsocks")
protocol = s:option(ListValue, "protocol", translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do protocol:value(t) end
protocol:depends("type", "SSR")
ssr_protocol = s:option(ListValue, "ssr_protocol", translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do ssr_protocol:value(t) end
ssr_protocol:depends("type", "SSR")
protocol_param = s:option(Value, "protocol_param", translate("Protocol_param"))
protocol_param:depends("type", "SSR")
@ -246,6 +265,7 @@ tcp_fast_open:value("true")
tcp_fast_open:depends("type", "SS")
tcp_fast_open:depends("type", "SSR")
tcp_fast_open:depends("type", "Trojan")
tcp_fast_open:depends("type", "Trojan-Go")
ss_plugin = s:option(ListValue, "ss_plugin", translate("plugin"))
ss_plugin:value("none", translate("none"))
@ -281,205 +301,281 @@ kcp_opts.placeholder =
"--crypt aes192 --key abc123 --mtu 1350 --sndwnd 128 --rcvwnd 1024 --mode fast"
kcp_opts:depends("use_kcp", "1")
v2ray_VMess_id = s:option(Value, "v2ray_VMess_id", translate("ID"))
v2ray_VMess_id.password = true
v2ray_VMess_id:depends("v2ray_protocol", "vmess")
vmess_id = s:option(Value, "vmess_id", translate("ID"))
vmess_id.password = true
vmess_id:depends("protocol", "vmess")
v2ray_VMess_alterId = s:option(Value, "v2ray_VMess_alterId",
alter_id = s:option(Value, "alter_id",
translate("Alter ID"))
v2ray_VMess_alterId:depends("v2ray_protocol", "vmess")
alter_id:depends("protocol", "vmess")
v2ray_VMess_level =
s:option(Value, "v2ray_VMess_level", translate("User Level"))
v2ray_VMess_level.default = 1
v2ray_VMess_level:depends("v2ray_protocol", "vmess")
vmess_level =
s:option(Value, "vmess_level", translate("User Level"))
vmess_level.default = 1
vmess_level:depends("protocol", "vmess")
v2ray_stream_security = s:option(ListValue, "v2ray_stream_security",
stream_security = s:option(ListValue, "stream_security",
translate("Transport Layer Encryption"),
translate(
'Whether or not transport layer encryption is enabled, the supported options are "none" for unencrypted (default) and "TLS" for using TLS.'))
v2ray_stream_security:value("none", "none")
v2ray_stream_security:value("tls", "tls")
v2ray_stream_security:depends("v2ray_protocol", "vmess")
v2ray_stream_security:depends("v2ray_protocol", "http")
v2ray_stream_security:depends("v2ray_protocol", "shadowsocks")
stream_security:value("none", "none")
stream_security:value("tls", "tls")
stream_security.default = "tls"
stream_security:depends("protocol", "vmess")
stream_security:depends("protocol", "shadowsocks")
stream_security:depends("type", "Trojan")
stream_security:depends("type", "Trojan-Go")
stream_security.validate = function(self, value)
if value == "none" and type:formvalue(arg[1]) == "Trojan" then
return nil, translate("'none' not supported for original Trojan.")
end
return value
end
-- [[ TLS部分 ]] --
tls_serverName = s:option(Value, "tls_serverName", translate("Domain"))
tls_serverName:depends("v2ray_stream_security", "tls")
tls_serverName:depends("trojan_verify_cert", "1")
tls_allowInsecure = s:option(Flag, "tls_allowInsecure",
translate("allowInsecure"), translate(
tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket"))
tls_sessionTicket.default = "0"
tls_sessionTicket:depends("stream_security", "tls")
-- [[ Trojan TLS ]]--
trojan_force_fp = s:option(ListValue, "fingerprint", translate("Finger Print"))
for a, t in ipairs(force_fp) do trojan_force_fp:value(t) end
trojan_force_fp.default = "firefox"
trojan_force_fp:depends({ type = "Trojan-Go", stream_security = "tls" })
tls_serverName = s:option(Value, "tls_serverName", translate("Domain"))
tls_serverName:depends("stream_security", "tls")
tls_allowInsecure = s:option(Flag, "tls_allowInsecure", translate("allowInsecure"), translate(
"Whether unsafe connections are allowed. When checked, V2Ray does not check the validity of the TLS certificate provided by the remote host."))
tls_allowInsecure.default = "0"
tls_allowInsecure.rmempty = false
tls_allowInsecure:depends("v2ray_stream_security", "tls")
tls_allowInsecure:depends("stream_security", "tls")
v2ray_transport = s:option(ListValue, "v2ray_transport", translate("Transport"))
v2ray_transport:value("tcp", "TCP")
v2ray_transport:value("mkcp", "mKCP")
v2ray_transport:value("ws", "WebSocket")
v2ray_transport:value("h2", "HTTP/2")
v2ray_transport:value("ds", "DomainSocket")
v2ray_transport:value("quic", "QUIC")
v2ray_transport:depends("v2ray_protocol", "vmess")
-- [[ Trojan Cert ]]--
trojan_cert_path = s:option(Value, "trojan_cert_path", translate("Trojan Cert Path"))
trojan_cert_path.default = ""
trojan_cert_path:depends({ stream_security = "tls", tls_allowInsecure = false })
trojan_transport = s:option(ListValue, "trojan_transport", translate("Transport"))
trojan_transport:value("original", "Original")
trojan_transport:value("ws", "WebSocket")
trojan_transport:value("h2", "HTTP/2")
trojan_transport:value("h2+ws", "HTTP/2 & WebSocket")
trojan_transport.default = "ws"
trojan_transport:depends("type", "Trojan-Go")
trojan_plugin = s:option(ListValue, "plugin_type", translate("Plugin Type"))
trojan_plugin:value("plaintext", "Plain Text")
trojan_plugin:value("shadowsocks", "ShadowSocks")
trojan_plugin:value("other", "Other")
trojan_plugin.default = "plaintext"
trojan_plugin:depends({ stream_security = "none", trojan_transport = "original" })
trojan_plugin_cmd = s:option(Value, "plugin_cmd", translate("Plugin Binary"))
trojan_plugin_cmd.placeholder = "eg: /usr/bin/v2ray-plugin"
trojan_plugin_cmd:depends({ plugin_type = "shadowsocks" })
trojan_plugin_cmd:depends({ plugin_type = "other" })
trojan_plugin_op = s:option(Value, "plugin_option", translate("Plugin Option"))
trojan_plugin_op.placeholder = "eg: obfs=http;obfs-host=www.baidu.com"
trojan_plugin_op:depends({ plugin_type = "shadowsocks" })
trojan_plugin_op:depends({ plugin_type = "other" })
trojan_plugin_arg = s:option(DynamicList, "plugin_arg", translate("Plugin Option Args"))
trojan_plugin_arg.placeholder = "eg: [\"-config\", \"test.json\"]"
trojan_plugin_arg:depends({ plugin_type = "shadowsocks" })
trojan_plugin_arg:depends({ plugin_type = "other" })
transport = s:option(ListValue, "transport", translate("Transport"))
transport:value("tcp", "TCP")
transport:value("mkcp", "mKCP")
transport:value("ws", "WebSocket")
transport:value("h2", "HTTP/2")
transport:value("ds", "DomainSocket")
transport:value("quic", "QUIC")
transport:depends("protocol", "vmess")
--[[
v2ray_ss_transport = s:option(ListValue, "v2ray_ss_transport", translate("Transport"))
v2ray_ss_transport:value("ws", "WebSocket")
v2ray_ss_transport:value("h2", "HTTP/2")
v2ray_ss_transport:depends("v2ray_protocol", "shadowsocks")
ss_transport = s:option(ListValue, "ss_transport", translate("Transport"))
ss_transport:value("ws", "WebSocket")
ss_transport:value("h2", "HTTP/2")
ss_transport:value("ws", "WebSocket")
ss_transport:value("h2+ws", "HTTP/2 & WebSocket")
ss_transport:depends("protocol", "shadowsocks")
]]--
-- [[ TCP部分 ]]--
-- TCP伪装
v2ray_tcp_guise = s:option(ListValue, "v2ray_tcp_guise",
tcp_guise = s:option(ListValue, "tcp_guise",
translate("Camouflage Type"))
v2ray_tcp_guise:value("none", "none")
v2ray_tcp_guise:value("http", "http")
v2ray_tcp_guise:depends("v2ray_transport", "tcp")
tcp_guise:value("none", "none")
tcp_guise:value("http", "http")
tcp_guise:depends("transport", "tcp")
-- HTTP域名
v2ray_tcp_guise_http_host = s:option(DynamicList, "v2ray_tcp_guise_http_host",
tcp_guise_http_host = s:option(DynamicList, "tcp_guise_http_host",
translate("HTTP Host"))
v2ray_tcp_guise_http_host:depends("v2ray_tcp_guise", "http")
tcp_guise_http_host:depends("tcp_guise", "http")
-- HTTP路径
v2ray_tcp_guise_http_path = s:option(DynamicList, "v2ray_tcp_guise_http_path",
tcp_guise_http_path = s:option(DynamicList, "tcp_guise_http_path",
translate("HTTP Path"))
v2ray_tcp_guise_http_path:depends("v2ray_tcp_guise", "http")
tcp_guise_http_path:depends("tcp_guise", "http")
-- [[ mKCP部分 ]]--
v2ray_mkcp_guise = s:option(ListValue, "v2ray_mkcp_guise",
mkcp_guise = s:option(ListValue, "mkcp_guise",
translate("Camouflage Type"), translate(
'<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
for a, t in ipairs(v2ray_header_type_list) do v2ray_mkcp_guise:value(t) end
v2ray_mkcp_guise:depends("v2ray_transport", "mkcp")
for a, t in ipairs(header_type_list) do mkcp_guise:value(t) end
mkcp_guise:depends("transport", "mkcp")
v2ray_mkcp_mtu = s:option(Value, "v2ray_mkcp_mtu", translate("KCP MTU"))
v2ray_mkcp_mtu:depends("v2ray_transport", "mkcp")
mkcp_mtu = s:option(Value, "mkcp_mtu", translate("KCP MTU"))
mkcp_mtu:depends("transport", "mkcp")
v2ray_mkcp_tti = s:option(Value, "v2ray_mkcp_tti", translate("KCP TTI"))
v2ray_mkcp_tti:depends("v2ray_transport", "mkcp")
mkcp_tti = s:option(Value, "mkcp_tti", translate("KCP TTI"))
mkcp_tti:depends("transport", "mkcp")
v2ray_mkcp_uplinkCapacity = s:option(Value, "v2ray_mkcp_uplinkCapacity",
mkcp_uplinkCapacity = s:option(Value, "mkcp_uplinkCapacity",
translate("KCP uplinkCapacity"))
v2ray_mkcp_uplinkCapacity:depends("v2ray_transport", "mkcp")
mkcp_uplinkCapacity:depends("transport", "mkcp")
v2ray_mkcp_downlinkCapacity = s:option(Value, "v2ray_mkcp_downlinkCapacity",
mkcp_downlinkCapacity = s:option(Value, "mkcp_downlinkCapacity",
translate("KCP downlinkCapacity"))
v2ray_mkcp_downlinkCapacity:depends("v2ray_transport", "mkcp")
mkcp_downlinkCapacity:depends("transport", "mkcp")
v2ray_mkcp_congestion = s:option(Flag, "v2ray_mkcp_congestion",
mkcp_congestion = s:option(Flag, "mkcp_congestion",
translate("KCP Congestion"))
v2ray_mkcp_congestion:depends("v2ray_transport", "mkcp")
mkcp_congestion:depends("transport", "mkcp")
v2ray_mkcp_readBufferSize = s:option(Value, "v2ray_mkcp_readBufferSize",
mkcp_readBufferSize = s:option(Value, "mkcp_readBufferSize",
translate("KCP readBufferSize"))
v2ray_mkcp_readBufferSize:depends("v2ray_transport", "mkcp")
mkcp_readBufferSize:depends("transport", "mkcp")
v2ray_mkcp_writeBufferSize = s:option(Value, "v2ray_mkcp_writeBufferSize",
mkcp_writeBufferSize = s:option(Value, "mkcp_writeBufferSize",
translate("KCP writeBufferSize"))
v2ray_mkcp_writeBufferSize:depends("v2ray_transport", "mkcp")
mkcp_writeBufferSize:depends("transport", "mkcp")
-- [[ WebSocket部分 ]]--
v2ray_ws_host = s:option(Value, "v2ray_ws_host", translate("WebSocket Host"))
v2ray_ws_host:depends("v2ray_transport", "ws")
v2ray_ws_host:depends("v2ray_ss_transport", "ws")
ws_host = s:option(Value, "ws_host", translate("WebSocket Host"))
ws_host:depends("transport", "ws")
ws_host:depends("ss_transport", "ws")
ws_host:depends("trojan_transport", "h2+ws")
ws_host:depends("trojan_transport", "ws")
v2ray_ws_path = s:option(Value, "v2ray_ws_path", translate("WebSocket Path"))
v2ray_ws_path:depends("v2ray_transport", "ws")
v2ray_ws_path:depends("v2ray_ss_transport", "ws")
ws_path = s:option(Value, "ws_path", translate("WebSocket Path"))
ws_path:depends("transport", "ws")
ws_path:depends("ss_transport", "ws")
ws_path:depends("trojan_transport", "h2+ws")
ws_path:depends("trojan_transport", "ws")
-- [[ HTTP/2部分 ]]--
v2ray_h2_host = s:option(DynamicList, "v2ray_h2_host", translate("HTTP/2 Host"))
v2ray_h2_host:depends("v2ray_transport", "h2")
v2ray_h2_host:depends("v2ray_ss_transport", "h2")
h2_host = s:option(Value, "h2_host", translate("HTTP/2 Host"))
h2_host:depends("transport", "h2")
h2_host:depends("ss_transport", "h2")
h2_host:depends("trojan_transport", "h2+ws")
h2_host:depends("trojan_transport", "h2")
v2ray_h2_path = s:option(Value, "v2ray_h2_path", translate("HTTP/2 Path"))
v2ray_h2_path:depends("v2ray_transport", "h2")
v2ray_h2_path:depends("v2ray_ss_transport", "h2")
h2_path = s:option(Value, "h2_path", translate("HTTP/2 Path"))
h2_path:depends("transport", "h2")
h2_path:depends("ss_transport", "h2")
h2_path:depends("trojan_transport", "h2+ws")
h2_path:depends("trojan_transport", "h2")
-- [[ DomainSocket部分 ]]--
v2ray_ds_path = s:option(Value, "v2ray_ds_path", "Path", translate(
ds_path = s:option(Value, "ds_path", "Path", translate(
"A legal file path. This file must not exist before running V2Ray."))
v2ray_ds_path:depends("v2ray_transport", "ds")
ds_path:depends("transport", "ds")
-- [[ QUIC部分 ]]--
v2ray_quic_security = s:option(ListValue, "v2ray_quic_security",
quic_security = s:option(ListValue, "quic_security",
translate("Encrypt Method"))
v2ray_quic_security:value("none")
v2ray_quic_security:value("aes-128-gcm")
v2ray_quic_security:value("chacha20-poly1305")
v2ray_quic_security:depends("v2ray_transport", "quic")
quic_security:value("none")
quic_security:value("aes-128-gcm")
quic_security:value("chacha20-poly1305")
quic_security:depends("transport", "quic")
v2ray_quic_key = s:option(Value, "v2ray_quic_key",
quic_key = s:option(Value, "quic_key",
translate("Encrypt Method") .. translate("Key"))
v2ray_quic_key:depends("v2ray_transport", "quic")
quic_key:depends("transport", "quic")
v2ray_quic_guise = s:option(ListValue, "v2ray_quic_guise",
quic_guise = s:option(ListValue, "quic_guise",
translate("Camouflage Type"))
for a, t in ipairs(v2ray_header_type_list) do v2ray_quic_guise:value(t) end
v2ray_quic_guise:depends("v2ray_transport", "quic")
for a, t in ipairs(header_type_list) do quic_guise:value(t) end
quic_guise:depends("transport", "quic")
-- [[ Trojan-Go Shadowsocks2 ]] --
ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks2"))
ss_aead:depends("type", "Trojan-Go")
ss_aead.default = "0"
ss_aead_method = s:option(ListValue, "ss_aead_method", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods_ss_aead) do ss_aead_method:value(v, v:upper()) end
ss_aead_method.default = "aead_aes_128_gcm"
ss_aead_method:depends("ss_aead", "1")
ss_aead_pwd = s:option(Value, "ss_aead_pwd", translate("Password"))
ss_aead_pwd.password = true
ss_aead_pwd:depends("ss_aead", "1")
-- [[ Mux ]]--
v2ray_mux = s:option(Flag, "v2ray_mux", translate("Mux"))
v2ray_mux:depends({ type = "V2ray", v2ray_protocol = "vmess" })
v2ray_mux:depends({ type = "V2ray", v2ray_protocol = "http" })
v2ray_mux:depends({ type = "V2ray", v2ray_protocol = "socks" })
v2ray_mux:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" })
mux = s:option(Flag, "mux", translate("Mux"))
mux:depends({ type = "V2ray", protocol = "vmess" })
mux:depends({ type = "V2ray", protocol = "http" })
mux:depends({ type = "V2ray", protocol = "socks" })
mux:depends({ type = "V2ray", protocol = "shadowsocks" })
mux:depends("type", "Trojan-Go")
v2ray_mux_concurrency = s:option(Value, "v2ray_mux_concurrency",
translate("Mux Concurrency"))
v2ray_mux_concurrency.default = 8
v2ray_mux_concurrency:depends("v2ray_mux", "1")
mux_concurrency = s:option(Value, "mux_concurrency", translate("Mux Concurrency"))
mux_concurrency.default = 8
mux_concurrency:depends("mux", "1")
-- [[ 当作为TCP节点时是否同时开启socks代理 ]]--
--[[
v2ray_tcp_socks = s:option(Flag, "v2ray_tcp_socks", translate("TCP Open Socks"),
tcp_socks = s:option(Flag, "tcp_socks", translate("TCP Open Socks"),
translate(
"When using this TCP node, whether to open the socks proxy at the same time"))
v2ray_tcp_socks.default = 0
v2ray_tcp_socks:depends("type", "V2ray")
tcp_socks.default = 0
tcp_socks:depends("type", "V2ray")
v2ray_tcp_socks_port = s:option(Value, "v2ray_tcp_socks_port",
tcp_socks_port = s:option(Value, "tcp_socks_port",
"Socks " .. translate("Port"),
translate("Do not conflict with other ports"))
v2ray_tcp_socks_port.datatype = "port"
v2ray_tcp_socks_port.default = 1080
v2ray_tcp_socks_port:depends("v2ray_tcp_socks", "1")
tcp_socks_port.datatype = "port"
tcp_socks_port.default = 1080
tcp_socks_port:depends("tcp_socks", "1")
v2ray_tcp_socks_auth = s:option(ListValue, "v2ray_tcp_socks_auth",
tcp_socks_auth = s:option(ListValue, "tcp_socks_auth",
translate("Socks for authentication"),
translate(
'Socks protocol authentication, support anonymous and password.'))
v2ray_tcp_socks_auth:value("noauth", translate("anonymous"))
v2ray_tcp_socks_auth:value("password", translate("User Password"))
v2ray_tcp_socks_auth:depends("v2ray_tcp_socks", "1")
tcp_socks_auth:value("noauth", translate("anonymous"))
tcp_socks_auth:value("password", translate("User Password"))
tcp_socks_auth:depends("tcp_socks", "1")
v2ray_tcp_socks_auth_username = s:option(Value, "v2ray_tcp_socks_auth_username",
tcp_socks_auth_username = s:option(Value, "tcp_socks_auth_username",
"Socks " .. translate("Username"))
v2ray_tcp_socks_auth_username:depends("v2ray_tcp_socks_auth", "password")
tcp_socks_auth_username:depends("tcp_socks_auth", "password")
v2ray_tcp_socks_auth_password = s:option(Value, "v2ray_tcp_socks_auth_password",
tcp_socks_auth_password = s:option(Value, "tcp_socks_auth_password",
"Socks " .. translate("Password"))
v2ray_tcp_socks_auth_password:depends("v2ray_tcp_socks_auth", "password")
tcp_socks_auth_password:depends("tcp_socks_auth", "password")
--]]
-- [[ Trojan Cert ]]--
trojan_verify_cert = s:option(Flag, "trojan_verify_cert",
translate("Trojan Verify Cert"))
trojan_verify_cert:depends("type", "Trojan")
trojan_cert_path = s:option(Value, "trojan_cert_path",
translate("Trojan Cert Path"))
trojan_cert_path.default = ""
trojan_cert_path:depends("trojan_verify_cert", "1")
protocol.validate = function(self, value)
if value == "_shunt" or value == "_balancing" then
address.rmempty = true
port.rmempty = true
end
return value
end
return m

View File

@ -72,7 +72,7 @@ if m:get("@global_other[0]", "compact_display_nodes") == "1" then
local remarks = m:get(n, "remarks") or ""
local type = m:get(n, "type") or ""
if type == "V2ray" then
local protocol = m:get(n, "v2ray_protocol")
local protocol = m:get(n, "protocol")
if protocol == "_balancing" then
type = type .. " 负载均衡"
elseif protocol == "_shunt" then
@ -111,7 +111,7 @@ else
if v then
result = translate(v)
if v == "V2ray" then
local protocol = m:get(n, "v2ray_protocol")
local protocol = m:get(n, "protocol")
if protocol == "_balancing" then
result = result .. " 负载均衡"
elseif protocol == "_shunt" then
@ -149,7 +149,7 @@ end
o.cfgvalue = function(t, n)
local type = m:get(n, "type") or ""
if type == "V2ray" then
local protocol = m:get(n, "v2ray_protocol","")
local protocol = m:get(n, "protocol","")
if protocol == "_balancing" or protocol == "_shunt" then
return "---"
end

View File

@ -165,8 +165,8 @@ local nodes_table = {}
uci:foreach(appname, "nodes", function(e)
if e.type and e.remarks then
local remarks = ""
if e.type == "V2ray" and (e.v2ray_protocol == "_balancing" or e.v2ray_protocol == "_shunt") then
remarks = "%s[%s] " % {translatef(e.type .. e.v2ray_protocol), e.remarks}
if e.type == "V2ray" and (e.protocol == "_balancing" or e.protocol == "_shunt") then
remarks = "%s[%s] " % {translatef(e.type .. e.protocol), e.remarks}
else
if e.use_kcp and e.use_kcp == "1" then
remarks = "%s+%s[%s] %s" % {e.type, "Kcptun", e.remarks, e.address}

View File

@ -69,32 +69,37 @@ s = m:section(TypedSection, "global_app", translate("App Update"),
"</font>")
s.anonymous = true
s:append(Template(appname .. "/rule/v2ray_version"))
s:append(Template(appname .. "/rule/trojan_go_version"))
s:append(Template(appname .. "/rule/kcptun_version"))
s:append(Template(appname .. "/rule/brook_version"))
---- V2ray Path
o = s:option(Value, "v2ray_file", translate("V2ray Path"), translate(
"if you want to run from memory, change the path, such as /tmp/v2ray/, Then save the application and update it manually."))
o = s:option(Value, "v2ray_file", translate("V2ray Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/v2ray/"))
o.default = "/usr/bin/v2ray/"
o.rmempty = false
---- Trojan-Go Path
o = s:option(Value, "trojan_go_file", translate("Trojan-Go Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/trojan-go"))
o.default = "/usr/bin/trojan-go"
o.rmempty = false
o = s:option(Value, "trojan_go_latest", translate("Trojan-Go Version API"), translate("alternate API URL for version checking"))
o.default = "https://api.github.com/repos/peter-tank/trojan-go/releases/latest"
---- Kcptun client Path
o = s:option(Value, "kcptun_client_file", translate("Kcptun Client Path"),
translate(
"if you want to run from memory, change the path, such as /tmp/kcptun-client, Then save the application and update it manually."))
o = s:option(Value, "kcptun_client_file", translate("Kcptun Client Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/kcptun-client"))
o.default = "/usr/bin/kcptun-client"
o.rmempty = false
--[[
o = s:option(Button, "_check_kcptun", translate("Manually update"), translate("Make sure there is enough space to install Kcptun"))
o = s:option(Button, "_check_kcptun", translate("Manually update"), translatef("Make sure there is enough space to install %s", "kcptun"))
o.template = appname .. "/kcptun"
o.inputstyle = "apply"
o.btnclick = "onBtnClick_kcptun(this);"
o.id = "_kcptun-check_btn"]] --
---- Brook Path
o = s:option(Value, "brook_file", translate("Brook Path"), translate(
"if you want to run from memory, change the path, such as /tmp/brook, Then save the application and update it manually."))
o = s:option(Value, "brook_file", translate("Brook Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/brook"))
o.default = "/usr/bin/brook"
o.rmempty = false

View File

@ -81,7 +81,7 @@ local function start()
bin = ln_start(_api.get_v2ray_path(), "v2ray", "-config=" .. config_file)
elseif type == "Trojan" then
config = require("luci.model.cbi.passwall.server.api.trojan").gen_config(user)
bin = ln_start("/usr/sbin/trojan", "trojan", "-c " .. config_file)
bin = ln_start("/usr/sbin/trojan-plus", "trojan-plus", "-c " .. config_file)
elseif type == "Brook" then
local brook_protocol = user.brook_protocol
local brook_password = user.password
@ -127,4 +127,4 @@ if action then
elseif action == "stop" then
stop()
end
end
end

View File

@ -7,7 +7,7 @@ function gen_config(user)
config.timeout = tonumber(user.timeout)
config.fast_open = (user.tcp_fast_open and user.tcp_fast_open == "true") and true or false
config.method = user.ssr_encrypt_method
config.protocol = user.protocol
config.protocol = user.ssr_protocol
config.protocol_param = user.protocol_param
config.obfs = user.obfs
config.obfs_param = user.obfs_param

View File

@ -1,28 +1,58 @@
module("luci.model.cbi.passwall.server.api.trojan", package.seeall)
function gen_config(user)
local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA"
local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"
local config = {
run_type = "server",
local_addr = "0.0.0.0",
local_port = tonumber(user.port),
remote_addr = (user.remote_enable == "1" and user.remote_address) and user.remote_address or nil,
remote_port = (user.remote_enable == "1" and user.remote_port) and user.remote_port or nil,
password = user.password,
password = { user.password },
log_level = 1,
ssl = {
(user.stream_security == nil or user.stream_security == "tls") and ssl = {
cert = user.tls_certificateFile,
key = user.tls_keyFile,
key_password = "",
cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA",
cipher_tls13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384",
prefer_server_cipher = true,
alpn = {"http/1.1"},
cipher = user.fingerprint == nil and cipher or (user.fingerprint == "disable" and cipher13 .. ":" .. cipher or ""),
cipher_tls13 = user.fingerprint == nil and cipher13 or nil,
sni = "",
verify = false,
verify_hostname = false,
reuse_session = true,
session_ticket = false,
session_ticket = (user.tls_sessionTicket == "1") and true or false,
prefer_server_cipher = true,
session_timeout = 600,
plain_http_response = "",
curves = "",
dhparam = ""
},
} or nil,
udp_timeout = 60,
disable_http_check = true,
tcp = {
mux = (user.mux == "1") and {
enabled = true,
concurrency = tonumber(user.mux_concurrency),
idle_timeout = 60,
} or nil,
transport_plugin = user.stream_security == "none" and user.trojan_transport == "original" and {
enabled = user.plugin_type ~= nil,
type = user.plugin_type or "plaintext",
command = user.plugin_type ~= "plaintext" and user.plugin_cmd or nil,
plugin_option = user.plugin_type ~= "plaintext" and user.plugin_option or nil,
arg = user.plugin_type ~= "plaintext" and { user.plugin_arg } or nil,
env = {}
} or nil,
websocket = user.trojan_transport and user.trojan_transport:find('ws') and {
enabled = true,
path = (user.ws_path ~= nil) and user.ws_path or "/",
hostname = (user.ws_host ~= nil) and user.ws_host or (user.tls_serverName ~= nil and user.tls_serverName or user.address)
} or nil,
shadowsocks = (user.ss_aead == "1") and {
enabled = true,
method = (user.ss_aead_method ~= nil) and user.ss_aead_method or "aead_aes_128_gcm",
password = (user.ss_aead_pwd ~= nil) and user.ss_aead_pwd or ""
} or nil,
tcp = {
prefer_ipv4 = false,
no_delay = true,

View File

@ -8,19 +8,19 @@ function gen_config(user)
{protocol = "freedom"}, {protocol = "blackhole", tag = "blocked"}
}
if user.v2ray_protocol == "vmess" then
if user.protocol == "vmess" then
if user.vmess_id then
local clients = {}
for i = 1, #user.vmess_id do
clients[i] = {
id = user.vmess_id[i],
level = tonumber(user.vmess_level),
alterId = tonumber(user.vmess_alterId)
alterId = tonumber(user.alter_id)
}
end
settings = {clients = clients}
end
elseif user.v2ray_protocol == "socks" then
elseif user.protocol == "socks" then
settings = {
auth = (user.username == nil and user.password == nil) and "noauth" or "password",
accounts = {
@ -30,7 +30,7 @@ function gen_config(user)
}
}
}
elseif user.v2ray_protocol == "http" then
elseif user.protocol == "http" then
settings = {
allowTransparent = false,
accounts = {
@ -40,13 +40,13 @@ function gen_config(user)
}
}
}
elseif user.v2ray_protocol == "shadowsocks" then
elseif user.protocol == "shadowsocks" then
settings = {
method = user.v2ray_ss_encrypt_method,
method = user.ss_encrypt_method,
password = user.password,
level = tonumber(user.vmess_level) or 1,
network = user.v2ray_ss_network or "TCP,UDP",
ota = (user.v2ray_ss_ota == '1') and true or false
network = user.ss_network or "TCP,UDP",
ota = (user.ss_ota == '1') and true or false
}
end
@ -68,84 +68,83 @@ function gen_config(user)
if node and node ~= "nil" and node.type and node.type == "V2ray" then
local transit_node = {
tag = "transit",
protocol = node.v2ray_protocol or "vmess",
protocol = node.protocol or "vmess",
mux = {
enabled = (node.v2ray_mux == "1") and true or false,
concurrency = (node.v2ray_mux_concurrency) and
tonumber(node.v2ray_mux_concurrency) or 8
enabled = (node.mux == "1") and true or false,
concurrency = (node.mux_concurrency) and tonumber(node.mux_concurrency) or 8
},
-- 底层传输配置
streamSettings = (node.v2ray_protocol == "vmess") and {
network = node.v2ray_transport,
security = node.v2ray_stream_security,
tlsSettings = (node.v2ray_stream_security == "tls") and {
streamSettings = (node.protocol == "vmess") and {
network = node.transport,
security = node.stream_security,
tlsSettings = (node.stream_security == "tls") and {
disableSessionResumption = node.sessionTicket ~= "1" and true or false,
serverName = node.tls_serverName,
allowInsecure = (node.tls_allowInsecure == "1") and true or
false
} or nil,
tcpSettings = (node.v2ray_transport == "tcp") and {
tcpSettings = (node.transport == "tcp") and {
header = {
type = node.v2ray_tcp_guise,
type = node.tcp_guise,
request = {
path = node.v2ray_tcp_guise_http_path or {"/"},
path = node.tcp_guise_http_path or {"/"},
headers = {
Host = node.v2ray_tcp_guise_http_host or {}
Host = node.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),
uplinkCapacity = tonumber(node.v2ray_mkcp_uplinkCapacity),
kcpSettings = (node.transport == "mkcp") and {
mtu = tonumber(node.mkcp_mtu),
tti = tonumber(node.mkcp_tti),
uplinkCapacity = tonumber(node.mkcp_uplinkCapacity),
downlinkCapacity = tonumber(
node.v2ray_mkcp_downlinkCapacity),
congestion = (node.v2ray_mkcp_congestion == "1") and
node.mkcp_downlinkCapacity),
congestion = (node.mkcp_congestion == "1") and
true or false,
readBufferSize = tonumber(node.v2ray_mkcp_readBufferSize),
readBufferSize = tonumber(node.mkcp_readBufferSize),
writeBufferSize = tonumber(
node.v2ray_mkcp_writeBufferSize),
header = {type = node.v2ray_mkcp_guise}
node.mkcp_writeBufferSize),
header = {type = node.mkcp_guise}
} or nil,
wsSettings = (node.v2ray_transport == "ws") and {
path = node.v2ray_ws_path or "",
headers = (node.v2ray_ws_host ~= nil) and
{Host = node.v2ray_ws_host} or nil
wsSettings = (node.transport == "ws") and {
path = node.ws_path or "",
headers = (node.ws_host ~= nil) and
{Host = node.ws_host} or nil
} or nil,
httpSettings = (node.v2ray_transport == "h2") and
{path = node.v2ray_h2_path, host = node.v2ray_h2_host} or
httpSettings = (node.transport == "h2") and
{path = node.h2_path, host = node.h2_host} or
nil,
dsSettings = (node.v2ray_transport == "ds") and
{path = node.v2ray_ds_path} or nil,
quicSettings = (node.v2ray_transport == "quic") and {
security = node.v2ray_quic_security,
key = node.v2ray_quic_key,
header = {type = node.v2ray_quic_guise}
dsSettings = (node.transport == "ds") and
{path = node.ds_path} or nil,
quicSettings = (node.transport == "quic") and {
security = node.quic_security,
key = node.quic_key,
header = {type = node.quic_guise}
} or nil
} or nil,
settings = {
vnext = (node.v2ray_protocol == "vmess") and {
vnext = (node.protocol == "vmess") and {
{
address = node.address,
port = tonumber(node.port),
users = {
{
id = node.v2ray_VMess_id,
alterId = tonumber(node.v2ray_VMess_alterId),
level = tonumber(node.v2ray_VMess_level),
security = node.v2ray_security
id = node.vmess_id,
alterId = tonumber(node.alter_id),
level = tonumber(node.vmess_level),
security = node.security
}
}
}
} or nil,
servers = (node.v2ray_protocol == "http" or
node.v2ray_protocol == "socks" or node.v2ray_protocol == "shadowsocks") and {
servers = (node.protocol == "http" or node.protocol == "socks" or node.protocol == "shadowsocks") and {
{
address = node.address,
port = tonumber(node.port),
method = node.v2ray_ss_encrypt_method,
method = node.v_ss_encrypt_method,
password = node.password or "",
ota = (node.v2ray_ss_ota == '1') and true or false,
ota = (node.ss_ota == '1') and true or false,
users = (node.username and node.password) and
{
{
@ -171,13 +170,14 @@ function gen_config(user)
{
listen = (user.bind_local == "1") and "127.0.0.1" or nil,
port = tonumber(user.port),
protocol = user.v2ray_protocol,
protocol = user.protocol,
-- 底层传输配置
settings = settings,
streamSettings = (user.v2ray_protocol == "vmess") and {
network = user.v2ray_transport,
security = (user.tls_enable == '1') and "tls" or "none",
tlsSettings = (user.tls_enable == '1') and {
streamSettings = (user.protocol == "vmess") and {
network = user.transport,
security = (user.stream_security == 'tls') and "tls" or "none",
tlsSettings = (user.stream_security == 'tls') and {
disableSessionResumption = user.sessionTicket ~= "1" and true or false,
-- serverName = (user.tls_serverName),
allowInsecure = false,
disableSystemRoot = false,
@ -188,41 +188,41 @@ function gen_config(user)
}
}
} or nil,
tcpSettings = (user.v2ray_transport == "tcp") and {
tcpSettings = (user.transport == "tcp") and {
header = {
type = user.v2ray_tcp_guise,
type = user.tcp_guise,
request = {
path = user.v2ray_tcp_guise_http_path or {"/"},
path = user.tcp_guise_http_path or {"/"},
headers = {
Host = user.v2ray_tcp_guise_http_host or {}
Host = user.tcp_guise_http_host or {}
}
} or {}
}
} or nil,
kcpSettings = (user.v2ray_transport == "mkcp") and {
mtu = tonumber(user.v2ray_mkcp_mtu),
tti = tonumber(user.v2ray_mkcp_tti),
uplinkCapacity = tonumber(user.v2ray_mkcp_uplinkCapacity),
downlinkCapacity = tonumber(user.v2ray_mkcp_downlinkCapacity),
congestion = (user.v2ray_mkcp_congestion == "1") and true or false,
readBufferSize = tonumber(user.v2ray_mkcp_readBufferSize),
writeBufferSize = tonumber(user.v2ray_mkcp_writeBufferSize),
header = {type = user.v2ray_mkcp_guise}
kcpSettings = (user.transport == "mkcp") and {
mtu = tonumber(user.mkcp_mtu),
tti = tonumber(user.mkcp_tti),
uplinkCapacity = tonumber(user.mkcp_uplinkCapacity),
downlinkCapacity = tonumber(user.mkcp_downlinkCapacity),
congestion = (user.mkcp_congestion == "1") and true or false,
readBufferSize = tonumber(user.mkcp_readBufferSize),
writeBufferSize = tonumber(user.mkcp_writeBufferSize),
header = {type = user.mkcp_guise}
} or nil,
wsSettings = (user.v2ray_transport == "ws") and
wsSettings = (user.transport == "ws") and
{
headers = (user.v2ray_ws_host) and {Host = user.v2ray_ws_host} or
headers = (user.ws_host) and {Host = user.ws_host} or
nil,
path = user.v2ray_ws_path
path = user.ws_path
} or nil,
httpSettings = (user.v2ray_transport == "h2") and
{path = user.v2ray_h2_path, host = user.v2ray_h2_host} or nil,
dsSettings = (user.v2ray_transport == "ds") and
{path = user.v2ray_ds_path} or nil,
quicSettings = (user.v2ray_transport == "quic") and {
security = user.v2ray_quic_security,
key = user.v2ray_quic_key,
header = {type = user.v2ray_quic_guise}
httpSettings = (user.transport == "h2") and
{path = user.h2_path, host = user.h2_host} or nil,
dsSettings = (user.transport == "ds") and
{path = user.ds_path} or nil,
quicSettings = (user.transport == "quic") and {
security = user.quic_security,
key = user.quic_key,
header = {type = user.quic_guise}
} or nil
} or nil
}

View File

@ -31,14 +31,24 @@ local ssr_obfs_list = {
"tls1.0_session_auth", "tls1.2_ticket_auth"
}
local v2ray_ss_encrypt_method_list = {
local v_ss_encrypt_method_list = {
"aes-128-cfb", "aes-256-cfb", "aes-128-gcm", "aes-256-gcm", "chacha20", "chacha20-ietf", "chacha20-poly1305", "chacha20-ietf-poly1305"
}
local v2ray_header_type_list = {
local header_type_list = {
"none", "srtp", "utp", "wechat-video", "dtls", "wireguard"
}
local encrypt_methods_ss_aead = {
"dummy",
"aead_chacha20_poly1305",
"aead_aes_128_gcm",
"aead_aes_256_gcm",
"chacha20-ietf-poly1305",
"aes-128-gcm",
"aes-256-gcm",
}
map = Map("passwall_server", translate("Server Config"))
map.redirect = d.build_url("admin", "vpn", "passwall", "server")
@ -64,16 +74,19 @@ end
if is_installed("brook") or is_finded("brook") then
type:value("Brook", translate("Brook"))
end
if is_installed("trojan") or is_finded("trojan") then
type:value("Trojan", translate("Trojan"))
if is_installed("trojan-plus") or is_finded("trojan-plus") then
type:value("Trojan", translate("Trojan-Plus"))
end
if is_installed("trojan-go") or is_finded("trojan-go") then
type:value("Trojan-Go", translate("Trojan-Go"))
end
v2ray_protocol = s:option(ListValue, "v2ray_protocol", translate("Protocol"))
v2ray_protocol:value("vmess", translate("Vmess"))
v2ray_protocol:value("http", translate("HTTP"))
v2ray_protocol:value("socks", translate("Socks"))
v2ray_protocol:value("shadowsocks", translate("Shadowsocks"))
v2ray_protocol:depends("type", "V2ray")
protocol = s:option(ListValue, "protocol", translate("Protocol"))
protocol:value("vmess", translate("Vmess"))
protocol:value("http", translate("HTTP"))
protocol:value("socks", translate("Socks"))
protocol:value("shadowsocks", translate("Shadowsocks"))
protocol:depends("type", "V2ray")
-- Brook协议
brook_protocol = s:option(ListValue, "brook_protocol",
@ -89,51 +102,53 @@ port = s:option(Value, "port", translate("Port"))
port.datatype = "port"
port.rmempty = false
port:depends("type", "SSR")
port:depends({ type = "V2ray", v2ray_protocol = "vmess" })
port:depends({ type = "V2ray", v2ray_protocol = "http" })
port:depends({ type = "V2ray", v2ray_protocol = "socks" })
port:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" })
port:depends({ type = "V2ray", protocol = "vmess" })
port:depends({ type = "V2ray", protocol = "http" })
port:depends({ type = "V2ray", protocol = "socks" })
port:depends({ type = "V2ray", protocol = "shadowsocks" })
port:depends("type", "Brook")
port:depends("type", "Trojan")
port:depends("type", "Trojan-Go")
username = s:option(Value, "username", translate("Username"))
username:depends("v2ray_protocol", "http")
username:depends("v2ray_protocol", "socks")
username:depends("protocol", "http")
username:depends("protocol", "socks")
password = s:option(Value, "password", translate("Password"))
password.password = true
password:depends("type", "SSR")
password:depends("type", "Brook")
password:depends("type", "Trojan")
password:depends({ type = "V2ray", v2ray_protocol = "http" })
password:depends({ type = "V2ray", v2ray_protocol = "socks" })
password:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" })
password:depends("type", "Trojan-Go")
password:depends({ type = "V2ray", protocol = "http" })
password:depends({ type = "V2ray", protocol = "socks" })
password:depends({ type = "V2ray", protocol = "shadowsocks" })
ssr_encrypt_method = s:option(ListValue, "ssr_encrypt_method", translate("Encrypt Method"))
for a, t in ipairs(ssr_encrypt_method_list) do ssr_encrypt_method:value(t) end
ssr_encrypt_method:depends("type", "SSR")
v2ray_ss_encrypt_method = s:option(ListValue, "v2ray_ss_encrypt_method", translate("Encrypt Method"))
for a, t in ipairs(v2ray_ss_encrypt_method_list) do v2ray_ss_encrypt_method:value(t) end
v2ray_ss_encrypt_method:depends("v2ray_protocol", "shadowsocks")
v_ss_encrypt_method = s:option(ListValue, "v_ss_encrypt_method", translate("Encrypt Method"))
for a, t in ipairs(v_ss_encrypt_method_list) do v_ss_encrypt_method:value(t) end
v_ss_encrypt_method:depends("protocol", "shadowsocks")
v2ray_ss_network = s:option(ListValue, "v2ray_ss_network", translate("Transport"))
v2ray_ss_network.default = "tcp,udp"
v2ray_ss_network:value("tcp", "TCP")
v2ray_ss_network:value("udp", "UDP")
v2ray_ss_network:value("tcp,udp", "TCP,UDP")
v2ray_ss_network:depends("v2ray_protocol", "shadowsocks")
ss_network = s:option(ListValue, "ss_network", translate("Transport"))
ss_network.default = "tcp,udp"
ss_network:value("tcp", "TCP")
ss_network:value("udp", "UDP")
ss_network:value("tcp,udp", "TCP,UDP")
ss_network:depends("protocol", "shadowsocks")
v2ray_ss_ota = s:option(Flag, "v2ray_ss_ota", translate("OTA"), translate("When OTA is enabled, V2Ray will reject connections that are not OTA enabled. This option is invalid when using AEAD encryption."))
v2ray_ss_ota.default = "0"
v2ray_ss_ota:depends("v2ray_protocol", "shadowsocks")
ss_ota = s:option(Flag, "ss_ota", translate("OTA"), translate("When OTA is enabled, V2Ray will reject connections that are not OTA enabled. This option is invalid when using AEAD encryption."))
ss_ota.default = "0"
ss_ota:depends("protocol", "shadowsocks")
protocol = s:option(ListValue, "protocol", translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do protocol:value(t) end
protocol:depends("type", "SSR")
ssr_protocol = s:option(ListValue, "ssr_protocol", translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do ssr_protocol:value(t) end
ssr_protocol:depends("type", "SSR")
protocol_param = s:option(Value, "protocol_param", translate("Protocol_param"))
protocol_param:depends("type", "SSR")
ssr_protocol_param = s:option(Value, "protocol_param", translate("Protocol_param"))
ssr_protocol_param:depends("type", "SSR")
obfs = s:option(ListValue, "obfs", translate("Obfs"))
for a, t in ipairs(ssr_obfs_list) do obfs:value(t) end
@ -152,6 +167,7 @@ tcp_fast_open:value("false")
tcp_fast_open:value("true")
tcp_fast_open:depends("type", "SSR")
tcp_fast_open:depends("type", "Trojan")
tcp_fast_open:depends("type", "Trojan-Go")
udp_forward = s:option(Flag, "udp_forward", translate("UDP Forward"))
udp_forward.default = "1"
@ -163,107 +179,169 @@ for i = 1, 3 do
local uuid = luci.sys.exec("echo -n $(cat /proc/sys/kernel/random/uuid)")
vmess_id:value(uuid)
end
vmess_id:depends({ type = "V2ray", v2ray_protocol = "vmess" })
vmess_id:depends({ type = "V2ray", protocol = "vmess" })
vmess_alterId = s:option(Value, "vmess_alterId", translate("Alter ID"))
vmess_alterId.default = 16
vmess_alterId:depends({ type = "V2ray", v2ray_protocol = "vmess" })
alter_id = s:option(Value, "alter_id", translate("Alter ID"))
alter_id.default = 16
alter_id:depends({ type = "V2ray", protocol = "vmess" })
vmess_level = s:option(Value, "vmess_level", translate("User Level"))
vmess_level.default = 1
vmess_level:depends({ type = "V2ray", v2ray_protocol = "vmess" })
vmess_level:depends({ type = "V2ray", v2ray_protocol = "shadowsocks" })
vmess_level:depends({ type = "V2ray", protocol = "vmess" })
vmess_level:depends({ type = "V2ray", protocol = "shadowsocks" })
v2ray_transport = s:option(ListValue, "v2ray_transport", translate("Transport"))
v2ray_transport:value("tcp", "TCP")
v2ray_transport:value("mkcp", "mKCP")
v2ray_transport:value("ws", "WebSocket")
v2ray_transport:value("h2", "HTTP/2")
v2ray_transport:value("ds", "DomainSocket")
v2ray_transport:value("quic", "QUIC")
v2ray_transport:depends("v2ray_protocol", "vmess")
stream_security = s:option(ListValue, "stream_security",
translate("Transport Layer Encryption"),
translate(
'Whether or not transport layer encryption is enabled, the supported options are "none" for unencrypted (default) and "TLS" for using TLS.'))
stream_security:value("none", "none")
stream_security:value("tls", "tls")
stream_security.default = "tls"
stream_security:depends({ type = "V2ray", protocol = "vmess", transport = "ws" })
stream_security:depends({ type = "V2ray", protocol = "vmess", transport = "h2" })
stream_security:depends("protocol", "shadowsocks")
stream_security:depends("type", "Trojan-Go")
-- [[ TLS部分 ]] --
tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket"))
tls_sessionTicket.default = "0"
tls_sessionTicket:depends("stream_security", "tls")
tls_certificateFile = s:option(Value, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
tls_certificateFile:depends("stream_security", "tls")
tls_keyFile = s:option(Value, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
tls_keyFile:depends("stream_security", "tls")
transport = s:option(ListValue, "transport", translate("Transport"))
transport:value("tcp", "TCP")
transport:value("mkcp", "mKCP")
transport:value("ws", "WebSocket")
transport:value("h2", "HTTP/2")
transport:value("ds", "DomainSocket")
transport:value("quic", "QUIC")
transport:depends("protocol", "vmess")
trojan_transport = s:option(ListValue, "trojan_transport", translate("Transport"))
trojan_transport:value("original", "Original")
trojan_transport:value("ws", "WebSocket")
trojan_transport:value("h2", "HTTP/2")
trojan_transport:value("h2+ws", "HTTP/2 & WebSocket")
trojan_transport.default = "ws"
trojan_transport:depends("type", "Trojan-Go")
trojan_plugin = s:option(ListValue, "plugin_type", translate("Plugin Type"))
trojan_plugin:value("plaintext", "Plain Text")
trojan_plugin:value("shadowsocks", "ShadowSocks")
trojan_plugin:value("other", "Other")
trojan_plugin.default = "plaintext"
trojan_plugin:depends({ stream_security = "none", trojan_transport = "original" })
trojan_plugin_cmd = s:option(Value, "plugin_cmd", translate("Plugin Binary"))
trojan_plugin_cmd.placeholder = "eg: /usr/bin/v2ray-plugin"
trojan_plugin_cmd:depends({ plugin_type = "shadowsocks" })
trojan_plugin_cmd:depends({ plugin_type = "other" })
trojan_plugin_op = s:option(Value, "plugin_option", translate("Plugin Option"))
trojan_plugin_op.placeholder = "eg: obfs=http;obfs-host=www.baidu.com"
trojan_plugin_op:depends({ plugin_type = "shadowsocks" })
trojan_plugin_op:depends({ plugin_type = "other" })
trojan_plugin_arg = s:option(DynamicList, "plugin_arg", translate("Plugin Option Args"))
trojan_plugin_arg.placeholder = "eg: [\"-config\", \"test.json\"]"
trojan_plugin_arg:depends({ plugin_type = "shadowsocks" })
trojan_plugin_arg:depends({ plugin_type = "other" })
-- [[ TCP部分 ]]--
-- TCP伪装
v2ray_tcp_guise = s:option(ListValue, "v2ray_tcp_guise", translate("Camouflage Type"))
v2ray_tcp_guise:value("none", "none")
v2ray_tcp_guise:value("http", "http")
v2ray_tcp_guise:depends("v2ray_transport", "tcp")
tcp_guise = s:option(ListValue, "tcp_guise", translate("Camouflage Type"))
tcp_guise:value("none", "none")
tcp_guise:value("http", "http")
tcp_guise:depends("transport", "tcp")
-- HTTP域名
v2ray_tcp_guise_http_host = s:option(DynamicList, "v2ray_tcp_guise_http_host", translate("HTTP Host"))
v2ray_tcp_guise_http_host:depends("v2ray_tcp_guise", "http")
tcp_guise_http_host = s:option(DynamicList, "tcp_guise_http_host", translate("HTTP Host"))
tcp_guise_http_host:depends("tcp_guise", "http")
-- HTTP路径
v2ray_tcp_guise_http_path = s:option(DynamicList, "v2ray_tcp_guise_http_path", translate("HTTP Path"))
v2ray_tcp_guise_http_path:depends("v2ray_tcp_guise", "http")
tcp_guise_http_path = s:option(DynamicList, "tcp_guise_http_path", translate("HTTP Path"))
tcp_guise_http_path:depends("tcp_guise", "http")
-- [[ mKCP部分 ]]--
v2ray_mkcp_guise = s:option(ListValue, "v2ray_mkcp_guise", translate("Camouflage Type"), translate('<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
for a, t in ipairs(v2ray_header_type_list) do v2ray_mkcp_guise:value(t) end
v2ray_mkcp_guise:depends("v2ray_transport", "mkcp")
mkcp_guise = s:option(ListValue, "mkcp_guise", translate("Camouflage Type"), translate('<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
for a, t in ipairs(header_type_list) do mkcp_guise:value(t) end
mkcp_guise:depends("transport", "mkcp")
v2ray_mkcp_mtu = s:option(Value, "v2ray_mkcp_mtu", translate("KCP MTU"))
v2ray_mkcp_mtu:depends("v2ray_transport", "mkcp")
mkcp_mtu = s:option(Value, "mkcp_mtu", translate("KCP MTU"))
mkcp_mtu:depends("transport", "mkcp")
v2ray_mkcp_tti = s:option(Value, "v2ray_mkcp_tti", translate("KCP TTI"))
v2ray_mkcp_tti:depends("v2ray_transport", "mkcp")
mkcp_tti = s:option(Value, "mkcp_tti", translate("KCP TTI"))
mkcp_tti:depends("transport", "mkcp")
v2ray_mkcp_uplinkCapacity = s:option(Value, "v2ray_mkcp_uplinkCapacity", translate("KCP uplinkCapacity"))
v2ray_mkcp_uplinkCapacity:depends("v2ray_transport", "mkcp")
mkcp_uplinkCapacity = s:option(Value, "mkcp_uplinkCapacity", translate("KCP uplinkCapacity"))
mkcp_uplinkCapacity:depends("transport", "mkcp")
v2ray_mkcp_downlinkCapacity = s:option(Value, "v2ray_mkcp_downlinkCapacity", translate("KCP downlinkCapacity"))
v2ray_mkcp_downlinkCapacity:depends("v2ray_transport", "mkcp")
mkcp_downlinkCapacity = s:option(Value, "mkcp_downlinkCapacity", translate("KCP downlinkCapacity"))
mkcp_downlinkCapacity:depends("transport", "mkcp")
v2ray_mkcp_congestion = s:option(Flag, "v2ray_mkcp_congestion", translate("KCP Congestion"))
v2ray_mkcp_congestion:depends("v2ray_transport", "mkcp")
mkcp_congestion = s:option(Flag, "mkcp_congestion", translate("KCP Congestion"))
mkcp_congestion:depends("transport", "mkcp")
v2ray_mkcp_readBufferSize = s:option(Value, "v2ray_mkcp_readBufferSize", translate("KCP readBufferSize"))
v2ray_mkcp_readBufferSize:depends("v2ray_transport", "mkcp")
mkcp_readBufferSize = s:option(Value, "mkcp_readBufferSize", translate("KCP readBufferSize"))
mkcp_readBufferSize:depends("transport", "mkcp")
v2ray_mkcp_writeBufferSize = s:option(Value, "v2ray_mkcp_writeBufferSize", translate("KCP writeBufferSize"))
v2ray_mkcp_writeBufferSize:depends("v2ray_transport", "mkcp")
mkcp_writeBufferSize = s:option(Value, "mkcp_writeBufferSize", translate("KCP writeBufferSize"))
mkcp_writeBufferSize:depends("transport", "mkcp")
-- [[ WebSocket部分 ]]--
v2ray_ws_host = s:option(Value, "v2ray_ws_host", translate("WebSocket Host"))
v2ray_ws_host:depends("v2ray_transport", "ws")
v2ray_ws_host:depends("v2ray_ss_transport", "ws")
ws_host = s:option(Value, "ws_host", translate("WebSocket Host"))
ws_host:depends("transport", "ws")
ws_host:depends("ss_transport", "ws")
ws_host:depends("trojan_transport", "h2+ws")
ws_host:depends("trojan_transport", "ws")
v2ray_ws_path = s:option(Value, "v2ray_ws_path", translate("WebSocket Path"))
v2ray_ws_path:depends("v2ray_transport", "ws")
v2ray_ws_path:depends("v2ray_ss_transport", "ws")
ws_path = s:option(Value, "ws_path", translate("WebSocket Path"))
ws_path:depends("transport", "ws")
ws_path:depends("ss_transport", "ws")
ws_path:depends("trojan_transport", "h2+ws")
ws_path:depends("trojan_transport", "ws")
-- [[ HTTP/2部分 ]]--
v2ray_h2_host = s:option(DynamicList, "v2ray_h2_host", translate("HTTP/2 Host"))
v2ray_h2_host:depends("v2ray_transport", "h2")
v2ray_h2_host:depends("v2ray_ss_transport", "h2")
h2_host = s:option(Value, "h2_host", translate("HTTP/2 Host"))
h2_host:depends("transport", "h2")
h2_host:depends("ss_transport", "h2")
h2_host:depends("trojan_transport", "h2+ws")
h2_host:depends("trojan_transport", "h2")
v2ray_h2_path = s:option(Value, "v2ray_h2_path", translate("HTTP/2 Path"))
v2ray_h2_path:depends("v2ray_transport", "h2")
v2ray_h2_path:depends("v2ray_ss_transport", "h2")
h2_path = s:option(Value, "h2_path", translate("HTTP/2 Path"))
h2_path:depends("transport", "h2")
h2_path:depends("ss_transport", "h2")
h2_path:depends("trojan_transport", "h2+ws")
h2_path:depends("trojan_transport", "h2")
-- [[ DomainSocket部分 ]]--
v2ray_ds_path = s:option(Value, "v2ray_ds_path", "Path", translate("A legal file path. This file must not exist before running V2Ray."))
v2ray_ds_path:depends("v2ray_transport", "ds")
ds_path = s:option(Value, "ds_path", "Path", translate("A legal file path. This file must not exist before running V2Ray."))
ds_path:depends("transport", "ds")
-- [[ QUIC部分 ]]--
v2ray_quic_security = s:option(ListValue, "v2ray_quic_security", translate("Encrypt Method"))
v2ray_quic_security:value("none")
v2ray_quic_security:value("aes-128-gcm")
v2ray_quic_security:value("chacha20-poly1305")
v2ray_quic_security:depends("v2ray_transport", "quic")
quic_security = s:option(ListValue, "quic_security", translate("Encrypt Method"))
quic_security:value("none")
quic_security:value("aes-128-gcm")
quic_security:value("chacha20-poly1305")
quic_security:depends("transport", "quic")
v2ray_quic_key = s:option(Value, "v2ray_quic_key", translate("Encrypt Method") .. translate("Key"))
v2ray_quic_key:depends("v2ray_transport", "quic")
quic_key = s:option(Value, "quic_key", translate("Encrypt Method") .. translate("Key"))
quic_key:depends("transport", "quic")
v2ray_quic_guise = s:option(ListValue, "v2ray_quic_guise", translate("Camouflage Type"))
for a, t in ipairs(v2ray_header_type_list) do v2ray_quic_guise:value(t) end
v2ray_quic_guise:depends("v2ray_transport", "quic")
quic_guise = s:option(ListValue, "quic_guise", translate("Camouflage Type"))
for a, t in ipairs(header_type_list) do quic_guise:value(t) end
quic_guise:depends("transport", "quic")
remote_enable = s:option(Flag, "remote_enable", translate("Enable Remote"),translate("You can forward to Nginx/Caddy/V2ray WebSocket and more."))
remote_enable.default = "1"
@ -279,20 +357,28 @@ remote_port.datatype = "port"
remote_port.default = "80"
remote_port:depends("remote_enable", 1)
-- [[ TLS部分 ]] --
tls_enable = s:option(Flag, "tls_enable", "TLS/SSL")
tls_enable:depends({ type = "V2ray", v2ray_protocol = "vmess", v2ray_transport = "ws" })
tls_enable:depends({ type = "V2ray", v2ray_protocol = "vmess", v2ray_transport = "h2" })
tls_enable.default = "0"
tls_enable.rmempty = false
ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks2"))
ss_aead:depends("type", "Trojan-Go")
ss_aead.default = "0"
tls_certificateFile = s:option(Value, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
tls_certificateFile:depends("tls_enable", 1)
tls_certificateFile:depends("type", "Trojan")
ss_aead_method = s:option(ListValue, "ss_aead_method", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods_ss_aead) do ss_aead_method:value(v, v:upper()) end
ss_aead_method.default = "aead_aes_128_gcm"
ss_aead_method.rmempty = false
ss_aead_method:depends("ss_aead", "1")
tls_keyFile = s:option(Value, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
tls_keyFile:depends("tls_enable", 1)
tls_keyFile:depends("type", "Trojan")
ss_aead_pwd = s:option(Value, "ss_aead_pwd", translate("Password"))
ss_aead_pwd.password = true
ss_aead_pwd.rmempty = false
ss_aead_pwd:depends("ss_aead", "1")
-- [[ Mux ]]--
mux = s:option(Flag, "mux", translate("Mux"))
mux_concurrency = s:option(Value, "mux_concurrency",
translate("Mux Concurrency"))
mux_concurrency.default = 8
mux_concurrency:depends("mux", "1")
local nodes_table = {}
uci:foreach("passwall", "nodes", function(e)

File diff suppressed because one or more lines are too long

View File

@ -209,7 +209,8 @@ local status_show_ip111 = api.uci_get_type("global_other", "status_show_ip111",
text += '<font color="red" size="3"> X</font>';
}
}
kcptun_tcp_node_status.innerHTML = text;
if(kcptun_tcp_node_status)
kcptun_tcp_node_status.innerHTML = text;
}
}

View File

@ -1,11 +1,7 @@
<%
local dsp = require "luci.dispatcher"
-%>
<p id="_status"></p>
<script type="text/javascript">//<![CDATA[
XHR.poll(3,'<%=dsp.build_url("admin/vpn/passwall/status")%>', null,
XHR.poll(3, '<%=url([[admin]], [[vpn]], [[passwall]], [[status]])%>', null,
function(x, json) {
if (x && x.status == 200) {
var _status = document.getElementById('_status');

View File

@ -1,11 +1,7 @@
<%
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">
//<![CDATA[
function clearlog(btn) {
XHR.get('<%=dsp.build_url("admin/vpn/passwall/clear_log")%>', null,
XHR.get('<%=url([[admin]], [[vpn]], [[passwall]], [[clear_log]])%>', null,
function(x, data) {
if(x && x.status == 200) {
var log_textarea = document.getElementById('log_textarea');
@ -15,7 +11,7 @@ local dsp = require "luci.dispatcher"
}
);
}
XHR.poll(2, '<%=dsp.build_url("admin/vpn/passwall/get_log")%>', null,
XHR.poll(2, '<%=url([[admin]], [[vpn]], [[passwall]], [[get_log]])%>', null,
function(x, data) {
if(x && x.status == 200) {
var log_textarea = document.getElementById('log_textarea');

View File

@ -1,13 +1,9 @@
<%
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">
//<![CDATA[
var _status = document.getElementsByClassName('_status');
for (var i = 0; i < _status.length; i++) {
var id = _status[i].getAttribute("socks_id");
XHR.get('<%=dsp.build_url("admin/vpn/passwall/socks_status")%>', {
XHR.get('<%=url([[admin]], [[vpn]], [[passwall]], [[socks_status]])%>', {
index: i,
id: id
},

View File

@ -1,8 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local dsp = require "luci.dispatcher"
local brook_version = api.get_brook_version()
local brook_version = require "luci.model.cbi.passwall.api.api".get_brook_version()
-%>
<script type="text/javascript">
@ -74,7 +71,7 @@ local brook_version = api.get_brook_version()
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=dsp.build_url("admin/vpn/passwall/brook_check")%>', {
XHR.get('<%=url([[admin]], [[vpn]], [[passwall]], [[brook_check]])%>', {
token: tokenStr,
arch: ''
}, function(x,json) {
@ -114,7 +111,7 @@ local brook_version = api.get_brook_version()
addPageNotice_brook();
var brookUpdateUrl = '<%=dsp.build_url("admin/vpn/passwall/brook_update")%>';
var brookUpdateUrl = '<%=url([[admin]], [[vpn]], [[passwall]], [[brook_update]])%>';
// Download file
XHR.get(brookUpdateUrl, {
token: tokenStr,
@ -150,7 +147,7 @@ local brook_version = api.get_brook_version()
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<span><%=brook_version%>】</span>
<span><%=brook_version%> </span>
<input class="cbi-button cbi-input-apply" type="button" id="_brook-check_btn" onclick="onBtnClick_brook(this);" value="<%:Manually update%>" />
<span id="_brook-check_btn-detail"></span>
</div>

View File

@ -1,8 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local dsp = require "luci.dispatcher"
local kcptun_version = api.get_kcptun_version()
local kcptun_version = require "luci.model.cbi.passwall.api.api".get_kcptun_version()
-%>
<script type="text/javascript">
@ -74,7 +71,7 @@ local kcptun_version = api.get_kcptun_version()
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=dsp.build_url("admin/vpn/passwall/kcptun_check")%>', {
XHR.get('<%=url([[admin]], [[vpn]], [[passwall]], [[kcptun_check]])%>', {
token: tokenStr,
arch: ''
}, function(x,json) {
@ -114,7 +111,7 @@ local kcptun_version = api.get_kcptun_version()
addPageNotice_kcptun();
var kcptunUpdateUrl = '<%=dsp.build_url("admin/vpn/passwall/kcptun_update")%>';
var kcptunUpdateUrl = '<%=url([[admin]], [[vpn]], [[passwall]], [[kcptun_update]])%>';
// Download file
XHR.get(kcptunUpdateUrl, {
token: tokenStr,
@ -166,7 +163,7 @@ local kcptun_version = api.get_kcptun_version()
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<span><%=kcptun_version%>】</span>
<span><%=kcptun_version%> </span>
<input class="cbi-button cbi-input-apply" type="button" id="_kcptun-check_btn" onclick="onBtnClick_kcptun(this);" value="<%:Manually update%>" />
<span id="_kcptun-check_btn-detail"></span>
</div>

View File

@ -1,6 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local dsp = require "luci.dispatcher"
local gfwlist_version = api.uci_get_type("global_rules", "gfwlist_version")
local chnroute_version = api.uci_get_type("global_rules", "chnroute_version")
@ -26,12 +25,12 @@ local chnlist_update = api.uci_get_type("global_rules", "chnlist_update", "1") =
checkBoxList.push(dom.name);  
}
}
XHR.get('<%=dsp.build_url("admin/vpn/passwall/update_rules")%>', {
XHR.get('<%=url([[admin]], [[vpn]], [[passwall]], [[update_rules]])%>', {
update: checkBoxList
},
function(x, data) {
if(x && x.status == 200) {
window.location.href = '<%=dsp.build_url("admin/vpn/passwall/log")%>';
window.location.href = '<%=url([[admin]], [[vpn]], [[passwall]], [[log]])%>';
} else {
alert("<%:Error%>");
btn.disabled = false;

View File

@ -0,0 +1,171 @@
<%
local trojan_go_version = require "luci.model.cbi.passwall.api.api".get_trojan_go_version()
-%>
<script type="text/javascript">
//<![CDATA[
var trojanInfo;
var tokenStr = '<%=token%>';
var noUpdateText = '<%:It is the latest version%>';
var updateSuccessText = '<%:Update successful%>';
var clickToUpdateText = '<%:Click to update%>';
var inProgressText = '<%:Updating...%>';
var unexpectedErrorText = '<%:Unexpected error%>';
var updateInProgressNotice = '<%:Updating, are you sure to close?%>';
var downloadingText = '<%:Downloading...%>';
var decompressioningText = '<%:Unpacking...%>';
var movingText = '<%:Moving...%>';
window.onload = function() {
var trojanCheckBtn = document.getElementById('_trojan-check_btn');
var trojanDetailElm = document.getElementById('_trojan-check_btn-detail');
};
function addPageNotice_trojan() {
window.onbeforeunload = function(e) {
e.returnValue = updateInProgressNotice;
return updateInProgressNotice;
};
}
function removePageNotice_trojan() {
window.onbeforeunload = undefined;
}
function onUpdateSuccess_trojan(btn) {
alert(updateSuccessText);
if(btn) {
btn.value = updateSuccessText;
btn.placeholder = updateSuccessText;
btn.disabled = true;
}
window.setTimeout(function() {
window.location.reload();
}, 1000);
}
function onRequestError_trojan(btn, errorMessage) {
btn.disabled = false;
btn.value = btn.placeholder;
if(errorMessage) {
alert(errorMessage);
}
}
function onBtnClick_trojan(btn) {
if(trojanInfo === undefined) {
checkUpdate_trojan(btn);
} else {
doUpdate_trojan(btn);
}
}
function checkUpdate_trojan(btn) {
btn.disabled = true;
btn.value = inProgressText;
addPageNotice_trojan();
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=url([[admin]], [[vpn]], [[passwall]], [[trojan_go_check]])%>', {
token: tokenStr,
arch: ''
}, function(x,json) {
removePageNotice_trojan();
if(json.code) {
trojanInfo = undefined;
onRequestError_trojan(btn, json.error);
} else {
if(json.update) {
trojanInfo = json;
btn.disabled = false;
btn.value = clickToUpdateText;
btn.placeholder = clickToUpdateText;
if(ckeckDetailElm) {
var urlNode = '';
if(json.version) {
urlNode = '<em style="color:red;">最新版本号:' + json.version + '</em>';
if(json.url && json.url.html) {
urlNode = '<a href="' + json.url.html + '" target="_blank">' + urlNode + '</a>';
}
}
ckeckDetailElm.innerHTML = urlNode;
}
} else {
btn.disabled = true;
btn.value = noUpdateText;
}
}
},300);
}
function doUpdate_trojan(btn) {
btn.disabled = true;
btn.value = downloadingText;
addPageNotice_trojan();
var trojanUpdateUrl = '<%=url([[admin]], [[vpn]], [[passwall]], [[trojan_go_update]])%>';
// Download file
XHR.get(trojanUpdateUrl, {
token: tokenStr,
url: trojanInfo ? trojanInfo.url.download : ''
}, function(x,json) {
if(json.code) {
removePageNotice_trojan();
onRequestError_trojan(btn, json.error);
} else {
btn.value = decompressioningText;
// Extract file
XHR.get(trojanUpdateUrl, {
token: tokenStr,
task: 'extract',
file: json.file,
subfix: trojanInfo ? trojanInfo.type : ''
}, function(x,json) {
if(json.code) {
removePageNotice_trojan();
onRequestError_trojan(btn, json.error);
} else {
btn.value = movingText;
// Move file to target dir
XHR.get(trojanUpdateUrl, {
token: tokenStr,
task: 'move',
file: json.file
}, function(x,json) {
removePageNotice_trojan();
if(json.code) {
onRequestError_trojan(btn, json.error);
} else {
onUpdateSuccess_trojan(btn);
}
},300)
}
},300)
}
},300)
}
//]]>
</script>
<div class="cbi-value">
<label class="cbi-value-title">Trojan-Go
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<span><%=trojan_go_version%> 】</span>
<input class="cbi-button cbi-input-apply" type="button" id="_trojan-check_btn" onclick="onBtnClick_trojan(this);" value="<%:Manually update%>" />
<span id="_trojan-check_btn-detail"></span>
</div>
</div>
</div>

View File

@ -1,8 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local dsp = require "luci.dispatcher"
local v2ray_version = api.get_v2ray_version()
local v2ray_version = require "luci.model.cbi.passwall.api.api".get_v2ray_version()
-%>
<script type="text/javascript">
@ -74,7 +71,7 @@ local v2ray_version = api.get_v2ray_version()
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=dsp.build_url("admin/vpn/passwall/v2ray_check")%>', {
XHR.get('<%=url([[admin]], [[vpn]], [[passwall]], [[v2ray_check]])%>', {
token: tokenStr,
arch: ''
}, function(x,json) {
@ -114,7 +111,7 @@ local v2ray_version = api.get_v2ray_version()
addPageNotice_v2ray();
var v2rayUpdateUrl = '<%=dsp.build_url("admin/vpn/passwall/v2ray_update")%>';
var v2rayUpdateUrl = '<%=url([[admin]], [[vpn]], [[passwall]], [[v2ray_update]])%>';
// Download file
XHR.get(v2rayUpdateUrl, {
token: tokenStr,
@ -166,7 +163,7 @@ local v2ray_version = api.get_v2ray_version()
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<span><%=v2ray_version%>】</span>
<span><%=v2ray_version%> </span>
<input class="cbi-button cbi-input-apply" type="button" id="_v2ray-check_btn" onclick="onBtnClick_v2ray(this);" value="<%:Manually update%>" />
<span id="_v2ray-check_btn-detail"></span>
</div>

View File

@ -26,6 +26,6 @@
<legend>
<%:Logs%>
</legend>
<input class="cbi-button cbi-input-remove" type="button" onclick="clear_log()" value="<%:Clear logs%>">
<input class="cbi-button cbi-input-remove" type="button" onclick="clear_log()" value="<%:Clear logs%>" />
<textarea id="log_textarea" class="cbi-input-textarea" style="width: 100%;margin-top: 10px;" data-update="change" rows="20" wrap="off" readonly="readonly"></textarea>
</fieldset>

View File

@ -1,7 +1,3 @@
<%
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">
//<![CDATA[
var _users_status = document.getElementsByClassName('_users_status');

View File

@ -382,6 +382,12 @@ msgstr "验证证书"
msgid "Trojan Cert Path"
msgstr "证书路径"
msgid "Finger Print"
msgstr "指纹伪造"
msgid "Shadowsocks2"
msgstr "双重加密"
msgid "Encrypt Method"
msgstr "加密"
@ -649,26 +655,23 @@ msgstr "更新主程序"
msgid "Please confirm that your firmware supports FPU."
msgstr "请确认你的固件支持FPU。"
msgid "V2ray Path"
msgstr "V2ray路径"
msgid "if you want to run from memory, change the path, such as %s, Then save the application and update it manually."
msgstr "如果你希望从内存中运行,请更改路径,例如%s然后保存应用后再手动更新。"
msgid "if you want to run from memory, change the path, such as /tmp/v2ray/, Then save the application and update it manually."
msgstr "如果你希望从内存中运行,请更改路径,例如/tmp/v2ray/,然后保存应用后,再手动更新。"
msgid "Make sure there is enough space to install %s"
msgstr "确保有足够的空间安装%s"
msgid "V2ray Path"
msgstr "V2ray 路径"
msgid "Trojan-Go Path"
msgstr "Trojan-Go 路径"
msgid "Kcptun Client Path"
msgstr "Kcptun客户端路径"
msgid "if you want to run from memory, change the path, such as /tmp/kcptun-client, Then save the application and update it manually."
msgstr "如果你希望从内存中运行,请更改路径,例如/tmp/kcptun-client然后保存应用后再手动更新。"
msgid "Make sure there is enough space to install Kcptun"
msgstr "确保有足够的空间安装Kcptun"
msgstr "Kcptun 客户端路径"
msgid "Brook Path"
msgstr "Brook路径"
msgid "if you want to run from memory, change the path, such as /tmp/brook, Then save the application and update it manually."
msgstr "如果你希望从内存中运行,请更改路径,例如/tmp/brook然后保存应用后再手动更新。"
msgstr "Brook 路径"
msgid "Node Subscribe"
msgstr "节点订阅"

View File

@ -54,6 +54,7 @@ config global_rules
config global_app
option v2ray_file '/usr/bin/v2ray/'
option trojan_go_file '/usr/bin/trojan-go'
option kcptun_client_file '/usr/bin/kcptun-client'
option brook_file '/usr/bin/brook'

View File

@ -90,9 +90,9 @@ check_port_exists() {
protocol=$2
result=
if [ "$protocol" = "tcp" ]; then
result=$(netstat -tln | grep -c ":$port")
result=$(netstat -tln | grep -c ":$port ")
elif [ "$protocol" = "udp" ]; then
result=$(netstat -uln | grep -c ":$port")
result=$(netstat -uln | grep -c ":$port ")
fi
if [ "$result" = 1 ]; then
echo 1
@ -255,7 +255,10 @@ run_socks() {
ln_start_bin $(config_t_get global_app v2ray_file $(find_bin v2ray))/v2ray v2ray "-config=$config_file"
elif [ "$type" == "trojan" ]; then
lua $API_GEN_TROJAN $node client $bind $local_port > $config_file
ln_start_bin $(find_bin trojan) trojan "-c $config_file"
ln_start_bin $(find_bin trojan-plus) trojan-plus "-c $config_file"
elif [ "$type" == "trojan-go" ]; then
lua $API_GEN_TROJAN $node client $bind $local_port > $config_file
ln_start_bin $(config_t_get global_app trojan_go_file $(find_bin trojan-go)) trojan-go "-config $config_file"
elif [ "$type" == "brook" ]; then
local protocol=$(config_n_get $node brook_protocol client)
local brook_tls=$(config_n_get $node brook_tls 0)
@ -304,16 +307,11 @@ run_redir() {
lua $API_GEN_V2RAY $node udp $local_port nil > $config_file
ln_start_bin $(config_t_get global_app v2ray_file $(find_bin v2ray))/v2ray v2ray "-config=$config_file"
elif [ "$type" == "trojan" ]; then
local_port=$(get_new_port 2080 tcp)
lua $API_GEN_TROJAN $node client "127.0.0.1" $local_port > $config_file
ln_start_bin $(find_bin trojan) trojan "-c $config_file"
local node_address=$(config_n_get $node address)
local node_port=$(config_n_get $node port)
local server_username=$(config_n_get $node username)
local server_password=$(config_n_get $node password)
eval port=\$UDP_REDIR_PORT$6
ln_start_bin $(find_bin ipt2socks) ipt2socks_udp_$6 "-U -l $port -b 0.0.0.0 -s 127.0.0.1 -p $local_port -R"
lua $API_GEN_TROJAN $node nat "0.0.0.0" $local_port >$config_file
ln_start_bin $(find_bin trojan-plus) trojan-plus "-c $config_file"
elif [ "$type" == "trojan-go" ]; then
lua $API_GEN_TROJAN $node nat "0.0.0.0" $local_port >$config_file
ln_start_bin $(config_t_get global_app trojan_go_file $(find_bin trojan-go)) trojan-go "-config $config_file"
elif [ "$type" == "brook" ]; then
local protocol=$(config_n_get $node brook_protocol client)
if [ "$protocol" == "wsclient" ]; then
@ -344,14 +342,17 @@ run_redir() {
ln_start_bin $(config_t_get global_app v2ray_file $(find_bin v2ray))/v2ray v2ray "-config=$config_file"
elif [ "$type" == "trojan" ]; then
lua $API_GEN_TROJAN $node nat "0.0.0.0" $local_port > $config_file
[ "$6" == 1 ] && [ "$UDP_NODE1" == "tcp" ] && echolog "Trojan的NAT模式不支持UDP转发"
for k in $(seq 1 $process); do
ln_start_bin $(find_bin trojan) trojan "-c $config_file"
ln_start_bin $(find_bin trojan-plus) trojan-plus "-c $config_file"
done
elif [ "$type" == "trojan-go" ]; then
lua $API_GEN_TROJAN $node nat "0.0.0.0" $local_port > $config_file
ln_start_bin $(config_t_get global_app trojan_go_file $(find_bin trojan-go)) trojan-go "-config $config_file"
else
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 network_type="ipv4"
local kcptun_port=$(config_n_get $node kcp_port)
local kcptun_config="$(config_n_get $node kcp_opts)"
if [ -z "$kcptun_port" -o -z "$kcptun_config" ]; then
@ -463,7 +464,7 @@ clean_log() {
start_crontab() {
touch /etc/crontabs/root
sed -i '/$CONFIG/d' /etc/crontabs/root >/dev/null 2>&1 &
sed -i "/$CONFIG/d" /etc/crontabs/root >/dev/null 2>&1 &
auto_on=$(config_t_get global_delay auto_on 0)
if [ "$auto_on" = "1" ]; then
time_off=$(config_t_get global_delay time_off)
@ -926,4 +927,4 @@ start)
boot)
boot
;;
esac
esac

View File

@ -219,7 +219,7 @@ filter_node() {
fi
}
}
local v2ray_protocol=$(config_n_get $1 v2ray_protocol)
local v2ray_protocol=$(config_n_get $1 protocol)
if [ "$v2ray_protocol" == "_shunt" ]; then
local default_node=$(config_n_get $1 default_node nil)
filter_rules $default_node $2
@ -240,7 +240,7 @@ filter_node() {
filter_rules $(config_n_get $1 $shunt_id) $2 $_proxy $3
done
elif [ "$v2ray_protocol" == "_balancing" ]; then
local balancing_node=$(config_n_get $1 v2ray_balancing_node)
local balancing_node=$(config_n_get $1 balancing_node)
for node_id in $balancing_node
do
filter_rules $node_id $2

View File

@ -13,10 +13,11 @@ local gfwlist_update = 0
local chnroute_update = 0
local chnlist_update = 0
-- match comments/title/whitelist/ip address
-- match comments/title/whitelist/ip address/excluded_domain
local comment_pattern = "^[!\\[@]+"
local ip_pattern = "^%d+%.%d+%.%d+%.%d+"
local domain_pattern = "([%w%-%_]+%.[%w%.%-%_]+)[%/%*]*"
local excluded_domain = {"apple.com", "sina.cn","sina.com.cn","baidu.com","byr.cn","jlike.com","weibo.com","zhongsou.com","youdao.com","sogou.com","so.com","soso.com","aliyun.com","taobao.com","jd.com","qq.com"}
-- gfwlist parameter
local mydnsip = '127.0.0.1'
@ -137,13 +138,22 @@ local function fetch_chnlist()
return sret;
end
--check excluded domain
local function check_excluded_domain(value)
for k,v in ipairs(excluded_domain) do
if value:find(v) then
return true
end
end
end
--gfwlist转码至dnsmasq格式
local function generate_gfwlist()
local domains = {}
local out = io.open("/tmp/gfwlist_tmp", "w")
for line in io.lines("/tmp/gfwlist.txt") do
if not (string.find(line, comment_pattern) or string.find(line, ip_pattern)) then
if not (string.find(line, comment_pattern) or string.find(line, ip_pattern) or check_excluded_domain(line)) then
local start, finish, match = string.find(line, domain_pattern)
if (start) then
domains[match] = true

View File

@ -4,7 +4,7 @@
-- @author William Chan <root@williamchan.me>
------------------------------------------------
require 'nixio'
require 'uci'
require 'luci.model.uci'
require 'luci.util'
require 'luci.jsonc'
require 'luci.sys'
@ -20,9 +20,9 @@ local b64decode = nixio.bin.b64decode
local nodeResult = {} -- update result
local application = 'passwall'
local uciType = 'nodes'
local ucic2 = uci.cursor()
local ucic2 = luci.model.uci.cursor()
local arg2 = arg[2]
local allowInsecure_default = ucic2:get(application, "@global_subscribe[0]", "allowInsecure")
local allowInsecure_default = ucic2:get_bool(application, "@global_subscribe[0]", "allowInsecure")
ucic2:revert(application)
local log = function(...)
@ -125,7 +125,7 @@ do
end
ucic2:foreach(application, uciType, function(node)
if node.type == 'V2ray' and node.v2ray_protocol == '_shunt' then
if node.type == 'V2ray' and node.protocol == '_shunt' then
local node_id = node[".name"]
ucic2:foreach(application, "shunt_rules", function(e)
local _node_id = node[e[".name"]] or nil
@ -156,29 +156,31 @@ do
ucic2:set(application, node_id, "default_node", server)
end
}
elseif node.type == 'V2ray' and node.v2ray_protocol == '_balancing' then
elseif node.type == 'V2ray' and node.protocol == '_balancing' then
local node_id = node[".name"]
local nodes = {}
local new_nodes = {}
for k, v in pairs(node.v2ray_balancing_node) do
local node = v
local currentNode
if node then
currentNode = ucic2:get_all(application, node)
end
nodes[#nodes + 1] = {
log = false,
node = node,
currentNode = currentNode,
remarks = node,
set = function(server)
for kk, vv in pairs(CONFIG) do
if (vv.remarks == "V2ray负载均衡节点列表" .. node_id) then
table.insert(vv.new_nodes, server)
if node.balancing_node then
for k, v in pairs(node.balancing_node) do
local node = v
local currentNode
if node then
currentNode = ucic2:get_all(application, node)
end
nodes[#nodes + 1] = {
log = false,
node = node,
currentNode = currentNode,
remarks = node,
set = function(server)
for kk, vv in pairs(CONFIG) do
if (vv.remarks == "V2ray负载均衡节点列表" .. node_id) then
table.insert(vv.new_nodes, server)
end
end
end
end
}
}
end
end
CONFIG[#CONFIG + 1] = {
remarks = "V2ray负载均衡节点列表" .. node_id,
@ -191,7 +193,7 @@ do
ucic2:foreach(application, uciType, function(node2)
if node2[".name"] == node[".name"] then
local index = node2[".index"]
ucic2:set_list(application, "@nodes[" .. index .. "]", "v2ray_balancing_node", vv.new_nodes)
ucic2:set_list(application, "@nodes[" .. index .. "]", "balancing_node", vv.new_nodes)
end
end)
end
@ -276,7 +278,7 @@ end
local function get_urldecode(h) return schar(tonumber(h, 16)) end
local function UrlDecode(szText)
return szText:gsub("+", " "):gsub("%%(%x%x)", get_urldecode)
return (szText and szText:gsub("+", " "):gsub("%%(%x%x)", get_urldecode)) or nil
end
-- trim
@ -303,6 +305,7 @@ local function base64Decode(text)
end
-- 处理数据
local function processData(szType, content, add_mode)
log(content, add_mode)
local result = {
timeout = 60,
add_mode = add_mode,
@ -314,7 +317,7 @@ local function processData(szType, content, add_mode)
result.type = "SSR"
result.address = hostInfo[1]
result.port = hostInfo[2]
result.protocol = hostInfo[3]
result.ssr_protocol = hostInfo[3]
result.ssr_encrypt_method = hostInfo[4]
result.obfs = hostInfo[5]
result.password = base64Decode(hostInfo[6])
@ -333,50 +336,50 @@ local function processData(szType, content, add_mode)
result.type = 'V2ray'
result.address = info.add
result.port = info.port
result.v2ray_protocol = 'vmess'
result.v2ray_transport = info.net
result.v2ray_VMess_alterId = info.aid
result.v2ray_VMess_id = info.id
result.protocol = 'vmess'
result.transport = info.net
result.alter_id = info.aid
result.vmess_id = info.id
result.remarks = info.ps
-- result.v2ray_mux = 1
-- result.v2ray_mux_concurrency = 8
-- result.mux = 1
-- result.mux_concurrency = 8
if info.net == 'ws' then
result.v2ray_ws_host = info.host
result.v2ray_ws_path = info.path
result.ws_host = info.host
result.ws_path = info.path
end
if info.net == 'h2' then
result.v2ray_h2_host = info.host
result.v2ray_h2_path = info.path
result.h2_host = info.host
result.h2_path = info.path
end
if info.net == 'tcp' then
if info.type and info.type ~= "http" then
info.type = "none"
end
result.v2ray_tcp_guise = info.type
result.v2ray_tcp_guise_http_host = info.host
result.v2ray_tcp_guise_http_path = info.path
result.tcp_guise = info.type
result.tcp_guise_http_host = info.host
result.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
result.mkcp_guise = info.type
result.mkcp_mtu = 1350
result.mkcp_tti = 50
result.mkcp_uplinkCapacity = 5
result.mkcp_downlinkCapacity = 20
result.mkcp_readBufferSize = 2
result.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
result.quic_guise = info.type
result.quic_key = info.key
result.quic_security = info.securty
end
if not info.security then result.v2ray_security = "auto" end
if not info.security then result.security = "auto" end
if info.tls == "tls" or info.tls == "1" then
result.v2ray_stream_security = "tls"
result.stream_security = "tls"
result.tls_serverName = info.host
result.tls_allowInsecure = allowInsecure_default
result.tls_allowInsecure = allowInsecure_default and "1" or "0"
else
result.v2ray_stream_security = "none"
result.stream_security = "none"
end
elseif szType == "ss" then
local idx_sp = 0
@ -387,14 +390,26 @@ local function processData(szType, content, add_mode)
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 hostInfoLen = #hostInfo
local host = nil
local userinfo = nil
if hostInfoLen > 2 then
host = split(hostInfo[hostInfoLen], ":")
userinfo = {}
for i = 1, hostInfoLen - 1 do
tinsert(userinfo, hostInfo[i])
end
userinfo = table.concat(userinfo, '@')
else
host = split(hostInfo[2], ":")
userinfo = base64Decode(hostInfo[1])
end
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
if host[2] and host[2]:find("/%?") then
local query = split(host[2], "/%?")
result.port = query[1]
local params = {}
@ -428,35 +443,123 @@ local function processData(szType, content, add_mode)
alias = content:sub(idx_sp + 1, -1)
content = content:sub(0, idx_sp - 1)
end
local Info = split(content, "@")
if Info then
local address, port, peer
local password = Info[1]
local allowInsecure = allowInsecure_default
local params = {}
local hostInfo = split(Info[2], ":")
if hostInfo then
address = hostInfo[1]
hostInfo = split(hostInfo[2], "?")
if hostInfo then
port = hostInfo[1]
for _, v in pairs(split(hostInfo[2], '&')) do
local t = split(v, '=')
params[t[1]] = t[2]
end
if params.allowInsecure then
allowInsecure = params.allowInsecure
end
if params.peer then peer = params.peer end
result.type = "Trojan"
result.remarks = UrlDecode(alias)
if content:find("@") then
local Info = split(content, "@")
result.password = UrlDecode(Info[1])
local port = "443"
Info[2] = (Info[2] or ""):gsub("/%?", "?")
local hostInfo = nil
if Info[2]:find(":") then
hostInfo = split(Info[2], ":")
result.address = hostInfo[1]
local idx_port = 2
if hostInfo[2]:find("?") then
hostInfo = split(hostInfo[2], "?")
idx_port = 1
end
if hostInfo[idx_port] ~= "" then port = hostInfo[idx_port] end
else
if Info[2]:find("?") then
hostInfo = split(Info[2], "?")
end
result.address = hostInfo and hostInfo[1] or Info[2]
end
local peer, sni = nil, ""
local allowInsecure = allowInsecure_default
local query = split(Info[2], "?")
local params = {}
for _, v in pairs(split(query[2], '&')) do
local t = split(v, '=')
params[string.lower(t[1])] = UrlDecode(t[2])
end
if params.allowinsecure then
allowInsecure = params.allowinsecure
end
if params.peer then peer = params.peer end
sni = params.sni and params.sni or ""
if params.mux and params.mux == "1" then result.mux = "1" end
if params.ws and params.ws == "1" then
result.trojan_transport = "ws"
if params.wshost then result.ws_host = params.wshost end
if params.wspath then result.ws_path = params.wspath end
if sni == "" and params.wshost then sni = params.wshost end
end
if params.ss and params.ss == "1" then
result.ss_aead = "1"
if params.ssmethod then result.ss_aead_method = string.lower(params.ssmethod) end
if params.sspasswd then result.ss_aead_pwd = params.sspasswd end
end
result.type = "Trojan"
result.address = address
result.port = port
result.password = password
result.tls_allowInsecure = allowInsecure
result.tls_serverName = peer
result.remarks = UrlDecode(alias)
if result.mux or result.trojan_transport == "ws" or result.ss_aead then
result.type = "Trojan-Go"
result.fingerprint = "firefox"
end
result.stream_security = 'tls'
result.tls_serverName = peer and peer or sni
result.tls_allowInsecure = allowInsecure and "1" or "0"
end
elseif szType == "trojan-go" then
local alias = ""
if content:find("#") then
local idx_sp = content:find("#")
alias = content:sub(idx_sp + 1, -1)
content = content:sub(0, idx_sp - 1)
end
result.type = "Trojan-Go"
result.remarks = UrlDecode(alias)
if content:find("@") then
local Info = split(content, "@")
result.password = UrlDecode(Info[1])
local port = "443"
Info[2] = (Info[2] or ""):gsub("/%?", "?")
local hostInfo = nil
if Info[2]:find(":") then
hostInfo = split(Info[2], ":")
result.address = hostInfo[1]
local idx_port = 2
if hostInfo[2]:find("?") then
hostInfo = split(hostInfo[2], "?")
idx_port = 1
end
if hostInfo[idx_port] ~= "" then port = hostInfo[idx_port] end
else
if Info[2]:find("?") then
hostInfo = split(Info[2], "?")
end
result.address = hostInfo and hostInfo[1] or Info[2]
end
local peer, sni = nil, ""
local allowInsecure = allowInsecure_default
local query = split(Info[2], "?")
local params = {}
for _, v in pairs(split(query[2], '&')) do
local t = split(v, '=')
params[string.lower(t[1])] = UrlDecode(t[2])
end
if params.allowinsecure then
allowInsecure = params.allowinsecure
end
if params.peer then peer = params.peer end
sni = params.sni and params.sni or ""
if params.mux and params.mux == "1" then result.mux = "1" end
if params.type and params.type == "ws" then
result.trojan_transport = "ws"
if params.host then result.ws_host = params.host end
if params.path then result.ws_path = params.path end
if sni == "" and params.host then sni = params.host end
end
if params.encryption and params.encryption:match('^ss;[^;:]*[;:].*$') then
result.ss_aead = "1"
result.ss_aead_method, result.ss_aead_pwd = params.encryption:match('^ss;([^;:]*)[;:](.*)$')
result.ss_aead_method = string.lower(result.ss_aead_method)
end
result.port = port
result.fingerprint = "firefox"
result.stream_security = 'tls'
result.tls_serverName = peer and peer or sni
result.tls_allowInsecure = allowInsecure and "1" or "0"
end
elseif szType == "ssd" then
result.type = "SS"
@ -535,7 +638,7 @@ local function select_node(nodes, config)
local server
if config.currentNode then
-- 特别优先级 V2ray分流 + 备注
if config.currentNode.type == 'V2ray' and config.currentNode.v2ray_protocol == '_shunt' then
if config.currentNode.type == 'V2ray' and config.currentNode.protocol == '_shunt' then
for id, node in pairs(nodes) do
if node.remarks == config.currentNode.remarks then
log('选择【' .. config.remarks .. '】V2ray分流匹配节点' .. node.remarks)
@ -545,7 +648,7 @@ local function select_node(nodes, config)
end
end
-- 特别优先级 V2ray负载均衡 + 备注
if config.currentNode.type == 'V2ray' and config.currentNode.v2ray_protocol == '_balancing' then
if config.currentNode.type == 'V2ray' and config.currentNode.protocol == '_balancing' then
for id, node in pairs(nodes) do
if node.remarks == config.currentNode.remarks then
log('选择【' .. config.remarks .. '】V2ray负载均衡匹配节点' .. node.remarks)
@ -554,25 +657,23 @@ local function select_node(nodes, config)
end
end
end
-- 第一优先级 IP + 端口
-- 第一优先级 cfgid
if not server then
for id, node in pairs(nodes) do
if id == config.currentNode['.name'] then
if config.log == nil or config.log == true then
log('选择【' .. config.remarks .. '】第一匹配节点:' .. node.remarks)
end
server = id
break
end
end
end
-- 第二优先级 IP + 端口
if not server then
for id, node in pairs(nodes) do
if node.address and node.port then
if node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port then
if config.log == nil or config.log == true then
log('选择【' .. config.remarks .. '】第一匹配节点:' .. node.remarks)
end
server = id
break
end
end
end
end
-- 第二优先级 IP
if not server then
for id, node in pairs(nodes) do
if node.address then
if node.address == config.currentNode.address then
if config.log == nil or config.log == true then
log('选择【' .. config.remarks .. '】第二匹配节点:' .. node.remarks)
end
@ -582,11 +683,11 @@ local function select_node(nodes, config)
end
end
end
-- 第三优先级备注
-- 第三优先级 IP
if not server then
for id, node in pairs(nodes) do
if node.remarks then
if node.remarks == config.currentNode.remarks then
if node.address then
if node.address == config.currentNode.address then
if config.log == nil or config.log == true then
log('选择【' .. config.remarks .. '】第三匹配节点:' .. node.remarks)
end
@ -596,15 +697,17 @@ local function select_node(nodes, config)
end
end
end
-- 第四 cfgid
-- 第四优先级备注
if not server then
for id, node in pairs(nodes) do
if id == config.currentNode['.name'] then
if config.log == nil or config.log == true then
log('选择【' .. config.remarks .. '】第四匹配节点:' .. node.remarks)
if node.remarks then
if node.remarks == config.currentNode.remarks then
if config.log == nil or config.log == true then
log('选择【' .. config.remarks .. '】第四匹配节点:' .. node.remarks)
end
server = id
break
end
server = id
break
end
end
end
@ -638,9 +741,8 @@ local function update_node(manual)
end)
for _, v in ipairs(nodeResult) do
for _, vv in ipairs(v) do
local cfgid = ucic2:add(application, uciType)
local uuid = _api.gen_uuid()
ucic2:rename(application, cfgid, uuid)
local cfgid = ucic2:section(application, uciType, uuid)
cfgid = uuid
for kkk, vvv in pairs(vv) do
ucic2:set(application, cfgid, kkk, vvv)
@ -728,7 +830,7 @@ local function parse_link(raw, remark, manual)
local node = trim(v)
local dat = split(node, "://")
if dat and dat[1] and dat[2] then
if dat[1] == 'ss' or dat[1] == 'trojan' then
if dat[1] == 'ss' or dat[1] == 'trojan' or dat[1] == 'trojan-go' then
result = processData(dat[1], dat[2], add_mode)
else
result = processData(dat[1], base64Decode(dat[2]), add_mode)
@ -753,7 +855,7 @@ local function parse_link(raw, remark, manual)
end
end
end
log('成功解析节点数量: ' .. #nodes)
log('成功解析节点数量: ' .. #all_nodes)
else
if not manual then
log('获取到的节点内容为空...')

View File

@ -0,0 +1,85 @@
# Copyright (C) 2020 Lienol
#
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=trojan-go
PKG_VERSION:=0.7.8
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/p4gefau1t/trojan-go.git
PKG_SOURCE_VERSION:=9866c030058870bf18d60f1d3677c6d4ed9de35d
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION)
PKG_CONFIG_DEPENDS := \
CONFIG_TROJAN_GO_COMPRESS_GOPROXY \
CONFIG_TROJAN_GO_COMPRESS_UPX
PKG_BUILD_DEPENDS:=golang/host
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
GO_PKG:=github.com/p4gefau1t/trojan-go
GO_PKG_LDFLAGS:=-s -w
GO_PKG_LDFLAGS_X:= \
$(GO_PKG)/constant.Version=$(PKG_VERSION) \
$(GO_PKG)/constant.Commit=$(PKG_SOURCE_VERSION)
GO_PKG_TAG:=-tags full
include $(INCLUDE_DIR)/package.mk
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
define Package/$(PKG_NAME)
SECTION:=net
CATEGORY:=Network
DEPENDS:=$$(GO_ARCH_DEPENDS)
TITLE:=An unidentifiable mechanism that helps you bypass GFW. It's compatible with original trojan with experimental features.
URL:=https://github.com/p4gefau1t/trojan-go
endef
define Package/$(PKG_NAME)/config
menu "Configuration"
depends on PACKAGE_$(PKG_NAME)
config TROJAN_GO_COMPRESS_GOPROXY
bool "Compiling with GOPROXY proxy"
default n
config TROJAN_GO_COMPRESS_UPX
bool "Compress executable files with UPX"
default y
endmenu
endef
ifeq ($(CONFIG_TROJAN_GO_COMPRESS_GOPROXY),y)
export GO111MODULE=on
export GOPROXY=https://goproxy.cn
endif
define Build/Prepare
tar -zxvf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR) --strip-components 1
endef
define Build/Compile
$(call GoPackage/Build/Configure)
$(call GoPackage/Build/Compile)
ifeq ($(CONFIG_TROJAN_GO_COMPRESS_UPX),y)
$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/$(PKG_NAME)
endif
endef
define Package/$(PKG_NAME)/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/$(PKG_NAME) $(1)/usr/bin/$(PKG_NAME)
endef
$(eval $(call GoBinPackage,$(PKG_NAME)))
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -0,0 +1,69 @@
#
# Copyright (C) 2018-2019 wongsyrone
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=trojan-plus
PKG_VERSION:=10.0.1
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/peter-tank/trojan-plus.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=2a15d2c886cb23f4d5a8ff975fa3c87819046390
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
CMAKE_INSTALL:=1
PKG_BUILD_PARALLEL:=0
PKG_BUILD_DEPENDS:=openssl
PKG_LICENSE:=GPL-3.0
PKG_MAINTAINER:=Trojan-Plus-Group
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
TARGET_CXXFLAGS += -Wall -Wextra
TARGET_CXXFLAGS += $(FPIC)
# LTO
TARGET_CXXFLAGS += -flto
TARGET_LDFLAGS += -flto
# CXX standard
TARGET_CXXFLAGS += -std=c++11
TARGET_CXXFLAGS := $(filter-out -O%,$(TARGET_CXXFLAGS)) -O3
TARGET_CXXFLAGS += -ffunction-sections -fdata-sections
TARGET_LDFLAGS += -Wl,--gc-sections
CMAKE_OPTIONS += \
-DENABLE_MYSQL=OFF \
-DENABLE_NAT=ON \
-DENABLE_REUSE_PORT=ON \
-DENABLE_SSL_KEYLOG=ON \
-DENABLE_TLS13_CIPHERSUITES=ON \
-DFORCE_TCP_FASTOPEN=OFF \
-DSYSTEMD_SERVICE=OFF \
-DOPENSSL_USE_STATIC_LIBS=FALSE \
-DBoost_DEBUG=ON \
-DBoost_NO_BOOST_CMAKE=ON
define Package/trojan-plus
SECTION:=net
CATEGORY:=Network
TITLE:=An unidentifiable mechanism that helps you bypass GFW. It's compatible with original trojan with experimental features.
URL:=https://github.com/Trojan-Plus-Group/trojan-plus
DEPENDS:=+libpthread +libstdcpp +libopenssl \
+boost +boost-system +boost-program_options
endef
define Package/trojan-plus/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/trojan $(1)/usr/sbin/trojan-plus
endef
$(eval $(call BuildPackage,trojan-plus))

View File

@ -10,7 +10,7 @@ include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=dsl_cpe_control_danube
PKG_VERSION:=3.24.4.4
PKG_RELEASE:=6
PKG_RELEASE:=8
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_BUILD_DIR:=$(BUILD_DIR)/dsl_cpe_control-$(PKG_VERSION)
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/
@ -35,7 +35,7 @@ define Package/ltq-adsl-app
CATEGORY:=Network
TITLE:=Lantiq DSL userland tool
URL:=http://www.lantiq.com/
DEPENDS:=@(TARGET_lantiq_xway||TARGET_lantiq_xway_legacy||TARGET_lantiq_ase) +libpthread
DEPENDS:=@(TARGET_lantiq_xway||TARGET_lantiq_xway_legacy||TARGET_lantiq_ase) +libpthread +ltq-dsl-base
MENU:=1
endef

8
package/network/config/ltq-adsl-app/files/dsl_control Executable file → Normal file
View File

@ -4,11 +4,11 @@
START=97
USE_PROCD=1
EXTRA_COMMANDS="status lucistat"
EXTRA_HELP=" status Get DSL status information
lucistat Get status information if lua friendly format"
EXTRA_COMMANDS="dslstat lucistat"
EXTRA_HELP=" dslstat Get DSL status information
lucistat Get status information in lua friendly format"
[ -f /lib/functions/lantiq_dsl.sh ] && . /lib/functions/lantiq_dsl.sh
. /lib/functions/lantiq_dsl.sh
annex_b=10_00_10_00_00_04_00_00
annex_bdmt=10_00_00_00_00_00_00_00

View File

@ -9,7 +9,7 @@ include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=ltq-vdsl-app
PKG_VERSION:=4.17.18.6
PKG_RELEASE:=2
PKG_RELEASE:=4
PKG_BASE_NAME:=dsl_cpe_control
PKG_SOURCE:=$(PKG_BASE_NAME)_vrx-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
@ -19,7 +19,6 @@ PKG_LICENSE:=BSD-2-Clause
PKG_BUILD_DEPENDS:=ltq-vdsl
PKG_ASLR_PIE:=0
PKG_FLAGS:=nonshared
include $(INCLUDE_DIR)/package.mk
@ -29,7 +28,7 @@ define Package/ltq-vdsl-app
CATEGORY:=Network
TITLE:=Lantiq VDSL userland tool
URL:=http://www.lantiq.com/
DEPENDS:=@TARGET_lantiq_xrx200 +libpthread +librt
DEPENDS:=@TARGET_lantiq_xrx200 +libpthread +librt +ltq-dsl-base
endef
define Package/ltq-vdsl-app/description

8
package/network/config/ltq-vdsl-app/files/dsl_control Executable file → Normal file
View File

@ -4,11 +4,11 @@
START=97
USE_PROCD=1
EXTRA_COMMANDS="status lucistat"
EXTRA_HELP=" status Get DSL status information
lucistat Get status information if lua friendly format"
EXTRA_COMMANDS="dslstat lucistat"
EXTRA_HELP=" dslstat Get DSL status information
lucistat Get status information in lua friendly format"
[ -f /lib/functions/lantiq_dsl.sh ] && . /lib/functions/lantiq_dsl.sh
. /lib/functions/lantiq_dsl.sh
#
# ITU-T G.997.1 (06/2012) - Section 7.3.1.1.1 (xTU transmission system enabling (XTSE))

View File

@ -12,7 +12,7 @@ esac
#echo "Call dsl_pipe with $*"
lock /var/lock/dsl_pipe
echo $* > /tmp/pipe/dsl_cpe${pipe_no}_cmd
result=`cat /tmp/pipe/dsl_cpe${pipe_no}_ack`
result=$(cat /tmp/pipe/dsl_cpe${pipe_no}_ack)
lock -u /var/lock/dsl_pipe
echo "$result"

View File

@ -0,0 +1,32 @@
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=ltq-dsl-base
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/ltq-dsl-base
SECTION:=net
CATEGORY:=Network
TITLE:=DSL related files for Intel/Lantiq DSL Chipsets
URL:=http://openwrt.org/
DEPENDS:=@TARGET_lantiq +jshn
endef
define Package/ltq-dsl-base/description
This package contains DSL related files for Intel/Lantiq DSL Chipsets.
endef
define Build/Compile
endef
define Package/ltq-dsl-base/install
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,ltq-dsl-base))

View File

@ -8,13 +8,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=procd
PKG_RELEASE:=3
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/procd.git
PKG_SOURCE_DATE:=2020-07-14
PKG_SOURCE_VERSION:=b2230e4ff28b29472d0a232fee5d9f4168390b52
PKG_MIRROR_HASH:=67dd91d469a2e996a6b350575cfc0accedcf9ac948feaeee0d665199820bb6b0
PKG_SOURCE_DATE:=2020-07-17
PKG_SOURCE_VERSION:=268126a3b159fbd488eb56ebbd19c7384f1aa8a5
PKG_MIRROR_HASH:=77f143f600570c26f9305a744e8cad9c799c71b7873b4cbcff3151c43d796671
CMAKE_INSTALL:=1
PKG_LICENSE:=GPL-2.0

View File

@ -4,10 +4,6 @@
model = "Qualcomm IPQ8064/DB149";
compatible = "qcom,ipq8064-db149", "qcom,ipq8064";
aliases {
serial0 = &gsbi2_serial;
};
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
@ -18,6 +14,11 @@
};
};
alias {
serial0 = &uart2;
mdio-gpio0 = &mdio0;
};
chosen {
stdout-path = "serial0:115200n8";
};
@ -60,7 +61,7 @@
gsbi2: gsbi@12480000 {
qcom,mode = <GSBI_PROT_I2C_UART>;
status = "ok";
gsbi2_serial: serial@12490000 {
uart2: serial@12490000 {
status = "ok";
};
};

View File

@ -734,7 +734,7 @@
syscon-tcsr = <&tcsr>;
gsbi2_serial: serial@12490000 {
uart2: serial@12490000 {
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
reg = <0x12490000 0x1000>,
<0x12480000 0x1000>;
@ -809,7 +809,7 @@
syscon-tcsr = <&tcsr>;
gsbi5_serial: serial@1a240000 {
uart5: serial@1a240000 {
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
reg = <0x1a240000 0x1000>,
<0x1a200000 0x1000>;

View File

@ -0,0 +1,32 @@
#
# Copyright (C) 2013 OpenWrt.org
#
. /lib/functions/migrations.sh
do_internet_led_rename()
{
config_load system
[ -n $(config_get led_internet name) ] || return
[ -z $(config_get led_dsl name) ] || return
uci rename system.led_internet=led_dsl
uci set system.led_dsl.name=dsl
logger -t led-migration "internet led renamed to dsl"
}
case "$(board_name)" in
alphanetworks,asl56026|\
arcadyan,arv7519rw22|\
arcadyan,vg3503j|\
avm,fritz7360sl|\
bt,homehub-v5a)
do_internet_led_rename
;;
esac
migrations_apply system
exit 0

View File

@ -18,17 +18,11 @@ do_internet_led_rename()
}
case "$(board_name)" in
alphanetworks,asl56026|\
arcadyan,arv452cqw|\
arcadyan,arv7510pw22|\
arcadyan,arv7519rw22|\
arcadyan,arv752dpw|\
arcadyan,arv752dpw22|\
arcadyan,vg3503j|\
avm,fritz7360sl|\
bt,homehub-v2b|\
bt,homehub-v3a|\
bt,homehub-v5a)
bt,homehub-v3a)
do_internet_led_rename
;;
netgear,dgn3500|\

View File

@ -0,0 +1,28 @@
#
# Copyright (C) 2013 OpenWrt.org
#
. /lib/functions/migrations.sh
do_internet_led_rename()
{
config_load system
[ -n $(config_get led_internet name) ] || return
[ -z $(config_get led_dsl name) ] || return
uci rename system.led_internet=led_dsl
uci set system.led_dsl.name=dsl
logger -t led-migration "internet led renamed to dsl"
}
case "$(board_name)" in
arcadyan,arv452cqw)
do_internet_led_rename
;;
esac
migrations_apply system
exit 0