luci-app-passwall2: sync upstream

This commit is contained in:
sbwml 2023-09-06 10:57:10 +08:00
parent 0a9636efda
commit 714c9178fa
28 changed files with 3088 additions and 650 deletions

View File

@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2 PKG_NAME:=luci-app-passwall2
PKG_VERSION:=1.19-6 PKG_VERSION:=1.20-4
PKG_RELEASE:= PKG_RELEASE:=
PKG_CONFIG_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \
@ -23,8 +23,8 @@ PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_SingBox \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin
LUCI_TITLE:=LuCI support for PassWall 2 LUCI_TITLE:=LuCI support for PassWall 2
@ -47,8 +47,8 @@ LUCI_DEPENDS:=+coreutils +coreutils-base64 +coreutils-nohup +curl \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-redir \ +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-redir \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server:shadowsocksr-libev-ssr-server \ +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server:shadowsocksr-libev-ssr-server \
+PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs:simple-obfs \ +PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs:simple-obfs \
+PACKAGE_$(PKG_NAME)_INCLUDE_SingBox:sing-box \
+PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client:tuic-client \ +PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client:tuic-client \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray-core \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin:v2ray-plugin +PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin:v2ray-plugin
define Package/$(PKG_NAME)/config define Package/$(PKG_NAME)/config
@ -133,15 +133,15 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs
bool "Include Simple-Obfs (Shadowsocks Plugin)" bool "Include Simple-Obfs (Shadowsocks Plugin)"
default y default y
config PACKAGE_$(PKG_NAME)_INCLUDE_SingBox
bool "Include Sing-Box"
default y if aarch64||arm||i386||x86_64
config PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client config PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client
bool "Include tuic-client" bool "Include tuic-client"
depends on aarch64||arm||i386||x86_64 depends on aarch64||arm||i386||x86_64
default n default n
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray
bool "Include V2ray"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin
bool "Include V2ray-Plugin (Shadowsocks Plugin)" bool "Include V2ray-Plugin (Shadowsocks Plugin)"
default y if aarch64||arm||i386||x86_64 default y if aarch64||arm||i386||x86_64

View File

