diff --git a/luci-app-passwall2/Makefile b/luci-app-passwall2/Makefile
index efa7d2015..8cca7af07 100644
--- a/luci-app-passwall2/Makefile
+++ b/luci-app-passwall2/Makefile
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2
-PKG_VERSION:=1.20-14
+PKG_VERSION:=1.20-15
PKG_RELEASE:=
PKG_CONFIG_DEPENDS:= \
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl.lua
index c346ce364..26a07ac3b 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl.lua
@@ -4,6 +4,7 @@ local sys = api.sys
local has_chnlist = api.fs.access("/usr/share/passwall2/rules/chnlist")
m = Map(appname)
+api.set_apply_on_parse(m)
s = m:section(TypedSection, "global", translate("ACLs"), "" .. translate("ACLs is a tools which used to designate specific IP proxy mode.") .. "")
s.anonymous = true
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua
index c3fec1d01..2b68e0082 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua
@@ -3,6 +3,7 @@ local appname = api.appname
local sys = api.sys
m = Map(appname)
+api.set_apply_on_parse(m)
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/app_update.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/app_update.lua
index 5364eaacb..5649b016c 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/app_update.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/app_update.lua
@@ -2,6 +2,7 @@ local api = require "luci.passwall2.api"
local appname = api.appname
m = Map(appname)
+api.set_apply_on_parse(m)
-- [[ App Settings ]]--
s = m:section(TypedSection, "global_app", translate("App Update"),
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua
index a82cd965b..90f4e639e 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua
@@ -6,6 +6,7 @@ local has_singbox = api.finded_com("singbox")
local has_xray = api.finded_com("xray")
m = Map(appname)
+api.set_apply_on_parse(m)
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
@@ -254,6 +255,7 @@ 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).") .. "
" ..
translate("This feature requires the DNS server to support the Edns Client Subnet (RFC7871).")
o.datatype = "ipaddr"
+o:depends({ __hide = true })
o = s:taboption("DNS", Flag, "remote_fakedns", "FakeDNS", translate("Use FakeDNS work in the shunt domain that proxy."))
o.default = "0"
@@ -268,6 +270,7 @@ o:value("UseIPv6")
o = s:taboption("DNS", TextValue, "dns_hosts", translate("Domain Override"))
o.rows = 5
o.wrap = "off"
+o:depends({ __hide = true })
o.remove = function(self, section)
local node_value = node:formvalue(global_cfgid)
if node_value ~= "nil" then
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/haproxy.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/haproxy.lua
index 515fa5efa..ad5082d62 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/haproxy.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/haproxy.lua
@@ -16,6 +16,7 @@ for k, e in ipairs(api.get_valid_nodes()) do
end
m = Map(appname)
+api.set_apply_on_parse(m)
-- [[ Haproxy Settings ]]--
s = m:section(TypedSection, "global_haproxy")
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua
index 2cb20ec64..611765bc5 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua
@@ -10,6 +10,7 @@ end
m = Map(appname, translate("Node Config"))
m.redirect = api.url()
+api.set_apply_on_parse(m)
s = m:section(NamedSection, arg[1], "nodes", "")
s.addremove = false
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua
index 83584fe2c..9dab90f17 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_list.lua
@@ -4,6 +4,7 @@ local sys = api.sys
local datatypes = api.datatypes
m = Map(appname)
+api.set_apply_on_parse(m)
-- [[ Other Settings ]]--
s = m:section(TypedSection, "global_other")
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua
index c539fb1ab..d5cf52953 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua
@@ -19,6 +19,7 @@ if has_xray then
end
m = Map(appname)
+api.set_apply_on_parse(m)
-- [[ Subscribe Settings ]]--
s = m:section(TypedSection, "global_subscribe", "")
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua
index a9b7ef011..72d7a3a6a 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua
@@ -21,6 +21,7 @@ end
m = Map(appname)
m.redirect = api.url("node_subscribe")
+api.set_apply_on_parse(m)
s = m:section(NamedSection, arg[1])
s.addremove = false
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua
index 853f615b7..fc2d37388 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua
@@ -8,6 +8,7 @@ local has_fw3 = api.is_finded("fw3")
local has_fw4 = api.is_finded("fw4")
m = Map(appname)
+api.set_apply_on_parse(m)
-- [[ Delay Settings ]]--
s = m:section(TypedSection, "global_delay", translate("Delay Settings"))
@@ -164,7 +165,7 @@ if has_singbox then
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.default = 0
o.rmempty = false
o = s:option(Value, "geoip_path", translate("Custom geoip Path"))
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/rule.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/rule.lua
index 706ac26e3..beab119a9 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/rule.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/rule.lua
@@ -2,6 +2,8 @@ local api = require "luci.passwall2.api"
local appname = api.appname
m = Map(appname)
+api.set_apply_on_parse(m)
+
-- [[ Rule Settings ]]--
s = m:section(TypedSection, "global_rules", translate("Rule status"))
s.anonymous = true
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/shunt_rules.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/shunt_rules.lua
index 77f111151..3a998a05d 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/shunt_rules.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/shunt_rules.lua
@@ -4,6 +4,7 @@ local datatypes = api.datatypes
m = Map(appname, "Xray " .. translate("Shunt Rule"))
m.redirect = api.url()
+api.set_apply_on_parse(m)
s = m:section(NamedSection, arg[1], "shunt_rules", "")
s.addremove = false
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua
index 0bd346dec..ae1072d78 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/socks_config.lua
@@ -5,6 +5,7 @@ local has_singbox = api.finded_com("singbox")
local has_xray = api.finded_com("xray")
m = Map(appname)
+api.set_apply_on_parse(m)
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua
index a8fc17d66..178651d13 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua
@@ -68,4 +68,8 @@ o = s:option(Flag, option_name("disable_mtu_discovery"), translate("Disable MTU
o.default = "0"
o.rewrite_option = o.option
+o = s:option(Flag, option_name("lazy_start"), translate("Lazy Start"))
+o.default = "0"
+o.rewrite_option = o.option
+
api.luci_types(arg[1], m, s, type_name, option_prefix)
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua
index 53706cccc..977d452ad 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua
@@ -378,6 +378,27 @@ o:depends({ [option_name("protocol")] = "hysteria"})
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" })
+if singbox_tags:find("with_ech") then
+ o = s:option(Flag, option_name("ech"), translate("ECH"))
+ o.default = "0"
+ o:depends({ [option_name("tls")] = true, [option_name("flow")] = "", [option_name("reality")] = false })
+ o:depends({ [option_name("protocol")] = "tuic" })
+ o:depends({ [option_name("protocol")] = "hysteria" })
+ o:depends({ [option_name("protocol")] = "hysteria2" })
+
+ o = s:option(Value, option_name("ech_config"), translate("ECH Config"))
+ o.default = ""
+ o:depends({ [option_name("ech")] = true })
+
+ o = s:option(Flag, option_name("pq_signature_schemes_enabled"), translate("PQ signature schemes"))
+ o.default = "0"
+ o:depends({ [option_name("ech")] = true })
+
+ o = s:option(Flag, option_name("dynamic_record_sizing_disabled"), translate("Disable adaptive sizing of TLS records"))
+ o.default = "0"
+ o:depends({ [option_name("ech")] = true })
+end
+
if singbox_tags:find("with_utls") then
o = s:option(Flag, option_name("utls"), translate("uTLS"))
o.default = "0"
@@ -533,11 +554,8 @@ o:depends({ [option_name("mux")] = true })
o = s:option(Flag, option_name("shadowtls"), "ShadowTLS")
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")] = "vmess", [option_name("tls")] = false })
+o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("tls")] = false })
o = s:option(ListValue, option_name("shadowtls_version"), "ShadowTLS " .. translate("Version"))
o.default = "1"
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/index.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/index.lua
index 46753e365..1fb77ea66 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/index.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/index.lua
@@ -1,6 +1,7 @@
local api = require "luci.passwall2.api"
m = Map("passwall2_server", translate("Server-Side"))
+api.set_apply_on_parse(m)
t = m:section(NamedSection, "global", "global")
t.anonymous = true
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua
index 28bcb185c..25119500e 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua
@@ -284,6 +284,28 @@ o.validate = function(self, value, t)
return nil
end
+if singbox_tags:find("with_ech") then
+ o = s:option(Flag, option_name("ech"), translate("ECH"))
+ o.default = "0"
+ o:depends({ [option_name("tls")] = true, [option_name("flow")] = "", [option_name("reality")] = false })
+ o:depends({ [option_name("protocol")] = "naive" })
+ o:depends({ [option_name("protocol")] = "hysteria" })
+ o:depends({ [option_name("protocol")] = "tuic" })
+ o:depends({ [option_name("protocol")] = "hysteria2" })
+
+ o = s:option(Value, option_name("ech_key"), translate("ECH Key"))
+ o.default = ""
+ o:depends({ [option_name("ech")] = true })
+
+ o = s:option(Flag, option_name("pq_signature_schemes_enabled"), translate("PQ signature schemes"))
+ o.default = "0"
+ o:depends({ [option_name("ech")] = true })
+
+ o = s:option(Flag, option_name("dynamic_record_sizing_disabled"), translate("Disable adaptive sizing of TLS records"))
+ o.default = "0"
+ o:depends({ [option_name("ech")] = true })
+end
+
o = s:option(ListValue, option_name("transport"), translate("Transport"))
o:value("tcp", "TCP")
o:value("http", "HTTP")
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua
index 7c31ef33d..47d6d4700 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua
@@ -4,6 +4,7 @@ local types_dir = "/usr/lib/lua/luci/model/cbi/passwall2/server/type/"
m = Map("passwall2_server", translate("Server Config"))
m.redirect = api.url("server")
+api.set_apply_on_parse(m)
s = m:section(NamedSection, arg[1], "user", "")
s.addremove = false
diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua
index 9b535febb..6bb885a7d 100644
--- a/luci-app-passwall2/luasrc/passwall2/api.lua
+++ b/luci-app-passwall2/luasrc/passwall2/api.lua
@@ -921,6 +921,22 @@ function to_move(app_name,file)
return {code = 0}
end
+function is_js_luci()
+ return sys.call('[ -f "/www/luci-static/resources/uci.js" ]') == 0
+end
+
+function set_apply_on_parse(map)
+ if is_js_luci() == true then
+ map.apply_on_parse = false
+ map.on_after_apply = function(self)
+ if self.redirect then
+ os.execute("sleep 1")
+ luci.http.redirect(self.redirect)
+ end
+ end
+ end
+end
+
function luci_types(id, m, s, type_name, option_prefix)
local rewrite_option_table = {}
for key, value in pairs(s.fields) do
diff --git a/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua b/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua
index ef2155b6a..90aa0a5f3 100644
--- a/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua
+++ b/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua
@@ -87,7 +87,7 @@ function gen_config(var)
down = node.hysteria2_down_mbps and node.hysteria2_down_mbps .. " mbps" or "100 mbps"
},
fast_open = (node.fast_open == "1") and true or false,
- lazy = true,
+ lazy = (node.hysteria2_lazy_start == "1") and true or false,
socks5 = (local_socks_address and local_socks_port) and {
listen = local_socks_address .. ":" .. local_socks_port,
username = (local_socks_username and local_socks_password) and local_socks_username or nil,
diff --git a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua
index 0f9f30df6..ff3cbf4f5 100644
--- a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua
+++ b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua
@@ -93,6 +93,12 @@ function gen_outbound(flag, node, tag, proxy_table)
alpn = alpn, --支持的应用层协议协商列表,按优先顺序排列。如果两个对等点都支持 ALPN,则选择的协议将是此列表中的一个,如果没有相互支持的协议则连接将失败。
--min_version = "1.2",
--max_version = "1.3",
+ ech = {
+ enabled = (node.ech == "1") and true or false,
+ config = (node.ech_config and node.ech_config:gsub("\\n","\n")) and node.ech_config:gsub("\\n","\n") or nil,
+ pq_signature_schemes_enabled = node.pq_signature_schemes_enabled and true or false,
+ dynamic_record_sizing_disabled = node.dynamic_record_sizing_disabled and true or false
+ },
utls = {
enabled = (node.utls == "1" or node.reality == "1") and true or false,
fingerprint = node.fingerprint or "chrome"
@@ -282,7 +288,13 @@ function gen_outbound(flag, node, tag, proxy_table)
insecure = (node.tls_allowInsecure == "1") and true or false,
alpn = (node.hysteria_alpn and node.hysteria_alpn ~= "") and {
node.hysteria_alpn
- } or nil
+ } or nil,
+ ech = {
+ enabled = (node.ech == "1") and true or false,
+ config = (node.ech_config and node.ech_config:gsub("\\n","\n")) and node.ech_config:gsub("\\n","\n") or nil,
+ pq_signature_schemes_enabled = node.pq_signature_schemes_enabled and true or false,
+ dynamic_record_sizing_disabled = node.dynamic_record_sizing_disabled and true or false
+ }
}
}
end
@@ -311,7 +323,13 @@ function gen_outbound(flag, node, tag, proxy_table)
alpn = (node.tuic_alpn and node.tuic_alpn ~= "") and {
node.tuic_alpn
} or nil,
- },
+ ech = {
+ enabled = (node.ech == "1") and true or false,
+ config = (node.ech_config and node.ech_config:gsub("\\n","\n")) and node.ech_config:gsub("\\n","\n") or nil,
+ pq_signature_schemes_enabled = node.pq_signature_schemes_enabled and true or false,
+ dynamic_record_sizing_disabled = node.dynamic_record_sizing_disabled and true or false
+ }
+ }
}
end
@@ -328,7 +346,13 @@ function gen_outbound(flag, node, tag, proxy_table)
enabled = true,
server_name = node.tls_serverName,
insecure = (node.tls_allowInsecure == "1") and true or false,
- },
+ ech = {
+ enabled = (node.ech == "1") and true or false,
+ config = (node.ech_config and node.ech_config:gsub("\\n","\n")) and node.ech_config:gsub("\\n","\n") or nil,
+ pq_signature_schemes_enabled = node.pq_signature_schemes_enabled and true or false,
+ dynamic_record_sizing_disabled = node.dynamic_record_sizing_disabled and true or false
+ }
+ }
}
end
@@ -369,6 +393,15 @@ function gen_config_server(node)
}
end
+ if node.tls == "1" and node.ech == "1" then
+ tls.ech = {
+ enabled = true,
+ key = (node.ech_key and node.ech_key:gsub("\\n","\n")) and node.ech_key:gsub("\\n","\n") or nil,
+ pq_signature_schemes_enabled = (node.pq_signature_schemes_enabled == "1") and true or false,
+ dynamic_record_sizing_disabled = (node.dynamic_record_sizing_disabled == "1") and true or false,
+ }
+ end
+
local v2ray_transport = nil
if node.transport == "http" then
@@ -1061,7 +1094,7 @@ function gen_config(var)
rule.geosite = #domain_table.geosite > 0 and domain_table.geosite or nil
if outboundTag and outboundTag ~= "nil" then
- table.insert(dns_domain_rules, domain_table)
+ table.insert(dns_domain_rules, api.clone(domain_table))
end
end
@@ -1220,7 +1253,7 @@ function gen_config(var)
table.insert(domain, w)
end)
if #domain > 0 then
- table.insert(dns_domain_rules, {
+ table.insert(dns_domain_rules, 1, {
outboundTag = "direct",
domain = domain
})
diff --git a/luci-app-passwall2/luasrc/view/passwall2/global/status.htm b/luci-app-passwall2/luasrc/view/passwall2/global/status.htm
index fa88004e9..008809926 100644
--- a/luci-app-passwall2/luasrc/view/passwall2/global/status.htm
+++ b/luci-app-passwall2/luasrc/view/passwall2/global/status.htm
@@ -127,7 +127,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md