Compare commits

...
2 Commits
Author SHA1 Message Date
action 3003d5612b update 2026-09-03 03:09:55 2026-09-03 03:09:55 +08:00
action beae9d285e update 2026-09-02 23:49:44 2026-09-02 23:49:44 +08:00
35 changed files with 350 additions and 148 deletions
+2 -2
View File
@@ -5,12 +5,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=dae
PKG_VERSION:=2026.08.31
PKG_VERSION:=2026.09.02
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=93a9957e08c14a40e742581e6342450122916294
PKG_SOURCE_VERSION:=ebbec6b5624d7790c58a11e081604e30b6c947b3
PKG_SOURCE_URL:=https://github.com/olicesx/dae.git
PKG_MIRROR_HASH:=skip
@@ -346,12 +346,8 @@ function index_status()
has_tproxy = (mods:find("TPROXY") or mods:find("nft_tproxy")) and "1" or "0"
api.set_cache_var("HAS_TPROXY", has_tproxy)
end
local tcp_redir = api.get_cache_var("DEFAULT_TCP_REDIR")
local udp_redir = api.get_cache_var("DEFAULT_UDP_REDIR")
if tcp_redir == "1" then
e["tcp_status"] = luci.sys.call("/bin/busybox top -bn1 | grep -v 'grep' | grep '%s/bin/' | grep 'default' | grep 'global' >/dev/null" % api.TMP_PATH) == 0
end
if has_tproxy == "1" and udp_redir == "1" then
if has_tproxy == "1" then
e["udp_status"] = luci.sys.call("/bin/busybox top -bn1 | grep -v -E 'grep|naive' | grep '%s/bin/' | grep 'default' | grep 'global' >/dev/null" % api.TMP_PATH) == 0
end
end
@@ -40,6 +40,7 @@ local security_list = { "none", "auto", "aes-128-gcm", "chacha20-poly1305", "zer
local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'")
local singbox_version = api.get_app_version("sing-box"):match("[^v]+")
local version_ge_1_14_0 = api.compare_versions(singbox_version, ">=", "1.14.0")
o = s:option(ListValue, "protocol", translate("Protocol"))
o:value("socks", "Socks")
@@ -65,6 +66,9 @@ o:value("ssh", "SSH")
if singbox_tags:find("with_naive_outbound") then
o:value("naive", "NaïveProxy")
end
if version_ge_1_14_0 then
o:value("snell", "Snell")
end
o:value("_urltest", translate("URLTest"))
o:value("_shunt", translate("Shunt"))
o:value("_iface", translate("Custom Interface"))
@@ -232,6 +236,43 @@ o:depends({ protocol = "anytls" })
o:depends({ protocol = "ssh" })
o:depends({ protocol = "naive" })
if version_ge_1_14_0 then
-- snell
s.fields["password"]:depends({ protocol = "snell" })
o = s:option(Value, "snell_psk", translate("Pre shared key"))
o.rmempty = false
o:depends({ protocol = "snell" })
o = s:option(ListValue, "snell_version", translate("Version"))
o:value("4")
o:value("6")
o:depends({ protocol = "snell" })
o = s:option(Flag, "snell_reuse", translate("Connection Reuse"))
o:depends({ protocol = "snell" })
o = s:option(ListValue, "snell_network", translate("Transport"))
o:value("", "TCP UDP")
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:depends({ protocol = "snell" })
o = s:option(ListValue, "snell_obfs_mode", translate("Camouflage Type"))
o:value("none")
o:value("http")
o:depends({ protocol = "snell", snell_version = "4" })
o = s:option(Value, "snell_obfs_host", translate("HTTP Host"))
o:depends({ protocol = "snell", snell_version = "4", snell_obfs_mode = "http" })
o = s:option(ListValue, "snell_mode", translate("Mode"))
o:value("default")
o:value("unshaped")
o:value("unsafe-raw")
o:depends({ protocol = "snell", snell_version = "6" })
end
o = s:option(ListValue, "security", translate("Encrypt Method"))
for a, t in ipairs(security_list) do o:value(t) end
o:depends({ protocol = "vmess" })
@@ -364,7 +405,7 @@ if singbox_tags:find("with_quic") then
o = s:option(Flag, "hysteria2_realms", translate("Realms"))
o.default = "0"
if api.compare_versions(singbox_version, ">=", "1.14.0") then
if version_ge_1_14_0 then
o:depends({ protocol = "hysteria2"})
else
o:depends({ protocol = "__hide"})
@@ -2,6 +2,7 @@ local api = require "luci.passwall.api"
api.set_default_cbi()
m = Map(api.s_config)
m.redirect = api.url("server")
t = m:section(NamedSection, "global", "global", translate("Server-Side"))
t.anonymous = true
@@ -27,6 +27,9 @@ s.option_prefix = "singbox_"
local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'")
local local_version = api.get_app_version("sing-box"):match("[^v]+")
local version_ge_1_14_0 = api.compare_versions(local_version, ">=", "1.14.0")
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"
@@ -56,6 +59,7 @@ o.custom_write = function(self, section, value)
end
o = s:option(ListValue, "protocol", translate("Protocol"))
o:value("direct", "Direct")
o:value("mixed", "Mixed")
o:value("socks", "Socks")
o:value("http", "HTTP")
@@ -63,29 +67,12 @@ 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")
if singbox_tags:find("with_naive_outbound") then
o:value("naive", "Naive")
end
o:value("anytls", "AnyTLS")
if singbox_tags:find("with_wireguard") then
o:value("wireguard", "WireGuard")
end
o:value("direct", "Direct")
o:depends({ custom = false })
o = s:option(DummyValue, "is_endpoint", "")
o.not_rewrite = true
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ custom = false, protocol = "wireguard" })
o = s:option(Value, "port", translate("Listen Port"))
o.datatype = "port"
o:depends({ custom = false })
@@ -102,13 +89,13 @@ o:depends({ protocol = "vmess" })
o:depends({ protocol = "vless" })
o:depends({ protocol = "trojan" })
o:depends({ protocol = "naive" })
o:depends({ protocol = "hysteria" })
o:depends({ protocol = "tuic" })
o:depends({ protocol = "hysteria2" })
o:depends({ protocol = "anytls" })
o:depends({ protocol = "wireguard" })
if singbox_tags:find("with_quic") then
-- hysteria
s.fields["protocol"]:value("hysteria", "Hysteria")
s.fields["users"]:depends({ protocol = "hysteria" })
o = s:option(Value, "hysteria_obfs", translate("Obfs Password"))
o:depends({ protocol = "hysteria" })
@@ -135,6 +122,10 @@ if singbox_tags:find("with_quic") then
end
if singbox_tags:find("with_quic") then
-- tuic
s.fields["protocol"]:value("tuic", "TUIC")
s.fields["users"]:depends({ protocol = "tuic" })
o = s:option(ListValue, "tuic_congestion_control", translate("Congestion control algorithm"))
o.default = "cubic"
o:value("bbr", translate("BBR"))
@@ -166,6 +157,10 @@ if singbox_tags:find("with_quic") then
end
if singbox_tags:find("with_quic") then
-- hysteria2
s.fields["protocol"]:value("hysteria2", "Hysteria2")
s.fields["users"]:depends({ protocol = "hysteria2" })
o = s:option(Flag, "hysteria2_realms", translate("Realms"))
o.default = "0"
o:depends({ protocol = "hysteria2"})
@@ -436,6 +431,10 @@ o.default = "50"
o:depends({ tcpbrutal = true })
if singbox_tags:find("with_wireguard") then
-- wireguard
s.fields["protocol"]:value("wireguard", "WireGuard")
s.fields["users"]:depends({ protocol = "wireguard" })
o = s:option(Flag, "wireguard_system_interface", translate("System interface"))
o.default = 0
o:depends({ protocol = "wireguard" })
@@ -460,6 +459,32 @@ if singbox_tags:find("with_wireguard") then
o:depends({ protocol = "wireguard" })
end
if version_ge_1_14_0 then
-- snell
s.fields["protocol"]:value("snell", "Snell")
s.fields["users"]:depends({ protocol = "snell" })
o = s:option(ListValue, "snell_version", translate("Version"))
o:value("5")
o:value("6")
o:depends({ protocol = "snell" })
o = s:option(Value, "snell_psk", translate("Pre shared key"))
o.rmempty = false
o:depends({ protocol = "snell" })
o = s:option(ListValue, "snell_obfs_mode", translate("Obfs"))
o:value("none")
o:value("http")
o:depends({ protocol = "snell", snell_version = "5" })
o = s:option(ListValue, "snell_mode", translate("Mode"))
o:value("default")
o:value("unshaped")
o:value("unsafe-raw")
o:depends({ protocol = "snell", snell_version = "6" })
end
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
o.default = "0"
o:depends({ custom = false })
@@ -597,6 +597,7 @@ function gen_outbound(flag, node, tag, proxy_table)
realm.address = nil
realm.port = nil
realm.port_mapping = (node.hysteria2_realm_upnp == "1") and { enabled = true } or nil
realm.http_client = "direct_http_client"
return realm
end
return nil
@@ -645,6 +646,19 @@ function gen_outbound(flag, node, tag, proxy_table)
}
end
if node.protocol == "snell" then
protocol_table = {
version = tonumber(node.snell_version),
psk = node.snell_psk,
userkey = node.password,
reuse = node.snell_reuse == "1" and true or false,
network = node.snell_network,
obfs_mode = node.snell_version == "4" and node.snell_obfs_mode or nil,
obfs_host = node.snell_version == "4" and node.snell_obfs_host or nil,
mode = node.snell_version == "6" and node.snell_mode or nil,
}
end
if protocol_table then
for key, value in pairs(protocol_table) do
result[key] = value
@@ -801,6 +815,10 @@ function gen_config_server(node)
u.allowed_ips = user.allowed_ips or {}
u.persistent_keepalive_interval = 0
end
if node.protocol == "snell" then
u.name = user.username
u.userkey = user.password
end
users[#users + 1] = u
end
end
@@ -953,6 +971,7 @@ function gen_config_server(node)
realm.port = nil
realm.stun_domain_resolver = "direct"
realm.port_mapping = (node.hysteria2_realm_upnp == "1") and { enabled = true } or nil
realm.http_client = { detour = "direct" }
return realm
end
return nil
@@ -981,6 +1000,16 @@ function gen_config_server(node)
end
end
if node.protocol == "snell" then
protocol_table = {
users = users,
version = tonumber(node.snell_version),
psk = node.snell_psk,
obfs_mode = node.snell_version == "5" and node.snell_obfs_mode or nil,
mode = node.snell_version == "6" and node.snell_mode or nil,
}
end
if node.protocol == "direct" then
protocol_table = {
network = (node.d_protocol ~= "TCP,UDP") and node.d_protocol or nil,
@@ -1167,8 +1196,8 @@ function gen_config(var)
format = format,
path = _type == "local" and w or nil,
url = _type == "remote" and w or nil,
--download_detour = _type == "remote" and "",
--update_interval = _type == "remote" and "",
http_client = _type == "remote" and "remote_http_client" or nil,
--update_interval = _type == "remote" and "1d" or nil,
}
end
end
@@ -2203,6 +2232,36 @@ function gen_config(var)
end
end
local http_clients
if outbounds then
local proxy_tag = COMMON.default_outbound_tag
if proxy_tag == "block" or proxy_tag == "direct" then -- 如默认节点是特殊节点,则选一个可用节点作为出口(urltest优先)
local first_node
for _, v in ipairs(outbounds) do
if not v["_flag_proxy_tag"] and not v.detour and v["_id"] and ((v.server and (v.server_port or v.server_ports)) or v.type == "urltest") then
first_node = first_node or v.tag
if v.type == "urltest" then
proxy_tag = v.tag
break
end
end
end
if proxy_tag == COMMON.default_outbound_tag then
proxy_tag = first_node
end
end
http_clients = {
{
tag = "remote_http_client",
detour = proxy_tag
},
{
tag = "direct_http_client",
detour = "direct"
}
}
end
if inbounds or outbounds then
local config = {
log = {
@@ -2219,8 +2278,10 @@ function gen_config(var)
outbounds = outbounds,
-- 路由
route = route,
--实验性
-- 实验性
experimental = experimental,
-- HTTP Client
http_clients = http_clients
}
table.insert(outbounds, {
type = "direct",
+3
View File
@@ -2183,3 +2183,6 @@ msgstr "密码套件"
msgid "Configures the list of supported cipher suites, separated by :"
msgstr "配置支持的密码套件列表,以冒号 (:) 分隔。"
msgid "Connection Reuse"
msgstr "连接复用"
@@ -491,7 +491,6 @@ if IS_SHUNT_NODE then
}
insert_array_after(config_lines, tmp_lines, "#--4")
end
end
if is_file_nonzero(file_shunt_host) then
@@ -560,8 +560,6 @@ load_acl() {
msg="【默认】,"
local ipt_tmp=$ipt_n
[ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m
local DEFAULT_TCP_REDIR=1
local DEFAULT_UDP_REDIR=1
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN"
@@ -570,7 +568,6 @@ load_acl() {
echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]"
else
unset TCP_PROXY_MODE
DEFAULT_TCP_REDIR=0
echolog " - ${msg}不代理所有 TCP 端口"
fi
}
@@ -582,7 +579,6 @@ load_acl() {
echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]"
else
unset UDP_PROXY_MODE
DEFAULT_UDP_REDIR=0
echolog " - ${msg}不代理所有 UDP 端口"
fi
}
@@ -630,9 +626,6 @@ load_acl() {
[ "${USE_SHUNT_NODE}" = "1" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS $(dst $IPSET_SHUNT) "-j MARK --set-mark 88"
[ "${TCP_PROXY_MODE}" != "disable" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "-j MARK --set-mark 88"
echolog " - ${msg}屏蔽代理 TCP 端口[${TCP_PROXY_DROP_PORTS}]"
if has_1_65535 "$TCP_PROXY_DROP_PORTS"; then
DEFAULT_TCP_REDIR=0
fi
}
[ "$UDP_PROXY_DROP_PORTS" != "disable" ] && {
@@ -651,9 +644,6 @@ load_acl() {
[ "${USE_SHUNT_NODE}" = "1" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "$(dst $IPSET_SHUNT) -j MARK --set-mark 88"
[ "${UDP_PROXY_MODE}" != "disable" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "-j MARK --set-mark 88"
echolog " - ${msg}屏蔽代理 UDP 端口[${UDP_PROXY_DROP_PORTS}]"
if has_1_65535 "$UDP_PROXY_DROP_PORTS"; then
DEFAULT_UDP_REDIR=0
fi
}
$ipt_m -A PSW $(comment "默认") -m mark --mark 88 -j ACCEPT 2>/dev/null
@@ -662,9 +652,6 @@ load_acl() {
}
}
set_cache_var "DEFAULT_TCP_REDIR" "$DEFAULT_TCP_REDIR"
set_cache_var "DEFAULT_UDP_REDIR" "$DEFAULT_UDP_REDIR"
# 加载TCP默认代理模式
if [ -n "${TCP_PROXY_MODE}" ]; then
[ -n "$NODE" ] && {
@@ -620,8 +620,6 @@ load_acl() {
}
[ "$ENABLED_DEFAULT_ACL" = 1 ] && [ "$CLIENT_PROXY" = 1 ] && {
local DEFAULT_TCP_REDIR=1
local DEFAULT_UDP_REDIR=1
msg="【默认】,"
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\""
@@ -630,7 +628,6 @@ load_acl() {
echolog " - ${msg}不代理 TCP 端口[${TCP_NO_REDIR_PORTS}]"
else
unset TCP_PROXY_MODE
DEFAULT_TCP_REDIR=0
echolog " - ${msg}不代理所有 TCP 端口"
fi
}
@@ -642,7 +639,6 @@ load_acl() {
echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]"
else
unset UDP_PROXY_MODE
DEFAULT_UDP_REDIR=0
echolog " - ${msg}不代理所有 UDP 端口"
fi
}
@@ -693,9 +689,6 @@ load_acl() {
[ "${USE_SHUNT_NODE}" = "1" ] && nft_rule_dual "$nft_prerouting_chain" "ip protocol tcp $(factor $TCP_PROXY_DROP_PORTS "tcp dport") ip daddr" "$NFTSET_SHUNT" "counter reject comment \"默认\""
[ "${TCP_PROXY_MODE}" != "disable" ] && nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp $(factor $TCP_PROXY_DROP_PORTS "tcp dport") counter reject comment \"默认\""
echolog " - ${msg}屏蔽代理 TCP 端口[${TCP_PROXY_DROP_PORTS}]"
if has_1_65535 "$TCP_PROXY_DROP_PORTS"; then
DEFAULT_TCP_REDIR=0
fi
}
[ "$UDP_PROXY_DROP_PORTS" != "disable" ] && {
@@ -714,15 +707,9 @@ load_acl() {
[ "${USE_SHUNT_NODE}" = "1" ] && nft_rule_dual "PSW_MANGLE" "ip protocol udp $(factor $UDP_PROXY_DROP_PORTS "udp dport") ip daddr" "$NFTSET_SHUNT" "counter reject comment \"默认\""
[ "${UDP_PROXY_MODE}" != "disable" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp $(factor $UDP_PROXY_DROP_PORTS "udp dport") counter reject comment \"默认\""
echolog " - ${msg}屏蔽代理 UDP 端口[${UDP_PROXY_DROP_PORTS}]"
if has_1_65535 "$UDP_PROXY_DROP_PORTS"; then
DEFAULT_UDP_REDIR=0
fi
}
}
set_cache_var "DEFAULT_TCP_REDIR" "$DEFAULT_TCP_REDIR"
set_cache_var "DEFAULT_UDP_REDIR" "$DEFAULT_UDP_REDIR"
# 加载TCP默认代理模式
if [ -n "${TCP_PROXY_MODE}" ]; then
[ -n "$NODE" ] && {
+1 -1
View File
@@ -6,7 +6,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2
PKG_VERSION:=26.8.27
PKG_VERSION:=26.9.2
PKG_RELEASE:=1
PKG_PO_VERSION:=$(PKG_VERSION)
@@ -797,7 +797,7 @@ function geo_view()
return
end
local function get_rules(str, type)
local rules_id = {}
local rules = {}
uci_foreach("shunt_rules", function(s)
local list
if type == "geoip" then list = s.ip_list else list = s.domain_list end
@@ -806,14 +806,18 @@ function geo_view()
local prefix, main = line:match("^(.-):(.*)")
if not main then main = line end
if type == "geoip" and (api.datatypes.ipaddr(str) or api.datatypes.ip6addr(str)) then
if main:find(str, 1, true) then rules_id[#rules_id + 1] = s[".name"] end
if main:find(str, 1, true) then
table.insert(rules, {id = s[".name"], group = s.group or i18n.translate("default")})
end
else
if main == str then rules_id[#rules_id + 1] = s[".name"] end
if main == str then
table.insert(rules, {id = s[".name"], group = s.group or i18n.translate("default")})
end
end
end
end
end)
return rules_id
return rules
end
local geo_dir = (uci_get("@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"):match("^(.*)/")
local geosite_path = geo_dir .. "/geosite.dat"
@@ -834,11 +838,17 @@ function geo_view()
for line in geo_string:gmatch("([^\n]+)") do
lines[#lines + 1] = geo_type .. ":" .. line
for _, r in ipairs(get_rules(line, geo_type) or {}) do
if not seen[r] then seen[r] = true; rules[#rules + 1] = r end
if not seen[r.id] then
seen[r.id] = true
rules[#rules + 1] = string.format("[%s]%s", r.group, r.id)
end
end
end
for _, r in ipairs(get_rules(value, geo_type) or {}) do
if not seen[r] then seen[r] = true; rules[#rules + 1] = r end
if not seen[r.id] then
seen[r.id] = true
rules[#rules + 1] = string.format("[%s]%s", r.group, r.id)
end
end
geo_string = table.concat(lines, "\n")
if #rules > 0 then
@@ -40,6 +40,7 @@ local security_list = { "none", "auto", "aes-128-gcm", "chacha20-poly1305", "zer
local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'")
local singbox_version = api.get_app_version("sing-box"):match("[^v]+")
local version_ge_1_14_0 = api.compare_versions(singbox_version, ">=", "1.14.0")
o = s:option(ListValue, "protocol", translate("Protocol"))
o:value("socks", "Socks")
@@ -68,6 +69,9 @@ o:value("ssh", "SSH")
if singbox_tags:find("with_naive_outbound") then
o:value("naive", "NaïveProxy")
end
if version_ge_1_14_0 then
o:value("snell", "Snell")
end
o:value("_urltest", translate("URLTest"))
o:value("_shunt", translate("Shunt"))
o:value("_iface", translate("Custom Interface"))
@@ -237,6 +241,43 @@ o:depends({ protocol = "anytls" })
o:depends({ protocol = "ssh" })
o:depends({ protocol = "naive" })
if version_ge_1_14_0 then
-- snell
s.fields["password"]:depends({ protocol = "snell" })
o = s:option(Value, "snell_psk", translate("Pre shared key"))
o.rmempty = false
o:depends({ protocol = "snell" })
o = s:option(ListValue, "snell_version", translate("Version"))
o:value("4")
o:value("6")
o:depends({ protocol = "snell" })
o = s:option(Flag, "snell_reuse", translate("reuse"))
o:depends({ protocol = "snell" })
o = s:option(ListValue, "snell_network", translate("Transport"))
o:value("", "TCP UDP")
o:value("tcp", "TCP")
o:value("udp", "UDP")
o:depends({ protocol = "snell" })
o = s:option(ListValue, "snell_obfs_mode", translate("Camouflage Type"))
o:value("none")
o:value("http")
o:depends({ protocol = "snell", snell_version = "4" })
o = s:option(Value, "snell_obfs_host", translate("HTTP Host"))
o:depends({ protocol = "snell", snell_version = "4", snell_obfs_mode = "http" })
o = s:option(ListValue, "snell_mode", translate("Mode"))
o:value("default")
o:value("unshaped")
o:value("unsafe-raw")
o:depends({ protocol = "snell", snell_version = "6" })
end
o = s:option(ListValue, "security", translate("Encrypt Method"))
for a, t in ipairs(security_list) do o:value(t) end
o:depends({ protocol = "vmess" })
@@ -400,7 +441,7 @@ if singbox_tags:find("with_quic") then
o = s:option(Flag, "hysteria2_realms", translate("Realms"))
o.default = "0"
if api.compare_versions(singbox_version, ">=", "1.14.0") then
if version_ge_1_14_0 then
o:depends({ protocol = "hysteria2"})
else
o:depends({ protocol = "__hide"})
@@ -2,6 +2,7 @@ local api = require "luci.passwall2.api"
api.set_default_cbi()
m = Map(api.s_config)
m.redirect = api.url("server")
t = m:section(NamedSection, "global", "global", translate("Server-Side"))
t.anonymous = true
@@ -27,6 +27,9 @@ s.option_prefix = "singbox_"
local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'")
local local_version = api.get_app_version("sing-box"):match("[^v]+")
local version_ge_1_14_0 = api.compare_versions(local_version, ">=", "1.14.0")
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"
@@ -56,6 +59,7 @@ o.custom_write = function(self, section, value)
end
o = s:option(ListValue, "protocol", translate("Protocol"))
o:value("direct", "Direct")
o:value("mixed", "Mixed")
o:value("socks", "Socks")
o:value("http", "HTTP")
@@ -64,28 +68,9 @@ 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("anytls", "AnyTLS")
if singbox_tags:find("with_wireguard") then
o:value("wireguard", "WireGuard")
end
o:value("direct", "Direct")
o:depends({ custom = false })
o = s:option(DummyValue, "is_endpoint", "")
o.not_rewrite = true
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ custom = false, protocol = "wireguard" })
o = s:option(Value, "port", translate("Listen Port"))
o.datatype = "port"
o:depends({ custom = false })
@@ -102,13 +87,13 @@ o:depends({ protocol = "vmess" })
o:depends({ protocol = "vless" })
o:depends({ protocol = "trojan" })
o:depends({ protocol = "naive" })
o:depends({ protocol = "hysteria" })
o:depends({ protocol = "tuic" })
o:depends({ protocol = "hysteria2" })
o:depends({ protocol = "anytls" })
o:depends({ protocol = "wireguard" })
if singbox_tags:find("with_quic") then
-- hysteria
s.fields["protocol"]:value("hysteria", "Hysteria")
s.fields["users"]:depends({ protocol = "hysteria" })
o = s:option(Value, "hysteria_obfs", translate("Obfs Password"))
o:depends({ protocol = "hysteria" })
@@ -135,6 +120,10 @@ if singbox_tags:find("with_quic") then
end
if singbox_tags:find("with_quic") then
-- tuic
s.fields["protocol"]:value("tuic", "TUIC")
s.fields["users"]:depends({ protocol = "tuic" })
o = s:option(ListValue, "tuic_congestion_control", translate("Congestion control algorithm"))
o.default = "cubic"
o:value("bbr", translate("BBR"))
@@ -166,6 +155,10 @@ if singbox_tags:find("with_quic") then
end
if singbox_tags:find("with_quic") then
-- hysteria2
s.fields["protocol"]:value("hysteria2", "Hysteria2")
s.fields["users"]:depends({ protocol = "hysteria2" })
o = s:option(Flag, "hysteria2_realms", translate("Realms"))
o.default = "0"
o:depends({ protocol = "hysteria2"})
@@ -435,6 +428,10 @@ o.default = "50"
o:depends({ tcpbrutal = true })
if singbox_tags:find("with_wireguard") then
-- wireguard
s.fields["protocol"]:value("wireguard", "WireGuard")
s.fields["users"]:depends({ protocol = "wireguard" })
o = s:option(Flag, "wireguard_system_interface", translate("System interface"))
o.default = 0
o:depends({ protocol = "wireguard" })
@@ -459,6 +456,32 @@ if singbox_tags:find("with_wireguard") then
o:depends({ protocol = "wireguard" })
end
if version_ge_1_14_0 then
-- snell
s.fields["protocol"]:value("snell", "Snell")
s.fields["users"]:depends({ protocol = "snell" })
o = s:option(ListValue, "snell_version", translate("Version"))
o:value("5")
o:value("6")
o:depends({ protocol = "snell" })
o = s:option(Value, "snell_psk", translate("Pre shared key"))
o.rmempty = false
o:depends({ protocol = "snell" })
o = s:option(ListValue, "snell_obfs_mode", translate("Obfs"))
o:value("none")
o:value("http")
o:depends({ protocol = "snell", snell_version = "5" })
o = s:option(ListValue, "snell_mode", translate("Mode"))
o:value("default")
o:value("unshaped")
o:value("unsafe-raw")
o:depends({ protocol = "snell", snell_version = "6" })
end
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
o.default = "0"
o:depends({ custom = false })
@@ -667,6 +667,19 @@ function gen_outbound(flag, node, tag, proxy_table)
}
end
if node.protocol == "snell" then
protocol_table = {
version = tonumber(node.snell_version),
psk = node.snell_psk,
userkey = node.password,
reuse = node.snell_reuse == "1" and true or false,
network = node.snell_network,
obfs_mode = node.snell_version == "4" and node.snell_obfs_mode or nil,
obfs_host = node.snell_version == "4" and node.snell_obfs_host or nil,
mode = node.snell_version == "6" and node.snell_mode or nil,
}
end
if protocol_table then
for key, value in pairs(protocol_table) do
result[key] = value
@@ -823,6 +836,10 @@ function gen_config_server(node)
u.allowed_ips = user.allowed_ips or {}
u.persistent_keepalive_interval = 0
end
if node.protocol == "snell" then
u.name = user.username
u.userkey = user.password
end
users[#users + 1] = u
end
end
@@ -1003,6 +1020,16 @@ function gen_config_server(node)
end
end
if node.protocol == "snell" then
protocol_table = {
users = users,
version = tonumber(node.snell_version),
psk = node.snell_psk,
obfs_mode = node.snell_version == "5" and node.snell_obfs_mode or nil,
mode = node.snell_version == "6" and node.snell_mode or nil,
}
end
if node.protocol == "direct" then
protocol_table = {
network = (node.d_protocol ~= "TCP,UDP") and node.d_protocol or nil,
@@ -1838,7 +1838,7 @@ function gen_config(var)
end
end
end
if dns_outboundTag == "blackhole" then
if value.outboundTag == "blackhole" then
table.insert(dns_out_rules, {
action = "return",
rCode = 0,