@ -2,7 +2,7 @@ local api = require "luci.passwall2.api"
local appname = api.appname local appname = api.appname
local uci = api.uci local uci = api.uci
local datatypes = api.datatypes local datatypes = api.datatypes
local has_v2ray = api.is_finded("v2ray") local has_singbox = api.is_finded("sing-box")
local has_xray = api.is_finded("xray") local has_xray = api.is_finded("xray")
m = Map(appname) m = Map(appname)
@ -36,6 +36,8 @@ end
m:append(Template(appname .. "/global/status")) m:append(Template(appname .. "/global/status"))
local global_cfgid = uci:get_all(appname, "@global[0]")[".name"]
s = m:section(TypedSection, "global") s = m:section(TypedSection, "global")
s.anonymous = true s.anonymous = true
s.addremove = false s.addremove = false
@ -51,7 +53,7 @@ node = s:taboption("Main", ListValue, "node", "<a style='color: red'>" .. transl
node:value("nil", translate("Close")) node:value("nil", translate("Close"))
-- 分流 -- 分流
if (has_v2ray or has_xray) and #nodes_table > 0 then if (has_singbox or has_xray) and #nodes_table > 0 then
local normal_list = {} local normal_list = {}
local balancing_list = {} local balancing_list = {}
local shunt_list = {} local shunt_list = {}
@ -84,10 +86,10 @@ if (has_v2ray or has_xray) and #nodes_table > 0 then
if #normal_list > 0 then if #normal_list > 0 then
for k, v in pairs(shunt_list) do for k, v in pairs(shunt_list) do
local vid = v.id local vid = v.id
-- shunt node type, V2ray or Xray -- shunt node type, Sing-Box or Xray
local type = s:taboption("Main", ListValue, vid .. "-type", translate("Type")) local type = s:taboption("Main", ListValue, vid .. "-type", translate("Type"))
if has_v2ray then if has_singbox then
type:value("V2ray", translate("V2ray")) type:value("sing-box", translate("Sing-Box"))
end end
if has_xray then if has_xray then
type:value("Xray", translate("Xray")) type:value("Xray", translate("Xray"))
@ -119,7 +121,7 @@ if (has_v2ray or has_xray) and #nodes_table > 0 then
o.cfgvalue = get_cfgvalue(v.id, "main_node") o.cfgvalue = get_cfgvalue(v.id, "main_node")
o.write = get_write(v.id, "main_node") o.write = get_write(v.id, "main_node")
if (has_v2ray and has_xray) or (v.type == "V2ray" and not has_v2ray) or (v.type == "Xray" and not has_xray) then if (has_singbox and has_xray) or (v.type == "sing-box" and not has_singbox) or (v.type == "Xray" and not has_xray) then
type:depends("node", v.id) type:depends("node", v.id)
else else
type:depends("node", "hide") --不存在的依赖,即始终隐藏 type:depends("node", "hide") --不存在的依赖,即始终隐藏
@ -212,14 +214,6 @@ node_socks_port = s:taboption("Main", Value, "node_socks_port", translate("Node"
node_socks_port.default = 1070 node_socks_port.default = 1070
node_socks_port.datatype = "port" node_socks_port.datatype = "port"
--[[
if has_v2ray or has_xray then
node_http_port = s:taboption("Main", Value, "node_http_port", translate("Node") .. " HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use"))
node_http_port.default = 0
node_http_port.datatype = "port"
end
]]--
s:tab("DNS", translate("DNS")) s:tab("DNS", translate("DNS"))
o = s:taboption("DNS", ListValue, "remote_dns_protocol", translate("Remote DNS Protocol")) o = s:taboption("DNS", ListValue, "remote_dns_protocol", translate("Remote DNS Protocol"))
@ -260,8 +254,6 @@ o = s:taboption("DNS", Value, "remote_dns_client_ip", translate("Remote DNS EDNS
o.description = translate("Notify the DNS server when the DNS query is notified, the location of the client (cannot be a private IP address).") .. "<br />" .. o.description = translate("Notify the DNS server when the DNS query is notified, the location of the client (cannot be a private IP address).") .. "<br />" ..
translate("This feature requires the DNS server to support the Edns Client Subnet (RFC7871).") translate("This feature requires the DNS server to support the Edns Client Subnet (RFC7871).")
o.datatype = "ipaddr" o.datatype = "ipaddr"
o:depends("remote_dns_protocol", "tcp")
o:depends("remote_dns_protocol", "doh")
o = s:taboption("DNS", Flag, "remote_fakedns", "FakeDNS", translate("Use FakeDNS work in the shunt domain that proxy.")) o = s:taboption("DNS", Flag, "remote_fakedns", "FakeDNS", translate("Use FakeDNS work in the shunt domain that proxy."))
o.default = "0" o.default = "0"
@ -273,9 +265,16 @@ o:value("UseIP")
o:value("UseIPv4") o:value("UseIPv4")
o:value("UseIPv6") o:value("UseIPv6")
hosts = s:taboption("DNS", TextValue, "dns_hosts", translate("Domain Override")) o = s:taboption("DNS", TextValue, "dns_hosts", translate("Domain Override"))
hosts.rows = 5 o.rows = 5
hosts.wrap = "off" o.wrap = "off"
o.remove = function(self, section)
local node_value = node:formvalue(global_cfgid)
local node_t = m:get(node_value)
if node_t.type == "Xray" then
AbstractValue.remove(self, section)
end
end
o = s:taboption("DNS", Button, "clear_ipset", translate("Clear IPSET"), translate("Try this feature if the rule modification does not take effect.")) o = s:taboption("DNS", Button, "clear_ipset", translate("Clear IPSET"), translate("Try this feature if the rule modification does not take effect."))
o.inputstyle = "remove" o.inputstyle = "remove"
@ -284,6 +283,14 @@ function o.write(e, e)
luci.http.redirect(api.url("log")) luci.http.redirect(api.url("log"))
end end
for k, v in pairs(nodes_table) do
if v.type == "Xray" then
s.fields["remote_dns_client_ip"]:depends({ node = v.id, remote_dns_protocol = "tcp" })
s.fields["remote_dns_client_ip"]:depends({ node = v.id, remote_dns_protocol = "doh" })
s.fields["dns_hosts"]:depends({ node = v.id })
end
end
s:tab("log", translate("Log")) s:tab("log", translate("Log"))
o = s:taboption("log", Flag, "close_log", translate("Close Node Log")) o = s:taboption("log", Flag, "close_log", translate("Close Node Log"))
o.rmempty = false o.rmempty = false
@ -342,7 +349,7 @@ o.default = n + 1080
o.datatype = "port" o.datatype = "port"
o.rmempty = false o.rmempty = false
if has_v2ray or has_xray then if has_singbox or has_xray then
o = s:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use")) o = s:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use"))
o.default = 0 o.default = 0
o.datatype = "port" o.datatype = "port"
@ -351,7 +358,7 @@ end
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
node:value(v.id, v["remark"]) node:value(v.id, v["remark"])
if v.type == "Socks" then if v.type == "Socks" then
if has_v2ray or has_xray then if has_singbox or has_xray then
socks_node:value(v.id, v["remark"]) socks_node:value(v.id, v["remark"])
end end
else else

View File

@ -83,7 +83,7 @@ o.cfgvalue = function(t, n)
local remarks = m:get(n, "remarks") or "" local remarks = m:get(n, "remarks") or ""
local type = m:get(n, "type") or "" local type = m:get(n, "type") or ""
str = str .. string.format("<input type='hidden' id='cbid.%s.%s.type' value='%s'/>", appname, n, type) str = str .. string.format("<input type='hidden' id='cbid.%s.%s.type' value='%s'/>", appname, n, type)
if type == "V2ray" or type == "Xray" then if type == "sing-box" or type == "Xray" then
local protocol = m:get(n, "protocol") local protocol = m:get(n, "protocol")
if protocol == "_balancing" then if protocol == "_balancing" then
protocol = translate("Balancing") protocol = translate("Balancing")

View File

@ -2,7 +2,7 @@ local api = require "luci.passwall2.api"
local appname = api.appname local appname = api.appname
local has_ss = api.is_finded("ss-redir") local has_ss = api.is_finded("ss-redir")
local has_ss_rust = api.is_finded("sslocal") local has_ss_rust = api.is_finded("sslocal")
local has_v2ray = api.is_finded("v2ray") local has_singbox = api.is_finded("sing-box")
local has_xray = api.is_finded("xray") local has_xray = api.is_finded("xray")
local ss_aead_type = {} local ss_aead_type = {}
if has_ss then if has_ss then
@ -11,8 +11,8 @@ end
if has_ss_rust then if has_ss_rust then
ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust" ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust"
end end
if has_v2ray then if has_singbox then
ss_aead_type[#ss_aead_type + 1] = "v2ray" ss_aead_type[#ss_aead_type + 1] = "sing-box"
end end
if has_xray then if has_xray then
ss_aead_type[#ss_aead_type + 1] = "xray" ss_aead_type[#ss_aead_type + 1] = "xray"

View File

@ -3,7 +3,7 @@ local appname = api.appname
local sys = api.sys local sys = api.sys
local has_ss = api.is_finded("ss-redir") local has_ss = api.is_finded("ss-redir")
local has_ss_rust = api.is_finded("sslocal") local has_ss_rust = api.is_finded("sslocal")
local has_v2ray = api.is_finded("v2ray") local has_singbox = api.is_finded("sing-box")
local has_xray = api.is_finded("xray") local has_xray = api.is_finded("xray")
local ss_aead_type = {} local ss_aead_type = {}
if has_ss then if has_ss then
@ -12,8 +12,8 @@ end
if has_ss_rust then if has_ss_rust then
ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust" ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust"
end end
if has_v2ray then if has_singbox then
ss_aead_type[#ss_aead_type + 1] = "v2ray" ss_aead_type[#ss_aead_type + 1] = "sing-box"
end end
if has_xray then if has_xray then
ss_aead_type[#ss_aead_type + 1] = "xray" ss_aead_type[#ss_aead_type + 1] = "xray"

View File

@ -1,7 +1,8 @@
local api = require "luci.passwall2.api" local api = require "luci.passwall2.api"
local appname = api.appname local appname = api.appname
local fs = api.fs local fs = api.fs
local has_v2ray = api.is_finded("v2ray") local uci = api.uci
local has_singbox = api.is_finded("sing-box")
local has_xray = api.is_finded("xray") local has_xray = api.is_finded("xray")
local has_fw3 = api.is_finded("fw3") local has_fw3 = api.is_finded("fw3")
local has_fw4 = api.is_finded("fw4") local has_fw4 = api.is_finded("fw4")
@ -126,8 +127,8 @@ o = s:option(Flag, "accept_icmpv6", translate("Hijacking ICMPv6 (IPv6 PING)"))
o:depends("ipv6_tproxy", true) o:depends("ipv6_tproxy", true)
o.default = 0 o.default = 0
if has_v2ray or has_xray then if has_xray then
s = m:section(TypedSection, "global_xray", "V2Ray/Xray " .. translate("Settings")) s = m:section(TypedSection, "global_xray", "Xray " .. translate("Settings"))
s.anonymous = true s.anonymous = true
s.addremove = false s.addremove = false
@ -158,4 +159,33 @@ if has_v2ray or has_xray then
end end
end end
if has_singbox then
s = m:section(TypedSection, "global_singbox", "Sing-Box " .. translate("Settings"))
s.anonymous = true
s.addremove = false
o = s:option(Flag, "sniff_override_destination", translate("Override the connection destination address"), translate("Override the connection destination address with the sniffed domain."))
o.default = 1
o.rmempty = false
o = s:option(Value, "geoip_path", translate("Custom geoip Path"))
o.default = "/tmp/singbox/geoip.db"
o.rmempty = false
o = s:option(Value, "geoip_url", translate("Custom geoip URL"))
o.default = "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db"
o:value("https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db")
o.rmempty = false
o = s:option(Value, "geosite_path", translate("Custom geosite Path"))
o.default = "/tmp/singbox/geosite.db"
o.rmempty = false
o = s:option(Value, "geosite_url", translate("Custom geosite URL"))
o.default = "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db"
o:value("https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db")
o.rmempty = false
end
return m return m

View File

@ -41,7 +41,7 @@ for e = 0, 23 do o:value(e, e .. translate("oclock")) end
o.default = 0 o.default = 0
o:depends("auto_update", true) o:depends("auto_update", true)
s = m:section(TypedSection, "shunt_rules", "V2ray/Xray " .. translate("Shunt Rule"), "<a style='color: red'>" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "</a>") s = m:section(TypedSection, "shunt_rules", "Xray " .. translate("Shunt Rule"), "<a style='color: red'>" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "</a>")
s.template = "cbi/tblsection" s.template = "cbi/tblsection"
s.anonymous = false s.anonymous = false
s.addremove = true s.addremove = true

View File

@ -2,7 +2,7 @@ local api = require "luci.passwall2.api"
local appname = api.appname local appname = api.appname
local datatypes = api.datatypes local datatypes = api.datatypes
m = Map(appname, "V2ray/Xray " .. translate("Shunt Rule")) m = Map(appname, "Xray " .. translate("Shunt Rule"))
m.redirect = api.url() m.redirect = api.url()
s = m:section(NamedSection, arg[1], "shunt_rules", "") s = m:section(NamedSection, arg[1], "shunt_rules", "")

View File

@ -1,7 +1,7 @@
local api = require "luci.passwall2.api" local api = require "luci.passwall2.api"
local appname = api.appname local appname = api.appname
local uci = api.uci local uci = api.uci
local has_v2ray = api.is_finded("v2ray") local has_singbox = api.is_finded("sing-box")
local has_xray = api.is_finded("xray") local has_xray = api.is_finded("xray")
m = Map(appname) m = Map(appname)
@ -54,7 +54,7 @@ o.default = n + 1080
o.datatype = "port" o.datatype = "port"
o.rmempty = false o.rmempty = false
if has_v2ray or has_xray then if has_singbox or has_xray then
o = s:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use")) o = s:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use"))
o.default = 0 o.default = 0
o.datatype = "port" o.datatype = "port"

View File

@ -2,13 +2,15 @@ local m, s = ...
local api = require "luci.passwall2.api" local api = require "luci.passwall2.api"
if not api.is_finded("xray") and not api.is_finded("v2ray") then if not api.is_finded("xray") then
return return
end end
local appname = api.appname local appname = api.appname
local uci = api.uci local uci = api.uci
local type_name = "Xray"
local option_prefix = "xray_" local option_prefix = "xray_"
local function option_name(name) local function option_name(name)
@ -21,52 +23,20 @@ local function rm_prefix_cfgvalue(self, section)
end end
end end
local function rm_prefix_write(self, section, value) local function rm_prefix_write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == "Xray" or s.fields["type"]:formvalue(arg[1]) == "V2ray" then if s.fields["type"]:formvalue(arg[1]) == type_name then
if self.option:find(option_prefix) == 1 then if self.option:find(option_prefix) == 1 then
m:set(section, self.option:sub(1 + #option_prefix), value) m:set(section, self.option:sub(1 + #option_prefix), value)
end end
end end
end end
local function rm_prefix_remove(self, section, value) local function rm_prefix_remove(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == "Xray" or s.fields["type"]:formvalue(arg[1]) == "V2ray" then if s.fields["type"]:formvalue(arg[1]) == type_name then
if self.option:find(option_prefix) == 1 then if self.option:find(option_prefix) == 1 then
m:del(section, self.option:sub(1 + #option_prefix)) m:del(section, self.option:sub(1 + #option_prefix))
end end
end end
end end
local function add_xray_depends(o, field, value)
local deps = { type = "Xray" }
if field then
if type(field) == "string" then
deps[field] = value
else
for key, value in pairs(field) do
deps[key] = value
end
end
end
o:depends(deps)
end
local function add_v2ray_depends(o, field, value)
local deps = { type = "V2ray" }
if field then
if type(field) == "string" then
deps[field] = value
else
for key, value in pairs(field) do
deps[key] = value
end
end
end
o:depends(deps)
end
local v_ss_encrypt_method_list = {
"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305"
}
local x_ss_encrypt_method_list = { local x_ss_encrypt_method_list = {
"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"
} }
@ -79,12 +49,7 @@ local header_type_list = {
-- [[ Xray ]] -- [[ Xray ]]
if api.is_finded("xray") then s.fields["type"]:value(type_name, "Xray")
s.fields["type"]:value("Xray", translate("Xray"))
end
if api.is_finded("v2ray") then
s.fields["type"]:value("V2ray", translate("V2ray"))
end
o = s:option(ListValue, option_name("protocol"), translate("Protocol")) o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
o:value("vmess", translate("Vmess")) o:value("vmess", translate("Vmess"))
@ -97,8 +62,6 @@ o:value("wireguard", translate("WireGuard"))
o:value("_balancing", translate("Balancing")) o:value("_balancing", translate("Balancing"))
o:value("_shunt", translate("Shunt")) o:value("_shunt", translate("Shunt"))
o:value("_iface", translate("Custom Interface") .. " (Only Support Xray)") o:value("_iface", translate("Custom Interface") .. " (Only Support Xray)")
add_xray_depends(o)
add_v2ray_depends(o)
o = s:option(Value, option_name("iface"), translate("Interface")) o = s:option(Value, option_name("iface"), translate("Interface"))
o.default = "eth1" o.default = "eth1"
@ -131,31 +94,26 @@ end
-- 负载均衡列表 -- 负载均衡列表
local o = s:option(DynamicList, option_name("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>")) local o = s:option(DynamicList, option_name("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>"))
o:depends({ [option_name("protocol")] = "_balancing" }) o:depends({ [option_name("protocol")] = "_balancing" })
add_v2ray_depends(o, { [option_name("protocol")] = "_balancing" })
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
local o = s:option(ListValue, option_name("balancingStrategy"), translate("Balancing Strategy")) local o = s:option(ListValue, option_name("balancingStrategy"), translate("Balancing Strategy"))
add_xray_depends(o, { [option_name("protocol")] = "_balancing" }) o:depends({ [option_name("protocol")] = "_balancing" })
add_v2ray_depends(o, { [option_name("protocol")] = "_balancing" })
o:value("random") o:value("random")
o:value("leastPing") o:value("leastPing")
o.default = "random" o.default = "random"
-- 探测地址 -- 探测地址
local o = s:option(Flag, option_name("useCustomProbeUrl"), translate("Use Custome Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL.")) local o = s:option(Flag, option_name("useCustomProbeUrl"), translate("Use Custome Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL."))
add_xray_depends(o, { [option_name("balancingStrategy")] = "leastPing" }) o:depends({ [option_name("balancingStrategy")] = "leastPing" })
add_v2ray_depends(o, { [option_name("balancingStrategy")] = "leastPing" })
local o = s:option(Value, option_name("probeUrl"), translate("Probe URL")) local o = s:option(Value, option_name("probeUrl"), translate("Probe URL"))
add_xray_depends(o, { [option_name("useCustomProbeUrl")] = true }) o:depends({ [option_name("useCustomProbeUrl")] = true })
add_v2ray_depends(o, { [option_name("useCustomProbeUrl")] = true })
o.default = "https://www.google.com/generate_204" o.default = "https://www.google.com/generate_204"
o.description = translate("The URL used to detect the connection status.") o.description = translate("The URL used to detect the connection status.")
-- 探测间隔 -- 探测间隔
local o = s:option(Value, option_name("probeInterval"), translate("Probe Interval")) local o = s:option(Value, option_name("probeInterval"), translate("Probe Interval"))
add_xray_depends(o, { [option_name("balancingStrategy")] = "leastPing" }) o:depends({ [option_name("balancingStrategy")] = "leastPing" })
add_v2ray_depends(o, { [option_name("balancingStrategy")] = "leastPing" })
o.default = "1m" o.default = "1m"
o.description = translate("The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.") o.description = translate("The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.")
@ -163,11 +121,9 @@ o.description = translate("The interval between initiating probes. Every time th
if #nodes_table > 0 then if #nodes_table > 0 then
o = s:option(Flag, option_name("preproxy_enabled"), translate("Preproxy")) o = s:option(Flag, option_name("preproxy_enabled"), translate("Preproxy"))
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [option_name("protocol")] = "_shunt" })
add_v2ray_depends(o, { [option_name("protocol")] = "_shunt" })
o = s:option(Value, option_name("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not.")) o = s:option(Value, option_name("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not."))
o:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true }) o:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true })
add_v2ray_depends(o, { [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true })
for k, v in pairs(balancers_table) do for k, v in pairs(balancers_table) do
o:value(v.id, v.remarks) o:value(v.id, v.remarks)
end end
@ -187,7 +143,6 @@ uci:foreach(appname, "shunt_rules", function(e)
o:value("_direct", translate("Direct Connection")) o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole")) o:value("_blackhole", translate("Blackhole"))
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [option_name("protocol")] = "_shunt" })
add_v2ray_depends(o, { [option_name("protocol")] = "_shunt" })
if #nodes_table > 0 then if #nodes_table > 0 then
for k, v in pairs(balancers_table) do for k, v in pairs(balancers_table) do
@ -203,7 +158,6 @@ uci:foreach(appname, "shunt_rules", function(e)
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks) o:value(v.id, v.remarks)
pt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name(e[".name"])] = v.id }) pt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name(e[".name"])] = v.id })
add_v2ray_depends(o, { [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name(e[".name"])] = v.id })
end end
end end
end end
@ -258,134 +212,88 @@ o:depends({ [option_name("protocol")] = "_shunt" })
-- [[ 分流模块 End ]] -- [[ 分流模块 End ]]
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)")) o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
add_xray_depends(o, { [option_name("protocol")] = "vmess" })
add_xray_depends(o, { [option_name("protocol")] = "vless" })
add_xray_depends(o, { [option_name("protocol")] = "http" })
add_xray_depends(o, { [option_name("protocol")] = "socks" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" })
add_xray_depends(o, { [option_name("protocol")] = "trojan" })
add_xray_depends(o, { [option_name("protocol")] = "wireguard" })
add_v2ray_depends(o, { [option_name("protocol")] = "vmess" })
add_v2ray_depends(o, { [option_name("protocol")] = "vless" })
add_v2ray_depends(o, { [option_name("protocol")] = "http" })
add_v2ray_depends(o, { [option_name("protocol")] = "socks" })
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" })
add_v2ray_depends(o, { [option_name("protocol")] = "trojan" })
o = s:option(Value, option_name("port"), translate("Port")) o = s:option(Value, option_name("port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
add_xray_depends(o, { [option_name("protocol")] = "vmess" })
add_xray_depends(o, { [option_name("protocol")] = "vless" }) local protocols = s.fields[option_name("protocol")].keylist
add_xray_depends(o, { [option_name("protocol")] = "http" }) if #protocols > 0 then
add_xray_depends(o, { [option_name("protocol")] = "socks" }) for index, value in ipairs(protocols) do
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" }) if not value:find("_") then
add_xray_depends(o, { [option_name("protocol")] = "trojan" }) s.fields[option_name("address")]:depends({ [option_name("protocol")] = value })
add_xray_depends(o, { [option_name("protocol")] = "wireguard" }) s.fields[option_name("port")]:depends({ [option_name("protocol")] = value })
add_v2ray_depends(o, { [option_name("protocol")] = "vmess" }) end
add_v2ray_depends(o, { [option_name("protocol")] = "vless" }) end
add_v2ray_depends(o, { [option_name("protocol")] = "http" }) end
add_v2ray_depends(o, { [option_name("protocol")] = "socks" })
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" })
add_v2ray_depends(o, { [option_name("protocol")] = "trojan" })
o = s:option(Value, option_name("username"), translate("Username")) o = s:option(Value, option_name("username"), translate("Username"))
add_xray_depends(o, { [option_name("protocol")] = "http" }) o:depends({ [option_name("protocol")] = "http" })
add_xray_depends(o, { [option_name("protocol")] = "socks" }) o:depends({ [option_name("protocol")] = "socks" })
add_v2ray_depends(o, { [option_name("protocol")] = "http" })
add_v2ray_depends(o, { [option_name("protocol")] = "socks" })
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, option_name("password"), translate("Password"))
o.password = true o.password = true
add_xray_depends(o, { [option_name("protocol")] = "http" }) o:depends({ [option_name("protocol")] = "http" })
add_xray_depends(o, { [option_name("protocol")] = "socks" }) o:depends({ [option_name("protocol")] = "socks" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks" })
add_xray_depends(o, { [option_name("protocol")] = "trojan" }) o:depends({ [option_name("protocol")] = "trojan" })
add_v2ray_depends(o, { [option_name("protocol")] = "http" })
add_v2ray_depends(o, { [option_name("protocol")] = "socks" })
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" })
add_v2ray_depends(o, { [option_name("protocol")] = "trojan" })
o = s:option(ListValue, option_name("security"), translate("Encrypt Method")) o = s:option(ListValue, option_name("security"), translate("Encrypt Method"))
for a, t in ipairs(security_list) do o:value(t) end for a, t in ipairs(security_list) do o:value(t) end
add_xray_depends(o, { [option_name("protocol")] = "vmess" }) o:depends({ [option_name("protocol")] = "vmess" })
add_v2ray_depends(o, { [option_name("protocol")] = "vmess" })
o = s:option(Value, option_name("encryption"), translate("Encrypt Method")) o = s:option(Value, option_name("encryption"), translate("Encrypt Method"))
o.default = "none" o.default = "none"
o:value("none") o:value("none")
add_xray_depends(o, { [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "vless" })
add_v2ray_depends(o, { [option_name("protocol")] = "vless" })
o = s:option(ListValue, "v_ss_encrypt_method", translate("Encrypt Method"))
o.not_rewrite = true
for a, t in ipairs(v_ss_encrypt_method_list) do o:value(t) end
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" })
function o.cfgvalue(self, section)
return m:get(section, "method")
end
function o.write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == "Xray" or s.fields["type"]:formvalue(arg[1]) == "V2ray" then
m:set(section, "method", value)
end
end
o = s:option(ListValue, option_name("x_ss_encrypt_method"), translate("Encrypt Method")) o = s:option(ListValue, option_name("x_ss_encrypt_method"), translate("Encrypt Method"))
o.not_rewrite = true o.not_rewrite = true
for a, t in ipairs(x_ss_encrypt_method_list) do o:value(t) end for a, t in ipairs(x_ss_encrypt_method_list) do o:value(t) end
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks" })
function o.cfgvalue(self, section) function o.cfgvalue(self, section)
return m:get(section, "method") return m:get(section, "method")
end end
function o.write(self, section, value) function o.write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == "Xray" or s.fields["type"]:formvalue(arg[1]) == "V2ray" then if s.fields["type"]:formvalue(arg[1]) == type_name then
m:set(section, "method", value) m:set(section, "method", value)
end end
end end
o = s:option(Flag, option_name("iv_check"), translate("IV Check")) o = s:option(Flag, option_name("iv_check"), translate("IV Check"))
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "aes-128-gcm" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "aes-128-gcm" }) o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "aes-256-gcm" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "aes-256-gcm" }) o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "chacha20-poly1305" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "chacha20-poly1305" }) o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "xchacha20-poly1305" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "xchacha20-poly1305" })
o = s:option(Flag, option_name("uot"), translate("UDP over TCP"), translate("Need Xray-core or sing-box as server side.")) o = s:option(Flag, option_name("uot"), translate("UDP over TCP"), translate("Need Xray-core or sing-box as server side."))
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "2022-blake3-aes-128-gcm" }) o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "2022-blake3-aes-128-gcm" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "2022-blake3-aes-256-gcm" }) o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "2022-blake3-aes-256-gcm" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "2022-blake3-chacha20-poly1305" }) o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("x_ss_encrypt_method")] = "2022-blake3-chacha20-poly1305" })
o = s:option(Value, option_name("uuid"), translate("ID")) o = s:option(Value, option_name("uuid"), translate("ID"))
o.password = true o.password = true
add_xray_depends(o, { [option_name("protocol")] = "vmess" }) o:depends({ [option_name("protocol")] = "vmess" })
add_xray_depends(o, { [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "vless" })
add_v2ray_depends(o, { [option_name("protocol")] = "vmess" })
add_v2ray_depends(o, { [option_name("protocol")] = "vless" })
o = s:option(Flag, option_name("tls"), translate("TLS")) o = s:option(ListValue, option_name("flow"), translate("flow"))
o.default = 0
add_xray_depends(o, { [option_name("protocol")] = "vmess" })
add_xray_depends(o, { [option_name("protocol")] = "vless" })
add_xray_depends(o, { [option_name("protocol")] = "socks" })
add_xray_depends(o, { [option_name("protocol")] = "trojan" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" })
add_v2ray_depends(o, { [option_name("protocol")] = "vmess" })
add_v2ray_depends(o, { [option_name("protocol")] = "vless" })
add_v2ray_depends(o, { [option_name("protocol")] = "socks" })
add_v2ray_depends(o, { [option_name("protocol")] = "trojan" })
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" })
o = s:option(Value, option_name("tlsflow"), translate("flow"))
o.default = "" o.default = ""
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("xtls-rprx-vision") o:value("xtls-rprx-vision")
o:value("xtls-rprx-vision-udp443") o:depends({ [option_name("protocol")] = "vless" })
add_xray_depends(o, { [option_name("protocol")] = "vless", [option_name("tls")] = true, [option_name("transport")] = "tcp" })
o = s:option(Flag, option_name("reality"), translate("REALITY"), translate("Only recommend to use with VLESS-TCP-XTLS-Vision.")) o = s:option(Flag, option_name("tls"), translate("TLS"))
o.default = 0 o.default = 0
add_xray_depends(o, { [option_name("tls")] = true, [option_name("transport")] = "tcp" }) o:depends({ [option_name("protocol")] = "vmess" })
add_xray_depends(o, { [option_name("tls")] = true, [option_name("transport")] = "h2" }) o:depends({ [option_name("protocol")] = "vless" })
add_xray_depends(o, { [option_name("tls")] = true, [option_name("transport")] = "grpc" }) o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o = s:option(Flag, option_name("reality"), translate("REALITY"))
o.default = 0
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "tcp" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "h2" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "grpc" })
o = s:option(ListValue, option_name("alpn"), translate("alpn")) o = s:option(ListValue, option_name("alpn"), translate("alpn"))
o.default = "default" o.default = "default"
@ -393,72 +301,49 @@ o:value("default", translate("Default"))
o:value("h2,http/1.1") o:value("h2,http/1.1")
o:value("h2") o:value("h2")
o:value("http/1.1") o:value("http/1.1")
add_xray_depends(o, { [option_name("tls")] = true, [option_name("reality")] = false }) o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
add_v2ray_depends(o, { [option_name("tls")] = true })
-- o = s:option(Value, option_name("minversion"), translate("minversion")) -- o = s:option(Value, option_name("minversion"), translate("minversion"))
-- o.default = "1.3" -- o.default = "1.3"
-- o:value("1.3") -- o:value("1.3")
-- add_xray_depends(o, { [option_name("tls")] = true }) -- o:depends({ [option_name("tls")] = true })
-- add_v2ray_depends(o, { [option_name("tls")] = true })
o = s:option(Value, option_name("tls_serverName"), translate("Domain")) o = s:option(Value, option_name("tls_serverName"), translate("Domain"))
add_xray_depends(o, { [option_name("tls")] = true }) o:depends({ [option_name("tls")] = true })
add_v2ray_depends(o, { [option_name("tls")] = true })
o = s:option(Flag, option_name("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped.")) o = s:option(Flag, option_name("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
o.default = "0" o.default = "0"
add_xray_depends(o, { [option_name("tls")] = true, [option_name("reality")] = false }) o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
add_v2ray_depends(o, { [option_name("tls")] = true })
o = s:option(Value, option_name("fingerprint"), translate("Finger Print"), translate("Avoid using randomized, unless you have to."))
o:value("", translate("Disable"))
o:value("chrome")
o:value("firefox")
o:value("safari")
o:value("ios")
-- o:value("android")
o:value("edge")
-- o:value("360")
o:value("qq")
o:value("random")
o:value("randomized")
o.default = ""
add_xray_depends(o, { [option_name("tls")] = true, [option_name("reality")] = false })
-- [[ REALITY部分 ]] -- -- [[ REALITY部分 ]] --
o = s:option(Value, option_name("reality_publicKey"), translate("Public Key")) o = s:option(Value, option_name("reality_publicKey"), translate("Public Key"))
add_xray_depends(o, { [option_name("tls")] = true, [option_name("reality")] = true }) o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
o = s:option(Value, option_name("reality_shortId"), translate("Short Id")) o = s:option(Value, option_name("reality_shortId"), translate("Short Id"))
add_xray_depends(o, { [option_name("tls")] = true, [option_name("reality")] = true }) o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
o = s:option(Value, option_name("reality_spiderX"), translate("Spider X")) o = s:option(Value, option_name("reality_spiderX"), translate("Spider X"))
o.placeholder = "/" o.placeholder = "/"
add_xray_depends(o, { [option_name("tls")] = true, [option_name("reality")] = true }) o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
o = s:option(Value, option_name("reality_fingerprint"), translate("Finger Print"), translate("Avoid using randomized, unless you have to.")) o = s:option(Flag, option_name("utls"), translate("uTLS"))
o.not_rewrite = true o.default = "0"
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
o = s:option(ListValue, option_name("fingerprint"), translate("Finger Print"))
o:value("chrome") o:value("chrome")
o:value("firefox") o:value("firefox")
o:value("safari")
o:value("ios")
-- o:value("android")
o:value("edge") o:value("edge")
-- o:value("360") o:value("safari")
o:value("360")
o:value("qq") o:value("qq")
o:value("ios")
o:value("android")
o:value("random") o:value("random")
o:value("randomized") o:value("randomized")
o.default = "chrome" o.default = "chrome"
add_xray_depends(o, { [option_name("tls")] = true, [option_name("reality")] = true }) o:depends({ [option_name("tls")] = true, [option_name("utls")] = true })
function o.cfgvalue(self, section) o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
return m:get(section, "fingerprint")
end
function o.write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == "Xray" or s.fields["type"]:formvalue(arg[1]) == "V2ray" then
m:set(section, "fingerprint", value)
end
end
o = s:option(ListValue, option_name("transport"), translate("Transport")) o = s:option(ListValue, option_name("transport"), translate("Transport"))
o:value("tcp", "TCP") o:value("tcp", "TCP")
@ -468,50 +353,44 @@ o:value("h2", "HTTP/2")
o:value("ds", "DomainSocket") o:value("ds", "DomainSocket")
o:value("quic", "QUIC") o:value("quic", "QUIC")
o:value("grpc", "gRPC") o:value("grpc", "gRPC")
add_xray_depends(o, { [option_name("protocol")] = "vmess" }) o:depends({ [option_name("protocol")] = "vmess" })
add_xray_depends(o, { [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "vless" })
add_xray_depends(o, { [option_name("protocol")] = "socks" }) o:depends({ [option_name("protocol")] = "socks" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks" })
add_xray_depends(o, { [option_name("protocol")] = "trojan" }) o:depends({ [option_name("protocol")] = "trojan" })
add_v2ray_depends(o, { [option_name("protocol")] = "vmess" })
add_v2ray_depends(o, { [option_name("protocol")] = "vless" })
add_v2ray_depends(o, { [option_name("protocol")] = "socks" })
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" })
add_v2ray_depends(o, { [option_name("protocol")] = "trojan" })
--[[ --[[
o = s:option(ListValue, option_name("ss_transport"), translate("Transport")) o = s:option(ListValue, option_name("ss_transport"), translate("Transport"))
o:value("ws", "WebSocket") o:value("ws", "WebSocket")
o:value("h2", "HTTP/2") o:value("h2", "HTTP/2")
o:value("h2+ws", "HTTP/2 & WebSocket") o:value("h2+ws", "HTTP/2 & WebSocket")
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks" })
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" })
]]-- ]]--
o = s:option(Value, option_name("wireguard_public_key"), translate("Public Key")) o = s:option(Value, option_name("wireguard_public_key"), translate("Public Key"))
add_xray_depends(o, { [option_name("protocol")] = "wireguard" }) o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_secret_key"), translate("Private Key")) o = s:option(Value, option_name("wireguard_secret_key"), translate("Private Key"))
add_xray_depends(o, { [option_name("protocol")] = "wireguard" }) o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_preSharedKey"), translate("Pre shared key")) o = s:option(Value, option_name("wireguard_preSharedKey"), translate("Pre shared key"))
add_xray_depends(o, { [option_name("protocol")] = "wireguard" }) o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(DynamicList, option_name("wireguard_local_address"), translate("Local Address")) o = s:option(DynamicList, option_name("wireguard_local_address"), translate("Local Address"))
add_xray_depends(o, { [option_name("protocol")] = "wireguard" }) o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_mtu"), translate("MTU")) o = s:option(Value, option_name("wireguard_mtu"), translate("MTU"))
o.default = "1420" o.default = "1420"
add_xray_depends(o, { [option_name("protocol")] = "wireguard" }) o:depends({ [option_name("protocol")] = "wireguard" })
if api.compare_versions(api.get_app_version("xray"), ">=", "1.8.0") then if api.compare_versions(api.get_app_version("xray"), ">=", "1.8.0") then
o = s:option(Value, option_name("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings.")) o = s:option(Value, option_name("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
add_xray_depends(o, { [option_name("protocol")] = "wireguard" }) o:depends({ [option_name("protocol")] = "wireguard" })
end end
o = s:option(Value, option_name("wireguard_keepAlive"), translate("Keep Alive")) o = s:option(Value, option_name("wireguard_keepAlive"), translate("Keep Alive"))
o.default = "0" o.default = "0"
add_xray_depends(o, { [option_name("protocol")] = "wireguard" }) o:depends({ [option_name("protocol")] = "wireguard" })
-- [[ TCP部分 ]]-- -- [[ TCP部分 ]]--
@ -519,194 +398,152 @@ add_xray_depends(o, { [option_name("protocol")] = "wireguard" })
o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type")) o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type"))
o:value("none", "none") o:value("none", "none")
o:value("http", "http") o:value("http", "http")
add_xray_depends(o, { [option_name("transport")] = "tcp" }) o:depends({ [option_name("transport")] = "tcp" })
add_v2ray_depends(o, { [option_name("transport")] = "tcp" })
-- HTTP域名 -- HTTP域名
o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host")) o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host"))
add_xray_depends(o, { [option_name("tcp_guise")] = "http" }) o:depends({ [option_name("tcp_guise")] = "http" })
add_v2ray_depends(o, { [option_name("tcp_guise")] = "http" })
-- HTTP路径 -- HTTP路径
o = s:option(DynamicList, option_name("tcp_guise_http_path"), translate("HTTP Path")) o = s:option(DynamicList, option_name("tcp_guise_http_path"), translate("HTTP Path"))
o.placeholder = "/" o.placeholder = "/"
add_xray_depends(o, { [option_name("tcp_guise")] = "http" }) o:depends({ [option_name("tcp_guise")] = "http" })
add_v2ray_depends(o, { [option_name("tcp_guise")] = "http" })
-- [[ mKCP部分 ]]-- -- [[ mKCP部分 ]]--
o = s:option(ListValue, option_name("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)')) o = s:option(ListValue, option_name("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 o:value(t) end for a, t in ipairs(header_type_list) do o:value(t) end
add_xray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_mtu"), translate("KCP MTU")) o = s:option(Value, option_name("mkcp_mtu"), translate("KCP MTU"))
o.default = "1350" o.default = "1350"
add_xray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_tti"), translate("KCP TTI")) o = s:option(Value, option_name("mkcp_tti"), translate("KCP TTI"))
o.default = "20" o.default = "20"
add_xray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity")) o = s:option(Value, option_name("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity"))
o.default = "5" o.default = "5"
add_xray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity")) o = s:option(Value, option_name("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity"))
o.default = "20" o.default = "20"
add_xray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Flag, option_name("mkcp_congestion"), translate("KCP Congestion")) o = s:option(Flag, option_name("mkcp_congestion"), translate("KCP Congestion"))
add_xray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_readBufferSize"), translate("KCP readBufferSize")) o = s:option(Value, option_name("mkcp_readBufferSize"), translate("KCP readBufferSize"))
o.default = "1" o.default = "1"
add_xray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_writeBufferSize"), translate("KCP writeBufferSize")) o = s:option(Value, option_name("mkcp_writeBufferSize"), translate("KCP writeBufferSize"))
o.default = "1" o.default = "1"
add_xray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_seed"), translate("KCP Seed")) o = s:option(Value, option_name("mkcp_seed"), translate("KCP Seed"))
add_xray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" })
-- [[ WebSocket部分 ]]-- -- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host")) o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
add_xray_depends(o, { [option_name("transport")] = "ws" }) o:depends({ [option_name("transport")] = "ws" })
add_xray_depends(o, { [option_name("ss_transport")] = "ws" }) o:depends({ [option_name("ss_transport")] = "ws" })
add_v2ray_depends(o, { [option_name("transport")] = "ws" })
add_v2ray_depends(o, { [option_name("ss_transport")] = "ws" })
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path")) o = s:option(Value, option_name("ws_path"), translate("WebSocket Path"))
o.placeholder = "/" o.placeholder = "/"
add_xray_depends(o, { [option_name("transport")] = "ws" }) o:depends({ [option_name("transport")] = "ws" })
add_xray_depends(o, { [option_name("ss_transport")] = "ws" }) o:depends({ [option_name("ss_transport")] = "ws" })
add_v2ray_depends(o, { [option_name("transport")] = "ws" })
add_v2ray_depends(o, { [option_name("ss_transport")] = "ws" })
o = s:option(Flag, "v2ray_ws_enableEarlyData", translate("Enable early data"))
add_v2ray_depends(o, { [option_name("transport")] = "ws" })
o = s:option(Value, "v2ray_ws_maxEarlyData", translate("Early data length"))
o.default = "1024"
add_v2ray_depends(o, { v2ray_ws_enableEarlyData = true })
o = s:option(Value, "v2ray_ws_earlyDataHeaderName", translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol"))
add_v2ray_depends(o, { v2ray_ws_enableEarlyData = true })
-- [[ HTTP/2部分 ]]-- -- [[ HTTP/2部分 ]]--
o = s:option(Value, option_name("h2_host"), translate("HTTP/2 Host")) o = s:option(Value, option_name("h2_host"), translate("HTTP/2 Host"))
add_xray_depends(o, { [option_name("transport")] = "h2" }) o:depends({ [option_name("transport")] = "h2" })
add_xray_depends(o, { [option_name("ss_transport")] = "h2" }) o:depends({ [option_name("ss_transport")] = "h2" })
add_v2ray_depends(o, { [option_name("transport")] = "h2" })
add_v2ray_depends(o, { [option_name("ss_transport")] = "h2" })
o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path")) o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path"))
o.placeholder = "/" o.placeholder = "/"
add_xray_depends(o, { [option_name("transport")] = "h2" }) o:depends({ [option_name("transport")] = "h2" })
add_xray_depends(o, { [option_name("ss_transport")] = "h2" }) o:depends({ [option_name("ss_transport")] = "h2" })
add_v2ray_depends(o, { [option_name("transport")] = "h2" })
add_v2ray_depends(o, { [option_name("ss_transport")] = "h2" })
o = s:option(Flag, option_name("h2_health_check"), translate("Health check")) o = s:option(Flag, option_name("h2_health_check"), translate("Health check"))
add_xray_depends(o, { [option_name("transport")] = "h2" }) o:depends({ [option_name("transport")] = "h2" })
o = s:option(Value, option_name("h2_read_idle_timeout"), translate("Idle timeout")) o = s:option(Value, option_name("h2_read_idle_timeout"), translate("Idle timeout"))
o.default = "10" o.default = "10"
add_xray_depends(o, { [option_name("h2_health_check")] = true }) o:depends({ [option_name("h2_health_check")] = true })
o = s:option(Value, option_name("h2_health_check_timeout"), translate("Health check timeout")) o = s:option(Value, option_name("h2_health_check_timeout"), translate("Health check timeout"))
o.default = "15" o.default = "15"
add_xray_depends(o, { [option_name("h2_health_check")] = true }) o:depends({ [option_name("h2_health_check")] = true })
-- [[ DomainSocket部分 ]]-- -- [[ DomainSocket部分 ]]--
o = s:option(Value, option_name("ds_path"), "Path", translate("A legal file path. This file must not exist before running.")) o = s:option(Value, option_name("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
add_xray_depends(o, { [option_name("transport")] = "ds" }) o:depends({ [option_name("transport")] = "ds" })
add_v2ray_depends(o, { [option_name("transport")] = "ds" })
-- [[ QUIC部分 ]]-- -- [[ QUIC部分 ]]--
o = s:option(ListValue, option_name("quic_security"), translate("Encrypt Method")) o = s:option(ListValue, option_name("quic_security"), translate("Encrypt Method"))
o:value("none") o:value("none")
o:value("aes-128-gcm") o:value("aes-128-gcm")
o:value("chacha20-poly1305") o:value("chacha20-poly1305")
add_xray_depends(o, { [option_name("transport")] = "quic" }) o:depends({ [option_name("transport")] = "quic" })
add_v2ray_depends(o, { [option_name("transport")] = "quic" })
o = s:option(Value, option_name("quic_key"), translate("Encrypt Method") .. translate("Key")) o = s:option(Value, option_name("quic_key"), translate("Encrypt Method") .. translate("Key"))
add_xray_depends(o, { [option_name("transport")] = "quic" }) o:depends({ [option_name("transport")] = "quic" })
add_v2ray_depends(o, { [option_name("transport")] = "quic" })
o = s:option(ListValue, option_name("quic_guise"), translate("Camouflage Type")) o = s:option(ListValue, option_name("quic_guise"), translate("Camouflage Type"))
for a, t in ipairs(header_type_list) do o:value(t) end for a, t in ipairs(header_type_list) do o:value(t) end
add_xray_depends(o, { [option_name("transport")] = "quic" }) o:depends({ [option_name("transport")] = "quic" })
add_v2ray_depends(o, { [option_name("transport")] = "quic" })
-- [[ gRPC部分 ]]-- -- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName") o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
add_xray_depends(o, { [option_name("transport")] = "grpc" }) o:depends({ [option_name("transport")] = "grpc" })
add_v2ray_depends(o, { [option_name("transport")] = "grpc" })
o = s:option(ListValue, option_name("grpc_mode"), "gRPC " .. translate("Transfer mode")) o = s:option(ListValue, option_name("grpc_mode"), "gRPC " .. translate("Transfer mode"))
o:value("gun") o:value("gun")
o:value("multi") o:value("multi")
add_xray_depends(o, { [option_name("transport")] = "grpc" }) o:depends({ [option_name("transport")] = "grpc" })
o = s:option(Flag, option_name("grpc_health_check"), translate("Health check")) o = s:option(Flag, option_name("grpc_health_check"), translate("Health check"))
add_xray_depends(o, { [option_name("transport")] = "grpc" }) o:depends({ [option_name("transport")] = "grpc" })
o = s:option(Value, option_name("grpc_idle_timeout"), translate("Idle timeout")) o = s:option(Value, option_name("grpc_idle_timeout"), translate("Idle timeout"))
o.default = "10" o.default = "10"
add_xray_depends(o, { [option_name("grpc_health_check")] = true }) o:depends({ [option_name("grpc_health_check")] = true })
o = s:option(Value, option_name("grpc_health_check_timeout"), translate("Health check timeout")) o = s:option(Value, option_name("grpc_health_check_timeout"), translate("Health check timeout"))
o.default = "20" o.default = "20"
add_xray_depends(o, { [option_name("grpc_health_check")] = true }) o:depends({ [option_name("grpc_health_check")] = true })
o = s:option(Flag, option_name("grpc_permit_without_stream"), translate("Permit without stream")) o = s:option(Flag, option_name("grpc_permit_without_stream"), translate("Permit without stream"))
o.default = "0" o.default = "0"
add_xray_depends(o, { [option_name("grpc_health_check")] = true }) o:depends({ [option_name("grpc_health_check")] = true })
o = s:option(Value, option_name("grpc_initial_windows_size"), translate("Initial Windows Size")) o = s:option(Value, option_name("grpc_initial_windows_size"), translate("Initial Windows Size"))
o.default = "0" o.default = "0"
add_xray_depends(o, { [option_name("transport")] = "grpc" }) o:depends({ [option_name("transport")] = "grpc" })
-- [[ Mux ]]-- -- [[ Mux ]]--
o = s:option(Flag, option_name("mux"), translate("Mux")) o = s:option(Flag, option_name("mux"), translate("Mux"))
add_v2ray_depends(o, { [option_name("protocol")] = "vmess" }) o:depends({ [option_name("protocol")] = "vmess" })
add_v2ray_depends(o, { [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" })
add_v2ray_depends(o, { [option_name("protocol")] = "http" }) o:depends({ [option_name("protocol")] = "http" })
add_v2ray_depends(o, { [option_name("protocol")] = "socks" }) o:depends({ [option_name("protocol")] = "socks" })
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks" })
add_v2ray_depends(o, { [option_name("protocol")] = "trojan" }) o:depends({ [option_name("protocol")] = "trojan" })
add_xray_depends(o, { [option_name("protocol")] = "vmess" })
add_xray_depends(o, { [option_name("protocol")] = "vless", [option_name("tlsflow")] = "" })
add_xray_depends(o, { [option_name("protocol")] = "http" })
add_xray_depends(o, { [option_name("protocol")] = "socks" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" })
add_xray_depends(o, { [option_name("protocol")] = "trojan" })
o = s:option(Value, option_name("mux_concurrency"), translate("Mux concurrency")) o = s:option(Value, option_name("mux_concurrency"), translate("Mux concurrency"))
o.default = 8 o.default = 8
add_xray_depends(o, { [option_name("mux")] = true }) o:depends({ [option_name("mux")] = true })
add_v2ray_depends(o, { [option_name("mux")] = true })
-- [[ XUDP Mux ]]-- -- [[ XUDP Mux ]]--
o = s:option(Flag, option_name("xmux"), translate("xMux")) o = s:option(Flag, option_name("xmux"), translate("xMux"))
o.default = 1 o.default = 1
add_xray_depends(o, { [option_name("protocol")] = "vless", [option_name("tlsflow")] = "xtls-rprx-vision" }) o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "xtls-rprx-vision" })
add_xray_depends(o, { [option_name("protocol")] = "vless", [option_name("tlsflow")] = "xtls-rprx-vision-udp443" }) o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "xtls-rprx-vision-udp443" })
o = s:option(Value, option_name("xudp_concurrency"), translate("XUDP Mux concurrency")) o = s:option(Value, option_name("xudp_concurrency"), translate("XUDP Mux concurrency"))
o.default = 8 o.default = 8
add_xray_depends(o, { [option_name("xmux")] = true }) o:depends({ [option_name("xmux")] = true })
for key, value in pairs(s.fields) do for key, value in pairs(s.fields) do
if key:find(option_prefix) == 1 then if key:find(option_prefix) == 1 then
@ -715,5 +552,14 @@ for key, value in pairs(s.fields) do
s.fields[key].write = rm_prefix_write s.fields[key].write = rm_prefix_write
s.fields[key].remove = rm_prefix_remove s.fields[key].remove = rm_prefix_remove
end end
local deps = s.fields[key].deps
if #deps > 0 then
for index, value in ipairs(deps) do
deps[index]["type"] = type_name
end
else
s.fields[key]:depends({ type = type_name })
end
end end
end end

View File

@ -0,0 +1,567 @@
local m, s = ...
local api = require "luci.passwall2.api"
if not api.is_finded("sing-box") then
return
end
local singbox_tags = luci.sys.exec(api.finded("sing-box") .. " version | grep 'Tags:' | awk '{print $2}'")
local appname = api.appname
local uci = api.uci
local type_name = "sing-box"
local option_prefix = "singbox_"
local function option_name(name)
return option_prefix .. name
end
local function rm_prefix_cfgvalue(self, section)
if self.option:find(option_prefix) == 1 then
return m:get(section, self.option:sub(1 + #option_prefix))
end
end
local function rm_prefix_write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == type_name then
if self.option:find(option_prefix) == 1 then
m:set(section, self.option:sub(1 + #option_prefix), value)
end
end
end
local function rm_prefix_remove(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == type_name then
if self.option:find(option_prefix) == 1 then
m:del(section, self.option:sub(1 + #option_prefix))
end
end
end
local ss_method_new_list = {
"none", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"
}
local ss_method_old_list = {
"aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "rc4-md5", "chacha20-ietf", "xchacha20",
}
local security_list = { "none", "auto", "aes-128-gcm", "chacha20-poly1305", "zero" }
-- [[ sing-box ]]
s.fields["type"]:value(type_name, translate("Sing-Box"))
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
o:value("socks", "Socks")
o:value("http", "HTTP")
o:value("shadowsocks", "Shadowsocks")
if singbox_tags:find("with_shadowsocksr") then
o:value("shadowsocksr", "ShadowsocksR")
end
o:value("vmess", "Vmess")
o:value("trojan", "Trojan")
if singbox_tags:find("with_wireguard") then
o:value("wireguard", "WireGuard")
end
if singbox_tags:find("with_quic") then
o:value("hysteria", "Hysteria")
end
o:value("shadowtls", "ShadowTLS")
o:value("vless", "VLESS")
if singbox_tags:find("with_quic") then
o:value("tuic", "TUIC")
end
if singbox_tags:find("with_quic") then
o:value("hysteria2", "Hysteria2")
end
o:value("_shunt", translate("Shunt"))
o:value("_iface", translate("Custom Interface") .. " (Only Support Xray)")
o = s:option(Value, option_name("iface"), translate("Interface"))
o.default = "eth1"
o:depends({ [option_name("protocol")] = "_iface" })
local nodes_table = {}
local balancers_table = {}
local iface_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" then
nodes_table[#nodes_table + 1] = {
id = e[".name"],
remarks = e["remark"]
}
end
if e.protocol == "_iface" then
iface_table[#iface_table + 1] = {
id = e[".name"],
remarks = e["remark"]
}
end
end
-- [[ 分流模块 ]]
if #nodes_table > 0 then
o = s:option(Flag, option_name("preproxy_enabled"), translate("Preproxy"))
o:depends({ [option_name("protocol")] = "_shunt" })
o = s:option(Value, option_name("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not."))
o:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true })
for k, v in pairs(balancers_table) do
o:value(v.id, v.remarks)
end
for k, v in pairs(iface_table) do
o:value(v.id, v.remarks)
end
for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
end
o.default = "nil"
end
uci:foreach(appname, "shunt_rules", function(e)
if e[".name"] and e.remarks then
o = s:option(Value, option_name(e[".name"]), string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks))
o:value("nil", translate("Close"))
o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
o:depends({ [option_name("protocol")] = "_shunt" })
if #nodes_table > 0 then
for k, v in pairs(balancers_table) do
o:value(v.id, v.remarks)
end
for k, v in pairs(iface_table) do
o:value(v.id, v.remarks)
end
local pt = s:option(ListValue, option_name(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
pt:value("nil", translate("Close"))
pt:value("main", translate("Preproxy Node"))
pt.default = "nil"
for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
pt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name(e[".name"])] = v.id })
end
end
end
end)
o = s:option(DummyValue, option_name("shunt_tips"), " ")
o.not_rewrite = true
o.rawhtml = true
o.cfgvalue = function(t, n)
return string.format('<a style="color: red" href="../rule">%s</a>', translate("No shunt rules? Click me to go to add."))
end
o:depends({ [option_name("protocol")] = "_shunt" })
local o = s:option(Value, option_name("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default")))
o:depends({ [option_name("protocol")] = "_shunt" })
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
if #nodes_table > 0 then
for k, v in pairs(balancers_table) do
o:value(v.id, v.remarks)
end
for k, v in pairs(iface_table) do
o:value(v.id, v.remarks)
end
local dpt = s:option(ListValue, option_name("default_proxy_tag"), string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
dpt:value("nil", translate("Close"))
dpt:value("main", translate("Preproxy Node"))
dpt.default = "nil"
for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
dpt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name("default_node")] = v.id })
end
end
-- [[ 分流模块 End ]]
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
o = s:option(Value, option_name("port"), translate("Port"))
o.datatype = "port"
local protocols = s.fields[option_name("protocol")].keylist
if #protocols > 0 then
for index, value in ipairs(protocols) do
if not value:find("_") then
s.fields[option_name("address")]:depends({ [option_name("protocol")] = value })
s.fields[option_name("port")]:depends({ [option_name("protocol")] = value })
end
end
end
o = s:option(ListValue, option_name("shadowtls_version"), translate("Version"))
o.default = "1"
o:value("1", "ShadowTLS v1")
o:value("2", "ShadowTLS v2")
o:value("3", "ShadowTLS v3")
o:depends({ [option_name("protocol")] = "shadowtls" })
o = s:option(Value, option_name("username"), translate("Username"))
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" })
o = s:option(Value, option_name("password"), translate("Password"))
o.password = true
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "shadowsocksr" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "shadowtls", [option_name("shadowtls_version")] = "2" })
o:depends({ [option_name("protocol")] = "shadowtls", [option_name("shadowtls_version")] = "3" })
o:depends({ [option_name("protocol")] = "tuic" })
o = s:option(ListValue, option_name("security"), translate("Encrypt Method"))
for a, t in ipairs(security_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "vmess" })
o = s:option(ListValue, option_name("ss_method"), translate("Encrypt Method"))
o.not_rewrite = true
for a, t in ipairs(ss_method_new_list) do o:value(t) end
for a, t in ipairs(ss_method_old_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocks" })
function o.cfgvalue(self, section)
return m:get(section, "method")
end
function o.write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == type_name then
m:set(section, "method", value)
end
end
if singbox_tags:find("with_shadowsocksr") then
o = s:option(ListValue, option_name("ssr_method"), translate("Encrypt Method"))
o.not_rewrite = true
for a, t in ipairs(ss_method_old_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocksr" })
function o.cfgvalue(self, section)
return m:get(section, "method")
end
function o.write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == type_name then
m:set(section, "method", value)
end
end
local ssr_protocol_list = {
"origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple",
"auth_sha1", "auth_sha1_v2", "auth_sha1_v4", "auth_aes128_md5",
"auth_aes128_sha1", "auth_chain_a", "auth_chain_b", "auth_chain_c",
"auth_chain_d", "auth_chain_e", "auth_chain_f"
}
o = s:option(ListValue, option_name("ssr_protocol"), translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocksr" })
o = s:option(Value, option_name("ssr_protocol_param"), translate("Protocol_param"))
o:depends({ [option_name("protocol")] = "shadowsocksr" })
local ssr_obfs_list = {
"plain", "http_simple", "http_post", "random_head", "tls_simple",
"tls1.0_session_auth", "tls1.2_ticket_auth"
}
o = s:option(ListValue, option_name("ssr_obfs"), translate("Obfs"))
for a, t in ipairs(ssr_obfs_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocksr" })
o = s:option(Value, option_name("ssr_obfs_param"), translate("Obfs_param"))
o:depends({ [option_name("protocol")] = "shadowsocksr" })
end
o = s:option(Flag, option_name("uot"), translate("UDP over TCP"), translate("Need Xray-core or sing-box as server side."))
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "2022-blake3-aes-128-gcm" })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "2022-blake3-aes-256-gcm" })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "2022-blake3-chacha20-poly1305" })
o = s:option(Value, option_name("uuid"), translate("ID"))
o.password = true
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "tuic" })
o = s:option(ListValue, option_name("flow"), translate("flow"))
o.default = ""
o:value("", translate("Disable"))
o:value("xtls-rprx-vision")
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true })
if singbox_tags:find("with_quic") then
o = s:option(Value, option_name("hysteria_obfs"), translate("Obfs Password"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(ListValue, option_name("hysteria_auth_type"), translate("Auth Type"))
o:value("disable", translate("Disable"))
o:value("string", translate("STRING"))
o:value("base64", translate("BASE64"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_auth_password"), translate("Auth Password"))
o.password = true
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "string"})
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "base64"})
o = s:option(Value, option_name("hysteria_up_mbps"), translate("Max upload Mbps"))
o.default = "10"
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_down_mbps"), translate("Max download Mbps"))
o.default = "50"
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_recv_window"), translate("QUIC connection receive window"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Flag, option_name("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
o:depends({ [option_name("protocol")] = "hysteria" })
end
if singbox_tags:find("with_quic") then
o = s:option(ListValue, option_name("tuic_congestion_control"), translate("Congestion control algorithm"))
o.default = "cubic"
o:value("bbr", translate("BBR"))
o:value("cubic", translate("CUBIC"))
o:value("new_reno", translate("New Reno"))
o:depends({ [option_name("protocol")] = "tuic" })
o = s:option(ListValue, option_name("tuic_udp_relay_mode"), translate("UDP relay mode"))
o.default = "native"
o:value("native", translate("native"))
o:value("quic", translate("QUIC"))
o:depends({ [option_name("protocol")] = "tuic" })
--[[
o = s:option(Flag, option_name("tuic_udp_over_stream"), translate("UDP over stream"))
o:depends({ [option_name("protocol")] = "tuic" })
]]--
o = s:option(Flag, option_name("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
o.default = 0
o:depends({ [option_name("protocol")] = "tuic" })
o = s:option(Value, option_name("tuic_heartbeat"), translate("Heartbeat interval(second)"))
o.datatype = "uinteger"
o.default = "3"
o:depends({ [option_name("protocol")] = "tuic" })
end
if singbox_tags:find("with_quic") then
o = s:option(Value, option_name("hysteria2_up_mbps"), translate("Max upload Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_down_mbps"), translate("Max download Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(ListValue, option_name("hysteria2_obfs_type"), translate("Obfs Type"))
o:value("", translate("Disable"))
o:value("salamander")
o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_obfs_password"), translate("Obfs Password"))
o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_auth_password"), translate("Auth Password"))
o.password = true
o:depends({ [option_name("protocol")] = "hysteria2"})
end
o = s:option(Flag, option_name("tls"), translate("TLS"))
o.default = 0
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "shadowtls" })
if singbox_tags:find("with_reality") then
o = s:option(Flag, option_name("reality"), translate("REALITY"))
o.default = 0
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true })
-- [[ REALITY部分 ]] --
o = s:option(Value, option_name("reality_publicKey"), translate("Public Key"))
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
o = s:option(Value, option_name("reality_shortId"), translate("Short Id"))
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
end
o = s:option(ListValue, option_name("alpn"), translate("alpn"))
o.default = "default"
o:value("default", translate("Default"))
o:value("h2,http/1.1")
o:value("h2")
o:value("http/1.1")
o:depends({ [option_name("tls")] = true })
o = s:option(Value, option_name("tls_serverName"), translate("Domain"))
o:depends({ [option_name("tls")] = true })
o = s:option(Flag, option_name("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
o.default = "0"
o:depends({ [option_name("tls")] = true })
if singbox_tags:find("with_utls") then
o = s:option(Flag, option_name("utls"), translate("uTLS"))
o.default = "0"
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
o = s:option(ListValue, option_name("fingerprint"), translate("Finger Print"))
o:value("chrome")
o:value("firefox")
o:value("edge")
o:value("safari")
o:value("360")
o:value("qq")
o:value("ios")
o:value("android")
o:value("random")
o:value("randomized")
o.default = "chrome"
o:depends({ [option_name("tls")] = true, [option_name("utls")] = true })
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
end
o = s:option(ListValue, option_name("transport"), translate("Transport"))
o:value("tcp", "TCP")
o:value("http", "HTTP")
o:value("ws", "WebSocket")
if singbox_tags:find("with_quic") then
o:value("quic", "QUIC")
end
if singbox_tags:find("with_grpc") then
o:value("grpc", "gRPC")
end
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" })
if singbox_tags:find("with_wireguard") then
o = s:option(Value, option_name("wireguard_public_key"), translate("Public Key"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_secret_key"), translate("Private Key"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_preSharedKey"), translate("Pre shared key"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(DynamicList, option_name("wireguard_local_address"), translate("Local Address"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_mtu"), translate("MTU"))
o.default = "1420"
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
o:depends({ [option_name("protocol")] = "wireguard" })
end
-- [[ HTTP部分 ]]--
o = s:option(Value, option_name("http_host"), translate("HTTP Host"))
o:depends({ [option_name("transport")] = "http" })
o = s:option(Value, option_name("http_path"), translate("HTTP Path"))
o.placeholder = "/"
o:depends({ [option_name("transport")] = "http" })
o = s:option(Flag, option_name("http_h2_health_check"), translate("Health check"))
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "http" })
o = s:option(Value, option_name("http_h2_read_idle_timeout"), translate("Idle timeout"))
o.default = "10"
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "http", [option_name("http_h2_health_check")] = true })
o = s:option(Value, option_name("http_h2_health_check_timeout"), translate("Health check timeout"))
o.default = "15"
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "http", [option_name("http_h2_health_check")] = true })
-- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path"))
o.placeholder = "/"
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Flag, option_name("ws_enableEarlyData"), translate("Enable early data"))
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Value, option_name("ws_maxEarlyData"), translate("Early data length"))
o.default = "1024"
o:depends({ [option_name("ws_enableEarlyData")] = true })
o = s:option(Value, option_name("ws_earlyDataHeaderName"), translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol"))
o:depends({ [option_name("ws_enableEarlyData")] = true })
-- [[ gRPC部分 ]]--
if singbox_tags:find("with_grpc") then
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
o:depends({ [option_name("transport")] = "grpc" })
o = s:option(Flag, option_name("grpc_health_check"), translate("Health check"))
o:depends({ [option_name("transport")] = "grpc" })
o = s:option(Value, option_name("grpc_idle_timeout"), translate("Idle timeout"))
o.default = "10"
o:depends({ [option_name("grpc_health_check")] = true })
o = s:option(Value, option_name("grpc_health_check_timeout"), translate("Health check timeout"))
o.default = "20"
o:depends({ [option_name("grpc_health_check")] = true })
o = s:option(Flag, option_name("grpc_permit_without_stream"), translate("Permit without stream"))
o.default = "0"
o:depends({ [option_name("grpc_health_check")] = true })
end
-- [[ Mux ]]--
o = s:option(Flag, option_name("mux"), translate("Mux"))
o.rmempty = false
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" })
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" })
o = s:option(ListValue, option_name("mux_type"), translate("Mux"))
o:value("smux")
o:value("yamux")
o:value("h2mux")
o:depends({ [option_name("mux")] = true })
o = s:option(Value, option_name("mux_concurrency"), translate("Mux concurrency"))
o.default = 8
o:depends({ [option_name("mux")] = true })
for key, value in pairs(s.fields) do
if key:find(option_prefix) == 1 then
if not s.fields[key].not_rewrite then
s.fields[key].cfgvalue = rm_prefix_cfgvalue
s.fields[key].write = rm_prefix_write
s.fields[key].remove = rm_prefix_remove
end
local deps = s.fields[key].deps
if #deps > 0 then
for index, value in ipairs(deps) do
deps[index]["type"] = type_name
end
else
s.fields[key]:depends({ type = type_name })
end
end
end

View File

@ -45,15 +45,8 @@ e = t:option(DummyValue, "type", translate("Type"))
e.cfgvalue = function(t, n) e.cfgvalue = function(t, n)
local v = Value.cfgvalue(t, n) local v = Value.cfgvalue(t, n)
if v then if v then
if v == "V2ray" or v == "Xray" then if v == "sing-box" or v == "Xray" then
local protocol = m:get(n, "protocol") local protocol = m:get(n, "protocol")
if protocol == "vmess" then
protocol = "VMess"
elseif protocol == "vless" then
protocol = "VLESS"
else
protocol = protocol:gsub("^%l",string.upper)
end
return v .. " -> " .. protocol return v .. " -> " .. protocol
end end
return v return v

View File

@ -2,10 +2,12 @@ local m, s = ...
local api = require "luci.passwall2.api" local api = require "luci.passwall2.api"
if not api.is_finded("xray") and not api.is_finded("v2ray")then if not api.is_finded("xray") then
return return
end end
local type_name = "Xray"
local option_prefix = "xray_" local option_prefix = "xray_"
local function option_name(name) local function option_name(name)
@ -18,52 +20,20 @@ local function rm_prefix_cfgvalue(self, section)
end end
end end
local function rm_prefix_write(self, section, value) local function rm_prefix_write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == "Xray" or s.fields["type"]:formvalue(arg[1]) == "V2ray" then if s.fields["type"]:formvalue(arg[1]) == type_name then
if self.option:find(option_prefix) == 1 then if self.option:find(option_prefix) == 1 then
m:set(section, self.option:sub(1 + #option_prefix), value) m:set(section, self.option:sub(1 + #option_prefix), value)
end end
end end
end end
local function rm_prefix_remove(self, section, value) local function rm_prefix_remove(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == "Xray" or s.fields["type"]:formvalue(arg[1]) == "V2ray" then if s.fields["type"]:formvalue(arg[1]) == type_name then
if self.option:find(option_prefix) == 1 then if self.option:find(option_prefix) == 1 then
m:del(section, self.option:sub(1 + #option_prefix)) m:del(section, self.option:sub(1 + #option_prefix))
end end
end end
end end
local function add_xray_depends(o, field, value)
local deps = { type = "Xray" }
if field then
if type(field) == "string" then
deps[field] = value
else
for key, value in pairs(field) do
deps[key] = value
end
end
end
o:depends(deps)
end
local function add_v2ray_depends(o, field, value)
local deps = { type = "V2ray" }
if field then
if type(field) == "string" then
deps[field] = value
else
for key, value in pairs(field) do
deps[key] = value
end
end
end
o:depends(deps)
end
local v_ss_method_list = {
"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305"
}
local x_ss_method_list = { local x_ss_method_list = {
"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"
} }
@ -74,12 +44,7 @@ local header_type_list = {
-- [[ Xray ]] -- [[ Xray ]]
if api.is_finded("v2ray") then s.fields["type"]:value(type_name, "Xray")
s.fields["type"]:value("V2ray", translate("V2ray"))
end
if api.is_finded("xray") then
s.fields["type"]:value("Xray", translate("Xray"))
end
o = s:option(ListValue, option_name("protocol"), translate("Protocol")) o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
o:value("vmess", "Vmess") o:value("vmess", "Vmess")
@ -89,13 +54,9 @@ o:value("socks", "Socks")
o:value("shadowsocks", "Shadowsocks") o:value("shadowsocks", "Shadowsocks")
o:value("trojan", "Trojan") o:value("trojan", "Trojan")
o:value("dokodemo-door", "dokodemo-door") o:value("dokodemo-door", "dokodemo-door")
add_xray_depends(o)
add_v2ray_depends(o)
o = s:option(Value, option_name("port"), translate("Listen Port")) o = s:option(Value, option_name("port"), translate("Listen Port"))
o.datatype = "port" o.datatype = "port"
add_xray_depends(o)
add_v2ray_depends(o)
o = s:option(Flag, option_name("auth"), translate("Auth")) o = s:option(Flag, option_name("auth"), translate("Auth"))
o.validate = function(self, value, t) o.validate = function(self, value, t)
@ -108,60 +69,38 @@ o.validate = function(self, value, t)
end end
return value return value
end end
add_xray_depends(o, { [option_name("protocol")] = "socks" }) o:depends({ [option_name("protocol")] = "socks" })
add_xray_depends(o, { [option_name("protocol")] = "http" }) o:depends({ [option_name("protocol")] = "http" })
add_v2ray_depends(o, { [option_name("protocol")] = "socks" })
add_v2ray_depends(o, { [option_name("protocol")] = "http" })
o = s:option(Value, option_name("username"), translate("Username")) o = s:option(Value, option_name("username"), translate("Username"))
add_xray_depends(o, { [option_name("auth")] = true }) o:depends({ [option_name("auth")] = true })
add_v2ray_depends(o, { [option_name("auth")] = true })
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, option_name("password"), translate("Password"))
o.password = true o.password = true
add_xray_depends(o, { [option_name("auth")] = true }) o:depends({ [option_name("auth")] = true })
add_v2ray_depends(o, { [option_name("auth")] = true }) o:depends({ [option_name("protocol")] = "shadowsocks" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" })
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" })
o = s:option(ListValue, option_name("d_protocol"), translate("Destination protocol")) o = s:option(ListValue, option_name("d_protocol"), translate("Destination protocol"))
o:value("tcp", "TCP") o:value("tcp", "TCP")
o:value("udp", "UDP") o:value("udp", "UDP")
o:value("tcp,udp", "TCP,UDP") o:value("tcp,udp", "TCP,UDP")
add_v2ray_depends(o, { [option_name("protocol")] = "dokodemo-door" }) o:depends({ [option_name("protocol")] = "dokodemo-door" })
add_xray_depends(o, { [option_name("protocol")] = "dokodemo-door" })
o = s:option(Value, option_name("d_address"), translate("Destination address")) o = s:option(Value, option_name("d_address"), translate("Destination address"))
add_v2ray_depends(o, { [option_name("protocol")] = "dokodemo-door" }) o:depends({ [option_name("protocol")] = "dokodemo-door" })
add_xray_depends(o, { [option_name("protocol")] = "dokodemo-door" })
o = s:option(Value, option_name("d_port"), translate("Destination port")) o = s:option(Value, option_name("d_port"), translate("Destination port"))
o.datatype = "port" o.datatype = "port"
add_v2ray_depends(o, { [option_name("protocol")] = "dokodemo-door" }) o:depends({ [option_name("protocol")] = "dokodemo-door" })
add_xray_depends(o, { [option_name("protocol")] = "dokodemo-door" })
o = s:option(Value, option_name("decryption"), translate("Encrypt Method")) o = s:option(Value, option_name("decryption"), translate("Encrypt Method"))
o.default = "none" o.default = "none"
add_v2ray_depends(o, { [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "vless" })
add_xray_depends(o, { [option_name("protocol")] = "vless" })
o = s:option(ListValue, option_name("v_ss_method"), translate("Encrypt Method"))
o.not_rewrite = true
for a, t in ipairs(v_ss_method_list) do o:value(t) end
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" })
function o.cfgvalue(self, section)
return m:get(section, "method")
end
function o.write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == "V2ray" then
m:set(section, "method", value)
end
end
o = s:option(ListValue, option_name("x_ss_method"), translate("Encrypt Method")) o = s:option(ListValue, option_name("x_ss_method"), translate("Encrypt Method"))
o.not_rewrite = true o.not_rewrite = true
for a, t in ipairs(x_ss_method_list) do o:value(t) end for a, t in ipairs(x_ss_method_list) do o:value(t) end
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks" })
function o.cfgvalue(self, section) function o.cfgvalue(self, section)
return m:get(section, "method") return m:get(section, "method")
end end
@ -172,33 +111,33 @@ function o.write(self, section, value)
end end
o = s:option(Flag, option_name("iv_check"), translate("IV Check")) o = s:option(Flag, option_name("iv_check"), translate("IV Check"))
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" })
o = s:option(ListValue, option_name("ss_network"), translate("Transport")) o = s:option(ListValue, option_name("ss_network"), translate("Transport"))
o.default = "tcp,udp" o.default = "tcp,udp"
o:value("tcp", "TCP") o:value("tcp", "TCP")
o:value("udp", "UDP") o:value("udp", "UDP")
o:value("tcp,udp", "TCP,UDP") o:value("tcp,udp", "TCP,UDP")
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" })
o = s:option(Flag, option_name("udp_forward"), translate("UDP Forward")) o = s:option(Flag, option_name("udp_forward"), translate("UDP Forward"))
o.default = "1" o.default = "1"
o.rmempty = false o.rmempty = false
add_v2ray_depends(o, { [option_name("protocol")] = "socks" }) o:depends({ [option_name("protocol")] = "socks" })
add_xray_depends(o, { [option_name("protocol")] = "socks" })
o = s:option(DynamicList, option_name("uuid"), translate("ID") .. "/" .. translate("Password")) o = s:option(DynamicList, option_name("uuid"), translate("ID") .. "/" .. translate("Password"))
for i = 1, 3 do for i = 1, 3 do
o:value(api.gen_uuid(1)) o:value(api.gen_uuid(1))
end end
add_v2ray_depends(o, { [option_name("protocol")] = "vmess" }) o:depends({ [option_name("protocol")] = "vmess" })
add_v2ray_depends(o, { [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "vless" })
add_v2ray_depends(o, { [option_name("protocol")] = "trojan" }) o:depends({ [option_name("protocol")] = "trojan" })
add_xray_depends(o, { [option_name("protocol")] = "vmess" })
add_xray_depends(o, { [option_name("protocol")] = "vless" }) o = s:option(ListValue, option_name("flow"), translate("flow"))
add_xray_depends(o, { [option_name("protocol")] = "trojan" }) o.default = ""
o:value("", translate("Disable"))
o:value("xtls-rprx-vision")
o:depends({ [option_name("protocol")] = "vless" })
o = s:option(Flag, option_name("tls"), translate("TLS")) o = s:option(Flag, option_name("tls"), translate("TLS"))
o.default = 0 o.default = 0
@ -214,44 +153,29 @@ o.validate = function(self, value, t)
return value return value
end end
end end
add_v2ray_depends(o, { [option_name("protocol")] = "vmess" }) o:depends({ [option_name("protocol")] = "vmess" })
add_v2ray_depends(o, { [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "vless" })
add_v2ray_depends(o, { [option_name("protocol")] = "socks" }) o:depends({ [option_name("protocol")] = "socks" })
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks" })
add_v2ray_depends(o, { [option_name("protocol")] = "trojan" }) o:depends({ [option_name("protocol")] = "trojan" })
add_xray_depends(o, { [option_name("protocol")] = "vmess" })
add_xray_depends(o, { [option_name("protocol")] = "vless" })
add_xray_depends(o, { [option_name("protocol")] = "socks" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" })
add_xray_depends(o, { [option_name("protocol")] = "trojan" })
o = s:option(Value, option_name("tlsflow"), translate("flow"))
o.default = ""
o:value("", translate("Disable"))
o:value("xtls-rprx-vision")
o:value("xtls-rprx-vision-udp443")
add_xray_depends(o, { [option_name("protocol")] = "vless", [option_name("tls")] = true })
o = s:option(ListValue, option_name("alpn"), translate("alpn")) o = s:option(ListValue, option_name("alpn"), translate("alpn"))
o.default = "h2,http/1.1" o.default = "h2,http/1.1"
o:value("h2,http/1.1") o:value("h2,http/1.1")
o:value("h2") o:value("h2")
o:value("http/1.1") o:value("http/1.1")
add_v2ray_depends(o, { [option_name("tls")] = true }) o:depends({ [option_name("tls")] = true })
add_xray_depends(o, { [option_name("tls")] = true })
-- o = s:option(Value, option_name("minversion"), translate("minversion")) -- o = s:option(Value, option_name("minversion"), translate("minversion"))
-- o.default = "1.3" -- o.default = "1.3"
-- o:value("1.3") -- o:value("1.3")
--add_v2ray_depends(o, { [option_name("tls")] = true }) --o:depends({ [option_name("tls")] = true })
--add_xray_depends(o, { [option_name("tls")] = true })
-- [[ TLS部分 ]] -- -- [[ TLS部分 ]] --
o = s:option(FileUpload, option_name("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") o = s:option(FileUpload, option_name("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem" o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
add_v2ray_depends(o, { [option_name("tls")] = true }) o:depends({ [option_name("tls")] = true })
add_xray_depends(o, { [option_name("tls")] = true })
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value and value ~= "" then if value and value ~= "" then
if not nixio.fs.access(value) then if not nixio.fs.access(value) then
@ -265,8 +189,7 @@ end
o = s:option(FileUpload, option_name("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") o = s:option(FileUpload, option_name("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key" o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
add_v2ray_depends(o, { [option_name("tls")] = true }) o:depends({ [option_name("tls")] = true })
add_xray_depends(o, { [option_name("tls")] = true })
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value and value ~= "" then if value and value ~= "" then
if not nixio.fs.access(value) then if not nixio.fs.access(value) then
@ -286,36 +209,27 @@ o:value("h2", "HTTP/2")
o:value("ds", "DomainSocket") o:value("ds", "DomainSocket")
o:value("quic", "QUIC") o:value("quic", "QUIC")
o:value("grpc", "gRPC") o:value("grpc", "gRPC")
add_v2ray_depends(o, { [option_name("protocol")] = "vmess" }) o:depends({ [option_name("protocol")] = "vmess" })
add_v2ray_depends(o, { [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "vless" })
add_v2ray_depends(o, { [option_name("protocol")] = "socks" }) o:depends({ [option_name("protocol")] = "socks" })
add_v2ray_depends(o, { [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocks" })
add_v2ray_depends(o, { [option_name("protocol")] = "trojan" }) o:depends({ [option_name("protocol")] = "trojan" })
add_xray_depends(o, { [option_name("protocol")] = "vmess" })
add_xray_depends(o, { [option_name("protocol")] = "vless" })
add_xray_depends(o, { [option_name("protocol")] = "socks" })
add_xray_depends(o, { [option_name("protocol")] = "shadowsocks" })
add_xray_depends(o, { [option_name("protocol")] = "trojan" })
-- [[ WebSocket部分 ]]-- -- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host")) o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
add_v2ray_depends(o, { [option_name("transport")] = "ws" }) o:depends({ [option_name("transport")] = "ws" })
add_xray_depends(o, { [option_name("transport")] = "ws" })
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path")) o = s:option(Value, option_name("ws_path"), translate("WebSocket Path"))
add_v2ray_depends(o, { [option_name("transport")] = "ws" }) o:depends({ [option_name("transport")] = "ws" })
add_xray_depends(o, { [option_name("transport")] = "ws" })
-- [[ HTTP/2部分 ]]-- -- [[ HTTP/2部分 ]]--
o = s:option(Value, option_name("h2_host"), translate("HTTP/2 Host")) o = s:option(Value, option_name("h2_host"), translate("HTTP/2 Host"))
add_v2ray_depends(o, { [option_name("transport")] = "h2" }) o:depends({ [option_name("transport")] = "h2" })
add_xray_depends(o, { [option_name("transport")] = "h2" })
o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path")) o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path"))
add_v2ray_depends(o, { [option_name("transport")] = "h2" }) o:depends({ [option_name("transport")] = "h2" })
add_xray_depends(o, { [option_name("transport")] = "h2" })
-- [[ TCP部分 ]]-- -- [[ TCP部分 ]]--
@ -323,141 +237,111 @@ add_xray_depends(o, { [option_name("transport")] = "h2" })
o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type")) o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type"))
o:value("none", "none") o:value("none", "none")
o:value("http", "http") o:value("http", "http")
add_v2ray_depends(o, { [option_name("transport")] = "tcp" }) o:depends({ [option_name("transport")] = "tcp" })
add_xray_depends(o, { [option_name("transport")] = "tcp" })
-- HTTP域名 -- HTTP域名
o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host")) o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host"))
add_v2ray_depends(o, { [option_name("tcp_guise")] = "http" }) o:depends({ [option_name("tcp_guise")] = "http" })
add_xray_depends(o, { [option_name("tcp_guise")] = "http" })
-- HTTP路径 -- HTTP路径
o = s:option(DynamicList, option_name("tcp_guise_http_path"), translate("HTTP Path")) o = s:option(DynamicList, option_name("tcp_guise_http_path"), translate("HTTP Path"))
add_v2ray_depends(o, { [option_name("tcp_guise")] = "http" }) o:depends({ [option_name("tcp_guise")] = "http" })
add_xray_depends(o, { [option_name("tcp_guise")] = "http" })
-- [[ mKCP部分 ]]-- -- [[ mKCP部分 ]]--
o = s:option(ListValue, option_name("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)')) o = s:option(ListValue, option_name("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 o:value(t) end for a, t in ipairs(header_type_list) do o:value(t) end
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_xray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_mtu"), translate("KCP MTU")) o = s:option(Value, option_name("mkcp_mtu"), translate("KCP MTU"))
o.default = "1350" o.default = "1350"
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_xray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_tti"), translate("KCP TTI")) o = s:option(Value, option_name("mkcp_tti"), translate("KCP TTI"))
o.default = "20" o.default = "20"
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_xray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity")) o = s:option(Value, option_name("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity"))
o.default = "5" o.default = "5"
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_xray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity")) o = s:option(Value, option_name("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity"))
o.default = "20" o.default = "20"
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_xray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Flag, option_name("mkcp_congestion"), translate("KCP Congestion")) o = s:option(Flag, option_name("mkcp_congestion"), translate("KCP Congestion"))
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_xray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_readBufferSize"), translate("KCP readBufferSize")) o = s:option(Value, option_name("mkcp_readBufferSize"), translate("KCP readBufferSize"))
o.default = "1" o.default = "1"
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_xray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_writeBufferSize"), translate("KCP writeBufferSize")) o = s:option(Value, option_name("mkcp_writeBufferSize"), translate("KCP writeBufferSize"))
o.default = "1" o.default = "1"
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_xray_depends(o, { [option_name("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_seed"), translate("KCP Seed")) o = s:option(Value, option_name("mkcp_seed"), translate("KCP Seed"))
add_v2ray_depends(o, { [option_name("transport")] = "mkcp" }) o:depends({ [option_name("transport")] = "mkcp" })
add_xray_depends(o, { [option_name("transport")] = "mkcp" })
-- [[ DomainSocket部分 ]]-- -- [[ DomainSocket部分 ]]--
o = s:option(Value, option_name("ds_path"), "Path", translate("A legal file path. This file must not exist before running.")) o = s:option(Value, option_name("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
add_v2ray_depends(o, { [option_name("transport")] = "ds" }) o:depends({ [option_name("transport")] = "ds" })
add_xray_depends(o, { [option_name("transport")] = "ds" })
-- [[ QUIC部分 ]]-- -- [[ QUIC部分 ]]--
o = s:option(ListValue, option_name("quic_security"), translate("Encrypt Method")) o = s:option(ListValue, option_name("quic_security"), translate("Encrypt Method"))
o:value("none") o:value("none")
o:value("aes-128-gcm") o:value("aes-128-gcm")
o:value("chacha20-poly1305") o:value("chacha20-poly1305")
add_v2ray_depends(o, { [option_name("transport")] = "quic" }) o:depends({ [option_name("transport")] = "quic" })
add_xray_depends(o, { [option_name("transport")] = "quic" })
o = s:option(Value, option_name("quic_key"), translate("Encrypt Method") .. translate("Key")) o = s:option(Value, option_name("quic_key"), translate("Encrypt Method") .. translate("Key"))
add_v2ray_depends(o, { [option_name("transport")] = "quic" }) o:depends({ [option_name("transport")] = "quic" })
add_xray_depends(o, { [option_name("transport")] = "quic" })
o = s:option(ListValue, option_name("quic_guise"), translate("Camouflage Type")) o = s:option(ListValue, option_name("quic_guise"), translate("Camouflage Type"))
for a, t in ipairs(header_type_list) do o:value(t) end for a, t in ipairs(header_type_list) do o:value(t) end
add_v2ray_depends(o, { [option_name("transport")] = "quic" }) o:depends({ [option_name("transport")] = "quic" })
add_xray_depends(o, { [option_name("transport")] = "quic" })
-- [[ gRPC部分 ]]-- -- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName") o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
add_v2ray_depends(o, { [option_name("transport")] = "grpc" }) o:depends({ [option_name("transport")] = "grpc" })
add_xray_depends(o, { [option_name("transport")] = "grpc" })
o = s:option(Flag, option_name("acceptProxyProtocol"), translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used.")) o = s:option(Flag, option_name("acceptProxyProtocol"), translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used."))
add_v2ray_depends(o, { [option_name("transport")] = "tcp" }) o:depends({ [option_name("transport")] = "tcp" })
add_v2ray_depends(o, { [option_name("transport")] = "ws" }) o:depends({ [option_name("transport")] = "ws" })
add_xray_depends(o, { [option_name("transport")] = "tcp" })
add_xray_depends(o, { [option_name("transport")] = "ws" })
-- [[ Fallback部分 ]]-- -- [[ Fallback部分 ]]--
o = s:option(Flag, option_name("fallback"), translate("Fallback")) o = s:option(Flag, option_name("fallback"), translate("Fallback"))
add_v2ray_depends(o, { [option_name("protocol")] = "vless", [option_name("transport")] = "tcp" }) o:depends({ [option_name("protocol")] = "vless", [option_name("transport")] = "tcp" })
add_v2ray_depends(o, { [option_name("protocol")] = "trojan", [option_name("transport")] = "tcp" }) o:depends({ [option_name("protocol")] = "trojan", [option_name("transport")] = "tcp" })
add_xray_depends(o, { [option_name("protocol")] = "vless", [option_name("transport")] = "tcp" })
add_xray_depends(o, { [option_name("protocol")] = "trojan", [option_name("transport")] = "tcp" })
--[[ --[[
o = s:option(Value, option_name("fallback_alpn"), "Fallback alpn") o = s:option(Value, option_name("fallback_alpn"), "Fallback alpn")
add_v2ray_depends(o, { [option_name("fallback")] = true }) o:depends({ [option_name("fallback")] = true })
add_xray_depends(o, { [option_name("fallback")] = true })
o = s:option(Value, option_name("fallback_path"), "Fallback path") o = s:option(Value, option_name("fallback_path"), "Fallback path")
add_v2ray_depends(o, { [option_name("fallback")] = true }) o:depends({ [option_name("fallback")] = true })
add_xray_depends(o, { [option_name("fallback")] = true })
o = s:option(Value, option_name("fallback_dest"), "Fallback dest") o = s:option(Value, option_name("fallback_dest"), "Fallback dest")
add_v2ray_depends(o, { [option_name("fallback")] = true }) o:depends({ [option_name("fallback")] = true })
add_xray_depends(o, { [option_name("fallback")] = true })
o = s:option(Value, option_name("fallback_xver"), "Fallback xver") o = s:option(Value, option_name("fallback_xver"), "Fallback xver")
o.default = 0 o.default = 0
add_v2ray_depends(o, { [option_name("fallback")] = true }) o:depends({ [option_name("fallback")] = true })
add_xray_depends(o, { [option_name("fallback")] = true })
]]-- ]]--
o = s:option(DynamicList, option_name("fallback_list"), "Fallback", translate("dest,path")) o = s:option(DynamicList, option_name("fallback_list"), "Fallback", translate("dest,path"))
add_v2ray_depends(o, { [option_name("fallback")] = true }) o:depends({ [option_name("fallback")] = true })
add_xray_depends(o, { [option_name("fallback")] = true })
o = s:option(Flag, option_name("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed locally, It is recommended to turn on when using reverse proxies or be fallback.")) o = s:option(Flag, option_name("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed locally, It is recommended to turn on when using reverse proxies or be fallback."))
o.default = "0" o.default = "0"
add_v2ray_depends(o)
add_xray_depends(o)
o = s:option(Flag, option_name("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!")) o = s:option(Flag, option_name("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
o.default = "0" o.default = "0"
add_v2ray_depends(o)
add_xray_depends(o)
local nodes_table = {} local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" and (e.type == "V2ray" or e.type == "Xray") then if e.node_type == "normal" and e.type == type_name then
nodes_table[#nodes_table + 1] = { nodes_table[#nodes_table + 1] = {
id = e[".name"], id = e[".name"],
remarks = e["remark"] remarks = e["remark"]
@ -472,45 +356,32 @@ o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface") .. " (Only Support Xray)") o:value("_iface", translate("Custom Interface") .. " (Only Support Xray)")
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
o.default = "nil" o.default = "nil"
add_v2ray_depends(o)
add_xray_depends(o)
o = s:option(Value, option_name("outbound_node_address"), translate("Address (Support Domain Name)")) o = s:option(Value, option_name("outbound_node_address"), translate("Address (Support Domain Name)"))
add_v2ray_depends(o, { [option_name("outbound_node")] = "_socks"}) o:depends({ [option_name("outbound_node")] = "_socks"})
add_v2ray_depends(o, { [option_name("outbound_node")] = "_http"}) o:depends({ [option_name("outbound_node")] = "_http"})
add_xray_depends(o, { [option_name("outbound_node")] = "_socks"})
add_xray_depends(o, { [option_name("outbound_node")] = "_http"})
o = s:option(Value, option_name("outbound_node_port"), translate("Port")) o = s:option(Value, option_name("outbound_node_port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
add_v2ray_depends(o, { [option_name("outbound_node")] = "_socks"}) o:depends({ [option_name("outbound_node")] = "_socks"})
add_v2ray_depends(o, { [option_name("outbound_node")] = "_http"}) o:depends({ [option_name("outbound_node")] = "_http"})
add_xray_depends(o, { [option_name("outbound_node")] = "_socks"})
add_xray_depends(o, { [option_name("outbound_node")] = "_http"})
o = s:option(Value, option_name("outbound_node_username"), translate("Username")) o = s:option(Value, option_name("outbound_node_username"), translate("Username"))
add_v2ray_depends(o, { [option_name("outbound_node")] = "_socks"}) o:depends({ [option_name("outbound_node")] = "_socks"})
add_v2ray_depends(o, { [option_name("outbound_node")] = "_http"}) o:depends({ [option_name("outbound_node")] = "_http"})
add_xray_depends(o, { [option_name("outbound_node")] = "_socks"})
add_xray_depends(o, { [option_name("outbound_node")] = "_http"})
o = s:option(Value, option_name("outbound_node_password"), translate("Password")) o = s:option(Value, option_name("outbound_node_password"), translate("Password"))
o.password = true o.password = true
add_v2ray_depends(o, { [option_name("outbound_node")] = "_socks"}) o:depends({ [option_name("outbound_node")] = "_socks"})
add_v2ray_depends(o, { [option_name("outbound_node")] = "_http"}) o:depends({ [option_name("outbound_node")] = "_http"})
add_xray_depends(o, { [option_name("outbound_node")] = "_socks"})
add_xray_depends(o, { [option_name("outbound_node")] = "_http"})
o = s:option(Value, option_name("outbound_node_iface"), translate("Interface")) o = s:option(Value, option_name("outbound_node_iface"), translate("Interface"))
o.default = "eth1" o.default = "eth1"
add_v2ray_depends(o, { [option_name("outbound_node")] = "_iface"}) o:depends({ [option_name("outbound_node")] = "_iface"})
add_xray_depends(o, { [option_name("outbound_node")] = "_iface"})
o = s:option(Flag, option_name("log"), translate("Log")) o = s:option(Flag, option_name("log"), translate("Log"))
o.default = "1" o.default = "1"
o.rmempty = false o.rmempty = false
add_v2ray_depends(o)
add_xray_depends(o)
o = s:option(ListValue, option_name("loglevel"), translate("Log Level")) o = s:option(ListValue, option_name("loglevel"), translate("Log Level"))
o.default = "warning" o.default = "warning"
@ -518,8 +389,7 @@ o:value("debug")
o:value("info") o:value("info")
o:value("warning") o:value("warning")
o:value("error") o:value("error")
add_v2ray_depends(o, { [option_name("log")] = true }) o:depends({ [option_name("log")] = true })
add_xray_depends(o, { [option_name("log")] = true })
for key, value in pairs(s.fields) do for key, value in pairs(s.fields) do
if key:find(option_prefix) == 1 then if key:find(option_prefix) == 1 then
@ -529,4 +399,13 @@ for key, value in pairs(s.fields) do
s.fields[key].remove = rm_prefix_remove s.fields[key].remove = rm_prefix_remove
end end
end end
local deps = s.fields[key].deps
if #deps > 0 then
for index, value in ipairs(deps) do
deps[index]["type"] = type_name
end
else
s.fields[key]:depends({ type = type_name })
end
end end

View File

@ -0,0 +1,377 @@
local m, s = ...
local api = require "luci.passwall2.api"
if not api.is_finded("sing-box")then
return
end
local singbox_tags = luci.sys.exec(api.finded("sing-box") .. " version | grep 'Tags:' | awk '{print $2}'")
local type_name = "sing-box"
local option_prefix = "singbox_"
local function option_name(name)
return option_prefix .. name
end
local function rm_prefix_cfgvalue(self, section)
if self.option:find(option_prefix) == 1 then
return m:get(section, self.option:sub(1 + #option_prefix))
end
end
local function rm_prefix_write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == type_name then
if self.option:find(option_prefix) == 1 then
m:set(section, self.option:sub(1 + #option_prefix), value)
end
end
end
local function rm_prefix_remove(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == type_name then
if self.option:find(option_prefix) == 1 then
m:del(section, self.option:sub(1 + #option_prefix))
end
end
end
local ss_method_list = {
"none", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305",
"2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"
}
-- [[ Sing-Box ]]
s.fields["type"]:value(type_name, "Sing-Box")
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
o:value("mixed", "Mixed")
o:value("socks", "Socks")
o:value("http", "HTTP")
o:value("shadowsocks", "Shadowsocks")
o:value("vmess", "Vmess")
o:value("vless", "VLESS")
o:value("trojan", "Trojan")
o:value("naive", "Naive")
if singbox_tags:find("with_quic") then
o:value("hysteria", "Hysteria")
end
if singbox_tags:find("with_quic") then
o:value("tuic", "TUIC")
end
if singbox_tags:find("with_quic") then
o:value("hysteria2", "Hysteria2")
end
o:value("direct", "Direct")
o = s:option(Value, option_name("port"), translate("Listen Port"))
o.datatype = "port"
o = s:option(Flag, option_name("auth"), translate("Auth"))
o.validate = function(self, value, t)
if value and value == "1" then
local user_v = s.fields[option_name("username")]:formvalue(t) or ""
local pass_v = s.fields[option_name("password")]:formvalue(t) or ""
if user_v == "" or pass_v == "" then
return nil, translate("Username and Password must be used together!")
end
end
return value
end
o:depends({ [option_name("protocol")] = "mixed" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "http" })
o = s:option(Value, option_name("username"), translate("Username"))
o:depends({ [option_name("auth")] = true })
o:depends({ [option_name("protocol")] = "naive" })
o = s:option(Value, option_name("password"), translate("Password"))
o.password = true
o:depends({ [option_name("auth")] = true })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "naive" })
o:depends({ [option_name("protocol")] = "tuic" })
if singbox_tags:find("with_quic") then
o = s:option(Value, option_name("hysteria_up_mbps"), translate("Max upload Mbps"))
o.default = "100"
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_down_mbps"), translate("Max download Mbps"))
o.default = "100"
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_obfs"), translate("Obfs Password"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(ListValue, option_name("hysteria_auth_type"), translate("Auth Type"))
o:value("disable", translate("Disable"))
o:value("string", translate("STRING"))
o:value("base64", translate("BASE64"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_auth_password"), translate("Auth Password"))
o.password = true
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "string"})
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "base64"})
o = s:option(Value, option_name("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_recv_window_client"), translate("QUIC connection receive window"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_max_conn_client"), translate("QUIC concurrent bidirectional streams"))
o.default = "1024"
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Flag, option_name("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
o:depends({ [option_name("protocol")] = "hysteria" })
end
if singbox_tags:find("with_quic") then
o = s:option(ListValue, option_name("tuic_congestion_control"), translate("Congestion control algorithm"))
o.default = "cubic"
o:value("bbr", translate("BBR"))
o:value("cubic", translate("CUBIC"))
o:value("new_reno", translate("New Reno"))
o:depends({ [option_name("protocol")] = "tuic" })
o = s:option(Flag, option_name("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
o.default = 0
o:depends({ [option_name("protocol")] = "tuic" })
o = s:option(Value, option_name("tuic_heartbeat"), translate("Heartbeat interval(second)"))
o.datatype = "uinteger"
o.default = "3"
o:depends({ [option_name("protocol")] = "tuic" })
end
if singbox_tags:find("with_quic") then
o = s:option(Flag, option_name("hysteria2_ignore_client_bandwidth"), translate("Commands the client to use the BBR flow control algorithm"))
o.default = 0
o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_up_mbps"), translate("Max upload Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2", [option_name("hysteria2_ignore_client_bandwidth")] = false })
o = s:option(Value, option_name("hysteria2_down_mbps"), translate("Max download Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2", [option_name("hysteria2_ignore_client_bandwidth")] = false })
o = s:option(ListValue, option_name("hysteria2_obfs_type"), translate("Obfs Type"))
o:value("", translate("Disable"))
o:value("salamander")
o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_obfs_password"), translate("Obfs Password"))
o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_auth_password"), translate("Auth Password"))
o.password = true
o:depends({ [option_name("protocol")] = "hysteria2"})
end
o = s:option(ListValue, option_name("d_protocol"), translate("Destination protocol"))
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:value("tcp,udp", "TCP,UDP")
o:depends({ [option_name("protocol")] = "direct" })
o = s:option(Value, option_name("d_address"), translate("Destination address"))
o:depends({ [option_name("protocol")] = "direct" })
o = s:option(Value, option_name("d_port"), translate("Destination port"))
o.datatype = "port"
o:depends({ [option_name("protocol")] = "direct" })
o = s:option(Value, option_name("decryption"), translate("Encrypt Method"))
o.default = "none"
o:depends({ [option_name("protocol")] = "vless" })
o = s:option(ListValue, option_name("ss_method"), translate("Encrypt Method"))
o.not_rewrite = true
for a, t in ipairs(ss_method_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocks" })
function o.cfgvalue(self, section)
return m:get(section, "method")
end
function o.write(self, section, value)
if s.fields["type"]:formvalue(arg[1]) == type_name then
m:set(section, "method", value)
end
end
o = s:option(DynamicList, option_name("uuid"), translate("ID") .. "/" .. translate("Password"))
for i = 1, 3 do
o:value(api.gen_uuid(1))
end
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "tuic" })
o = s:option(ListValue, option_name("flow"), translate("flow"))
o.default = ""
o:value("", translate("Disable"))
o:value("xtls-rprx-vision")
o:depends({ [option_name("protocol")] = "vless" })
o = s:option(Flag, option_name("tls"), translate("TLS"))
o.default = 0
o.validate = function(self, value, t)
if value then
if value == "1" then
local ca = s.fields[option_name("tls_certificateFile")]:formvalue(t) or ""
local key = s.fields[option_name("tls_keyFile")]:formvalue(t) or ""
if ca == "" or key == "" then
return nil, translate("Public key and Private key path can not be empty!")
end
end
return value
end
end
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" })
-- [[ TLS部分 ]] --
o = s:option(FileUpload, option_name("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
o:depends({ [option_name("tls")] = true })
o.validate = function(self, value, t)
if value and value ~= "" then
if not nixio.fs.access(value) then
return nil, translate("Can't find this file!")
else
return value
end
end
return nil
end
o = s:option(FileUpload, option_name("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
o:depends({ [option_name("tls")] = true })
o.validate = function(self, value, t)
if value and value ~= "" then
if not nixio.fs.access(value) then
return nil, translate("Can't find this file!")
else
return value
end
end
return nil
end
o = s:option(ListValue, option_name("transport"), translate("Transport"))
o:value("tcp", "TCP")
o:value("http", "HTTP")
o:value("ws", "WebSocket")
o:value("quic", "QUIC")
o:value("grpc", "gRPC")
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" })
-- [[ HTTP部分 ]]--
o = s:option(Value, option_name("http_host"), translate("HTTP Host"))
o:depends({ [option_name("transport")] = "http" })
o = s:option(Value, option_name("http_path"), translate("HTTP Path"))
o:depends({ [option_name("transport")] = "http" })
-- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path"))
o:depends({ [option_name("transport")] = "ws" })
-- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
o:depends({ [option_name("transport")] = "grpc" })
o = s:option(Flag, option_name("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed locally, It is recommended to turn on when using reverse proxies or be fallback."))
o.default = "0"
o = s:option(Flag, option_name("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
o.default = "0"
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" and e.type == type_name then
nodes_table[#nodes_table + 1] = {
id = e[".name"],
remarks = e["remark"]
}
end
end
o = s:option(ListValue, option_name("outbound_node"), translate("outbound node"))
o:value("nil", translate("Close"))
o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface"))
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
o.default = "nil"
o = s:option(Value, option_name("outbound_node_address"), translate("Address (Support Domain Name)"))
o:depends({ [option_name("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" })
o = s:option(Value, option_name("outbound_node_port"), translate("Port"))
o.datatype = "port"
o:depends({ [option_name("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" })
o = s:option(Value, option_name("outbound_node_username"), translate("Username"))
o:depends({ [option_name("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" })
o = s:option(Value, option_name("outbound_node_password"), translate("Password"))
o.password = true
o:depends({ [option_name("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" })
o = s:option(Value, option_name("outbound_node_iface"), translate("Interface"))
o.default = "eth1"
o:depends({ [option_name("outbound_node")] = "_iface" })
o = s:option(Flag, option_name("log"), translate("Log"))
o.default = "1"
o.rmempty = false
o = s:option(ListValue, option_name("loglevel"), translate("Log Level"))
o.default = "info"
o:value("debug")
o:value("info")
o:value("warn")
o:value("error")
o:depends({ [option_name("log")] = true })
for key, value in pairs(s.fields) do
if key:find(option_prefix) == 1 then
if not s.fields[key].not_rewrite then
s.fields[key].cfgvalue = rm_prefix_cfgvalue
s.fields[key].write = rm_prefix_write
s.fields[key].remove = rm_prefix_remove
end
local deps = s.fields[key].deps
if #deps > 0 then
for index, value in ipairs(deps) do
deps[index]["type"] = type_name
end
else
s.fields[key]:depends({ type = type_name })
end
end
end

View File

@ -282,7 +282,7 @@ function get_valid_nodes()
local address = e.address local address = e.address
if is_ip(address) or datatypes.hostname(address) then if is_ip(address) or datatypes.hostname(address) then
local type = e.type local type = e.type
if (type == "V2ray" or type == "Xray") and e.protocol then if (type == "sing-box" or type == "Xray") and e.protocol then
local protocol = e.protocol local protocol = e.protocol
if protocol == "vmess" then if protocol == "vmess" then
protocol = "VMess" protocol = "VMess"
@ -314,7 +314,7 @@ function get_node_remarks(n)
remarks = "%s[%s] " % {n.type .. " " .. i18n.translatef(n.protocol), n.remarks} remarks = "%s[%s] " % {n.type .. " " .. i18n.translatef(n.protocol), n.remarks}
else else
local type2 = n.type local type2 = n.type
if (n.type == "V2ray" or n.type == "Xray") and n.protocol then if (n.type == "sing-box" or n.type == "Xray") and n.protocol then
local protocol = n.protocol local protocol = n.protocol
if protocol == "vmess" then if protocol == "vmess" then
protocol = "VMess" protocol = "VMess"
@ -381,8 +381,12 @@ function get_customed_path(e)
return uci_get_type("global_app", e .. "_file") return uci_get_type("global_app", e .. "_file")
end end
function finded(e)
return luci.sys.exec('echo -n $(type -t -p "/bin/%s" -p "/usr/bin/%s" -p "%s" "%s" | head -n1)' % {e, e, get_customed_path(e), e})
end
function is_finded(e) function is_finded(e)
return luci.sys.exec('type -t -p "/bin/%s" -p "/usr/bin/%s" -p "%s" "%s"' % {e, e, get_customed_path(e), e}) ~= "" and true or false return finded(e) ~= "" and true or false
end end
function clone(org) function clone(org)

View File

@ -33,13 +33,26 @@ _M.hysteria = {
} }
} }
_M.v2ray = { _M.singbox = {
name = "V2ray", name = "Sing-Box",
repo = "v2fly/v2ray-core", repo = "SagerNet/sing-box",
get_url = gh_pre_release_url,
cmd_version = "version | awk '{print $3}' | sed -n 1P",
zipped = true,
default_path = "/usr/bin/sing-box",
match_fmt_str = "linux%%-%s",
file_tree = {
x86_64 = "amd64"
}
}
_M.xray = {
name = "Xray",
repo = "XTLS/Xray-core",
get_url = gh_pre_release_url, get_url = gh_pre_release_url,
cmd_version = "version | awk '{print $2}' | sed -n 1P", cmd_version = "version | awk '{print $2}' | sed -n 1P",
zipped = true, zipped = true,
default_path = "/usr/bin/v2ray", default_path = "/usr/bin/xray",
match_fmt_str = "linux%%-%s", match_fmt_str = "linux%%-%s",
file_tree = { file_tree = {
x86_64 = "64", x86_64 = "64",
@ -49,15 +62,4 @@ _M.v2ray = {
} }
} }
_M.xray = {
name = "Xray",
repo = "XTLS/Xray-core",
get_url = gh_pre_release_url,
cmd_version = _M.v2ray.cmd_version,
zipped = true,
default_path = "/usr/bin/xray",
match_fmt_str = _M.v2ray.match_fmt_str,
file_tree = _M.v2ray.file_tree
}
return _M return _M

View File

@ -144,12 +144,12 @@ local function start()
elseif type == "SS-Rust" then elseif type == "SS-Rust" then
config = require(require_dir .. "util_shadowsocks").gen_config_server(user) config = require(require_dir .. "util_shadowsocks").gen_config_server(user)
bin = ln_run("/usr/bin/ssserver", "ssserver", "-c " .. config_file, log_path) bin = ln_run("/usr/bin/ssserver", "ssserver", "-c " .. config_file, log_path)
elseif type == "V2ray" then
config = require(require_dir .. "util_xray").gen_config_server(user)
bin = ln_run(api.get_app_path("v2ray"), "v2ray", "run -c " .. config_file, log_path)
elseif type == "Xray" then elseif type == "Xray" then
config = require(require_dir .. "util_xray").gen_config_server(user) config = require(require_dir .. "util_xray").gen_config_server(user)
bin = ln_run(api.get_app_path("xray"), "xray", "run -c " .. config_file, log_path) bin = ln_run(api.get_app_path("xray"), "xray", "run -c " .. config_file, log_path)
elseif type == "sing-box" then
config = require(require_dir .. "util_sing-box").gen_config_server(user)
bin = ln_run(api.get_app_path("singbox"), "sing-box", "run -c " .. config_file, log_path)
elseif type == "Brook" then elseif type == "Brook" then
local brook_protocol = user.protocol local brook_protocol = user.protocol
local brook_password = user.password local brook_password = user.password

File diff suppressed because it is too large Load Diff

View File

@ -47,8 +47,8 @@ function gen_outbound(flag, node, tag, proxy_table)
proxy_tag = proxy_table.tag or "nil" proxy_tag = proxy_table.tag or "nil"
end end
if node.type == "V2ray" or node.type == "Xray" then if node.type == "Xray" then
if node.type == "Xray" and node.tlsflow == "xtls-rprx-vision" then if node.flow == "xtls-rprx-vision" then
else else
proxy = 0 proxy = 0
if proxy_tag ~= "nil" then if proxy_tag ~= "nil" then
@ -60,7 +60,7 @@ function gen_outbound(flag, node, tag, proxy_table)
end end
end end
if node.type ~= "V2ray" and node.type ~= "Xray" then if node.type ~= "Xray" then
local relay_port = node.port local relay_port = node.port
new_port = get_new_port() new_port = get_new_port()
local config_file = string.format("%s_%s_%s.json", flag, tag, new_port) local config_file = string.format("%s_%s_%s.json", flag, tag, new_port)
@ -87,10 +87,10 @@ function gen_outbound(flag, node, tag, proxy_table)
node.stream_security = "none" node.stream_security = "none"
end end
if node.type == "V2ray" or node.type == "Xray" then if node.type == "Xray" then
if node.tls and node.tls == "1" then if node.tls and node.tls == "1" then
node.stream_security = "tls" node.stream_security = "tls"
if node.type == "Xray" and node.reality and node.reality == "1" then if node.reality and node.reality == "1" then
node.stream_security = "reality" node.stream_security = "reality"
end end
end end
@ -133,7 +133,7 @@ function gen_outbound(flag, node, tag, proxy_table)
tlsSettings = (node.stream_security == "tls") and { tlsSettings = (node.stream_security == "tls") and {
serverName = node.tls_serverName, serverName = node.tls_serverName,
allowInsecure = (node.tls_allowInsecure == "1") and true or false, allowInsecure = (node.tls_allowInsecure == "1") and true or false,
fingerprint = (node.type == "Xray" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil
} or nil, } or nil,
realitySettings = (node.stream_security == "reality") and { realitySettings = (node.stream_security == "reality") and {
serverName = node.tls_serverName, serverName = node.tls_serverName,
@ -204,7 +204,7 @@ function gen_outbound(flag, node, tag, proxy_table)
level = 0, level = 0,
security = (node.protocol == "vmess") and node.security or nil, security = (node.protocol == "vmess") and node.security or nil,
encryption = node.encryption or "none", encryption = node.encryption or "none",
flow = (node.protocol == "vless" and node.tls == '1' and node.tlsflow) and node.tlsflow or nil flow = (node.protocol == "vless" and node.tls == '1' and node.flow) and node.flow or nil
} }
} }
} }
@ -267,7 +267,7 @@ function gen_config_server(node)
for i = 1, #node.uuid do for i = 1, #node.uuid do
clients[i] = { clients[i] = {
id = node.uuid[i], id = node.uuid[i],
flow = ("vless" == node.protocol and "1" == node.tls and node.tlsflow) and node.tlsflow or nil flow = ("vless" == node.protocol and "1" == node.tls and node.flow) and node.flow or nil
} }
end end
settings = { settings = {
@ -760,10 +760,10 @@ function gen_config(var)
else else
if proxy then if proxy then
local pre_proxy = nil local pre_proxy = nil
if _node.type ~= "V2ray" and _node.type ~= "Xray" then if _node.type ~= "Xray" then
pre_proxy = true pre_proxy = true
end end
if _node.type == "Xray" and _node.tlsflow == "xtls-rprx-vision" then if _node.type == "Xray" and _node.flow == "xtls-rprx-vision" then
pre_proxy = true pre_proxy = true
end end
if pre_proxy then if pre_proxy then

View File

@ -91,7 +91,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
</div> </div>
</div> </div>
<div class="pure-u-2-3"> <div class="pure-u-2-3">
<h4 id="status_node">V2ray<br /><span class="red"><%:NOT RUNNING%></span></h4> <h4 id="status_node">Xray<br /><span class="red"><%:NOT RUNNING%></span></h4>
</div> </div>
</div> </div>
</div> </div>
@ -145,7 +145,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
if (true) { if (true) {
var status_node = document.getElementById('status_node'); var status_node = document.getElementById('status_node');
if (status_node) { if (status_node) {
var text = 'V2ray<br />'; var text = 'Xray<br />';
if (data["global_status"]) if (data["global_status"])
text += '<span class="green"><%:RUNNING%></span>'; text += '<span class="green"><%:RUNNING%></span>';
else else

View File

@ -1,7 +1,6 @@
<%+cbi/valueheader%> <%+cbi/valueheader%>
<% <%
local api = require "luci.passwall2.api" local api = require "luci.passwall2.api"
local has_v2ray = api.is_finded("v2ray")
local has_xray = api.is_finded("xray") local has_xray = api.is_finded("xray")
-%> -%>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
@ -141,7 +140,7 @@ local has_xray = api.is_finded("xray")
} else if (v_type === "Hysteria") { } else if (v_type === "Hysteria") {
dom_prefix = "hysteria_" dom_prefix = "hysteria_"
protocol = "hysteria" protocol = "hysteria"
} else if (v_type === "V2ray" || v_type === "Xray") { } else if (v_type === "Xray") {
dom_prefix = "xray_" dom_prefix = "xray_"
} }
var _address = "" var _address = ""
@ -230,7 +229,7 @@ local has_xray = api.is_finded("xray")
"&protoparam=" + b64encsafe(v_protocol_param.value) + "&protoparam=" + b64encsafe(v_protocol_param.value) +
"&remarks=" + b64encutf8safe(v_alias.value); "&remarks=" + b64encutf8safe(v_alias.value);
url = b64encsafe(ssr_str); url = b64encsafe(ssr_str);
} else if ((v_type === "V2ray" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "vmess") { } else if (v_type === "Xray" && opt.get(dom_prefix + "protocol").value === "vmess") {
protocol = "vmess"; protocol = "vmess";
var info = {}; var info = {};
info.v = "2"; info.v = "2";
@ -275,7 +274,7 @@ local has_xray = api.is_finded("xray")
info.sni = opt.get(dom_prefix + "tls_serverName").value; info.sni = opt.get(dom_prefix + "tls_serverName").value;
} }
url = b64EncodeUnicode(JSON.stringify(info)); url = b64EncodeUnicode(JSON.stringify(info));
} else if ((v_type === "V2ray" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "vless") { } else if (v_type === "Xray" && opt.get(dom_prefix + "protocol").value === "vless") {
protocol = "vless"; protocol = "vless";
var v_password = opt.get(dom_prefix + "uuid"); var v_password = opt.get(dom_prefix + "uuid");
var v_port = opt.get(dom_prefix + "port"); var v_port = opt.get(dom_prefix + "port");
@ -328,8 +327,8 @@ local has_xray = api.is_finded("xray")
params += opt.query("sid", "reality_shortId"); params += opt.query("sid", "reality_shortId");
params += opt.query("spx", "reality_spiderX"); params += opt.query("spx", "reality_spiderX");
} }
if (opt.get(dom_prefix + "tlsflow") && opt.get(dom_prefix + "tlsflow").value) { if (opt.get(dom_prefix + "flow") && opt.get(dom_prefix + "flow").value) {
let v_flow = opt.get(dom_prefix + "tlsflow").value; let v_flow = opt.get(dom_prefix + "flow").value;
params += "&flow=" + v_flow; params += "&flow=" + v_flow;
} }
params += "&security=" + v_security; params += "&security=" + v_security;
@ -341,7 +340,7 @@ local has_xray = api.is_finded("xray")
params = params.substring(1); params = params.substring(1);
} }
url += params; url += params;
} else if (((v_type === "V2ray" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "trojan")) { } else if ((v_type === "Xray" && opt.get(dom_prefix + "protocol").value === "trojan")) {
protocol = "trojan"; protocol = "trojan";
var v_password = opt.get(dom_prefix + "password"); var v_password = opt.get(dom_prefix + "password");
var v_port = opt.get(dom_prefix + "port"); var v_port = opt.get(dom_prefix + "port");
@ -649,9 +648,7 @@ local has_xray = api.is_finded("xray")
queryParam[decodeURIComponent(params[0]).toLowerCase()] = decodeURIComponent(params[1] || ''); queryParam[decodeURIComponent(params[0]).toLowerCase()] = decodeURIComponent(params[1] || '');
} }
} }
<% if has_v2ray then %> <% if has_xray then %>
opt.set('type', "V2ray");
<% elseif has_xray then %>
opt.set('type', "Xray"); opt.set('type', "Xray");
<% end %> <% end %>
opt.set(dom_prefix + 'protocol', "trojan"); opt.set(dom_prefix + 'protocol', "trojan");
@ -670,9 +667,7 @@ local has_xray = api.is_finded("xray")
dom_prefix = "xray_" dom_prefix = "xray_"
var sstr = b64DecodeUnicode(ssu[1]); var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?"); var ploc = sstr.indexOf("/?");
<% if has_v2ray then %> <% if has_xray then %>
opt.set('type', "V2ray");
<% elseif has_xray then %>
opt.set('type', "Xray"); opt.set('type', "Xray");
<% end %> <% end %>
opt.set(dom_prefix + 'protocol', "vmess"); opt.set(dom_prefix + 'protocol', "vmess");
@ -723,8 +718,6 @@ local has_xray = api.is_finded("xray")
dom_prefix = "xray_" dom_prefix = "xray_"
<% if has_xray then %> <% if has_xray then %>
opt.set('type', "Xray"); opt.set('type', "Xray");
<% elseif has_v2ray then %>
opt.set('type', "V2ray");
<% end %> <% end %>
opt.set(dom_prefix + 'protocol', "vless"); opt.set(dom_prefix + 'protocol', "vless");
var m = parseNodeUrl(ssrurl); var m = parseNodeUrl(ssrurl);
@ -753,7 +746,7 @@ local has_xray = api.is_finded("xray")
if (queryParam.security == "tls") { if (queryParam.security == "tls") {
opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'tls', true);
opt.set('reality', false) opt.set('reality', false)
opt.set(dom_prefix + 'tlsflow', queryParam.flow || ''); opt.set(dom_prefix + 'flow', queryParam.flow || '');
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
opt.set(dom_prefix + 'tls_allowInsecure', true); opt.set(dom_prefix + 'tls_allowInsecure', true);
if (queryParam.allowinsecure === '0') { if (queryParam.allowinsecure === '0') {
@ -767,7 +760,7 @@ local has_xray = api.is_finded("xray")
if (queryParam.security == "reality") { if (queryParam.security == "reality") {
opt.set(dom_prefix + 'tls', true); opt.set(dom_prefix + 'tls', true);
opt.set('reality', true) opt.set('reality', true)
opt.set(dom_prefix + 'tlsflow', queryParam.flow || ''); opt.set(dom_prefix + 'flow', queryParam.flow || '');
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
if (queryParam.fp && queryParam.fp.trim() != "") { if (queryParam.fp && queryParam.fp.trim() != "") {
opt.set('reality_fingerprint', queryParam.fp); opt.set('reality_fingerprint', queryParam.fp);

View File

@ -8,7 +8,7 @@ local node = api.uci_get_type("global", "node", "nil")
if node ~= "nil" then if node ~= "nil" then
local node_type = api.uci_get_type_id(node, "type") local node_type = api.uci_get_type_id(node, "type")
local node_protocol = api.uci_get_type_id(node, "protocol") local node_protocol = api.uci_get_type_id(node, "protocol")
if (node_type == "V2ray" or node_type == "Xray") and node_protocol == "_shunt" then if node_type == "Xray" and node_protocol == "_shunt" then
default_node_type = node_protocol default_node_type = node_protocol
uci:foreach("passwall2", "shunt_rules", function(e) uci:foreach("passwall2", "shunt_rules", function(e)
if e[".name"] and e.remarks then if e[".name"] and e.remarks then

View File

@ -412,6 +412,9 @@ msgstr "传输层插件"
msgid "Shadowsocks secondary encryption" msgid "Shadowsocks secondary encryption"
msgstr "Shadowsocks 二次加密" msgstr "Shadowsocks 二次加密"
msgid "Obfs Type"
msgstr "混淆类型"
msgid "Obfs Password" msgid "Obfs Password"
msgstr "混淆密码" msgstr "混淆密码"
@ -421,6 +424,9 @@ msgstr "认证类型"
msgid "Auth Password" msgid "Auth Password"
msgstr "认证密码" msgstr "认证密码"
msgid "Commands the client to use the BBR flow control algorithm"
msgstr "命令客户端使用 BBR 流量控制算法"
msgid "Max upload Mbps" msgid "Max upload Mbps"
msgstr "最大上行(Mbps)" msgstr "最大上行(Mbps)"
@ -433,6 +439,9 @@ msgstr "QUIC 流接收窗口"
msgid "QUIC connection receive window" msgid "QUIC connection receive window"
msgstr "QUIC 连接接收窗口" msgstr "QUIC 连接接收窗口"
msgid "QUIC concurrent bidirectional streams"
msgstr "QUIC 并发双向流的最大数量"
msgid "Disable MTU detection" msgid "Disable MTU detection"
msgstr "禁用 MTU 检测" msgstr "禁用 MTU 检测"
@ -694,6 +703,9 @@ msgstr "启用自定义规则地址"
msgid "Rule status" msgid "Rule status"
msgstr "规则版本" msgstr "规则版本"
msgid "Manually update"
msgstr "手动更新"
msgid "Enable auto update rules" msgid "Enable auto update rules"
msgstr "开启自动更新规则" msgstr "开启自动更新规则"
@ -946,9 +958,6 @@ msgstr "从文件中加载 IP: 形如'ext:file:tag'必须以ext:(小写)
msgid "Clear logs" msgid "Clear logs"
msgstr "清空日志" msgstr "清空日志"
msgid "Only recommend to use with VLESS-TCP-XTLS-Vision."
msgstr "只推荐与 VLESS-TCP-XTLS-Vision 搭配使用。"
msgid "Password" msgid "Password"
msgstr "密码" msgstr "密码"
@ -1003,9 +1012,6 @@ msgstr "使用TLS"
msgid "Naiveproxy Protocol" msgid "Naiveproxy Protocol"
msgstr "Naiveproxy协议" msgstr "Naiveproxy协议"
msgid "V2ray Protocol"
msgstr "V2ray协议"
msgid "User Level" msgid "User Level"
msgstr "用户等级(level)" msgstr "用户等级(level)"
@ -1336,9 +1342,15 @@ msgstr "缓冲区大小"
msgid "Buffer size for every connection (kB)" msgid "Buffer size for every connection (kB)"
msgstr "每一个连接的缓冲区大小kB" msgstr "每一个连接的缓冲区大小kB"
msgid "Custom geoip Path"
msgstr "自定义geoip文件路径"
msgid "Custom geoip URL" msgid "Custom geoip URL"
msgstr "自定义geoip文件更新链接" msgstr "自定义geoip文件更新链接"
msgid "Custom geosite Path"
msgstr "自定义geosite文件路径"
msgid "Custom geosite URL" msgid "Custom geosite URL"
msgstr "自定义geosite文件更新链接" msgstr "自定义geosite文件更新链接"
@ -1353,3 +1365,9 @@ msgstr "端口跳跃时间 "
msgid "Additional ports for hysteria hop" msgid "Additional ports for hysteria hop"
msgstr "端口跳跃额外端口" msgstr "端口跳跃额外端口"
msgid "Override the connection destination address"
msgstr "覆盖连接目标地址"
msgid "Override the connection destination address with the sniffed domain."
msgstr "用探测出的域名覆盖连接目标地址。"

View File

@ -56,6 +56,17 @@ global_xray=$(uci -q get passwall2.@global_xray[0])
uci -q commit passwall2 uci -q commit passwall2
} }
global_singbox=$(uci -q get passwall2.@global_singbox[0])
[ -z "${global_singbox}" ] && {
cfgid=$(uci add passwall2 global_singbox)
uci -q set passwall2.${cfgid}.sniff_override_destination=1
uci -q set passwall2.${cfgid}.geoip_path="/tmp/singbox/geoip.db"
uci -q set passwall2.${cfgid}.geoip_url="https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db"
uci -q set passwall2.${cfgid}.geosite_path="/tmp/singbox/geosite.db"
uci -q set passwall2.${cfgid}.geosite_url="https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db"
uci -q commit passwall2
}
rm -f /tmp/luci-indexcache rm -f /tmp/luci-indexcache
rm -rf /tmp/luci-modulecache/ rm -rf /tmp/luci-modulecache/
killall -HUP rpcd 2>/dev/null killall -HUP rpcd 2>/dev/null

View File

@ -33,6 +33,8 @@ config global_forwarding
option use_nft '0' option use_nft '0'
option tcp_proxy_way 'redirect' option tcp_proxy_way 'redirect'
option ipv6_tproxy '0' option ipv6_tproxy '0'
config global_xray
option sniffing '1' option sniffing '1'
option route_only '0' option route_only '0'
@ -46,10 +48,10 @@ config global_rules
option v2ray_location_asset '/usr/share/v2ray/' option v2ray_location_asset '/usr/share/v2ray/'
config global_app config global_app
option v2ray_file '/usr/bin/v2ray'
option xray_file '/usr/bin/xray' option xray_file '/usr/bin/xray'
option brook_file '/usr/bin/brook' option brook_file '/usr/bin/brook'
option hysteria_file '/usr/bin/hysteria' option hysteria_file '/usr/bin/hysteria'
option singbox_file '/usr/bin/sing-box'
config global_subscribe config global_subscribe
option filter_keyword_mode '1' option filter_keyword_mode '1'
@ -58,6 +60,13 @@ config global_subscribe
list filter_discard_list 'QQ群' list filter_discard_list 'QQ群'
list filter_discard_list '官网' list filter_discard_list '官网'
config global_singbox
option sniff_override_destination '1'
option geoip_path '/tmp/singbox/geoip.db'
option geoip_url 'https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db'
option geosite_path '/tmp/singbox/geosite.db'
option geosite_url 'https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db'
config nodes 'myshunt' config nodes 'myshunt'
option remarks '分流总节点' option remarks '分流总节点'
option type 'Xray' option type 'Xray'
@ -229,7 +238,7 @@ config shunt_rules 'China'
config shunt_rules 'QUIC' config shunt_rules 'QUIC'
option remarks 'QUIC' option remarks 'QUIC'
option port '80,443' option port '443'
option network 'udp' option network 'udp'
config shunt_rules 'UDP' config shunt_rules 'UDP'

View File

@ -27,6 +27,7 @@ ENABLED_ACLS=0
PROXY_IPV6=0 PROXY_IPV6=0
PROXY_IPV6_UDP=0 PROXY_IPV6_UDP=0
LUA_UTIL_PATH=/usr/lib/lua/luci/passwall2 LUA_UTIL_PATH=/usr/lib/lua/luci/passwall2
UTIL_SINGBOX=$LUA_UTIL_PATH/util_sing-box.lua
UTIL_SS=$LUA_UTIL_PATH/util_shadowsocks.lua UTIL_SS=$LUA_UTIL_PATH/util_shadowsocks.lua
UTIL_XRAY=$LUA_UTIL_PATH/util_xray.lua UTIL_XRAY=$LUA_UTIL_PATH/util_xray.lua
UTIL_NAIVE=$LUA_UTIL_PATH/util_naiveproxy.lua UTIL_NAIVE=$LUA_UTIL_PATH/util_naiveproxy.lua
@ -283,21 +284,16 @@ lua_api() {
echo $(lua -e "local api = require 'luci.passwall2.api' print(api.${func})") echo $(lua -e "local api = require 'luci.passwall2.api' print(api.${func})")
} }
run_v2ray() { run_xray() {
local flag node redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password local flag node redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password
local dns_listen_port direct_dns_protocol direct_dns_udp_server direct_dns_tcp_server direct_dns_doh direct_dns_client_ip direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy dns_cache local dns_listen_port direct_dns_protocol direct_dns_udp_server direct_dns_tcp_server direct_dns_doh direct_dns_client_ip direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy dns_cache
local loglevel log_file config_file local loglevel log_file config_file
local _extra_param="" local _extra_param=""
eval_set_val $@ eval_set_val $@
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
if [ "$type" != "v2ray" ] && [ "$type" != "xray" ]; then if [ "$type" != "xray" ]; then
local bin=$(first_type $(config_t_get global_app xray_file) xray) local bin=$(first_type $(config_t_get global_app xray_file) xray)
if [ -n "$bin" ]; then [ -n "$bin" ] && type="xray"
type="xray"
else
bin=$(first_type $(config_t_get global_app v2ray_file) v2ray)
[ -n "$bin" ] && type="v2ray"
fi
fi fi
[ -z "$type" ] && return 1 [ -z "$type" ] && return 1
[ -n "$log_file" ] || local log_file="/dev/null" [ -n "$log_file" ] || local log_file="/dev/null"
@ -412,6 +408,162 @@ run_v2ray() {
ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $log_file run -c "$config_file" ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $log_file run -c "$config_file"
} }
run_singbox() {
local flag node redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password
local dns_listen_port direct_dns_protocol direct_dns_udp_server direct_dns_tcp_server direct_dns_doh direct_dns_client_ip direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy dns_cache
local loglevel log_file config_file
local _extra_param=""
eval_set_val $@
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
[ -z "$type" ] && return 1
[ -n "$log_file" ] || local log_file="/dev/null"
_extra_param="${_extra_param} -log 1 -logfile ${log_file}"
if [ "$log_file" = "/dev/null" ]; then
_extra_param="${_extra_param} -log 0"
else
_extra_param="${_extra_param} -log 1 -logfile ${log_file}"
fi
[ -z "$loglevel" ] && local loglevel=$(config_t_get global loglevel "warn")
[ "$loglevel" = "warning" ] && loglevel="warn"
_extra_param="${_extra_param} -loglevel $loglevel"
_extra_param="${_extra_param} -tags $($(first_type $(config_t_get global_app singbox_file) sing-box) version | grep 'Tags:' | awk '{print $2}')"
[ -n "$flag" ] && pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1{print $1}' | xargs kill -9 >/dev/null 2>&1
[ -n "$flag" ] && _extra_param="${_extra_param} -flag $flag"
[ -n "$socks_address" ] && _extra_param="${_extra_param} -local_socks_address $socks_address"
[ -n "$socks_port" ] && _extra_param="${_extra_param} -local_socks_port $socks_port"
[ -n "$socks_username" ] && [ -n "$socks_password" ] && _extra_param="${_extra_param} -local_socks_username $socks_username -local_socks_password $socks_password"
[ -n "$http_address" ] && _extra_param="${_extra_param} -local_http_address $http_address"
[ -n "$http_port" ] && _extra_param="${_extra_param} -local_http_port $http_port"
[ -n "$http_username" ] && [ -n "$http_password" ] && _extra_param="${_extra_param} -local_http_username $http_username -local_http_password $http_password"
[ -n "$dns_listen_port" ] && {
V2RAY_DNS_DIRECT_ARGS="-dns_out_tag direct"
V2RAY_DNS_DIRECT_CONFIG="${TMP_PATH}/${flag}_dns_direct.json"
V2RAY_DNS_DIRECT_LOG="${TMP_PATH}/${flag}_dns_direct.log"
V2RAY_DNS_DIRECT_ARGS="${V2RAY_DNS_DIRECT_ARGS} -log 1 -logfile ${V2RAY_DNS_DIRECT_LOG}"
dns_direct_listen_port=$(get_new_port $(expr $dns_listen_port + 1) udp)
V2RAY_DNS_DIRECT_ARGS="${V2RAY_DNS_DIRECT_ARGS} -dns_listen_port ${dns_direct_listen_port}"
[ "$direct_dns_protocol" = "auto" ] && {
direct_dns_protocol="udp"
direct_dns_udp_server=${AUTO_DNS}
direct_dns_query_strategy="UseIP"
}
case "$direct_dns_protocol" in
udp)
local _dns=$(get_first_dns direct_dns_udp_server 53 | sed 's/#/:/g')
local _dns_address=$(echo ${_dns} | awk -F ':' '{print $1}')
local _dns_port=$(echo ${_dns} | awk -F ':' '{print $2}')
V2RAY_DNS_DIRECT_ARGS="${V2RAY_DNS_DIRECT_ARGS} -direct_dns_server ${_dns_address} -direct_dns_port ${_dns_port} -direct_dns_udp_server ${_dns_address}"
;;
esac
[ -n "$direct_dns_query_strategy" ] && V2RAY_DNS_DIRECT_ARGS="${V2RAY_DNS_DIRECT_ARGS} -dns_query_strategy ${direct_dns_query_strategy}"
[ -n "$direct_dns_client_ip" ] && V2RAY_DNS_DIRECT_ARGS="${V2RAY_DNS_DIRECT_ARGS} -dns_client_ip ${direct_dns_client_ip}"
lua $UTIL_SINGBOX gen_dns_config ${V2RAY_DNS_DIRECT_ARGS} > $V2RAY_DNS_DIRECT_CONFIG
ln_run "$(first_type $(config_t_get global_app singbox_file) sing-box)" "sing-box" "/dev/null" run -c "$V2RAY_DNS_DIRECT_CONFIG"
direct_dnsmasq_listen_port=$(get_new_port $(expr $dns_direct_listen_port + 1) udp)
local set_flag="${flag}"
local direct_ipset_conf=$TMP_PATH/dnsmasq_${flag}_direct.conf
[ -n "$(echo ${flag} | grep '^acl')" ] && {
direct_ipset_conf=${TMP_ACL_PATH}/${sid}/dnsmasq_${flag}_direct.conf
set_flag=$(echo ${flag} | awk -F '_' '{print $2}')
}
if [ "${nftflag}" = "1" ]; then
local direct_nftset="4#inet#fw4#passwall2_${set_flag}_whitelist,6#inet#fw4#passwall2_${set_flag}_whitelist6"
else
local direct_ipset="passwall2_${set_flag}_whitelist,passwall2_${set_flag}_whitelist6"
fi
run_ipset_dnsmasq listen_port=${direct_dnsmasq_listen_port} server_dns=127.0.0.1#${dns_direct_listen_port} ipset="${direct_ipset}" nftset="${direct_nftset}" config_file=${direct_ipset_conf}
_extra_param="${_extra_param} -direct_dns_port ${direct_dnsmasq_listen_port} -direct_dns_udp_server 127.0.0.1 -direct_dns_query_strategy ${direct_dns_query_strategy}"
:<<eof
V2RAY_DNS_REMOTE_ARGS="-dns_out_tag remote"
V2RAY_DNS_REMOTE_CONFIG="${TMP_PATH}/${flag}_dns_remote.json"
V2RAY_DNS_REMOTE_LOG="${TMP_PATH}/${flag}_dns_remote.log"
V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -log 1 -logfile ${V2RAY_DNS_REMOTE_LOG}"
dns_remote_listen_port=$(get_new_port $(expr $direct_dnsmasq_listen_port + 1) udp)
V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -dns_listen_port ${dns_remote_listen_port}"
case "$remote_dns_protocol" in
udp)
local _dns=$(get_first_dns remote_dns_udp_server 53 | sed 's/#/:/g')
local _dns_address=$(echo ${_dns} | awk -F ':' '{print $1}')
local _dns_port=$(echo ${_dns} | awk -F ':' '{print $2}')
V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -remote_dns_server ${_dns_address} -remote_dns_port ${_dns_port} -remote_dns_udp_server ${_dns_address}"
;;
tcp)
local _dns=$(get_first_dns remote_dns_tcp_server 53 | sed 's/#/:/g')
local _dns_address=$(echo ${_dns} | awk -F ':' '{print $1}')
local _dns_port=$(echo ${_dns} | awk -F ':' '{print $2}')
V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -remote_dns_server ${_dns_address} -remote_dns_port ${_dns_port} -remote_dns_tcp_server tcp://${_dns}"
;;
doh)
local _doh_url=$(echo $remote_dns_doh | awk -F ',' '{print $1}')
local _doh_host_port=$(lua_api "get_domain_from_url(\"${_doh_url}\")")
#local _doh_host_port=$(echo $_doh_url | sed "s/https:\/\///g" | awk -F '/' '{print $1}')
local _doh_host=$(echo $_doh_host_port | awk -F ':' '{print $1}')
local is_ip=$(lua_api "is_ip(\"${_doh_host}\")")
local _doh_port=$(echo $_doh_host_port | awk -F ':' '{print $2}')
[ -z "${_doh_port}" ] && _doh_port=443
local _doh_bootstrap=$(echo $remote_dns_doh | cut -d ',' -sf 2-)
[ "${is_ip}" = "true" ] && _doh_bootstrap=${_doh_host}
[ -n "$_doh_bootstrap" ] && V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -remote_dns_server ${_doh_bootstrap}"
V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -remote_dns_port ${_doh_port} -remote_dns_doh_url ${_doh_url} -remote_dns_doh_host ${_doh_host}"
;;
esac
[ -n "$remote_dns_query_strategy" ] && V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -dns_query_strategy ${remote_dns_query_strategy}"
[ -n "$remote_dns_client_ip" ] && V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -dns_client_ip ${remote_dns_client_ip}"
V2RAY_DNS_REMOTE_ARGS="${V2RAY_DNS_REMOTE_ARGS} -remote_dns_outbound_socks_address 127.0.0.1 -remote_dns_outbound_socks_port ${socks_port}"
lua $UTIL_SINGBOX gen_dns_config ${V2RAY_DNS_REMOTE_ARGS} > $V2RAY_DNS_REMOTE_CONFIG
ln_run "$(first_type $(config_t_get global_app singbox_file) sing-box)" "sing-box" "/dev/null" run -c "$V2RAY_DNS_REMOTE_CONFIG"
_extra_param="${_extra_param} -remote_dns_port ${dns_remote_listen_port} -remote_dns_udp_server 127.0.0.1"
eof
case "$remote_dns_protocol" in
udp)
local _dns=$(get_first_dns remote_dns_udp_server 53 | sed 's/#/:/g')
local _dns_address=$(echo ${_dns} | awk -F ':' '{print $1}')
local _dns_port=$(echo ${_dns} | awk -F ':' '{print $2}')
_extra_param="${_extra_param} -remote_dns_port ${_dns_port} -remote_dns_udp_server ${_dns_address}"
;;
tcp)
local _dns=$(get_first_dns remote_dns_tcp_server 53 | sed 's/#/:/g')
local _dns_address=$(echo ${_dns} | awk -F ':' '{print $1}')
local _dns_port=$(echo ${_dns} | awk -F ':' '{print $2}')
_extra_param="${_extra_param} -remote_dns_server ${_dns_address} -remote_dns_port ${_dns_port} -remote_dns_tcp_server tcp://${_dns}"
;;
doh)
local _doh_url=$(echo $remote_dns_doh | awk -F ',' '{print $1}')
local _doh_host_port=$(lua_api "get_domain_from_url(\"${_doh_url}\")")
#local _doh_host_port=$(echo $_doh_url | sed "s/https:\/\///g" | awk -F '/' '{print $1}')
local _doh_host=$(echo $_doh_host_port | awk -F ':' '{print $1}')
local is_ip=$(lua_api "is_ip(\"${_doh_host}\")")
local _doh_port=$(echo $_doh_host_port | awk -F ':' '{print $2}')
[ -z "${_doh_port}" ] && _doh_port=443
local _doh_bootstrap=$(echo $remote_dns_doh | cut -d ',' -sf 2-)
[ "${is_ip}" = "true" ] && _doh_bootstrap=${_doh_host}
[ -n "$_doh_bootstrap" ] && _extra_param="${_extra_param} -remote_dns_server ${_doh_bootstrap}"
_extra_param="${_extra_param} -remote_dns_port ${_doh_port} -remote_dns_doh_url ${_doh_url} -remote_dns_doh_host ${_doh_host}"
;;
esac
[ -n "$remote_dns_query_strategy" ] && _extra_param="${_extra_param} -remote_dns_query_strategy ${remote_dns_query_strategy}"
[ -n "$dns_listen_port" ] && _extra_param="${_extra_param} -dns_listen_port ${dns_listen_port}"
[ -n "$dns_cache" ] && _extra_param="${_extra_param} -dns_cache ${dns_cache}"
[ "$remote_fakedns" = "1" ] && _extra_param="${_extra_param} -remote_dns_fake 1"
}
lua $UTIL_SINGBOX gen_config -node $node -redir_port $redir_port -tcp_proxy_way $tcp_proxy_way ${_extra_param} > $config_file
ln_run "$(first_type $(config_t_get global_app singbox_file) sing-box)" "sing-box" "${log_file}" run -c "$config_file"
}
run_socks() { run_socks() {
local flag node bind socks_port config_file http_port http_config_file relay_port log_file local flag node bind socks_port config_file http_port http_config_file relay_port log_file
eval_set_val $@ eval_set_val $@
@ -444,7 +596,7 @@ run_socks() {
error_msg="某种原因,此 Socks 服务的相关配置已失联,启动中止!" error_msg="某种原因,此 Socks 服务的相关配置已失联,启动中止!"
fi fi
if [ "$type" == "v2ray" ] || [ "$type" == "xray" ]; then if [ "$type" == "sing-box" ] || [ "$type" == "xray" ]; then
local protocol=$(config_n_get $node protocol) local protocol=$(config_n_get $node protocol)
if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ]; then if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ]; then
unset error_msg unset error_msg
@ -458,7 +610,15 @@ run_socks() {
[ "$bind" != "127.0.0.1" ] && echolog " - Socks节点[$remarks]${tmp},启动 ${bind}:${socks_port}" [ "$bind" != "127.0.0.1" ] && echolog " - Socks节点[$remarks]${tmp},启动 ${bind}:${socks_port}"
case "$type" in case "$type" in
v2ray|\ sing-box)
[ "$http_port" != "0" ] && {
http_flag=1
config_file=$(echo $config_file | sed "s/SOCKS/HTTP_SOCKS/g")
local _extra_param="-local_http_port $http_port"
}
lua $UTIL_SINGBOX gen_config -flag SOCKS_$flag -node $node -local_socks_port $socks_port ${_extra_param} > $config_file
ln_run "$(first_type $(config_t_get global_app singbox_file) sing-box)" "sing-box" $log_file run -c "$config_file"
;;
xray) xray)
[ "$http_port" != "0" ] && { [ "$http_port" != "0" ] && {
http_flag=1 http_flag=1
@ -466,7 +626,7 @@ run_socks() {
local _extra_param="-local_http_port $http_port" local _extra_param="-local_http_port $http_port"
} }
lua $UTIL_XRAY gen_config -flag SOCKS_$flag -node $node -local_socks_port $socks_port ${_extra_param} > $config_file lua $UTIL_XRAY gen_config -flag SOCKS_$flag -node $node -local_socks_port $socks_port ${_extra_param} > $config_file
ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $log_file run -c "$config_file" ln_run "$(first_type $(config_t_get global_app xray_file) xray)" "xray" $log_file run -c "$config_file"
;; ;;
naiveproxy) naiveproxy)
lua $UTIL_NAIVE gen_config -node $node -run_type socks -local_addr $bind -local_port $socks_port -server_host $server_host -server_port $port > $config_file lua $UTIL_NAIVE gen_config -node $node -run_type socks -local_addr $bind -local_port $socks_port -server_host $server_host -server_port $port > $config_file
@ -520,17 +680,19 @@ run_socks() {
esac esac
# http to socks # http to socks
[ -z "$http_flag" ] && [ "$http_port" != "0" ] && [ -n "$http_config_file" ] && [ "$type" != "v2ray" ] && [ "$type" != "xray" ] && [ "$type" != "socks" ] && { [ -z "$http_flag" ] && [ "$http_port" != "0" ] && [ -n "$http_config_file" ] && [ "$type" != "sing-box" ] && [ "$type" != "xray" ] && [ "$type" != "socks" ] && {
local bin=$(first_type $(config_t_get global_app v2ray_file) v2ray) local bin=$(first_type $(config_t_get global_app singbox_file) sing-box)
if [ -n "$bin" ]; then if [ -n "$bin" ]; then
type="v2ray" type="sing-box"
lua $UTIL_SINGBOX gen_proto_config -local_http_port $http_port -server_proto socks -server_address "127.0.0.1" -server_port $socks_port -server_username $_username -server_password $_password > $http_config_file
ln_run "$bin" ${type} /dev/null run -c "$http_config_file"
else else
bin=$(first_type $(config_t_get global_app xray_file) xray) bin=$(first_type $(config_t_get global_app xray_file) xray)
[ -n "$bin" ] && type="xray" [ -n "$bin" ] && type="xray"
fi
[ -z "$type" ] && return 1 [ -z "$type" ] && return 1
lua $UTIL_XRAY gen_proto_config -local_http_port $http_port -server_proto socks -server_address "127.0.0.1" -server_port $socks_port -server_username $_username -server_password $_password > $http_config_file lua $UTIL_XRAY gen_proto_config -local_http_port $http_port -server_proto socks -server_address "127.0.0.1" -server_port $socks_port -server_username $_username -server_password $_password > $http_config_file
ln_run "$bin" ${type} /dev/null run -c "$http_config_file" ln_run "$bin" ${type} /dev/null run -c "$http_config_file"
fi
} }
unset http_flag unset http_flag
} }
@ -646,7 +808,8 @@ run_global() {
node_http_port=$(config_t_get global node_http_port 0) node_http_port=$(config_t_get global node_http_port 0)
[ "$node_http_port" != "0" ] && V2RAY_ARGS="${V2RAY_ARGS} http_port=${node_http_port}" [ "$node_http_port" != "0" ] && V2RAY_ARGS="${V2RAY_ARGS} http_port=${node_http_port}"
run_v2ray $V2RAY_ARGS [ "${TYPE}" = "xray" ] && run_xray $V2RAY_ARGS
[ "${TYPE}" = "sing-box" ] && run_singbox $V2RAY_ARGS
} }
start_socks() { start_socks() {
@ -897,7 +1060,10 @@ acl_app() {
config_file=$TMP_ACL_PATH/${node}_TCP_UDP_DNS_${redir_port}.json config_file=$TMP_ACL_PATH/${node}_TCP_UDP_DNS_${redir_port}.json
dns_port=$(get_new_port $(expr $dns_port + 1)) dns_port=$(get_new_port $(expr $dns_port + 1))
local acl_socks_port=$(get_new_port $(expr $redir_port + $index)) local acl_socks_port=$(get_new_port $(expr $redir_port + $index))
run_v2ray flag=acl_$sid node=$node redir_port=$redir_port socks_address=127.0.0.1 socks_port=$acl_socks_port dns_listen_port=${dns_port} direct_dns_protocol=${direct_dns_protocol} direct_dns_udp_server=${direct_dns} direct_dns_tcp_server=${direct_dns} direct_dns_doh="${direct_dns}" direct_dns_client_ip=${direct_dns_client_ip} direct_dns_query_strategy=${direct_dns_query_strategy} remote_dns_protocol=${remote_dns_protocol} remote_dns_tcp_server=${remote_dns} remote_dns_udp_server=${remote_dns} remote_dns_doh="${remote_dns}" remote_dns_client_ip=${remote_dns_client_ip} remote_fakedns=${remote_fakedns} remote_dns_query_strategy=${remote_dns_query_strategy} config_file=${config_file} local run_func
[ "${TYPE}" = "xray" ] && run_func="run_xray"
[ "${TYPE}" = "sing-box" ] && run_func="run_singbox"
${run_func} flag=acl_$sid node=$node redir_port=$redir_port socks_address=127.0.0.1 socks_port=$acl_socks_port dns_listen_port=${dns_port} direct_dns_protocol=${direct_dns_protocol} direct_dns_udp_server=${direct_dns} direct_dns_tcp_server=${direct_dns} direct_dns_doh="${direct_dns}" direct_dns_client_ip=${direct_dns_client_ip} direct_dns_query_strategy=${direct_dns_query_strategy} remote_dns_protocol=${remote_dns_protocol} remote_dns_tcp_server=${remote_dns} remote_dns_udp_server=${remote_dns} remote_dns_doh="${remote_dns}" remote_dns_client_ip=${remote_dns_client_ip} remote_fakedns=${remote_fakedns} remote_dns_query_strategy=${remote_dns_query_strategy} config_file=${config_file}
fi fi
dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1)) dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1))
redirect_dns_port=$dnsmasq_port redirect_dns_port=$dnsmasq_port

View File

@ -12,7 +12,7 @@ local arg1 = arg[1]
local reboot = 0 local reboot = 0
local geoip_update = 0 local geoip_update = 0
local geosite_update = 0 local geosite_update = 0
local v2ray_asset_location = ucic:get_first(name, 'global_rules', "v2ray_location_asset", "/usr/share/v2ray/") local asset_location = ucic:get_first(name, 'global_rules', "v2ray_location_asset", "/usr/share/v2ray/")
-- Custom geo file -- Custom geo file
local geoip_api = ucic:get_first(name, 'global_rules', "geoip_url", "https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases/latest") local geoip_api = ucic:get_first(name, 'global_rules', "geoip_url", "https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases/latest")
@ -61,8 +61,8 @@ local function fetch_geoip()
f:write(content:gsub("geoip.dat", "/tmp/geoip.dat"), "") f:write(content:gsub("geoip.dat", "/tmp/geoip.dat"), "")
f:close() f:close()
if nixio.fs.access(v2ray_asset_location .. "geoip.dat") then if nixio.fs.access(asset_location .. "geoip.dat") then
luci.sys.call(string.format("cp -f %s %s", v2ray_asset_location .. "geoip.dat", "/tmp/geoip.dat")) luci.sys.call(string.format("cp -f %s %s", asset_location .. "geoip.dat", "/tmp/geoip.dat"))
if luci.sys.call('sha256sum -c /tmp/geoip.dat.sha256sum > /dev/null 2>&1') == 0 then if luci.sys.call('sha256sum -c /tmp/geoip.dat.sha256sum > /dev/null 2>&1') == 0 then
log("geoip 版本一致,无需更新。") log("geoip 版本一致,无需更新。")
return 1 return 1
@ -72,7 +72,7 @@ local function fetch_geoip()
if v2.name and v2.name == "geoip.dat" then if v2.name and v2.name == "geoip.dat" then
sret = curl(v2.browser_download_url, "/tmp/geoip.dat") sret = curl(v2.browser_download_url, "/tmp/geoip.dat")
if luci.sys.call('sha256sum -c /tmp/geoip.dat.sha256sum > /dev/null 2>&1') == 0 then if luci.sys.call('sha256sum -c /tmp/geoip.dat.sha256sum > /dev/null 2>&1') == 0 then
luci.sys.call(string.format("mkdir -p %s && cp -f %s %s", v2ray_asset_location, "/tmp/geoip.dat", v2ray_asset_location .. "geoip.dat")) luci.sys.call(string.format("mkdir -p %s && cp -f %s %s", asset_location, "/tmp/geoip.dat", asset_location .. "geoip.dat"))
reboot = 1 reboot = 1
log("geoip 更新成功。") log("geoip 更新成功。")
return 1 return 1
@ -112,8 +112,8 @@ local function fetch_geosite()
f:write(content:gsub("geosite.dat", "/tmp/geosite.dat"), "") f:write(content:gsub("geosite.dat", "/tmp/geosite.dat"), "")
f:close() f:close()
if nixio.fs.access(v2ray_asset_location .. "geosite.dat") then if nixio.fs.access(asset_location .. "geosite.dat") then
luci.sys.call(string.format("cp -f %s %s", v2ray_asset_location .. "geosite.dat", "/tmp/geosite.dat")) luci.sys.call(string.format("cp -f %s %s", asset_location .. "geosite.dat", "/tmp/geosite.dat"))
if luci.sys.call('sha256sum -c /tmp/geosite.dat.sha256sum > /dev/null 2>&1') == 0 then if luci.sys.call('sha256sum -c /tmp/geosite.dat.sha256sum > /dev/null 2>&1') == 0 then
log("geosite 版本一致,无需更新。") log("geosite 版本一致,无需更新。")
return 1 return 1
@ -123,7 +123,7 @@ local function fetch_geosite()
if v2.name and v2.name == "geosite.dat" then if v2.name and v2.name == "geosite.dat" then
sret = curl(v2.browser_download_url, "/tmp/geosite.dat") sret = curl(v2.browser_download_url, "/tmp/geosite.dat")
if luci.sys.call('sha256sum -c /tmp/geosite.dat.sha256sum > /dev/null 2>&1') == 0 then if luci.sys.call('sha256sum -c /tmp/geosite.dat.sha256sum > /dev/null 2>&1') == 0 then
luci.sys.call(string.format("mkdir -p %s && cp -f %s %s", v2ray_asset_location, "/tmp/geosite.dat", v2ray_asset_location .. "geosite.dat")) luci.sys.call(string.format("mkdir -p %s && cp -f %s %s", asset_location, "/tmp/geosite.dat", asset_location .. "geosite.dat"))
reboot = 1 reboot = 1
log("geosite 更新成功。") log("geosite 更新成功。")
return 1 return 1

View File

@ -23,7 +23,7 @@ uci:revert(appname)
local has_ss = api.is_finded("ss-redir") local has_ss = api.is_finded("ss-redir")
local has_ss_rust = api.is_finded("sslocal") local has_ss_rust = api.is_finded("sslocal")
local has_v2ray = api.is_finded("v2ray") local has_singbox = api.is_finded("sing-box")
local has_xray = api.is_finded("xray") local has_xray = api.is_finded("xray")
local allowInsecure_default = true local allowInsecure_default = true
local ss_aead_type_default = uci:get(appname, "@global_subscribe[0]", "ss_aead_type") or "shadowsocks-libev" local ss_aead_type_default = uci:get(appname, "@global_subscribe[0]", "ss_aead_type") or "shadowsocks-libev"
@ -387,10 +387,12 @@ local function processData(szType, content, add_mode, add_from)
result.remarks = base64Decode(params.remarks) result.remarks = base64Decode(params.remarks)
elseif szType == 'vmess' then elseif szType == 'vmess' then
local info = jsonParse(content) local info = jsonParse(content)
result.type = 'V2ray'
if has_xray then if has_xray then
result.type = 'Xray' result.type = 'Xray'
end end
if has_singbox then
result.type = 'sing-box'
end
result.address = info.add result.address = info.add
result.port = info.port result.port = info.port
result.protocol = 'vmess' result.protocol = 'vmess'
@ -532,13 +534,9 @@ local function processData(szType, content, add_mode, add_from)
if method:lower() == "chacha20-poly1305" then if method:lower() == "chacha20-poly1305" then
result.method = "chacha20-ietf-poly1305" result.method = "chacha20-ietf-poly1305"
end end
elseif ss_aead_type_default == "v2ray" and has_v2ray and not result.plugin then elseif ss_aead_type_default == "sing-box" and has_singbox and not result.plugin then
result.type = 'V2ray' result.type = 'sing-box'
result.protocol = 'shadowsocks' result.protocol = 'shadowsocks'
result.transport = 'tcp'
if method:lower() == "chacha20-ietf-poly1305" then
result.method = "chacha20-poly1305"
end
elseif ss_aead_type_default == "xray" and has_xray and not result.plugin then elseif ss_aead_type_default == "xray" and has_xray and not result.plugin then
result.type = 'Xray' result.type = 'Xray'
result.protocol = 'shadowsocks' result.protocol = 'shadowsocks'
@ -557,10 +555,12 @@ local function processData(szType, content, add_mode, add_from)
content = content:sub(0, idx_sp - 1) content = content:sub(0, idx_sp - 1)
end end
result.remarks = UrlDecode(alias) result.remarks = UrlDecode(alias)
result.type = 'V2ray'
if has_xray then if has_xray then
result.type = 'Xray' result.type = 'Xray'
end end
if has_singbox then
result.type = 'sing-box'
end
result.protocol = 'trojan' result.protocol = 'trojan'
if content:find("@") then if content:find("@") then
local Info = split(content, "@") local Info = split(content, "@")
@ -622,10 +622,12 @@ local function processData(szType, content, add_mode, add_from)
result.group = content.airport result.group = content.airport
result.remarks = content.remarks result.remarks = content.remarks
elseif szType == "vless" then elseif szType == "vless" then
result.type = 'V2ray'
if has_xray then if has_xray then
result.type = 'Xray' result.type = 'Xray'
end end
if has_singbox then
result.type = 'sing-box'
end
result.protocol = "vless" result.protocol = "vless"
local alias = "" local alias = ""
if content:find("#") then if content:find("#") then
@ -699,10 +701,11 @@ local function processData(szType, content, add_mode, add_from)
result.encryption = params.encryption or "none" result.encryption = params.encryption or "none"
result.flow = params.flow or nil
result.tls = "0" result.tls = "0"
if params.security == "tls" or params.security == "reality" then if params.security == "tls" or params.security == "reality" then
result.tls = "1" result.tls = "1"
result.tlsflow = params.flow or nil
result.tls_serverName = (params.sni and params.sni ~= "") and params.sni or params.host result.tls_serverName = (params.sni and params.sni ~= "") and params.sni or params.host
result.fingerprint = (params.fp and params.fp ~= "") and params.fp or "chrome" result.fingerprint = (params.fp and params.fp ~= "") and params.fp or "chrome"
if params.security == "reality" then if params.security == "reality" then