update 2026-10-31 18:07:25

This commit is contained in:
action committed 2026-10-31 18:07:25 +08:00
1 parent 6ce64f7ba2
commit 04b58d28a1
39 files changed
+89 -91

No files matched your search

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 640 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 547 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 KiB

@@ -886,17 +886,17 @@ function read_rulelist()
end end
local backup_files = { local backup_files = {
"/etc/config/passwall", "/etc/config/passwall",
"/etc/config/passwall_server", "/etc/config/passwall_server",
"/etc/passwall/rules/block_host", "/etc/passwall/rules/block_host",
"/etc/passwall/rules/block_ip", "/etc/passwall/rules/block_ip",
"/etc/passwall/rules/direct_host", "/etc/passwall/rules/direct_host",
"/etc/passwall/rules/direct_ip", "/etc/passwall/rules/direct_ip",
"/etc/passwall/rules/proxy_host", "/etc/passwall/rules/proxy_host",
"/etc/passwall/rules/proxy_ip", "/etc/passwall/rules/proxy_ip",
"/etc/passwall/rules/lanlist_ipv4", "/etc/passwall/rules/lanlist_ipv4",
"/etc/passwall/rules/lanlist_ipv6", "/etc/passwall/rules/lanlist_ipv6",
"/etc/passwall/rules/domains_excluded" "/etc/passwall/rules/domains_excluded"
} }
function create_backup() function create_backup()
@@ -119,7 +119,7 @@ o.rawhtml = true
o.cfgvalue = function(self, section) o.cfgvalue = function(self, section)
return string.format([[ return string.format([[
<input type="button" class="btn cbi-button cbi-button-apply" onclick="ManualSubscribeAll()" value="%s" />]], <input type="button" class="btn cbi-button cbi-button-apply" onclick="ManualSubscribeAll()" value="%s" />]],
translate("Manual subscription All")) translate("Manual subscription All"))
end end
s = m:section(TypedSection, "subscribe_list", "", "<font color='red'>" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "</font>") s = m:section(TypedSection, "subscribe_list", "", "<font color='red'>" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "</font>")
@@ -68,9 +68,9 @@ o.validate = port_validate
---- UDP No Redir Ports ---- UDP No Redir Ports
o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"), o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"),
"<font color='red'>" .. translate( "<font color='red'>" .. translate(
"Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") .. "Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") ..
"</font>") "</font>")
o.default = "disable" o.default = "disable"
o:value("disable", translate("No patterns are used")) o:value("disable", translate("No patterns are used"))
o:value("1:65535", translate("All")) o:value("1:65535", translate("All"))
@@ -18,7 +18,7 @@ s.type_name = type_name
s.option_prefix = "socks_" s.option_prefix = "socks_"
api.set_type_cbi(s) api.set_type_cbi(s)
o = s:option(ListValue, "del_protocol", "¡¡") --ʼÖÕÒþ²Ø£¬ÓÃÓÚɾ³ý protocol o = s:option(ListValue, "del_protocol", " ") --始终隐藏,用于删除 protocol
o:depends({ __hide = "1" }) o:depends({ __hide = "1" })
o.rewrite_option = "protocol" o.rewrite_option = "protocol"
@@ -2178,7 +2178,7 @@ function gen_config(var)
local remote_dns_server = api.clone(remote_server) local remote_dns_server = api.clone(remote_server)
remote_dns_server.tag = value.shunt_tag remote_dns_server.tag = value.shunt_tag
local is_local = (remote_server.address and api.is_local_ip(remote_server.address)) or local is_local = (remote_server.address and api.is_local_ip(remote_server.address)) or
(remote_server.server and api.is_local_ip(remote_server.server)) --dns为本地ip,不走代理 (remote_server.server and api.is_local_ip(remote_server.server)) --dns为本地ip,不走代理
remote_dns_server.detour = is_local and "direct" or value.outboundTag remote_dns_server.detour = is_local and "direct" or value.outboundTag
table.insert(dns.servers, remote_dns_server) table.insert(dns.servers, remote_dns_server)
dns_rule.server = remote_dns_server.tag dns_rule.server = remote_dns_server.tag
@@ -175,7 +175,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -169,7 +169,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -125,7 +125,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -137,7 +137,7 @@ local dropdown_data = {
</select> </select>
</div> </div>
<!-- 隐藏 input(保存实际配置值) --> <!-- 隐藏 input(保存实际配置值) -->
<input type="text" id="<%=cbid%>" name="<%=cbid%>" value="<%=current_key%>" data-update="change" style="display:none !important;" /> <input type="text" id="<%=cbid%>" name="<%=cbid%>" value="<%=current_key%>" data-update="change" style="display:none !important;" />
<!-- 模拟 ListValue 控件外观 --> <!-- 模拟 ListValue 控件外观 -->
<div class="cbi-input-value cbi-input-select v-dropdown-display" id="<%=cbid%>.display" tabindex="0"> <div class="cbi-input-value cbi-input-select v-dropdown-display" id="<%=cbid%>.display" tabindex="0">
<span id="<%=cbid%>.label" class="v-dropdown-label" title="<%=pcdata(current_label)%>"> <span id="<%=cbid%>.label" class="v-dropdown-label" title="<%=pcdata(current_label)%>">
@@ -164,7 +164,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -5,11 +5,11 @@ local appname = map.config
local sid = "@global[0]" local sid = "@global[0]"
-%> -%>
<style> <style>
#cbi-<%=appname%>-socks .td.cbi-value-field > div { #cbi-<%=appname%>-socks .td.cbi-value-field > div {
white-space: nowrap; white-space: nowrap;
} }
@media (max-width: 1152px) { @media (max-width: 1152px) {
#cbi-<%=appname%>-socks .td.cbi-value-field > div { #cbi-<%=appname%>-socks .td.cbi-value-field > div {
white-space: normal; white-space: normal;
} }
} }
@@ -187,7 +187,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script> <script>
//<![CDATA[ //<![CDATA[
var imgs = document.getElementsByTagName('img'); var imgs = document.getElementsByTagName('img');
@@ -133,7 +133,7 @@ local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
var checkBoxList = []; var checkBoxList = [];
var len = domList.length; var len = domList.length;
while(len--) { while(len--) {
var dom = domList[len];   var dom = domList[len];
if(dom.type == 'checkbox' && dom.checked) { if(dom.type == 'checkbox' && dom.checked) {
checkBoxList.push(dom.name); checkBoxList.push(dom.name);
} }
@@ -162,7 +162,7 @@ local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
var checkBoxList = []; var checkBoxList = [];
var len = domList.length; var len = domList.length;
while(len--) { while(len--) {
var dom = domList[len];   var dom = domList[len];
if(dom.type == 'checkbox' && dom.checked) { if(dom.type == 'checkbox' && dom.checked) {
if(type == 'geoip' && (dom.name === 'chnroute' || dom.name === 'chnroute6')) { if(type == 'geoip' && (dom.name === 'chnroute' || dom.name === 'chnroute6')) {
checkBoxList.push(dom.name); checkBoxList.push(dom.name);
@@ -2,7 +2,7 @@
if [ -e "/etc/config/ucitrack" ]; then if [ -e "/etc/config/ucitrack" ]; then
uci -q batch <<-EOF uci -q batch <<-EOF
delete ucitrack.@passwall[-1] delete ucitrack.@passwall[-1]
add ucitrack passwall add ucitrack passwall
set ucitrack.@passwall[-1].init=passwall set ucitrack.@passwall[-1].init=passwall
commit ucitrack commit ucitrack
@@ -1088,7 +1088,7 @@ start_dns() {
local ACL_RULE_DNSMASQ=0 local ACL_RULE_DNSMASQ=0
for acl_section in $(uci show ${CONFIG} | grep "=acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do for acl_section in $(uci show ${CONFIG} | grep "=acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
if [ "$(config_n_get $acl_section enabled)" = "1" ] && \ if [ "$(config_n_get $acl_section enabled)" = "1" ] && \
[ "$(config_n_get $acl_section dns_shunt)" = "dnsmasq" ]; then [ "$(config_n_get $acl_section dns_shunt)" = "dnsmasq" ]; then
ACL_RULE_DNSMASQ=1 ACL_RULE_DNSMASQ=1
break break
fi fi
@@ -172,9 +172,7 @@ local auto_config_lines = {}
-- 直连规则显式覆盖远程兜底的缓存、IPv6、测速和双栈优选设置。 -- 直连规则显式覆盖远程兜底的缓存、IPv6、测速和双栈优选设置。
local DIRECT_RULE_OPTIONS = " -enable-cache -address -6 -speed-check-mode ping,tcp:80,tcp:443 -response-mode first-ping -d yes" local DIRECT_RULE_OPTIONS = " -enable-cache -address -6 -speed-check-mode ping,tcp:80,tcp:443 -response-mode first-ping -d yes"
--设置默认 DNS 分组(兜底组),全局代理模式仍使用远程组。 --设置默认 DNS 分组(兜底组),全局代理模式仍使用远程组。
local DEFAULT_DNS_GROUP = (USE_DEFAULT_DNS == "direct" and "direct") or local DEFAULT_DNS_GROUP = (USE_DEFAULT_DNS == "direct" and "direct") or (USE_DEFAULT_DNS == "remote" and "proxy") or (USE_DEFAULT_DNS == "auto" and AUTO_GROUP)
(USE_DEFAULT_DNS == "remote" and "proxy") or
(USE_DEFAULT_DNS == "auto" and AUTO_GROUP)
local only_global = (DEFAULT_PROXY_MODE == "proxy" and CHN_LIST == "0" and USE_GFW_LIST == "0") and 1 local only_global = (DEFAULT_PROXY_MODE == "proxy" and CHN_LIST == "0" and USE_GFW_LIST == "0") and 1
if only_global == 1 then if only_global == 1 then
DEFAULT_DNS_GROUP = "proxy" DEFAULT_DNS_GROUP = "proxy"
@@ -197,20 +197,20 @@ insert_nftset() {
RS = "[ \t\n\r]+" RS = "[ \t\n\r]+"
ORS = "" ORS = ""
} }
$0 != "" { $0 != "" {
if (!first) { if (!first) {
printf "add element %s %s { \n", t, n printf "add element %s %s { \n", t, n
first = 1 first = 1
} else { } else {
print ",\n" print ",\n"
} }
printf " %s", $0 printf " %s", $0
} }
END { END {
if (first) { if (first) {
print "\n }\n" print "\n }\n"
} }
}' | nft -f - }' | nft -f -
} }
gen_nftset() { gen_nftset() {
@@ -1502,7 +1502,7 @@ add_firewall_rule() {
del_firewall_rule() { del_firewall_rule() {
for nft in "dstnat" "srcnat" "nat_output" "mangle_prerouting" "mangle_output"; do for nft in "dstnat" "srcnat" "nat_output" "mangle_prerouting" "mangle_output"; do
local handles=$(nft -a list chain $NFTABLE_NAME ${nft} 2>/dev/null | grep -E "PSW_" | awk -F '# handle ' '{print$2}') local handles=$(nft -a list chain $NFTABLE_NAME ${nft} 2>/dev/null | grep -E "PSW_" | awk -F '# handle ' '{print$2}')
for handle in $handles; do for handle in $handles; do
nft delete rule $NFTABLE_NAME ${nft} handle ${handle} 2>/dev/null nft delete rule $NFTABLE_NAME ${nft} handle ${handle} 2>/dev/null
done done
@@ -114,7 +114,7 @@ o.rawhtml = true
o.cfgvalue = function(self, section) o.cfgvalue = function(self, section)
return string.format([[ return string.format([[
<input type="button" class="btn cbi-button cbi-button-apply" onclick="ManualSubscribeAll()" value="%s" />]], <input type="button" class="btn cbi-button cbi-button-apply" onclick="ManualSubscribeAll()" value="%s" />]],
translate("Manual subscription All")) translate("Manual subscription All"))
end end
s = m:section(TypedSection, "subscribe_list", "", "<font color='red'>" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "</font>") s = m:section(TypedSection, "subscribe_list", "", "<font color='red'>" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "</font>")
@@ -19,13 +19,13 @@ m.description = (m.description or "") .. [[
<style> <style>
/* Scope to passwall2 CBI fields so it won't leak elsewhere */ /* Scope to passwall2 CBI fields so it won't leak elsewhere */
div[id^="cbid.passwall2."] .cbi-value-field { div[id^="cbid.passwall2."] .cbi-value-field {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 1em; gap: 1em;
} }
div[id^="cbid.passwall2."] .cbi-checkbox { div[id^="cbid.passwall2."] .cbi-checkbox {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
} }
</style> </style>
]] ]]
@@ -982,7 +982,7 @@ function gen_config(var)
local routing = nil local routing = nil
local observatory = nil local observatory = nil
local burstObservatory = nil local burstObservatory = nil
local strategy = nil local strategy = nil
local COMMON = {} local COMMON = {}
local CACHE_TEXT_FILE = CACHE_PATH .. "/cache_" .. flag .. ".txt" local CACHE_TEXT_FILE = CACHE_PATH .. "/cache_" .. flag .. ".txt"
@@ -175,7 +175,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -169,7 +169,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -125,7 +125,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -137,7 +137,7 @@ local dropdown_data = {
</select> </select>
</div> </div>
<!-- 隐藏 input(保存实际配置值) --> <!-- 隐藏 input(保存实际配置值) -->
<input type="text" id="<%=cbid%>" name="<%=cbid%>" value="<%=current_key%>" data-update="change" style="display:none !important;" /> <input type="text" id="<%=cbid%>" name="<%=cbid%>" value="<%=current_key%>" data-update="change" style="display:none !important;" />
<!-- 模拟 ListValue 控件外观 --> <!-- 模拟 ListValue 控件外观 -->
<div class="cbi-input-value cbi-input-select v-dropdown-display" id="<%=cbid%>.display" tabindex="0"> <div class="cbi-input-value cbi-input-select v-dropdown-display" id="<%=cbid%>.display" tabindex="0">
<span id="<%=cbid%>.label" class="v-dropdown-label" title="<%=pcdata(current_label)%>"> <span id="<%=cbid%>.label" class="v-dropdown-label" title="<%=pcdata(current_label)%>">
@@ -164,7 +164,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -4,25 +4,25 @@ local api = map.api
-%> -%>
<style> <style>
.dns-con { .dns-con {
padding: 1rem; padding: 1rem;
} }
.faq-title { .faq-title {
color: var(--primary); color: var(--primary);
font-weight: bolder; font-weight: bolder;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
display: inline-block; display: inline-block;
} }
.reset-title { .reset-title {
color: var(--primary); color: var(--primary);
font-weight: bolder; font-weight: bolder;
margin-bottom: 0.3rem; margin-bottom: 0.3rem;
display: inline-block; display: inline-block;
margin-top: 1.2rem; margin-top: 1.2rem;
text-decoration: underline; text-decoration: underline;
} }
.dns-item { .dns-item {
margin-bottom: 0.8rem; margin-bottom: 0.8rem;
line-height:1.2rem; line-height:1.2rem;
} }
.dns-list { .dns-list {
text-indent:1rem; text-indent:1rem;
@@ -5,11 +5,11 @@ local appname = map.config
local sid = "@global[0]" local sid = "@global[0]"
-%> -%>
<style> <style>
#cbi-<%=appname%>-socks .td.cbi-value-field > div { #cbi-<%=appname%>-socks .td.cbi-value-field > div {
white-space: nowrap; white-space: nowrap;
} }
@media (max-width: 1152px) { @media (max-width: 1152px) {
#cbi-<%=appname%>-socks .td.cbi-value-field > div { #cbi-<%=appname%>-socks .td.cbi-value-field > div {
white-space: normal; white-space: normal;
} }
} }
@@ -132,7 +132,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script> <script>
//<![CDATA[ //<![CDATA[
var imgs = document.getElementsByTagName('img'); var imgs = document.getElementsByTagName('img');
@@ -87,9 +87,9 @@ local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
var checkBoxList = []; var checkBoxList = [];
var len = domList.length; var len = domList.length;
while(len--) { while(len--) {
var dom = domList[len];   var dom = domList[len];
if(dom.type == 'checkbox' && dom.checked) {   if(dom.type == 'checkbox' && dom.checked) {
checkBoxList.push(dom.name);   checkBoxList.push(dom.name);
} }
} }
XHR.get('<%=api.url("update_rules")%>', { XHR.get('<%=api.url("update_rules")%>', {
@@ -2,7 +2,7 @@
if [ -e "/etc/config/ucitrack" ]; then if [ -e "/etc/config/ucitrack" ]; then
uci -q batch <<-EOF uci -q batch <<-EOF
delete ucitrack.@passwall2[-1] delete ucitrack.@passwall2[-1]
add ucitrack passwall2 add ucitrack passwall2
set ucitrack.@passwall2[-1].init=passwall2 set ucitrack.@passwall2[-1].init=passwall2
commit ucitrack commit ucitrack
@@ -157,20 +157,20 @@ insert_nftset() {
RS = "[ \t\n\r]+" RS = "[ \t\n\r]+"
ORS = "" ORS = ""
} }
$0 != "" { $0 != "" {
if (!first) { if (!first) {
printf "add element %s %s { \n", t, n printf "add element %s %s { \n", t, n
first = 1 first = 1
} else { } else {
print ",\n" print ",\n"
} }
printf " %s", $0 printf " %s", $0
} }
END { END {
if (first) { if (first) {
print "\n }\n" print "\n }\n"
} }
}' | nft -f - }' | nft -f -
} }
gen_nftset() { gen_nftset() {