diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua
index 38c96631..b0b84851 100644
--- a/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua
+++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua
@@ -89,9 +89,8 @@ if has_xray or has_singbox then
o.rmempty = false
o.description = "
"
.. "- " .. translate("Experimental feature.") .. "
"
- .. "- " .. "1." .. translate("Analyzes and preloads GeoIP/Geosite data to enhance the shunt performance of Sing-box/Xray.") .. "
"
+ .. "- " .. "1." .. translate("Parses and preloads GeoIP/Geosite data to improve Sing-box/Xray routing performance.") .. "
"
.. "- " .. "2." .. translate("Once enabled, the rule list can support GeoIP/Geosite rules.") .. "
"
- .. "- " .. translate("Note: Increases resource usage; Geosite analysis is only supported in ChinaDNS-NG and SmartDNS modes.") .. "
"
.. "
"
function o.write(self, section, value)
local old = m:get(section, self.option) or "0"
diff --git a/luci-app-passwall/po/zh-cn/passwall.po b/luci-app-passwall/po/zh-cn/passwall.po
index 7137cdf4..9f29337b 100644
--- a/luci-app-passwall/po/zh-cn/passwall.po
+++ b/luci-app-passwall/po/zh-cn/passwall.po
@@ -1085,15 +1085,12 @@ msgstr "启用此选项后手动更新时,即使没有新版本也会从现有 G
msgid "Enable Geo Data Parsing"
msgstr "开启 Geo 数据解析"
-msgid "Analyzes and preloads GeoIP/Geosite data to enhance the shunt performance of Sing-box/Xray."
-msgstr "分析和预加载 GeoIP/Geosite 数据,以增强 Sing-box/Xray 的分流效果。"
+msgid "Parses and preloads GeoIP/Geosite data to improve Sing-box/Xray routing performance."
+msgstr "解析和预加载 GeoIP/Geosite 数据,以增强 Sing-box/Xray 的分流效果。"
msgid "Once enabled, the rule list can support GeoIP/Geosite rules."
msgstr "启用后,规则列表可以支持 GeoIP/Geosite 规则。"
-msgid "Note: Increases resource usage; Geosite analysis is only supported in ChinaDNS-NG and SmartDNS modes."
-msgstr "注:会增加一些系统资源的开销,仅在 ChinaDNS-NG 和 SmartDNS 模式下支持分析 Geosite 。"
-
msgid "Shunt Rule"
msgstr "分流规则"
diff --git a/luci-app-passwall/root/usr/share/passwall/helper_chinadns_add.lua b/luci-app-passwall/root/usr/share/passwall/helper_chinadns_add.lua
index 6ad220ee..04d7aab0 100644
--- a/luci-app-passwall/root/usr/share/passwall/helper_chinadns_add.lua
+++ b/luci-app-passwall/root/usr/share/passwall/helper_chinadns_add.lua
@@ -227,7 +227,7 @@ if USE_DIRECT_LIST == "1" and not fs.access(file_direct_host) then
geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line
else
line = api.get_std_domain(line)
- if line ~= "" and not line:find("#") then
+ if line ~= "" and not line:find("#") and not line:find(":") then
insert_unique(direct_domain, line, lookup_direct_domain)
end
end
@@ -277,7 +277,7 @@ if USE_PROXY_LIST == "1" and not fs.access(file_proxy_host) then
geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line
else
line = api.get_std_domain(line)
- if line ~= "" and not line:find("#") then
+ if line ~= "" and not line:find("#") and not line:find(":") then
insert_unique(proxy_domain, line, lookup_proxy_domain)
end
end
@@ -398,7 +398,7 @@ if IS_SHUNT_NODE then
local domain_list = s.domain_list or ""
for line in string.gmatch(domain_list, "[^\r\n]+") do
- if line ~= "" and not line:find("#") and not line:find("regexp:") and not line:find("ext:") then
+ if line ~= "" and not line:find("#") and not line:find("regexp:") and not line:find("ext:") and not line:find("rule-set:") and not line:find("rs:") then
if line:find("geosite:") then
line = string.match(line, ":([^:]+)$")
if _node_id == "_direct" then
diff --git a/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.lua b/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.lua
index b96d27fe..7c916ae9 100644
--- a/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.lua
+++ b/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.lua
@@ -181,10 +181,15 @@ function add_rule(var)
local CACHE_TEXT_FILE = CACHE_DNS_PATH .. ".txt"
local USE_CHINADNS_NG = "0"
local IS_SHUNT_NODE = uci:get(appname, TCP_NODE, "protocol") == "_shunt"
+ local USE_GEOVIEW = uci:get(appname, "@global_rules[0]", "enable_geoview")
local list1 = {}
local excluded_domain = {}
+ if not api.is_finded("geoview") then
+ USE_GEOVIEW = "0"
+ end
+
local function log(...)
if NO_LOGIC_LOG == "1" then
return
@@ -301,6 +306,21 @@ function add_rule(var)
return false
end
+ local function foreach_geosite(list_arg, callback)
+ local geosite_path = uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"
+ geosite_path = geosite_path:match("^(.*)/") .. "/geosite.dat"
+ if not fs.access(geosite_path) then return end
+ local bin = api.finded_com("geoview")
+ if not (bin and list_arg) then return end
+ local cmd = string.format("%q -type geosite -action extract -input %q -list %q -lowmem=true", bin, geosite_path, list_arg)
+ local pipe = io.popen(cmd)
+ if not pipe then return end
+ for line in pipe:lines() do
+ if line ~= "" then callback(line) end
+ end
+ pipe:close()
+ end
+
local cache_text = ""
local nodes_address_md5 = sys.exec("echo -n $(uci show passwall | grep '\\.address') | md5sum")
local new_rules = sys.exec("echo -n $(find /usr/share/passwall/rules -type f | xargs md5sum)")
@@ -347,16 +367,28 @@ function add_rule(var)
--屏蔽列表
if USE_CHINADNS_NG == "0" and USE_BLOCK_LIST == "1" then
+ local geosite_arg = ""
local f = io.open("/usr/share/passwall/rules/block_host")
if f then
for line in f:lines() do
- line = api.get_std_domain(line)
- if line ~= "" and not line:find("#") and not line:find(":") then
- set_domain_address(line, "")
+ if not line:find("#") and line:find("geosite:") then
+ line = string.match(line, ":([^:]+)$")
+ geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line
+ else
+ line = api.get_std_domain(line)
+ if line ~= "" and not line:find("#") and not line:find(":") then
+ set_domain_address(line, "")
+ end
end
end
f:close()
end
+ if USE_GEOVIEW == "1" and geosite_arg ~= "" then
+ foreach_geosite(geosite_arg, function(line)
+ set_domain_address(line, "")
+ end)
+ log(" - 解析[屏蔽列表] Geosite 到屏蔽域名表(blocklist)完成")
+ end
end
local fwd_dns
@@ -400,88 +432,124 @@ function add_rule(var)
--直连(白名单)列表
if USE_DIRECT_LIST == "1" then
- if fs.access("/usr/share/passwall/rules/direct_host") then
- fwd_dns = LOCAL_DNS
- if USE_CHINADNS_NG == "1" then
- fwd_dns = nil
- end
- if fwd_dns then
- local sets = {
- setflag_4 .. "psw_white",
- setflag_6 .. "psw_white6"
- }
- --始终用国内DNS解析直连(白名单)列表
- for line in io.lines("/usr/share/passwall/rules/direct_host") do
- line = api.get_std_domain(line)
- if line ~= "" and not line:find("#") and not line:find(":") then
- add_excluded_domain(line)
- set_domain_dns(line, fwd_dns)
- set_domain_ipset(line, table.concat(sets, ","))
+ fwd_dns = LOCAL_DNS
+ if USE_CHINADNS_NG == "1" then
+ fwd_dns = nil
+ end
+ if fwd_dns then
+ local sets = {
+ setflag_4 .. "psw_white",
+ setflag_6 .. "psw_white6"
+ }
+ --始终用国内DNS解析直连(白名单)列表
+ local geosite_arg = ""
+ local f = io.open("/usr/share/passwall/rules/direct_host")
+ if f then
+ for line in f:lines() do
+ if not line:find("#") and line:find("geosite:") then
+ line = string.match(line, ":([^:]+)$")
+ geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line
+ else
+ line = api.get_std_domain(line)
+ if line ~= "" and not line:find("#") and not line:find(":") then
+ add_excluded_domain(line)
+ set_domain_dns(line, fwd_dns)
+ set_domain_ipset(line, table.concat(sets, ","))
+ end
end
end
+ f:close()
log(string.format(" - 域名白名单(whitelist):%s", fwd_dns or "默认"))
end
+ if USE_GEOVIEW == "1" and geosite_arg ~= "" then
+ foreach_geosite(geosite_arg, function(line)
+ add_excluded_domain(line)
+ set_domain_dns(line, fwd_dns)
+ set_domain_ipset(line, table.concat(sets, ","))
+ end)
+ log(" - 解析[直连列表] Geosite 到域名白名单(whitelist)完成")
+ end
end
end
--代理(黑名单)列表
if USE_PROXY_LIST == "1" then
- if fs.access("/usr/share/passwall/rules/proxy_host") then
- fwd_dns = TUN_DNS
- if USE_CHINADNS_NG == "1" then
- fwd_dns = nil
+ fwd_dns = TUN_DNS
+ if USE_CHINADNS_NG == "1" then
+ fwd_dns = nil
+ end
+ if fwd_dns then
+ local set_name = "psw_black"
+ local set6_name = "psw_black6"
+ if FLAG ~= "default" then
+ set_name = "psw_" .. FLAG .. "_black"
+ set6_name = "psw_" .. FLAG .. "_black6"
end
- if fwd_dns then
- local set_name = "psw_black"
- local set6_name = "psw_black6"
- if FLAG ~= "default" then
- set_name = "psw_" .. FLAG .. "_black"
- set6_name = "psw_" .. FLAG .. "_black6"
- end
- local sets = {
- setflag_4 .. set_name
- }
- if NO_PROXY_IPV6 ~= "1" then
- table.insert(sets, setflag_6 .. set6_name)
- end
- --始终使用远程DNS解析代理(黑名单)列表
- for line in io.lines("/usr/share/passwall/rules/proxy_host") do
- line = api.get_std_domain(line)
- if line ~= "" and not line:find("#") and not line:find(":") then
- add_excluded_domain(line)
- if NO_PROXY_IPV6 == "1" then
- set_domain_address(line, "::")
+ local sets = {
+ setflag_4 .. set_name
+ }
+ if NO_PROXY_IPV6 ~= "1" then
+ table.insert(sets, setflag_6 .. set6_name)
+ end
+ --始终使用远程DNS解析代理(黑名单)列表
+ local geosite_arg = ""
+ local f = io.open("/usr/share/passwall/rules/proxy_host")
+ if f then
+ for line in f:lines() do
+ if not line:find("#") and line:find("geosite:") then
+ line = string.match(line, ":([^:]+)$")
+ geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line
+ else
+ line = api.get_std_domain(line)
+ if line ~= "" and not line:find("#") and not line:find(":") then
+ add_excluded_domain(line)
+ if NO_PROXY_IPV6 == "1" then
+ set_domain_address(line, "::")
+ end
+ set_domain_dns(line, fwd_dns)
+ set_domain_ipset(line, table.concat(sets, ","))
end
- set_domain_dns(line, fwd_dns)
- set_domain_ipset(line, table.concat(sets, ","))
end
end
+ f:close()
log(string.format(" - 代理域名表(blacklist):%s", fwd_dns or "默认"))
end
+ if USE_GEOVIEW == "1" and geosite_arg ~= "" then
+ foreach_geosite(geosite_arg, function(line)
+ add_excluded_domain(line)
+ if NO_PROXY_IPV6 == "1" then
+ set_domain_address(line, "::")
+ end
+ set_domain_dns(line, fwd_dns)
+ set_domain_ipset(line, table.concat(sets, ","))
+ end)
+ log(" - 解析[代理列表] Geosite 到代理域名表(blacklist)完成")
+ end
end
end
--GFW列表
if USE_GFW_LIST == "1" then
- if fs.access("/usr/share/passwall/rules/gfwlist") then
- fwd_dns = TUN_DNS
- if USE_CHINADNS_NG == "1" then
- fwd_dns = nil
+ fwd_dns = TUN_DNS
+ if USE_CHINADNS_NG == "1" then
+ fwd_dns = nil
+ end
+ if fwd_dns then
+ local set_name = "psw_gfw"
+ local set6_name = "psw_gfw6"
+ if FLAG ~= "default" then
+ set_name = "psw_" .. FLAG .. "_gfw"
+ set6_name = "psw_" .. FLAG .. "_gfw6"
end
- if fwd_dns then
- local set_name = "psw_gfw"
- local set6_name = "psw_gfw6"
- if FLAG ~= "default" then
- set_name = "psw_" .. FLAG .. "_gfw"
- set6_name = "psw_" .. FLAG .. "_gfw6"
- end
- local sets = {
- setflag_4 .. set_name
- }
- if NO_PROXY_IPV6 ~= "1" then
- table.insert(sets, setflag_6 .. set6_name)
- end
- for line in io.lines("/usr/share/passwall/rules/gfwlist") do
+ local sets = {
+ setflag_4 .. set_name
+ }
+ if NO_PROXY_IPV6 ~= "1" then
+ table.insert(sets, setflag_6 .. set6_name)
+ end
+ local f = io.open("/usr/share/passwall/rules/gfwlist")
+ if f then
+ for line in f:lines() do
if line ~= "" and not line:find("#") and not check_excluded_domain(line) then
if NO_PROXY_IPV6 == "1" then
set_domain_address(line, "::")
@@ -494,6 +562,7 @@ function add_rule(var)
set_domain_ipset(line, table.concat(sets, ","))
end
end
+ f:close()
log(string.format(" - 防火墙域名表(gfwlist):%s", fwd_dns or "默认"))
end
end
@@ -501,30 +570,31 @@ function add_rule(var)
--中国列表
if CHN_LIST ~= "0" then
- if fs.access("/usr/share/passwall/rules/chnlist") then
+ fwd_dns = nil
+ if CHN_LIST == "direct" then
+ fwd_dns = LOCAL_DNS
+ end
+ if CHN_LIST == "proxy" then
+ fwd_dns = TUN_DNS
+ end
+ if USE_CHINADNS_NG == "1" then
fwd_dns = nil
- if CHN_LIST == "direct" then
- fwd_dns = LOCAL_DNS
- end
+ end
+ if fwd_dns then
+ local sets = {
+ setflag_4 .. "psw_chn",
+ setflag_6 .. "psw_chn6"
+ }
if CHN_LIST == "proxy" then
- fwd_dns = TUN_DNS
- end
- if USE_CHINADNS_NG == "1" then
- fwd_dns = nil
- end
- if fwd_dns then
- local sets = {
- setflag_4 .. "psw_chn",
- setflag_6 .. "psw_chn6"
- }
- if CHN_LIST == "proxy" then
- if NO_PROXY_IPV6 == "1" then
- sets = {
- setflag_4 .. "psw_chn"
- }
- end
+ if NO_PROXY_IPV6 == "1" then
+ sets = {
+ setflag_4 .. "psw_chn"
+ }
end
- for line in io.lines("/usr/share/passwall/rules/chnlist") do
+ end
+ local f = io.open("/usr/share/passwall/rules/chnlist")
+ if f then
+ for line in f:lines() do
if line ~= "" and not line:find("#") and not check_excluded_domain(line) then
if CHN_LIST == "proxy" and NO_PROXY_IPV6 == "1" then
set_domain_address(line, "::")
@@ -537,6 +607,7 @@ function add_rule(var)
set_domain_ipset(line, table.concat(sets, ","))
end
end
+ f:close()
log(string.format(" - 中国域名表(chnroute):%s", fwd_dns or "默认"))
end
end
@@ -590,21 +661,40 @@ function add_rule(var)
end
local domain_list = s.domain_list or ""
+ local geosite_arg = ""
for line in string.gmatch(domain_list, "[^\r\n]+") do
- if line ~= "" and not line:find("#") and not line:find("regexp:") and not line:find("geosite:") and not line:find("ext:") then
- if line:find("domain:") or line:find("full:") then
+ if line ~= "" and not line:find("#") and not line:find("regexp:") and not line:find("ext:") and not line:find("rule-set:") and not line:find("rs:") then
+ if line:find("geosite:") then
line = string.match(line, ":([^:]+)$")
- end
- line = api.get_std_domain(line)
- add_excluded_domain(line)
+ geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line
+ else
+ if line:find("domain:") or line:find("full:") then
+ line = string.match(line, ":([^:]+)$")
+ end
+ line = api.get_std_domain(line)
+ add_excluded_domain(line)
+ if no_ipv6 then
+ set_domain_address(line, "::")
+ end
+ set_domain_dns(line, fwd_dns)
+ set_domain_ipset(line, table.concat(sets, ","))
+ end
+ end
+ end
+
+ if USE_GFW_LIST == "1" and CHN_LIST == "0" and USE_GEOVIEW == "1" and geosite_arg ~= "" then --仅GFW模式解析geosite
+ foreach_geosite(geosite_arg, function(line)
+ add_excluded_domain(line)
if no_ipv6 then
set_domain_address(line, "::")
end
set_domain_dns(line, fwd_dns)
set_domain_ipset(line, table.concat(sets, ","))
- end
+ end)
+ log(string.format(" - 解析分流规则(%s) Geosite 完成", s.remarks))
end
+
if _node_id ~= "_direct" then
log(string.format(" - Sing-Box/Xray分流规则(%s):%s", s.remarks, fwd_dns or "默认"))
end
diff --git a/luci-app-passwall/root/usr/share/passwall/helper_smartdns_add.lua b/luci-app-passwall/root/usr/share/passwall/helper_smartdns_add.lua
index 4011fc09..2d046099 100644
--- a/luci-app-passwall/root/usr/share/passwall/helper_smartdns_add.lua
+++ b/luci-app-passwall/root/usr/share/passwall/helper_smartdns_add.lua
@@ -388,7 +388,7 @@ if USE_DIRECT_LIST == "1" and not fs.access(file_direct_host) then
geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line
else
line = api.get_std_domain(line)
- if line ~= "" and not line:find("#") then
+ if line ~= "" and not line:find("#") and not line:find(":") then
insert_unique(direct_domain, line, lookup_direct_domain)
end
end
@@ -440,7 +440,7 @@ if USE_PROXY_LIST == "1" and not fs.access(file_proxy_host) then
geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line
else
line = api.get_std_domain(line)
- if line ~= "" and not line:find("#") then
+ if line ~= "" and not line:find("#") and not line:find(":") then
insert_unique(proxy_domain, line, lookup_proxy_domain)
end
end
@@ -566,7 +566,7 @@ if IS_SHUNT_NODE then
local domain_list = s.domain_list or ""
for line in string.gmatch(domain_list, "[^\r\n]+") do
- if line ~= "" and not line:find("#") and not line:find("regexp:") and not line:find("ext:") then
+ if line ~= "" and not line:find("#") and not line:find("regexp:") and not line:find("ext:") and not line:find("rule-set:") and not line:find("rs:") then
if line:find("geosite:") then
line = string.match(line, ":([^:]+)$")
if _node_id == "_direct" then
diff --git a/luci-app-passwall2/Makefile b/luci-app-passwall2/Makefile
index 6a80b3bb..25e88ebb 100644
--- a/luci-app-passwall2/Makefile
+++ b/luci-app-passwall2/Makefile
@@ -6,7 +6,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2
-PKG_VERSION:=26.7.16
+PKG_VERSION:=26.8.7
PKG_RELEASE:=1
PKG_PO_VERSION:=$(PKG_VERSION)
diff --git a/luci-app-passwall2/htdocs/luci-static/resources/view/passwall2/func.js b/luci-app-passwall2/htdocs/luci-static/resources/view/passwall2/func.js
new file mode 100644
index 00000000..252e8feb
--- /dev/null
+++ b/luci-app-passwall2/htdocs/luci-static/resources/view/passwall2/func.js
@@ -0,0 +1,45 @@
+function arraysEqual(a, b) {
+ if (a === b) return true;
+ if (a == null || b == null) return false;
+ if (a.length !== b.length) return false;
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] !== b[i]) return false;
+ }
+ return true;
+}
+
+function waitForElement(selector, callback) {
+ const el = document.querySelector(selector);
+ if (el) return callback(el);
+ const observer = new MutationObserver(() => {
+ const el = document.querySelector(selector);
+ if (el) {
+ observer.disconnect();
+ callback(el);
+ }
+ });
+ observer.observe(document.body, { childList: true, subtree: true });
+}
+
+function get_current_url() {
+ return window.location.origin + window.location.pathname;
+}
+
+function getOption(config, section, opt) {
+ let obj;
+ const id = `cbid.${config}.${section}.${opt}`;
+ obj = document.getElementsByName(id)[0] || document.getElementById(id);
+ if (obj) {
+ const combobox = document.getElementById('cbi.combobox.' + id);
+ if (combobox) {
+ obj.combobox = combobox;
+ }
+ const div = document.getElementById(id);
+ if (div && div.getElementsByTagName("li").length > 0) {
+ obj = div;
+ }
+ return obj;
+ } else {
+ return null;
+ }
+}
diff --git a/luci-app-passwall2/luasrc/controller/passwall2.lua b/luci-app-passwall2/luasrc/controller/passwall2.lua
index 9a9b1c35..13af6535 100644
--- a/luci-app-passwall2/luasrc/controller/passwall2.lua
+++ b/luci-app-passwall2/luasrc/controller/passwall2.lua
@@ -79,8 +79,8 @@ function index()
entry({"admin", "services", appname, "connect_status"}, call("connect_status")).leaf = true
entry({"admin", "services", appname, "ping_node"}, call("ping_node")).leaf = true
entry({"admin", "services", appname, "urltest_node"}, call("urltest_node")).leaf = true
+ entry({"admin", "services", appname, "update_config"}, call("update_config")).leaf = true
entry({"admin", "services", appname, "add_node"}, call("add_node")).leaf = true
- entry({"admin", "services", appname, "update_node"}, call("update_node")).leaf = true
entry({"admin", "services", appname, "set_node"}, call("set_node")).leaf = true
entry({"admin", "services", appname, "copy_node"}, call("copy_node")).leaf = true
entry({"admin", "services", appname, "clear_all_nodes"}, call("clear_all_nodes")).leaf = true
@@ -96,6 +96,10 @@ function index()
entry({"admin", "services", appname, "subscribe_manual"}, call("subscribe_manual")).leaf = true
entry({"admin", "services", appname, "subscribe_manual_all"}, call("subscribe_manual_all")).leaf = true
entry({"admin", "services", appname, "flush_set"}, call("flush_set")).leaf = true
+ entry({"admin", "services", appname, "get_shunt_rules"}, call("get_shunt_rules")).leaf = true
+ entry({"admin", "services", appname, "add_shunt_rule"}, call("add_shunt_rule")).leaf = true
+ entry({"admin", "services", appname, "delete_select_shunt_rules"}, call("delete_select_shunt_rules")).leaf = true
+ entry({"admin", "services", appname, "save_shunt_rule_order"}, call("save_shunt_rule_order")).leaf = true
--[[Components update]]
entry({"admin", "services", appname, "check_passwall2"}, call("app_check")).leaf = true
@@ -369,6 +373,23 @@ function urltest_node()
http_write_json(e)
end
+function update_config()
+ local id = http.formvalue("id") -- Node id
+ local data = http.formvalue("data") -- json new Data
+ if id and data then
+ local data_t = jsonParse(data) or {}
+ if next(data_t) then
+ for k, v in pairs(data_t) do
+ uci:set(appname, id, k, v)
+ end
+ api.uci_save(uci, appname)
+ http_write_json_ok()
+ return
+ end
+ end
+ http_write_json_error()
+end
+
function add_node()
local redirect = http.formvalue("redirect")
@@ -391,23 +412,6 @@ function add_node()
end
end
-function update_node()
- local id = http.formvalue("id") -- Node id
- local data = http.formvalue("data") -- json new Data
- if id and data then
- local data_t = jsonParse(data) or {}
- if next(data_t) then
- for k, v in pairs(data_t) do
- uci:set(appname, id, k, v)
- end
- api.uci_save(uci, appname)
- http_write_json_ok()
- return
- end
- end
- http_write_json_error()
-end
-
function set_node()
local type = http.formvalue("type")
local config = http.formvalue("config")
@@ -968,3 +972,87 @@ function fetch_certsha256()
local data = api.fetch_cert_sha256(address, port, sni, 5)
http_write_json(data ~= "" and { code = 1, data = data } or { code = 0 })
end
+
+function get_shunt_rules()
+ local id = http.formvalue("id")
+ local result = {}
+
+ if id then
+ result = uci:get_all(appname, id)
+ else
+ local default_items = {}
+ local other_items = {}
+ uci:foreach(appname, "shunt_rules", function(t)
+ if not t.group or t.group == "" then
+ default_items[#default_items + 1] = t
+ else
+ other_items[#other_items + 1] = t
+ end
+ end)
+ for i = 1, #default_items do result[#result + 1] = default_items[i] end
+ for i = 1, #other_items do result[#result + 1] = other_items[i] end
+ end
+ http_write_json(result)
+end
+
+function add_shunt_rule()
+ local add_name = http.formvalue("add_name")
+ local redirect = http.formvalue("redirect")
+
+ local uuid = add_name
+ if add_name then
+ local has = uci:get(appname, uuid)
+ if has then
+ http_write_json_error({ message = "This ID already exists." })
+ return
+ end
+ else
+ uuid = api.gen_short_uuid()
+ end
+ uci:section(appname, "shunt_rules", uuid)
+
+ local group = http.formvalue("group")
+ if group and group ~= "default" then
+ uci:set(appname, uuid, "group", group)
+ end
+
+ if redirect == "1" then
+ api.uci_save(uci, appname)
+ http.redirect(api.url("shunt_rules", uuid))
+ else
+ api.uci_save(uci, appname)
+ http_write_json_ok({uuid = uuid, redirect_url = api.url("shunt_rules", uuid)})
+ end
+end
+
+function delete_select_shunt_rules()
+ local ids = http.formvalue("ids")
+ local redirect = http.formvalue("redirect")
+ string.gsub(ids, '[^' .. "," .. ']+', function(w)
+ uci:foreach(appname, "nodes", function(s)
+ if s["protocol"] and s["protocol"] == "_shunt" then
+ uci:delete(appname, s[".name"], w)
+ end
+ end)
+ uci:delete(appname, w)
+ end)
+ if redirect == "1" then
+ api.uci_save(uci, appname)
+ http.redirect(api.url("rule"))
+ else
+ api.uci_save(uci, appname, true, true)
+ end
+end
+
+function save_shunt_rule_order()
+ local ids = http.formvalue("ids") or ""
+ local new_order = {}
+ for id in ids:gmatch("([^,]+)") do
+ new_order[#new_order + 1] = id
+ end
+ for idx, name in ipairs(new_order) do
+ luci.sys.call(string.format("uci -q reorder %s.%s=%d", appname, name, idx - 1))
+ end
+ api.sh_uci_commit(appname)
+ http_write_json({ status = "ok" })
+end
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 7e0e4a82..6f506950 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua
@@ -101,6 +101,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
if current_node.protocol == "_shunt" then
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall2/client/include/shunt_options.lua")
setfenv(shunt_lua, getfenv(1))(m, s, {
+ s_cfgid = s:cfgsections()[1],
node_id = current_node_id,
node = current_node,
socks_list = socks_list,
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/include/shunt_options.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/include/shunt_options.lua
index e1218026..3852aac1 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/include/shunt_options.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/include/shunt_options.lua
@@ -4,9 +4,17 @@ if not data.node_id or not data.node then
return
end
+local s_cfgid = data.s_cfgid
local current_node_id = data.node_id
local node_list = data.node_list or api.get_node_list()
+local groups = {}
+m.uci:foreach(appname, "shunt_rules", function(s)
+ if s.group and s.group ~= "" then
+ groups[s.group] = true
+ end
+end)
+
local function get_cfgvalue()
return function(self, section)
return m:get(current_node_id, self.option)
@@ -106,15 +114,27 @@ if api.is_finded("geoview") then
.. ""
end
+shunt_group = add_option(ListValue, "shunt_group", translate("Group Name"))
+shunt_group:value("", translate("default"))
+for k, v in pairs(groups) do
+ shunt_group:value(k)
+end
+
+local shunt_group_val = m:get(current_node_id, "shunt_group") or ""
+shunt_group_val = shunt_group_val:lower()
local shunt_rules = {}
m.uci:foreach(appname, "shunt_rules", function(e)
- e.id = e[".name"]
- e.remarks = e.remarks or e[".name"]
- e["_node_option"] = e[".name"]
- e["_node_default"] = ""
- e["_fakedns_option"] = e[".name"] .. "_fakedns"
- e["_proxy_tag_option"] = e[".name"] .. "_proxy_tag"
- table.insert(shunt_rules, e)
+ local group = e.group or ""
+ group = group:lower()
+ if group == shunt_group_val then
+ e.id = e[".name"]
+ e.remarks = e.remarks or e[".name"]
+ e["_node_option"] = e[".name"]
+ e["_node_default"] = ""
+ e["_fakedns_option"] = e[".name"] .. "_fakedns"
+ e["_proxy_tag_option"] = e[".name"] .. "_proxy_tag"
+ table.insert(shunt_rules, e)
+ end
end)
table.insert(shunt_rules, {
id = ".default",
@@ -199,6 +219,8 @@ end
local footer = Template(appname .. "/include/shunt_options")
footer.api = api
+footer.config = m.config
footer.id = current_node_id
+footer.s_cfgid = s_cfgid or current_node_id
footer.normal_list = api.jsonc.stringify(node_list.normal_list)
m:append(footer)
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 6ffdd44a..3a05c465 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
@@ -135,6 +135,9 @@ s.template = "cbi/tblsection"
s.extedit = api.url("node_subscribe_config", "%s")
function s.create(e, t)
local id = TypedSection.create(e, t)
+ uci:set(appname, id, "hysteria_up_mbps", "100")
+ uci:set(appname, id, "hysteria_down_mbps", "100")
+ api.uci_save(uci, appname)
luci.http.redirect(e.extedit:format(id))
end
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 198e19bc..0ea1e64e 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
@@ -223,11 +223,9 @@ if #hysteria2_type > 0 then
o = s:option(Value, "hysteria_up_mbps", "Hy/Hy2 " .. translate("Max upload Mbps"))
o.datatype = "uinteger"
- o.default = "100"
o = s:option(Value, "hysteria_down_mbps", "Hy/Hy2 " .. translate("Max download Mbps"))
o.datatype = "uinteger"
- o.default = "100"
end
o = s:option(Flag, "boot_update", translate("Update Once on Boot"), translate("Updates the subscription the first time runs automatically after each system boot."))
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 e0b65f42..7e2d3a7a 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/rule.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/rule.lua
@@ -88,31 +88,6 @@ end
s:append(Template(appname .. "/rule/rule_version"))
-local cfgname = "shunt_rules"
-s = m:section(TypedSection, cfgname, "Sing-Box/Xray " .. translate("Shunt Rule"), "" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "")
-s.template = "cbi/tblsection"
-s.anonymous = false
-s.addremove = true
-s.sortable = true
-s.extedit = api.url("shunt_rules", "%s")
-function s.create(e, t)
- TypedSection.create(e, t)
- luci.http.redirect(e.extedit:format(t))
-end
-function s.remove(e, t)
- m.uci:foreach(appname, "nodes", function(s)
- if s["protocol"] and s["protocol"] == "_shunt" then
- m:del(s[".name"], t)
- end
- end)
- TypedSection.remove(e, t)
-end
-
-o = s:option(DummyValue, "remarks", translate("Remarks"))
-
-local sortable = Template(appname .. "/cbi/sortable")
-sortable.api = api
-sortable.target_cfgname = cfgname
-m:append(sortable)
+s:append(Template(appname .. "/rule/shunt_rule_list"))
return api.return_map(m)
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 f7035984..ebeab5ab 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
@@ -45,6 +45,19 @@ function clean_text(text)
:gsub("[ \t]*\n[ \t]*", "\n")
end
+local remarks_lookup = {}
+local groups = {}
+m.uci:foreach(appname, "shunt_rules", function(s)
+ if s[".name"] ~= arg[1] then
+ if s.remarks then
+ remarks_lookup[s.remarks] = s[".name"]
+ end
+ if s.group and s.group ~= "" then
+ groups[s.group] = true
+ end
+ end
+end)
+
s = m:section(NamedSection, arg[1], "shunt_rules", "")
s.addremove = false
s.dynamic = false
@@ -57,9 +70,34 @@ remarks.validate = function(self, value, section)
if value == "" then
return nil, translate("Remark cannot be empty.")
end
+ if remarks_lookup[value] then
+ return nil, translate("This remark already exists, please change a new remark.")
+ end
return value
end
+o = s:option(Value, "group", translate("Group Name"))
+o.default = ""
+o:value("", translate("default"))
+for k, v in pairs(groups) do
+ o:value(k)
+end
+o.write = function(self, section, value)
+ value = api.trim(value)
+ local lower = value:lower()
+
+ if lower == "" or lower == "default" then
+ return m:del(section, self.option)
+ end
+
+ for _, v in ipairs(self.keylist or {}) do
+ if v:lower() == lower then
+ return m:set(section, self.option, v)
+ end
+ end
+ m:set(section, self.option, value)
+end
+
protocol = s:option(MultiValue, "protocol", translate("Protocol"))
protocol:value("http")
protocol:value("tls")
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 2cbeb54d..bc3c4946 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
@@ -109,10 +109,12 @@ o.rewrite_option = o.option
o = s:option(Value, _n("recv_window_conn"), translate("QUIC connection receive window"))
o.rewrite_option = o.option
-o = s:option(Value, _n("idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s~120s)")
+o = s:option(Value, _n("idle_timeout"), translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
+o.datatype = "range(4,120)"
o.rewrite_option = o.option
-o = s:option(Value, _n("keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Example:") .. "10s (2s~60s)")
+o = s:option(Value, _n("keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)")
+o.datatype = "range(2,60)"
o.rewrite_option = o.option
o = s:option(Flag, _n("disable_mtu_discovery"), translate("Disable MTU detection"))
diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua
index 12e44eb6..728ab2fc 100644
--- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua
+++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua
@@ -394,10 +394,12 @@ o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
o:depends({ [_n("protocol")] = "hysteria2" })
-o = s:option(Value, _n("hysteria2_idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s~120s)")
+o = s:option(Value, _n("hysteria2_idle_timeout"), translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
+o.datatype = "range(4,120)"
o:depends({ [_n("protocol")] = "hysteria2"})
-o = s:option(Value, _n("hysteria2_keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Example:") .. "10s (2s~60s)")
+o = s:option(Value, _n("hysteria2_keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)")
+o.datatype = "range(2,60)"
o:depends({ [_n("protocol")] = "hysteria2"})
o = s:option(Flag, _n("hysteria2_disable_mtu_discovery"), translate("Disable MTU detection"))
@@ -803,6 +805,9 @@ o:value("", translate("Auto"))
o:value("UseIPv4", translate("IPv4 Only"))
o:value("UseIPv6", translate("IPv6 Only"))
+o = s:option(Flag, _n("happy_eyeballs"), translate("Enable Happy Eyeballs"), translate("Attempts IPv4 and IPv6 simultaneously; automatically uses the faster connection."))
+o.default = 0
+
local protocols = s.fields[_n("protocol")].keylist
if #protocols > 0 then
for i, v in ipairs(protocols) do
@@ -814,7 +819,11 @@ if #protocols > 0 then
s.fields[_n("address")]:depends(depends_condition)
s.fields[_n("port")]:depends(depends_condition)
s.fields[_n("domain_resolver")]:depends(depends_condition)
- s.fields[_n("domain_strategy")]:depends(depends_condition)
+ s.fields[_n("happy_eyeballs")]:depends(depends_condition)
+
+ local strategy_depends = api.clone(depends_condition)
+ strategy_depends[_n("happy_eyeballs")] = false
+ s.fields[_n("domain_strategy")]:depends(strategy_depends)
if v ~= "hysteria2" then
s.fields[_n("tcp_fast_open")]:depends({ [_n("protocol")] = v })
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 8dde7edd..138922bc 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
@@ -457,10 +457,12 @@ if singbox_tags:find("with_quic") then
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
o:depends({ [_n("protocol")] = "hysteria2" })
- o = s:option(Value, _n("hysteria2_idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s~120s)")
+ o = s:option(Value, _n("hysteria2_idle_timeout"), translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
+ o.datatype = "range(4,120)"
o:depends({ [_n("protocol")] = "hysteria2"})
- o = s:option(Value, _n("hysteria2_keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Example:") .. "10s (2s~60s)")
+ o = s:option(Value, _n("hysteria2_keep_alive_period"), translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)")
+ o.datatype = "range(2,60)"
o:depends({ [_n("protocol")] = "hysteria2"})
o = s:option(Flag, _n("hysteria2_disable_mtu_discovery"), translate("Disable MTU detection"))
@@ -629,6 +631,10 @@ if singbox_tags:find("with_utls") then
o:depends({ [_n("reality")] = true })
end
+o = s:option(Flag, _n("anytls_disable_reuse"), translate("Disable TLS Reuse"))
+o.default = 0
+o:depends({ [_n("protocol")] = "anytls" })
+
o = s:option(ListValue, _n("transport"), translate("Transport"))
o:value("tcp", "TCP")
o:value("http", "HTTP")
diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua
index 18a13dec..3ec184d5 100644
--- a/luci-app-passwall2/luasrc/passwall2/api.lua
+++ b/luci-app-passwall2/luasrc/passwall2/api.lua
@@ -1170,7 +1170,7 @@ function to_extract(app_name, file, subfix)
exec("/bin/rm", {"-f", file})
return {
code = 1,
- error = i18n.translate("Not installed %s, Can't unzip!" % { tools_name })
+ error = i18n.translatef("Not installed %s, Can't unzip!", tools_name)
}
end
end
@@ -1383,8 +1383,6 @@ function set_apply_on_parse(map)
if old then old(self) end
map:set("@global[0]", "timestamp", os.time())
end
- local cbi = require "luci.cbi"
- map:append(cbi.Template(appname .. "/cbi/optimize_cbi_ui"))
end
end
end
diff --git a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua
index f25afa17..312787f3 100644
--- a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua
+++ b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua
@@ -647,6 +647,8 @@ function gen_outbound(flag, node, tag, proxy_table)
idle_session_check_interval = "30s",
idle_session_timeout = "30s",
min_idle_session = 5,
+ disable_reuse = (node.anytls_disable_reuse == "1") and true or nil,
+ client_metadata = api.compare_versions(local_version, ">=", "1.13.16") and "anytls/0.0.13" or nil,
tls = tls
}
end
@@ -1599,6 +1601,9 @@ function gen_config(var)
--shunt rule
uci:foreach(appname, "shunt_rules", function(e)
+ if node["shunt_group"] ~= e.group then
+ return
+ end
local outboundTag = gen_shunt_node(e[".name"])
if outboundTag and e.remarks then
if outboundTag == "default" then
diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua
index e8ba1589..5a953edd 100644
--- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua
+++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua
@@ -170,9 +170,15 @@ function gen_outbound(flag, node, tag, proxy_table)
mark = 255,
domainStrategy = node.domain_strategy or "UseIP",
tcpFastOpen = (node.tcp_fast_open == "1") and true or nil,
- tcpMptcp = (node.tcpMptcp == "1") and true or nil
+ tcpMptcp = (node.tcpMptcp == "1") and true or nil,
+ happyEyeballs = (node.happy_eyeballs == "1") and {
+ TryDelayMs = 250,
+ PrioritizeIPv6 = false,
+ Interleave = 1,
+ MaxConcurrentTry = 4
+ } or nil
},
- network = node.transport,
+ [(api.compare_versions(xray_version, "<", "26.7.11")) and "network" or "method"] = node.transport, -- Todo: Remove version check and "network"
security = node.stream_security,
tlsSettings = (node.stream_security == "tls") and {
serverName = node.tls_serverName,
@@ -659,7 +665,7 @@ function gen_config_server(node)
protocol = node.protocol,
settings = settings,
streamSettings = {
- network = node.transport,
+ [(api.compare_versions(xray_version, "<", "26.7.11")) and "network" or "method"] = node.transport, -- Todo: Remove version check and "network"
security = "none",
tlsSettings = ("1" == node.tls) and {
disableSystemRoot = false,
@@ -1073,6 +1079,10 @@ function gen_config(var)
if outboundTag then
valid_nodes[#valid_nodes + 1] = outboundTag
end
+ -- Check if balancing node duplicates fallback node
+ if _node.fallback_node == blc_node_id then
+ _node.fallback_node = nil
+ end
end
end
if #valid_nodes == 0 then return nil end
@@ -1392,6 +1402,9 @@ function gen_config(var)
--shunt rule
uci:foreach(appname, "shunt_rules", function(e)
+ if node["shunt_group"] ~= e.group then
+ return
+ end
local outboundTag = gen_shunt_node(e[".name"])
if outboundTag and e.remarks then
if outboundTag == "default" then
diff --git a/luci-app-passwall2/luasrc/view/passwall2/cbi/footer.htm b/luci-app-passwall2/luasrc/view/passwall2/cbi/footer.htm
index 46a25d3e..54777e11 100644
--- a/luci-app-passwall2/luasrc/view/passwall2/cbi/footer.htm
+++ b/luci-app-passwall2/luasrc/view/passwall2/cbi/footer.htm
@@ -1 +1,18 @@
+
\ No newline at end of file
diff --git a/luci-app-passwall2/luasrc/view/passwall2/cbi/header.htm b/luci-app-passwall2/luasrc/view/passwall2/cbi/header.htm
index 5d284d90..a2a716bb 100644
--- a/luci-app-passwall2/luasrc/view/passwall2/cbi/header.htm
+++ b/luci-app-passwall2/luasrc/view/passwall2/cbi/header.htm
@@ -1,2 +1,24 @@
+
+
+
diff --git a/luci-app-passwall2/luasrc/view/passwall2/cbi/optimize_cbi_ui.htm b/luci-app-passwall2/luasrc/view/passwall2/cbi/optimize_cbi_ui.htm
deleted file mode 100644
index 3fccf13c..00000000
--- a/luci-app-passwall2/luasrc/view/passwall2/cbi/optimize_cbi_ui.htm
+++ /dev/null
@@ -1,22 +0,0 @@
-
diff --git a/luci-app-passwall2/luasrc/view/passwall2/global/footer.htm b/luci-app-passwall2/luasrc/view/passwall2/global/footer.htm
index e1ba5c58..661c1bd9 100644
--- a/luci-app-passwall2/luasrc/view/passwall2/global/footer.htm
+++ b/luci-app-passwall2/luasrc/view/passwall2/global/footer.htm
@@ -207,7 +207,7 @@ local appname = api.appname
let new_val = el.target.value
const new_hasItem = shunt_list.find(element => element.id == new_val);
if (new_hasItem) {
- XHR.get('<%=api.url("update_node")%>', {
+ XHR.get('<%=api.url("update_config")%>', {
id: "<%=self.global_cfgid%>",
data: JSON.stringify({
node: new_val
diff --git a/luci-app-passwall2/luasrc/view/passwall2/include/shunt_options.htm b/luci-app-passwall2/luasrc/view/passwall2/include/shunt_options.htm
index 9dcc05c7..83b3c4f3 100644
--- a/luci-app-passwall2/luasrc/view/passwall2/include/shunt_options.htm
+++ b/luci-app-passwall2/luasrc/view/passwall2/include/shunt_options.htm
@@ -53,6 +53,22 @@
}
}
}
+ document.addEventListener("DOMContentLoaded", function () {
+ waitForElement('select[name*="<%=self.config%>"][name*="shunt_group"]', function(el) {
+ let o_val = el.value;
+ el.addEventListener("change", () => {
+ el.blur();
+ if (o_val != el.value) {
+ let save = true;
+ if (save) {
+ update_config("<%=self.id%>", {
+ shunt_group: getOption("<%=self.config%>", "<%=self.s_cfgid%>", "shunt_group").value,
+ }, get_current_url());
+ }
+ }
+ });
+ });
+ });
document.addEventListener("DOMContentLoaded", () => setTimeout(() => {
refresh_depends();
const table_dom = document.getElementById("cbi-passwall2-shunt_option_list");
diff --git a/luci-app-passwall2/luasrc/view/passwall2/node_config/footer.htm b/luci-app-passwall2/luasrc/view/passwall2/node_config/footer.htm
index feefc4dd..b2cfd367 100644
--- a/luci-app-passwall2/luasrc/view/passwall2/node_config/footer.htm
+++ b/luci-app-passwall2/luasrc/view/passwall2/node_config/footer.htm
@@ -1,8 +1,8 @@
-<%
-local api = self.api
--%>
+
+
+
+<% if api.is_js_luci() then -%>
+
+<%- end %>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/luci-app-passwall2/po/fa/passwall2.po b/luci-app-passwall2/po/fa/passwall2.po
index cd8e2625..7e8f93a7 100644
--- a/luci-app-passwall2/po/fa/passwall2.po
+++ b/luci-app-passwall2/po/fa/passwall2.po
@@ -1750,6 +1750,12 @@ msgstr "حل مشکل DNS دامنه"
msgid "If the node address is a domain name, this DNS will be used for resolution."
msgstr "اگر آدرس گره یک نام دامنه باشد، از این DNS برای حل مسئله استفاده خواهد شد."
+msgid "Enable Happy Eyeballs"
+msgstr "فعال کردن چشمهای خوشحال"
+
+msgid "Attempts IPv4 and IPv6 simultaneously; automatically uses the faster connection."
+msgstr "IPv4 و IPv6 را همزمان امتحان میکند؛ بهطور خودکار از اتصال سریعتر استفاده میکند."
+
msgid "Supports only Xray or Sing-box node types."
msgstr "فقط گرههای نوع Xray یا Sing-box پشتیبانی میشوند."
@@ -2413,3 +2419,9 @@ msgstr "اندازه بسته Gecko (حداکثر)"
msgid "valid time (hh:mm)"
msgstr "زمان معتبر (ساعت:میلیمتر)"
+
+msgid "Disable TLS Reuse"
+msgstr "غیرفعال کردن استفاده مجدد از TLS"
+
+msgid "Not Set"
+msgstr "تنظیم نشده"
diff --git a/luci-app-passwall2/po/ru/passwall2.po b/luci-app-passwall2/po/ru/passwall2.po
index 04797312..d9be19cb 100644
--- a/luci-app-passwall2/po/ru/passwall2.po
+++ b/luci-app-passwall2/po/ru/passwall2.po
@@ -1751,6 +1751,12 @@ msgstr "Разрешение DNS-запросов для домена"
msgid "If the node address is a domain name, this DNS will be used for resolution."
msgstr "Если адрес узла является доменным именем, для разрешения будет использоваться этот DNS-сервер."
+msgid "Enable Happy Eyeballs"
+msgstr "Включить счастливые глаза"
+
+msgid "Attempts IPv4 and IPv6 simultaneously; automatically uses the faster connection."
+msgstr "Одновременно пытается использовать IPv4 и IPv6; автоматически выбирает более быстрое соединение."
+
msgid "Supports only Xray or Sing-box node types."
msgstr "Поддерживаются только узлы типа Xray или Sing-box."
@@ -2411,3 +2417,9 @@ msgstr "Размер упаковки Gecko (макс)"
msgid "valid time (hh:mm)"
msgstr "Время действия (чч:мм)"
+
+msgid "Disable TLS Reuse"
+msgstr "Отключить повторное использование TLS"
+
+msgid "Not Set"
+msgstr "Не задано"
diff --git a/luci-app-passwall2/po/zh-cn/passwall2.po b/luci-app-passwall2/po/zh-cn/passwall2.po
index baad1ec2..0eaa07f2 100644
--- a/luci-app-passwall2/po/zh-cn/passwall2.po
+++ b/luci-app-passwall2/po/zh-cn/passwall2.po
@@ -1736,6 +1736,12 @@ msgstr "域名 DNS 解析"
msgid "If the node address is a domain name, this DNS will be used for resolution."
msgstr "如果节点地址是域名,则将使用此 DNS 进行解析。"
+msgid "Enable Happy Eyeballs"
+msgstr "启用 Happy Eyeballs"
+
+msgid "Attempts IPv4 and IPv6 simultaneously; automatically uses the faster connection."
+msgstr "同时尝试 IPv4 和 IPv6 连接,自动使用更快的连接。"
+
msgid "Supports only Xray or Sing-box node types."
msgstr "仅支持 Xray 或 Sing-box 类型节点。"
@@ -2399,3 +2405,9 @@ msgstr "Gecko 包大小(最大)"
msgid "valid time (hh:mm)"
msgstr "有效时间(hh:mm)"
+
+msgid "Disable TLS Reuse"
+msgstr "禁用 TLS 连接复用"
+
+msgid "Not Set"
+msgstr "未设置"
diff --git a/luci-app-passwall2/po/zh-tw/passwall2.po b/luci-app-passwall2/po/zh-tw/passwall2.po
index c7b79250..0a32d41e 100644
--- a/luci-app-passwall2/po/zh-tw/passwall2.po
+++ b/luci-app-passwall2/po/zh-tw/passwall2.po
@@ -1742,6 +1742,12 @@ msgstr "域名 DNS 解析"
msgid "If the node address is a domain name, this DNS will be used for resolution."
msgstr "如果節點地址是域名,則將使用此 DNS 進行解析。"
+msgid "Enable Happy Eyeballs"
+msgstr "啓用 Happy Eyeballs"
+
+msgid "Attempts IPv4 and IPv6 simultaneously; automatically uses the faster connection."
+msgstr "同時嘗試 IPv4 和 IPv6 鏈接,自動使用更快的鏈接。"
+
msgid "Supports only Xray or Sing-box node types."
msgstr "僅支援 Xray 或 Sing-box 類型節點。"
@@ -2405,3 +2411,9 @@ msgstr "Gecko 包大小(最大)"
msgid "valid time (hh:mm)"
msgstr "有效時間(hh:mm)"
+
+msgid "Disable TLS Reuse"
+msgstr "禁用 TLS 連接復用"
+
+msgid "Not Set"
+msgstr "未設置"
diff --git a/luci-app-passwall2/root/usr/share/passwall2/0_default_config b/luci-app-passwall2/root/usr/share/passwall2/0_default_config
index 16aa35f0..d6ce2fe5 100644
--- a/luci-app-passwall2/root/usr/share/passwall2/0_default_config
+++ b/luci-app-passwall2/root/usr/share/passwall2/0_default_config
@@ -59,51 +59,6 @@ config global_subscribe
config global_singbox
-config shunt_rules 'China'
- option remarks 'China'
- option network 'tcp,udp'
- option domain_list 'geosite:cn'
- option ip_list 'geoip:cn'
-
-config shunt_rules 'Iran'
- option remarks 'Iran'
- option network 'tcp,udp'
- option domain_list 'geosite:ir
-#rule-set:remote:https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geosite-ir.srs'
- option ip_list 'geoip:ir
-#rule-set:remote:https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geoip-ir.srs'
-
-config shunt_rules 'Russia_Block'
- option remarks 'Russia_Block'
- option network 'tcp,udp'
- option domain_list 'geosite:ru-blocked
-#rule-set:remote:https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/refs/heads/release/sing-box/rule-set-geosite/geosite-ru-blocked.srs'
- option ip_list 'geoip:ru-blocked
-#rule-set:remote:https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/refs/heads/release/sing-box/rule-set-geoip/geoip-ru-blocked.srs'
-
-config shunt_rules 'Russia'
- option remarks 'Russia'
- option network 'tcp,udp'
- option ip_list 'geoip:ru
-#rule-set:remote:https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/refs/heads/release/sing-box/rule-set-geoip/geoip-ru.srs'
-
-config shunt_rules 'PrivateIP'
- option remarks 'PrivateIP'
- option network 'tcp,udp'
- option ip_list '10.0.0.0/8
-127.0.0.0/8
-198.51.100.0/24
-192.0.0.0/24
-169.254.0.0/16
-224.0.0.0/3
-192.168.0.0/16
-192.88.99.0/24
-100.64.0.0/10
-172.16.0.0/12
-0.0.0.0/8
-192.0.2.0/24
-203.0.113.0/24'
-
config nodes 'examplenode'
option remarks 'Example'
option type 'Xray'
@@ -126,3 +81,151 @@ config nodes 'rulenode'
option domainMatcher 'hybrid'
option write_ipset_direct '1'
option enable_geoview_ip '1'
+ option shunt_group 'CN'
+
+config shunt_rules 'DirectFront'
+ option remarks 'DirectFront'
+ option network 'tcp,udp'
+ option domain_list 'domain:ip233.cn'
+ option group 'CN'
+
+config shunt_rules 'ProxyFront'
+ option remarks 'ProxyFront'
+ option network 'tcp,udp'
+ option domain_list 'domain:www.gstatic.com
+domain:ssl.gstatic.com
+domain:fonts.gstatic.com'
+ option group 'CN'
+
+config shunt_rules 'DirectGame'
+ option remarks 'DirectGame'
+ option domain_list '# steam直连域名获取国内CDN走国内线路下载
+cm.steampowered.com
+steamserver.net
+
+# steam国内CDN华为云
+steampipe.steamcontent.tnkjmec.com
+# steam国内CDN白山云
+st.dl.eccdnx.com
+st.dl.bscstorage.net
+st.dl.pinyuncloud.com
+# steam国内CDN新流云(原金山云)(支持ipv6)
+dl.steam.clngaa.com
+# steam国内CDN网宿
+cdn.mileweb.cs.steampowered.com.8686c.com
+cdn-ws.content.steamchina.com
+# steam国内CDN腾讯云 (蒸汽中国独占)
+cdn-qc.content.steamchina.com
+# steam国内CDN阿里云(支持ipv6)
+cdn-ali.content.steamchina.com
+xz.pphimalayanrt.com
+lv.queniujq.cn
+alibaba.cdn.steampipe.steamcontent.com
+
+# 国内游戏geosite域名
+geosite:category-games@cn'
+ option ip_list '# steam直连IP
+45.121.184.0/24
+103.10.124.0/23
+103.28.54.0/24
+146.66.152.0/24
+146.66.155.0/24
+153.254.86.0/24
+155.133.224.0/22
+155.133.230.0/24
+155.133.232.0/23
+155.133.234.0/24
+155.133.236.0/22
+155.133.240.0/23
+155.133.244.0/23
+155.133.246.0/24
+155.133.248.0/21
+162.254.192.0/21
+185.25.182.0/23
+190.217.32.0/22
+192.69.96.0/22
+205.196.6.0/24
+208.64.200.0/22
+208.78.164.0/22
+205.185.194.0/24'
+ option network 'tcp,udp'
+ option group 'CN'
+
+config shunt_rules 'ProxyGame'
+ option remarks 'ProxyGame'
+ option domain_list '# steam 商店/客服/聊天/网页布局/API/二维码/Google云同步 代理URL
+steamcommunity.com
+www.steamcommunity.com
+store.steampowered.com
+checkout.steampowered.com
+api.steampowered.com
+help.steampowered.com
+login.steampowered.com
+store.akamai.steamstatic.com
+steambroadcast.akamaized.net
+steamvideo-a.akamaihd.net
+steamusercontent-a.akamaihd.net
+steamstore-a.akamaihd.net
+steamcommunity-a.akamaihd.net
+steamcdn-a.akamaihd.net
+steamuserimages-a.akamaihd.net
+community.akamai.steamstatic.com
+avatars.akamai.steamstatic.com
+community.steamstatic.com
+cdn.akamai.steamstatic.com
+avatars.steamstatic.com
+shared.akamai.steamstatic.com
+clan.akamai.steamstatic.com
+cdn.cloudflare.steamstatic.com
+community.cloudflare.steamstatic.com
+store.cloudflare.steamstatic.com
+avatars.cloudflare.steamstatic.com
+clan.cloudflare.steamstatic.com
+shared.cloudflare.steamstatic.com
+steam-chat.com
+steamcloud-ugc.storage.googleapis.com
+steamcloud-eu-ams.storage.googleapis.com
+steamcloud-eu-fra.storage.googleapis.com
+steamcloud-finland.storage.googleapis.com
+steamcloud-saopaulo.storage.googleapis.com
+steamcloud-singapore.storage.googleapis.com
+steamcloud-sydney.storage.googleapis.com
+steamcloud-taiwan.storage.googleapis.com
+steamcloud-eu.storage.googleapis.com
+domain:blizzard.com
+geosite:category-games'
+ option network 'tcp,udp'
+ option group 'CN'
+
+config shunt_rules 'CN'
+ option remarks 'CN'
+ option domain_list 'geosite:cn'
+ option ip_list 'geoip:cn'
+ option network 'tcp,udp'
+ option group 'CN'
+
+config shunt_rules 'Iran'
+ option remarks 'Iran'
+ option network 'tcp,udp'
+ option domain_list 'geosite:ir
+#rule-set:remote:https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geosite-ir.srs'
+ option ip_list 'geoip:ir
+#rule-set:remote:https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geoip-ir.srs'
+ option group 'IR'
+
+config shunt_rules 'Russia_Block'
+ option remarks 'Russia_Block'
+ option network 'tcp,udp'
+ option domain_list 'geosite:ru-blocked
+#rule-set:remote:https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/refs/heads/release/sing-box/rule-set-geosite/geosite-ru-blocked.srs'
+ option ip_list 'geoip:ru-blocked
+#rule-set:remote:https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/refs/heads/release/sing-box/rule-set-geoip/geoip-ru-blocked.srs'
+ option group 'RU'
+
+config shunt_rules 'Russia'
+ option remarks 'Russia'
+ option network 'tcp,udp'
+ option ip_list 'geoip:ru
+#rule-set:remote:https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/refs/heads/release/sing-box/rule-set-geoip/geoip-ru.srs'
+ option group 'RU'
+
diff --git a/luci-app-passwall2/root/usr/share/passwall2/iptables.sh b/luci-app-passwall2/root/usr/share/passwall2/iptables.sh
index 52be6721..17255734 100755
--- a/luci-app-passwall2/root/usr/share/passwall2/iptables.sh
+++ b/luci-app-passwall2/root/usr/share/passwall2/iptables.sh
@@ -189,7 +189,9 @@ gen_shunt_list() {
local default_outbound="redirect"
[ "$default_node" = "_direct" ] && default_outbound="direct"
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
+ local shunt_group=$(config_n_get $node shunt_group)
for shunt_id in $shunt_ids; do
+ [ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue
local shunt_node=$(config_n_get ${node} "${shunt_id}")
[ -n "$shunt_node" ] && {
local ipset_v4="psw2_${node}_${shunt_id}"
@@ -702,15 +704,13 @@ add_firewall_rule() {
fi
$ipt_n -N PSW2
- $ipt_n -A PSW2 $(dst $IPSET_DIRECT) -j RETURN
$ipt_n -A PSW2 $(dst $IPSET_VPS) -j RETURN
$ipt_n -A PSW2 $(comment "WAN_IP_RETURN") $(dst $IPSET_WAN) -j RETURN
- [ "$accept_icmp" = "1" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "-p icmp -j PSW2"
- [ -z "${is_tproxy}" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "-p tcp -j PSW2"
+ [ "$accept_icmp" = "1" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "$(dst $IPSET_DIRECT !) -p icmp -j PSW2"
+ [ -z "${is_tproxy}" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "$(dst $IPSET_DIRECT !) -p tcp -j PSW2"
$ipt_n -N PSW2_OUTPUT
- $ipt_n -A PSW2_OUTPUT $(dst $IPSET_DIRECT) -j RETURN
$ipt_n -A PSW2_OUTPUT $(dst $IPSET_VPS) -j RETURN
$ipt_n -A PSW2_OUTPUT -m mark --mark 255 -j RETURN
@@ -722,10 +722,6 @@ add_firewall_rule() {
$ipt_n -I PREROUTING -m set --match-set $IPSET_DIRECT src -j PSW2_DNS
fi
- $ipt_m -N PSW2_DIVERT
- $ipt_m -A PSW2_DIVERT -j MARK --set-mark ${FWMARK}
- $ipt_m -A PSW2_DIVERT -j ACCEPT
-
$ipt_m -N PSW2_RULE
$ipt_m -A PSW2_RULE -j CONNMARK --restore-mark
$ipt_m -A PSW2_RULE -m mark --mark ${FWMARK} -j RETURN
@@ -734,17 +730,16 @@ add_firewall_rule() {
$ipt_m -A PSW2_RULE -j CONNMARK --save-mark
$ipt_m -N PSW2
- $ipt_m -A PSW2 $(dst $IPSET_DIRECT) -j RETURN
+ # Socket Only TCP, UDP Invalid.
+ $ipt_m -A PSW2 -p tcp -m socket -j MARK --set-mark ${FWMARK}
+ $ipt_m -A PSW2 -p tcp -m socket -j ACCEPT
$ipt_m -A PSW2 $(dst $IPSET_VPS) -j RETURN
$ipt_m -A PSW2 $(comment "WAN_IP_RETURN") $(dst $IPSET_WAN) -j RETURN
$ipt_m -A PSW2 -m conntrack --ctdir REPLY -j RETURN
- insert_rule_before "$ipt_m" "PREROUTING" "mwan3" "-j PSW2"
- # Only TCP, UDP Invalid.
- insert_rule_before "$ipt_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT"
+ insert_rule_before "$ipt_m" "PREROUTING" "mwan3" "$(dst $IPSET_DIRECT !) -j PSW2"
$ipt_m -N PSW2_OUTPUT
- $ipt_m -A PSW2_OUTPUT $(dst $IPSET_DIRECT) -j RETURN
$ipt_m -A PSW2_OUTPUT $(dst $IPSET_VPS) -j RETURN
$ipt_m -A PSW2_OUTPUT -m conntrack --ctdir REPLY -j RETURN
$ipt_m -A PSW2_OUTPUT -m mark --mark 255 -j RETURN
@@ -754,12 +749,10 @@ add_firewall_rule() {
[ "$accept_icmpv6" = "1" ] && {
$ip6t_n -N PSW2
- $ip6t_n -A PSW2 $(dst $IPSET_DIRECT6) -j RETURN
$ip6t_n -A PSW2 $(dst $IPSET_VPS6) -j RETURN
- $ip6t_n -A PREROUTING -p ipv6-icmp -j PSW2
+ $ip6t_n -A PREROUTING $(dst $IPSET_DIRECT6 !) -p ipv6-icmp -j PSW2
$ip6t_n -N PSW2_OUTPUT
- $ip6t_n -A PSW2_OUTPUT $(dst $IPSET_DIRECT6) -j RETURN
$ip6t_n -A PSW2_OUTPUT $(dst $IPSET_VPS6) -j RETURN
$ip6t_n -A PSW2_OUTPUT -m mark --mark 255 -j RETURN
}
@@ -772,10 +765,6 @@ add_firewall_rule() {
$ip6t_n -I PREROUTING -m set --match-set $IPSET_DIRECT6 src -j PSW2_DNS
fi
- $ip6t_m -N PSW2_DIVERT
- $ip6t_m -A PSW2_DIVERT -j MARK --set-mark ${FWMARK}
- $ip6t_m -A PSW2_DIVERT -j ACCEPT
-
$ip6t_m -N PSW2_RULE
$ip6t_m -A PSW2_RULE -j CONNMARK --restore-mark
$ip6t_m -A PSW2_RULE -m mark --mark ${FWMARK} -j RETURN
@@ -784,18 +773,17 @@ add_firewall_rule() {
$ip6t_m -A PSW2_RULE -j CONNMARK --save-mark
$ip6t_m -N PSW2
- $ip6t_m -A PSW2 $(dst $IPSET_DIRECT6) -j RETURN
+ # Socket Only TCP, UDP Invalid.
+ $ip6t_m -A PSW2 -p tcp -m socket -j MARK --set-mark ${FWMARK}
+ $ip6t_m -A PSW2 -p tcp -m socket -j ACCEPT
$ip6t_m -A PSW2 $(dst $IPSET_VPS6) -j RETURN
$ip6t_m -A PSW2 $(comment "WAN6_IP_RETURN") $(dst $IPSET_WAN6) -j RETURN
$ip6t_m -A PSW2 -m conntrack --ctdir REPLY -j RETURN
- insert_rule_before "$ip6t_m" "PREROUTING" "mwan3" "-j PSW2"
- # Only TCP, UDP Invalid.
- insert_rule_before "$ip6t_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT"
+ insert_rule_before "$ip6t_m" "PREROUTING" "mwan3" "$(dst $IPSET_DIRECT6 !) -j PSW2"
$ip6t_m -N PSW2_OUTPUT
$ip6t_m -A PSW2_OUTPUT -m mark --mark 255 -j RETURN
- $ip6t_m -A PSW2_OUTPUT $(dst $IPSET_DIRECT6) -j RETURN
$ip6t_m -A PSW2_OUTPUT $(dst $IPSET_VPS6) -j RETURN
$ip6t_m -A PSW2_OUTPUT -m conntrack --ctdir REPLY -j RETURN
@@ -860,14 +848,14 @@ add_firewall_rule() {
# Loading local router proxy TCP
if [ -n "$NODE" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then
[ "$accept_icmp" = "1" ] && {
- $ipt_n -A OUTPUT -p icmp -j PSW2_OUTPUT
+ $ipt_n -A OUTPUT $(dst $IPSET_DIRECT !) -p icmp -j PSW2_OUTPUT
$ipt_n -A PSW2_OUTPUT -p icmp -d $FAKE_IP $(REDIRECT)
add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_n -A PSW2_OUTPUT -p icmp" "$(REDIRECT)"
$ipt_n -A PSW2_OUTPUT -p icmp $(REDIRECT)
}
[ "$accept_icmpv6" = "1" ] && {
- $ip6t_n -A OUTPUT -p ipv6-icmp -j PSW2_OUTPUT
+ $ip6t_n -A OUTPUT $(dst $IPSET_DIRECT6 !) -p ipv6-icmp -j PSW2_OUTPUT
$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp -d $FAKE_IP_6 $(REDIRECT)
add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp" "$(REDIRECT)"
$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp $(REDIRECT)
@@ -882,11 +870,11 @@ add_firewall_rule() {
$ipt_tmp -A PSW2_OUTPUT -p tcp -d $FAKE_IP ${ipt_j}
add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_tmp -A PSW2_OUTPUT -p tcp" "${ipt_j}" $TCP_REDIR_PORTS
add_port_rules "$ipt_tmp -A PSW2_OUTPUT -p tcp" $TCP_REDIR_PORTS "${ipt_j}"
- [ -z "${is_tproxy}" ] && $ipt_n -A OUTPUT -p tcp -j PSW2_OUTPUT
+ [ -z "${is_tproxy}" ] && $ipt_n -A OUTPUT $(dst $IPSET_DIRECT !) -p tcp -j PSW2_OUTPUT
[ -n "${is_tproxy}" ] && {
$ipt_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo $(REDIRECT $REDIR_PORT TPROXY)
$ipt_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo -j RETURN
- insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -p tcp -j PSW2_OUTPUT"
+ insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT !) -p tcp -j PSW2_OUTPUT"
}
[ "$PROXY_IPV6" == "1" ] && {
@@ -895,7 +883,7 @@ add_firewall_rule() {
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p tcp" $TCP_REDIR_PORTS "-j PSW2_RULE"
$ip6t_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo $(REDIRECT $REDIR_PORT TPROXY)
$ip6t_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo -j RETURN
- insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -p tcp -j PSW2_OUTPUT"
+ insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT6 !) -p tcp -j PSW2_OUTPUT"
}
[ -d "${TMP_IFACE_PATH}" ] && {
@@ -913,7 +901,7 @@ add_firewall_rule() {
add_port_rules "$ipt_m -A PSW2_OUTPUT -p udp" $UDP_REDIR_PORTS "-j PSW2_RULE"
$ipt_m -A PSW2 $(comment "${comment_l}") -p udp -i lo $(REDIRECT $REDIR_PORT TPROXY)
$ipt_m -A PSW2 $(comment "${comment_l}") -p udp -i lo -j RETURN
- insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -p udp -j PSW2_OUTPUT"
+ insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT !) -p udp -j PSW2_OUTPUT"
[ "$PROXY_IPV6" == "1" ] && {
$ip6t_m -A PSW2_OUTPUT -p udp -d $FAKE_IP_6 -j PSW2_RULE
@@ -921,7 +909,7 @@ add_firewall_rule() {
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p udp" $UDP_REDIR_PORTS "-j PSW2_RULE"
$ip6t_m -A PSW2 $(comment "${comment_l}") -p udp -i lo $(REDIRECT $REDIR_PORT TPROXY)
$ip6t_m -A PSW2 $(comment "${comment_l}") -p udp -i lo -j RETURN
- insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -p udp -j PSW2_OUTPUT"
+ insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT6 !) -p udp -j PSW2_OUTPUT"
}
[ -d "${TMP_IFACE_PATH}" ] && {
@@ -938,8 +926,10 @@ add_firewall_rule() {
$ip6t_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -m mark --mark ${FWMARK} -j RETURN"
- $ipt_m -A PSW2 -p udp --dport 53 -j RETURN
- $ip6t_m -A PSW2 -p udp --dport 53 -j RETURN
+ $ipt_m -A PSW2 -p tcp --dport 53 -j ACCEPT
+ $ipt_m -A PSW2 -p udp --dport 53 -j ACCEPT
+ $ip6t_m -A PSW2 -p tcp --dport 53 -j ACCEPT
+ $ip6t_m -A PSW2 -p udp --dport 53 -j ACCEPT
}
load_acl
@@ -970,7 +960,7 @@ del_firewall_rule() {
$ipt -D $chain $index 2>/dev/null
done
done
- for chain in "PSW2" "PSW2_OUTPUT" "PSW2_DIVERT" "PSW2_DNS" "PSW2_RULE"; do
+ for chain in "PSW2" "PSW2_OUTPUT" "PSW2_DNS" "PSW2_RULE"; do
$ipt -F $chain 2>/dev/null
$ipt -X $chain 2>/dev/null
done
@@ -1004,7 +994,7 @@ gen_include() {
[ -z "${_ipt}" ] && return
echo "*$2"
- ${_ipt}-save -t $2 | grep "PSW2" | grep -v "\-j PSW2$" | grep -v "socket \-j PSW2_DIVERT$" | sed -e "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/"
+ ${_ipt}-save -t $2 | grep "PSW2" | grep -v "\-j PSW2$" | sed -e "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/"
echo 'COMMIT'
}
local __ipt=""
@@ -1017,11 +1007,10 @@ gen_include() {
$(extract_rules 4 mangle)
EOT
- [ "$accept_icmp" = "1" ] && \$(${MY_PATH} insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "-p icmp -j PSW2")
- [ -z "${is_tproxy}" ] && \$(${MY_PATH} insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "-p tcp -j PSW2")
+ [ "$accept_icmp" = "1" ] && \$(${MY_PATH} insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "$(dst $IPSET_DIRECT !) -p icmp -j PSW2")
+ [ -z "${is_tproxy}" ] && \$(${MY_PATH} insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "$(dst $IPSET_DIRECT !) -p tcp -j PSW2")
- \$(${MY_PATH} insert_rule_before "$ipt_m" "PREROUTING" "mwan3" "-j PSW2")
- \$(${MY_PATH} insert_rule_before "$ipt_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT")
+ \$(${MY_PATH} insert_rule_before "$ipt_m" "PREROUTING" "mwan3" "$(dst $IPSET_DIRECT !) -j PSW2")
EOF
)
}
@@ -1035,10 +1024,9 @@ gen_include() {
$(extract_rules 6 mangle)
EOT
- [ "$accept_icmpv6" = "1" ] && $ip6t_n -A PREROUTING -p ipv6-icmp -j PSW2
+ [ "$accept_icmpv6" = "1" ] && $ip6t_n -A PREROUTING $(dst $IPSET_DIRECT6 !) -p ipv6-icmp -j PSW2
- \$(${MY_PATH} insert_rule_before "$ip6t_m" "PREROUTING" "mwan3" "-j PSW2")
- \$(${MY_PATH} insert_rule_before "$ip6t_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT")
+ \$(${MY_PATH} insert_rule_before "$ip6t_m" "PREROUTING" "mwan3" "$(dst $IPSET_DIRECT6 !) -j PSW2")
EOF
)
}
diff --git a/luci-app-passwall2/root/usr/share/passwall2/nftables.sh b/luci-app-passwall2/root/usr/share/passwall2/nftables.sh
index 7993209a..3fc0e355 100755
--- a/luci-app-passwall2/root/usr/share/passwall2/nftables.sh
+++ b/luci-app-passwall2/root/usr/share/passwall2/nftables.sh
@@ -231,7 +231,9 @@ gen_shunt_list() {
local default_outbound="redirect"
[ "$default_node" = "_direct" ] && default_outbound="direct"
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
+ local shunt_group=$(config_n_get $node shunt_group)
for shunt_id in $shunt_ids; do
+ [ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue
local shunt_node=$(config_n_get ${node} "${shunt_id}")
[ -n "$shunt_node" ] && {
local nftset_v4="psw2_${node}_${shunt_id}"
@@ -700,13 +702,13 @@ add_firewall_rule() {
for ip in $(cat /usr/share/passwall2/direct_ip | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d"); do
if [[ "$ip" == *::* ]]; then
- echo "$ip" | insert_nftset $NFTSET_DIRECT6 0
+ echo "$ip" | insert_nftset $NFTSET_DIRECT6 "-1"
elif [[ "$ip" == "geoip:"* ]]; then
local _geoip_code=$(echo $ip | awk -F ':' '{print $2}')
- get_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_DIRECT "0"
- get_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_DIRECT6 "0"
+ get_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_DIRECT "-1"
+ get_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_DIRECT6 "-1"
else
- echo "$ip" | insert_nftset $NFTSET_DIRECT 0
+ echo "$ip" | insert_nftset $NFTSET_DIRECT "-1"
fi
done
@@ -726,14 +728,14 @@ add_firewall_rule() {
update_wan_sets
[ -n "$ISP_DNS" ] && {
- echo "$ISP_DNS" | insert_nftset $NFTSET_DIRECT 0
+ echo "$ISP_DNS" | insert_nftset $NFTSET_DIRECT "-1"
for ispip in $ISP_DNS; do
log_i18n 1 "$(i18n "Add ISP %s DNS to the whitelist: %s" "IPv4" "${ispip}")"
done
}
[ -n "$ISP_DNS6" ] && {
- echo $ISP_DNS6 | insert_nftset $NFTSET_DIRECT6 0
+ echo $ISP_DNS6 | insert_nftset $NFTSET_DIRECT6 "-1"
for ispip6 in $ISP_DNS6; do
log_i18n 1 "$(i18n "Add ISP %s DNS to the whitelist: %s" "IPv6" "${ispip6}")"
done
@@ -762,11 +764,6 @@ add_firewall_rule() {
nft_output_chain="PSW2_OUTPUT_MANGLE"
fi
- nft "add chain $NFTABLE_NAME PSW2_DIVERT"
- nft "flush chain $NFTABLE_NAME PSW2_DIVERT"
- # Only TCP, UDP Invalid.
- nft "add rule $NFTABLE_NAME PSW2_DIVERT meta l4proto tcp socket transparent 1 mark set ${FWMARK} counter accept"
-
nft "add chain $NFTABLE_NAME PSW2_DNS"
nft "flush chain $NFTABLE_NAME PSW2_DNS"
if [ $(config_t_get global dns_redirect "1") = "0" ]; then
@@ -790,33 +787,29 @@ add_firewall_rule() {
#ipv4 tproxy mode and udp
nft "add chain $NFTABLE_NAME PSW2_MANGLE"
nft "flush chain $NFTABLE_NAME PSW2_MANGLE"
- nft "add rule $NFTABLE_NAME PSW2_MANGLE ip daddr @$NFTSET_DIRECT counter return"
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip daddr @$NFTSET_VPS counter return"
nft "add rule $NFTABLE_NAME PSW2_MANGLE ct direction reply counter return"
-
nft "add chain $NFTABLE_NAME PSW2_OUTPUT_MANGLE"
nft "flush chain $NFTABLE_NAME PSW2_OUTPUT_MANGLE"
- nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip daddr @$NFTSET_DIRECT counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip daddr @$NFTSET_VPS counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ct direction reply counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE meta mark 255 counter return"
# jump chains
- nft "add rule $NFTABLE_NAME mangle_prerouting counter jump PSW2_DIVERT"
- nft "add rule $NFTABLE_NAME mangle_prerouting ip protocol udp counter jump PSW2_MANGLE"
- [ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME mangle_prerouting ip protocol tcp counter jump PSW2_MANGLE"
+ # Only TCP, UDP Invalid.
+ nft "add rule $NFTABLE_NAME mangle_prerouting meta nfproto ipv4 meta l4proto tcp socket transparent 1 mark set ${FWMARK} counter accept"
+ nft "add rule $NFTABLE_NAME mangle_prerouting ip daddr != @$NFTSET_DIRECT ip protocol udp counter jump PSW2_MANGLE"
+ [ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME mangle_prerouting ip daddr != @$NFTSET_DIRECT ip protocol tcp counter jump PSW2_MANGLE"
#ipv4 tcp redirect mode
[ -z "${is_tproxy}" ] && {
nft "add chain $NFTABLE_NAME PSW2_NAT"
nft "flush chain $NFTABLE_NAME PSW2_NAT"
- nft "add rule $NFTABLE_NAME PSW2_NAT ip daddr @$NFTSET_DIRECT counter return"
nft "add rule $NFTABLE_NAME PSW2_NAT ip daddr @$NFTSET_VPS counter return"
- nft "add rule $NFTABLE_NAME dstnat ip protocol tcp counter jump PSW2_NAT"
+ nft "add rule $NFTABLE_NAME dstnat ip daddr != @$NFTSET_DIRECT ip protocol tcp counter jump PSW2_NAT"
nft "add chain $NFTABLE_NAME PSW2_OUTPUT_NAT"
nft "flush chain $NFTABLE_NAME PSW2_OUTPUT_NAT"
- nft "add rule $NFTABLE_NAME PSW2_OUTPUT_NAT ip daddr @$NFTSET_DIRECT counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_NAT ip daddr @$NFTSET_VPS counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_NAT meta mark 255 counter return"
}
@@ -825,16 +818,16 @@ add_firewall_rule() {
if [ "$accept_icmp" = "1" ]; then
nft "add chain $NFTABLE_NAME PSW2_ICMP_REDIRECT"
nft "flush chain $NFTABLE_NAME PSW2_ICMP_REDIRECT"
- nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip daddr @$NFTSET_DIRECT counter return"
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip daddr @$NFTSET_VPS counter return"
[ "$accept_icmpv6" = "1" ] && {
- nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip6 daddr @$NFTSET_DIRECT6 counter return"
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip6 daddr @$NFTSET_VPS6 counter return"
}
- nft "add rule $NFTABLE_NAME dstnat meta l4proto {icmp,icmpv6} counter jump PSW2_ICMP_REDIRECT"
- nft "add rule $NFTABLE_NAME nat_output meta l4proto {icmp,icmpv6} counter jump PSW2_ICMP_REDIRECT"
+ nft "add rule $NFTABLE_NAME dstnat ip daddr != @$NFTSET_DIRECT meta l4proto icmp counter jump PSW2_ICMP_REDIRECT"
+ nft "add rule $NFTABLE_NAME dstnat ip6 daddr != @$NFTSET_DIRECT6 meta l4proto icmpv6 counter jump PSW2_ICMP_REDIRECT"
+ nft "add rule $NFTABLE_NAME nat_output ip daddr != @$NFTSET_DIRECT meta l4proto icmp counter jump PSW2_ICMP_REDIRECT"
+ nft "add rule $NFTABLE_NAME nat_output ip6 daddr != @$NFTSET_DIRECT6 meta l4proto icmpv6 counter jump PSW2_ICMP_REDIRECT"
fi
#ipv4 wan_ip
@@ -847,13 +840,11 @@ add_firewall_rule() {
#ipv6 tproxy mode and udp
nft "add chain $NFTABLE_NAME PSW2_MANGLE_V6"
nft "flush chain $NFTABLE_NAME PSW2_MANGLE_V6"
- nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ip6 daddr @$NFTSET_DIRECT6 counter return"
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ip6 daddr @$NFTSET_VPS6 counter return"
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ct direction reply counter return"
nft "add chain $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6"
nft "flush chain $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6"
- nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip6 daddr @$NFTSET_DIRECT6 counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip6 daddr @$NFTSET_VPS6 counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ct direction reply counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta mark 255 counter return"
@@ -874,8 +865,10 @@ add_firewall_rule() {
# jump chains
[ "$PROXY_IPV6" == "1" ] && {
- nft "add rule $NFTABLE_NAME mangle_prerouting meta nfproto {ipv6} counter jump PSW2_MANGLE_V6"
- nft "add rule $NFTABLE_NAME mangle_output meta nfproto {ipv6} counter jump PSW2_OUTPUT_MANGLE_V6 comment \"PSW2_OUTPUT_MANGLE\""
+ # Only TCP, UDP Invalid.
+ nft "add rule $NFTABLE_NAME mangle_prerouting meta nfproto ipv6 meta l4proto tcp socket transparent 1 mark set ${FWMARK} counter accept"
+ nft "add rule $NFTABLE_NAME mangle_prerouting ip6 daddr != @$NFTSET_DIRECT6 meta nfproto {ipv6} counter jump PSW2_MANGLE_V6"
+ nft "add rule $NFTABLE_NAME mangle_output ip6 daddr != @$NFTSET_DIRECT6 meta nfproto {ipv6} counter jump PSW2_OUTPUT_MANGLE_V6 comment \"PSW2_OUTPUT_MANGLE\""
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ip6 daddr @$NFTSET_WAN6 counter return comment \"WAN6_IP_RETURN\""
@@ -948,11 +941,11 @@ add_firewall_rule() {
nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr $FAKE_IP ${nft_j}"
add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip daddr" "${nft_j}"
nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ${nft_j}"
- [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME nat_output ip protocol tcp counter jump PSW2_OUTPUT_NAT"
+ [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME nat_output ip daddr != @$NFTSET_DIRECT ip protocol tcp counter jump PSW2_OUTPUT_NAT"
[ -n "${is_tproxy}" ] && {
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp iif lo $(REDIRECT $REDIR_PORT TPROXY4) comment \"${comment_l}\""
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp iif lo counter return comment \"${comment_l}\""
- nft "add rule $NFTABLE_NAME mangle_output ip protocol tcp counter jump PSW2_OUTPUT_MANGLE comment \"PSW2_OUTPUT_MANGLE\""
+ nft "add rule $NFTABLE_NAME mangle_output ip daddr != @$NFTSET_DIRECT ip protocol tcp counter jump PSW2_OUTPUT_MANGLE comment \"PSW2_OUTPUT_MANGLE\""
}
[ "$PROXY_IPV6" == "1" ] && {
@@ -978,7 +971,7 @@ add_firewall_rule() {
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE"
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp iif lo $(REDIRECT $REDIR_PORT TPROXY4) comment \"${comment_l}\""
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp iif lo counter return comment \"${comment_l}\""
- nft "add rule $NFTABLE_NAME mangle_output ip protocol udp counter jump PSW2_OUTPUT_MANGLE comment \"PSW2_OUTPUT_MANGLE\""
+ nft "add rule $NFTABLE_NAME mangle_output ip daddr != @$NFTSET_DIRECT ip protocol udp counter jump PSW2_OUTPUT_MANGLE comment \"PSW2_OUTPUT_MANGLE\""
[ "$PROXY_IPV6" == "1" ] && {
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 jump PSW2_RULE"
@@ -996,11 +989,13 @@ add_firewall_rule() {
}
fi
- nft "add rule $NFTABLE_NAME mangle_output oif lo counter return comment \"PSW2_OUTPUT_MANGLE\""
- nft "add rule $NFTABLE_NAME mangle_output meta mark ${FWMARK} counter return comment \"PSW2_OUTPUT_MANGLE\""
+ nft "add rule $NFTABLE_NAME mangle_output ip daddr != @$NFTSET_DIRECT oif lo counter return comment \"PSW2_OUTPUT_MANGLE\""
+ nft "add rule $NFTABLE_NAME mangle_output ip daddr != @$NFTSET_DIRECT meta mark ${FWMARK} counter return comment \"PSW2_OUTPUT_MANGLE\""
- nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp udp dport 53 counter return"
- nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp udp dport 53 counter return"
+ nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp tcp dport 53 counter accept"
+ nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp udp dport 53 counter accept"
+ nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp tcp dport 53 counter accept"
+ nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp udp dport 53 counter accept"
}
load_acl
diff --git a/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh b/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh
index 54b8b23f..36fda212 100755
--- a/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh
+++ b/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh
@@ -126,7 +126,11 @@ test_auto_switch() {
# If the current node is not found, or if the current node is the last node, then take the first node.
[ -z "$new_node" ] && new_node="$first_node"
local msg2="$(i18n "next backup node")"
- [ "$now_node" = "$main_node" ] && msg2="$(i18n "backup node")"
+ if [ "$new_node" = "$main_node" ]; then
+ msg2="$(i18n "main node")"
+ else
+ [ "$now_node" = "$main_node" ] && msg2="$(i18n "backup node")"
+ fi
msg="$(i18n "switch to %s test detect!" "${msg2}")"
else
# When there is only one backup node, poll with the primary node.
@@ -138,11 +142,6 @@ test_auto_switch() {
log_i18n 0 "Socks switch detection: %s 【%s:[%s]】 abnormal, %s" "${id}" "$(config_n_get $now_node type)" "$(config_n_get $now_node remarks)" "${msg}"
test_node ${new_node}
if [ $? -eq 0 ]; then
-# [ "$restore_switch" = "0" ] && {
-# uci set $CONFIG.${id}.node=$new_node
-# [ -z "$(echo $b_nodes | grep $main_node)" ] && uci add_list $CONFIG.${id}.autoswitch_backup_node=$main_node
-# uci commit $CONFIG
-# }
check_process
log_i18n 0 "Socks switch detection: %s 【%s:[%s]】 normal, switch to this node!" "${id}" "$(config_n_get $new_node type)" "$(config_n_get $new_node remarks)"
$APP_FILE socks_node_switch flag=${id} new_node=${new_node}
@@ -171,6 +170,10 @@ start() {
backup_node_num=$(printf "%s\n" "$backup_node" | wc -w)
if [ "$backup_node_num" -eq 1 ]; then
[ "$main_node" = "$backup_node" ] && return
+ elif [ "$backup_node_num" -gt 1 ]; then
+ [ "$restore_switch" != "1" ] && {
+ [ -z "$(echo $backup_node | grep -F "$main_node")" ] && backup_node="${backup_node} ${main_node}"
+ }
fi
else
return
diff --git a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua
index c5f81cbf..56464045 100755
--- a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua
+++ b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua
@@ -768,6 +768,9 @@ local function parseClashNode(node, add_mode, group, sub_cfg)
result.reality_publicKey = node["reality-opts"]["public-key"]
result.reality_shortId = node["reality-opts"]["short-id"]
end
+ if node["disable-reuse"] then
+ result.anytls_disable_reuse = "1"
+ end
end
if not result.remarks or result.remarks == "" then
if result.address and result.port then
@@ -1865,7 +1868,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
end
if params.security == "tls" or params.security == "reality" then
result.tls = "1"
- result.tls_serverName = params.sni
+ result.tls_serverName = params.sni or params.peer
result.alpn = params.alpn
if params.fp and params.fp ~= "" then
result.utls = "1"