From 6ceff0781d9c09110b8f82b6867c02ff66870157 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 10 Aug 2026 20:58:00 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=84=20Sync=202026-08-10=2020:58:00?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dae/Makefile | 4 +- daed/Makefile | 4 +- .../luci-static/resources/view/fchomo/node.js | 10 +- .../99_luci-app-fchomo-migration_node | 8 + .../root/usr/share/fchomo/generate_client.uc | 4 +- luci-app-modeminfo/Makefile | 2 +- luci-app-modeminfo/README.md | 4 +- luci-app-passwall/Makefile | 2 +- .../model/cbi/passwall/client/acl_config.lua | 13 - .../model/cbi/passwall/client/global.lua | 9 - .../passwall/client/node_subscribe_config.lua | 6 + .../model/cbi/passwall/client/shunt_rules.lua | 13 - .../model/cbi/passwall/client/type/ray.lua | 10 +- .../cbi/passwall/client/type/sing-box.lua | 10 +- .../model/cbi/passwall/server/type/ray.lua | 9 - luci-app-passwall/luasrc/passwall/api.lua | 39 ++- luci-app-passwall/po/zh-cn/passwall.po | 3 + .../usr/share/passwall/clash_subconverter.lua | 2 +- .../root/usr/share/passwall/subscribe.lua | 29 ++- luci-app-passwall2/Makefile | 2 +- .../model/cbi/passwall2/client/global.lua | 13 - luci-app-passwall2/luasrc/passwall2/api.lua | 5 +- .../luasrc/passwall2/util_sing-box.lua | 238 ++++-------------- .../luasrc/passwall2/util_xray.lua | 179 ------------- luci-app-passwall2/po/fa/passwall2.po | 6 - luci-app-passwall2/po/ru/passwall2.po | 6 - luci-app-passwall2/po/zh-cn/passwall2.po | 6 - luci-app-passwall2/po/zh-tw/passwall2.po | 6 - .../root/usr/share/passwall2/app.sh | 48 +--- luci-theme-footstrap/Makefile | 2 +- .../htdocs/luci-static/resources/fs-router.js | 40 +++ .../styles/pages/70-syslog.css | 43 ++-- modeminfo/Makefile | 4 +- modeminfo/root/usr/share/modeminfo/modem.list | 3 + .../share/modeminfo/scripts/QUALCOMM_LM960 | 73 ++++++ .../share/modeminfo/scripts/QUALCOMM_LM960.at | 10 + natflow/Makefile | 4 +- 37 files changed, 318 insertions(+), 551 deletions(-) create mode 100644 modeminfo/root/usr/share/modeminfo/scripts/QUALCOMM_LM960 create mode 100644 modeminfo/root/usr/share/modeminfo/scripts/QUALCOMM_LM960.at diff --git a/dae/Makefile b/dae/Makefile index 0188e0ca..6805bff6 100644 --- a/dae/Makefile +++ b/dae/Makefile @@ -6,9 +6,9 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dae PKG_VERSION:=2026.08.05 -PKG_RELEASE:=33 +PKG_RELEASE:=34 -PKG_SOURCE:=dae-src-2026.08.05-479f43645df5.tar.gz +PKG_SOURCE:=dae-src-2026.08.05-fc1a5bf558fd.tar.gz PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_HASH:=skip diff --git a/daed/Makefile b/daed/Makefile index fa2dd429..0baabf94 100644 --- a/daed/Makefile +++ b/daed/Makefile @@ -6,9 +6,9 @@ include $(TOPDIR)/rules.mk PKG_NAME:=daed PKG_VERSION:=2026.08.05 -PKG_RELEASE:=44 +PKG_RELEASE:=45 -PKG_SOURCE:=daed-src-2026.08.05-c389546b8c1f.tar.gz +PKG_SOURCE:=daed-src-2026.08.05-1d87c2949acc.tar.gz PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_HASH:=skip diff --git a/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js b/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js index 193a7360..8126f133 100644 --- a/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js +++ b/luci-app-fchomo/htdocs/luci-static/resources/view/fchomo/node.js @@ -1048,6 +1048,15 @@ return view.extend({ so.depends({type: /^(zerotier|wireguard|masque|openvpn)$/}); so.modalonly = true; + so = ss.taboption('field_general', form.ListValue, 'ipstack_congestion_controller', _('IP stack') + ': ' + _('Congestion controller')); + so.value('', _('Keep default')); + so.value('cubic', _('cubic')); + so.value('reno', _('reno')); + so.value('bbr', _('bbr')); + so.value('bbr3', _('bbr3')); + so.depends({ipstack: /^(auto|mips)$/}); // not empty not gvisor + so.modalonly = true; + so = ss.taboption('field_general', form.ListValue, 'congestion_controller', _('Congestion controller')); so.default = hm.congestion_controller[0][0]; hm.congestion_controller.forEach((res) => { @@ -1055,7 +1064,6 @@ return view.extend({ }) so.depends({type: /^(tuic|shadowquic|trusttunnel)$/}); so.depends({type: 'masque', masque_network: /^(|h3-l4proxy)$/}); - so.depends({ipstack: /^(auto|mips)$/}); // not empty not gvisor so.modalonly = true; so = ss.taboption('field_general', form.ListValue, 'bbr_profile', _('BBR profile')); diff --git a/luci-app-fchomo/root/etc/uci-defaults/99_luci-app-fchomo-migration_node b/luci-app-fchomo/root/etc/uci-defaults/99_luci-app-fchomo-migration_node index 078a2c78..a9485d1e 100755 --- a/luci-app-fchomo/root/etc/uci-defaults/99_luci-app-fchomo-migration_node +++ b/luci-app-fchomo/root/etc/uci-defaults/99_luci-app-fchomo-migration_node @@ -171,6 +171,14 @@ migrate() { uci_remove "$CONF" "$1" zerotier_ipstack uci_set "$CONF" "$1" ipstack "$zerotier_ipstack" fi + + # congestion_controller -> ipstack_congestion_controller + if isDefined "$1" congestion_controller && (isDefined "$1" zerotier_ipstack || isDefined "$1" ipstack); then + local congestion_controller + config_get congestion_controller "$1" congestion_controller "" + uci_remove "$CONF" "$1" congestion_controller + uci_set "$CONF" "$1" ipstack_congestion_controller "$congestion_controller" + fi } config_foreach migrate node diff --git a/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc b/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc index 7d6b96af..60442838 100644 --- a/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc +++ b/luci-app-fchomo/root/usr/share/fchomo/generate_client.uc @@ -678,12 +678,12 @@ uci.foreach(uciconf, ucinode, (cfg) => { /* Extra fields */ "ip-stack": cfg.ipstack ? { mode: cfg.ipstack, - "congestion-controller": replace(cfg.congestion_controller, 'new_reno', 'reno') + "congestion-controller": cfg.ipstack_congestion_controller } : null, "udp-over-stream": strToBool(cfg.shadowquic_udp_over_stream || cfg.tuic_udp_over_stream), "heartbeat-interval": strToInt(cfg.tuic_heartbeat) || null, "keep-alive-interval": strToInt(cfg.shadowquic_heartbeat) || null, - "congestion-controller": cfg.type in ['zerotier', 'wireguard', 'masque', 'openvpn'] ? null : cfg.congestion_controller, + "congestion-controller": cfg.congestion_controller, "bbr-profile": cfg.bbr_profile, "max-open-streams": strToInt(cfg.max_open_streams) || null, diff --git a/luci-app-modeminfo/Makefile b/luci-app-modeminfo/Makefile index b5bb013e..375e9394 100644 --- a/luci-app-modeminfo/Makefile +++ b/luci-app-modeminfo/Makefile @@ -4,7 +4,7 @@ LUCI_TITLE:=Information dashboard for 3G/LTE dongle LUCI_DEPENDS:=+modeminfo PKG_LICENSE:=GPLv3 PKG_VERSION:=0.4.8 -PKG_RELEASE:=11 +PKG_RELEASE:=12 include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-app-modeminfo/README.md b/luci-app-modeminfo/README.md index ed85080f..fd0f9411 100644 --- a/luci-app-modeminfo/README.md +++ b/luci-app-modeminfo/README.md @@ -16,7 +16,7 @@ Supported devices: - Sierra Wireless EM7455/EM9191 - - HP LT4220 + - Telit LN940(HP LT4220)/LM960 - Dell DW5821e/DW5829e @@ -43,7 +43,7 @@ Supported devices: |modeminfo |common files | |modeminfo-qmi |Qualcomm MSM Interface support | |modeminfo-serial-quectel |Quectel modems support | -|modeminfo-serial-telit |Telit LN940 (HP LT4220) modem support | +|modeminfo-serial-telit |Telit LN940(HP LT4220)/LM960 modem support | |modeminfo-serial-huawei |Huawei MU709/ME909/E3372(stick mode, LTE only) modems support| |modeminfo-serial-sierra |Sierra EM7455/EM9191 modem support | |modeminfo-serial-simcom |SimCOM modems support | diff --git a/luci-app-passwall/Makefile b/luci-app-passwall/Makefile index fed4d100..aa7b2245 100644 --- a/luci-app-passwall/Makefile +++ b/luci-app-passwall/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=26.8.1 -PKG_RELEASE:=211 +PKG_RELEASE:=212 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua index fec29453..9eec259b 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua @@ -49,18 +49,6 @@ m.uci:foreach(appname, "socks", function(s) end end) - -local dynamicList_write = function(self, section, value) - local new_t = {} - if type(value) == "table" then - new_t = api.table_remove_duplicates(value) - else - new_t = { value } - end - local new_val = table.concat(new_t, " ") - return DynamicList.write(self, section, new_val) -end - -- [[ ACLs Settings ]]-- s = m:section(NamedSection, cfgid, translate("ACLs"), translate("ACLs")) s.addremove = false @@ -173,7 +161,6 @@ sources.validate = function(self, value, t) return value end -sources.write = dynamicList_write o = s:option(ListValue, "mode", translate("Mode")) o:value("0", translate("No Proxy")) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua index 1cc2b268..5b436eaf 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -372,15 +372,6 @@ if api.is_finded("smartdns") then o.cfgvalue = function(self, section) return m:get(section, self.option) or {"tcp://1.1.1.1"} end - function o.write(self, section, value) - local new_t = {} - if type(value) == "table" then - new_t = api.table_remove_duplicates(value) - else - new_t = { value } - end - return DynamicList.write(self, section, new_t) - end end o = s:taboption("DNS", ListValue, "xray_dns_mode", translate("Remote DNS") .. " " .. translate("Request protocol")) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua index aa8215bc..d980fc17 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua @@ -156,6 +156,12 @@ o:value("UseIPv6v4", translate("Prefer IPv6")) o:value("UseIPv4", translate("IPv4 Only")) o:value("UseIPv6", translate("IPv6 Only")) +o = s:option(Flag, "allowInsecure", translate("allowInsecure")) +o.default = "0" +o.rmempty = false +o.description = translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped.") .. "
" .. + translate("Used when the node link does not include this parameter.") + o = s:option(ListValue, "filter_keyword_mode", translate("Filter keyword Mode")) o.default = "5" o:value("0", translate("Close")) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua index a02db5f6..6395451c 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua @@ -164,19 +164,6 @@ source.validate = function(self, value, t) return value end -local dynamicList_write = function(self, section, value) - local new_t = {} - if type(value) == "table" then - new_t = api.table_remove_duplicates(value) - else - new_t = { value } - end - local new_val = table.concat(new_t, " ") - return DynamicList.write(self, section, new_val) -end - -source.write = dynamicList_write - --[[ -- Too low usage rate, hidden sourcePort = s:option(Value, "sourcePort", translate("Source port")) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua index ab44838c..1ca41493 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua @@ -116,12 +116,12 @@ if load_balancing_options then -- [[ Load balancing Start ]] end end -- 读取旧 DynamicList - function o.cfgvalue(self, section) - return m.uci:get_list(appname, section, "balancing_node") or {} + function o.custom_cfgvalue(self, section) + return table.concat(m:get(section, "balancing_node") or {}, " ") end -- 写入保持 DynamicList function o.custom_write(self, section, value) - local old = m.uci:get_list(appname, section, "balancing_node") or {} + local old = m:get(section, "balancing_node") or {} local new, set = {}, {} for v in value:gmatch("%S+") do new[#new + 1] = v @@ -129,13 +129,13 @@ if load_balancing_options then -- [[ Load balancing Start ]] end for _, v in ipairs(old) do if not set[v] then - m.uci:set_list(appname, section, "balancing_node", new) + m:set(section, "balancing_node", new) return end set[v] = nil end for _ in pairs(set) do - m.uci:set_list(appname, section, "balancing_node", new) + m:set(section, "balancing_node", new) return end end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua index 7bcce0ba..61830237 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua @@ -115,12 +115,12 @@ if load_urltest_options then -- [[ URLTest Start ]] end end -- 读取旧 DynamicList - function o.cfgvalue(self, section) - return m.uci:get_list(appname, section, "urltest_node") or {} + function o.custom_cfgvalue(self, section) + return table.concat(m:get(section, "urltest_node") or {}, " ") end -- 写入保持 DynamicList function o.custom_write(self, section, value) - local old = m.uci:get_list(appname, section, "urltest_node") or {} + local old = m:get(section, "urltest_node") or {} local new, set = {}, {} for v in value:gmatch("%S+") do new[#new + 1] = v @@ -128,13 +128,13 @@ if load_urltest_options then -- [[ URLTest Start ]] end for _, v in ipairs(old) do if not set[v] then - m.uci:set_list(appname, section, "urltest_node", new) + m:set(section, "urltest_node", new) return end set[v] = nil end for _ in pairs(set) do - m.uci:set_list(appname, section, "urltest_node", new) + m:set(section, "urltest_node", new) return end end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ray.lua index ee7a72bc..e97a5379 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ray.lua @@ -216,15 +216,6 @@ o:depends({ [_n("reality")] = true }) o = s:option(DynamicList, _n("reality_serverNames"), translate("serverNames")) o:depends({ [_n("reality")] = true }) -function o.custom_write(self, section, value) - local new_t = {} - if type(value) == "table" then - new_t = api.table_remove_duplicates(value) - else - new_t = { value } - end - m:set(section, self.option:sub(1 + #option_prefix), new_t) -end o = s:option(ListValue, _n("alpn"), translate("alpn")) o.default = "default" diff --git a/luci-app-passwall/luasrc/passwall/api.lua b/luci-app-passwall/luasrc/passwall/api.lua index d026127d..6193e1f9 100644 --- a/luci-app-passwall/luasrc/passwall/api.lua +++ b/luci-app-passwall/luasrc/passwall/api.lua @@ -1014,7 +1014,6 @@ local default_file_tree = { } local function get_api_json(url) - local jsonc = require "luci.jsonc" local gh_proxy = uci_get_type("global_app", "github_proxy", "0") local return_code, content if gh_proxy == "1" then @@ -1345,6 +1344,25 @@ function set_default_cbi() self.template = appname .. "/cbi/tvalue" end end + if true then + --DynamicList + local DynamicList = cbi.DynamicList + function DynamicList.write(self, section, value) + local new_t = {} + if type(value) == "table" then + new_t = table_remove_duplicates(value) + else + new_t = { value } + end + local new_val + if self.cast == "string" then + new_val = table.concat(new_t, " ") + else + new_val = new_t + end + return cbi.AbstractValue.write(self, section, new_val) + end + end end function return_map(map) @@ -1369,6 +1387,7 @@ function return_map(map) end function luci_types(id, m, s, type_name, option_prefix) + local cbi = require "luci.cbi" local fv_type local field_type = s.fields["type"] if field_type then @@ -1406,11 +1425,25 @@ function luci_types(id, m, s, type_name, option_prefix) if self.custom_write then self:custom_write(section, value) else + local new_val = value + if util.instanceof(self, cbi.DynamicList) then + local new_t = {} + if type(value) == "table" then + new_t = table_remove_duplicates(value) + else + new_t = { value } + end + if self.cast == "string" then + new_val = table.concat(new_t, " ") + else + new_val = new_t + end + end if self.rewrite_option then - m:set(section, self.rewrite_option, value) + m:set(section, self.rewrite_option, new_val) else if self.option:find(option_prefix) == 1 then - m:set(section, self.option:sub(1 + #option_prefix), value) + m:set(section, self.option:sub(1 + #option_prefix), new_val) end end end diff --git a/luci-app-passwall/po/zh-cn/passwall.po b/luci-app-passwall/po/zh-cn/passwall.po index 89c5c558..72d7b95a 100644 --- a/luci-app-passwall/po/zh-cn/passwall.po +++ b/luci-app-passwall/po/zh-cn/passwall.po @@ -1283,6 +1283,9 @@ msgstr "使用全局配置" msgid "User-Agent" msgstr "用户代理(User-Agent)" +msgid "Used when the node link does not include this parameter." +msgstr "当节点链接未包含该参数时,将使用此设置。" + msgid "Add" msgstr "添加" diff --git a/luci-app-passwall/root/usr/share/passwall/clash_subconverter.lua b/luci-app-passwall/root/usr/share/passwall/clash_subconverter.lua index fd85c367..285072b8 100644 --- a/luci-app-passwall/root/usr/share/passwall/clash_subconverter.lua +++ b/luci-app-passwall/root/usr/share/passwall/clash_subconverter.lua @@ -220,7 +220,7 @@ local function encode_vless(node) local link = "vless://" .. node.uuid .. "@" .. o.server .. ":" .. o.port local p = {} - if node.flow then table.insert(p, "flow=" .. urlencode(node.flow)) end + if type(node.flow) == "string" and node.flow:sub(1, 5) == "xtls-" then table.insert(p, "flow=" .. urlencode(node.flow)) end if node.encryption then table.insert(p, "encryption=" .. urlencode(node.encryption)) end -- TLS diff --git a/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/luci-app-passwall/root/usr/share/passwall/subscribe.lua index fa6924ab..842a025d 100755 --- a/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -29,6 +29,7 @@ local has_ssr = api.is_finded("ssr-local") and api.is_finded("ssr-redir") local has_singbox = api.finded_com("sing-box") local has_xray = api.finded_com("xray") local has_hysteria2 = api.finded_com("hysteria") +local DEFAULT_ALLOWINSECURE = true local DEFAULT_FILTER_KEYWORD_MODE = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0" local DEFAULT_FILTER_KEYWORD_DISCARD_LIST = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {} local DEFAULT_FILTER_KEYWORD_KEEP_LIST = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {} @@ -516,6 +517,7 @@ end -- 处理数据 local function processData(szType, content, add_mode, group, sub_cfg) --log(2, content, add_mode, group) + local sub_allowinsecure = DEFAULT_ALLOWINSECURE local sub_ss_type = DEFAULT_SS_TYPE local sub_trojan_type = DEFAULT_TROJAN_TYPE local sub_vmess_type = DEFAULT_VMESS_TYPE @@ -523,6 +525,9 @@ local function processData(szType, content, add_mode, group, sub_cfg) local sub_hysteria2_type = DEFAULT_HYSTERIA2_TYPE local sub_hy_up_mbps, sub_hy_down_mbps = 1000, 1000 if sub_cfg then + if sub_cfg.allowInsecure and sub_cfg.allowInsecure ~= "1" then + sub_allowinsecure = nil + end local ss_type = sub_cfg.ss_type or "global" if ss_type ~= "global" and core_has[ss_type] then sub_ss_type = ss_type @@ -695,7 +700,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) result.tls_serverName = (info.sni and info.sni ~= "") and info.sni or info.host result.tls_pinSHA256 = info.pcs result.tls_CertByName = info.vcn - result.tls_allowInsecure = info.allowinsecure or info.allowInsecure or info.insecure + local insecure = info.allowinsecure or info.allowInsecure or info.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") else result.tls = "0" end @@ -971,7 +977,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) result.reality_mldsa65Verify = params.pqv or nil end end - result.tls_allowInsecure = params.allowinsecure or params.allowInsecure or params.insecure + local insecure = params.allowinsecure or params.allowInsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") result.uot = params.udp else result.error_msg = "请更换 Xray 或 Sing-Box 来支持 SS 更多的传输方式。" @@ -1089,7 +1096,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) end result.tls_pinSHA256 = params.pcs result.tls_CertByName = params.vcn - result.tls_allowInsecure = params.allowinsecure or params.allowInsecure or params.insecure + local insecure = params.allowinsecure or params.allowInsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") end if not params.type then params.type = "tcp" end @@ -1344,7 +1352,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) result.use_mldsa65Verify = (params.pqv and params.pqv ~= "") and "1" or nil result.reality_mldsa65Verify = params.pqv or nil end - result.tls_allowInsecure = params.allowinsecure or params.allowInsecure or params.insecure + local insecure = params.allowinsecure or params.allowInsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") end result.port = port @@ -1400,7 +1409,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) result.hysteria_auth_type = "string" result.hysteria_auth_password = params.auth result.tls_serverName = params.peer or params.sni or "" - result.tls_allowInsecure = params.allowinsecure or params.allowInsecure or params.insecure + local insecure = params.allowinsecure or params.allowInsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") result.alpn = params.alpn result.hysteria_up_mbps = params.upmbps or sub_hy_up_mbps result.hysteria_down_mbps = params.downmbps or sub_hy_down_mbps @@ -1445,7 +1455,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) result.tls_serverName = params.sni result.tls_pinSHA256 = params.pcs or params.pinsha256 result.tls_CertByName = params.vcn - result.tls_allowInsecure = params.allowinsecure or params.insecure + local insecure = params.allowinsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") result.hysteria2_up_mbps = params.upmbps or (sub_cfg and sub_hy_up_mbps or nil) result.hysteria2_down_mbps = params.downmbps or (sub_cfg and sub_hy_down_mbps or nil) result.hysteria2_hop = params.mport @@ -1526,7 +1537,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) result.tuic_alpn = params.alpn or "h3" result.tuic_congestion_control = params.congestion_control or "cubic" result.tuic_udp_relay_mode = params.udp_relay_mode or "native" - result.tls_allowInsecure = params.allowinsecure or params.insecure or params.allow_insecure + local insecure = params.allowinsecure or params.insecure or params.allow_insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") elseif szType == "anytls" then if has_singbox then result.type = 'sing-box' @@ -1593,7 +1605,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) end end result.port = port - result.tls_allowInsecure = params.allowinsecure or params.insecure + local insecure = params.allowinsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") end elseif szType == 'naive+https' or szType == 'naive+quic' then if has_singbox then diff --git a/luci-app-passwall2/Makefile b/luci-app-passwall2/Makefile index a1629ad8..31be01f2 100644 --- a/luci-app-passwall2/Makefile +++ b/luci-app-passwall2/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 PKG_VERSION:=26.8.7 -PKG_RELEASE:=75 +PKG_RELEASE:=76 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ 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 17d67606..2b1b32a7 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/global.lua @@ -171,19 +171,6 @@ node_socks_bind_local:depends({ node = "", ["!reverse"] = true }) s:tab("DNS", translate("DNS")) -o = s:taboption("DNS", TextValue, "direct_dns_shunt", translate("Direct domain DNS routing")) -o.description = "
" -o.rows = 3 -o.wrap = "off" - o = s:taboption("DNS", ListValue, "direct_dns_query_strategy", translate("Direct Query Strategy")) o.default = "UseIP" o:value("UseIP") diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua index 27d6485a..804fd092 100644 --- a/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/luci-app-passwall2/luasrc/passwall2/api.lua @@ -5,7 +5,6 @@ nixio = require "nixio" fs = require "nixio.fs" sys = require "luci.sys" uci = require"luci.model.uci".cursor() -cbi = require "luci.cbi" util = require "luci.util" datatypes = require "luci.cbi.datatypes" jsonc = require "luci.jsonc" @@ -1014,7 +1013,6 @@ local default_file_tree = { } function get_api_json(url) - local jsonc = require "luci.jsonc" local return_code, content = curl_logic(url, nil, curl_args) if return_code ~= 0 or content == "" then return {} end return jsonc.parse(content) or {} @@ -1387,6 +1385,7 @@ function set_apply_on_parse(map) end function set_default_cbi() + local cbi = require "luci.cbi" if true then --TextValue local TextValue = cbi.TextValue @@ -1418,6 +1417,7 @@ function set_default_cbi() end function return_map(map) + local cbi = require "luci.cbi" local api = require "luci.passwall2.api" if true then -- header @@ -1438,6 +1438,7 @@ function return_map(map) end function luci_types(id, m, s, type_name, option_prefix) + local cbi = require "luci.cbi" local fv_type local field_type = s.fields["type"] if field_type then diff --git a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index c63b53c4..72c17551 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -111,34 +111,6 @@ for i, v in ipairs(cipherSuites) do end ]]-- -function parseDNS(str) - local result_dns_server - -- [proto]://[ip] - -- [proto]://[ip]:[port] - -- https://[ip]/[path] - -- https://[ip]:[port]/[path] - local _a = api.parseURL(str) - if _a then - if _a.protocol == "tcp" or _a.protocol == "udp" or _a.protocol == "https" then - result_dns_server = { - type = _a.protocol, - server = _a.hostname - } - if _a.port then - result_dns_server.server_port = _a.port - else - if _a.protocol == "https" then - result_dns_server.server_port = 443 - else - result_dns_server.server_port = 53 - end - end - result_dns_server.path = _a.pathname - end - end - return result_dns_server -end - function gen_outbound(flag, node, tag, proxy_table) local result = nil if node then @@ -2023,6 +1995,7 @@ function gen_config(var) else default_dns_flag = "direct" end dns.final = default_dns_flag + dns.strategy = default_dns_flag == "remote" and remote_strategy or direct_strategy -- DNS in order of shunt if dns_domain_rules and #dns_domain_rules > 0 then @@ -2046,12 +2019,43 @@ function gen_config(var) dns_rule.server = nil end if value.outboundTag == "direct" then - dns_rule.strategy = direct_strategy + local block_rule + if direct_strategy == "ipv4_only" then + block_rule = api.clone(dns_rule) + block_rule.query_type = { "AAAA" } + elseif direct_strategy == "ipv6_only" then + block_rule = api.clone(dns_rule) + block_rule.query_type = { "A" } + end + if block_rule then + block_rule.action = "predefined" + block_rule.rcode = "NOERROR" + block_rule.disable_cache = nil + block_rule.server = nil + table.insert(dns.rules, block_rule) + end end if value.outboundTag ~= "block" and value.outboundTag ~= "direct" then dns_rule.server = "remote" dns_rule.rewrite_ttl = 30 - dns_rule.strategy = remote_strategy + if true then + local block_rule + if remote_strategy == "ipv4_only" then + block_rule = api.clone(dns_rule) + block_rule.query_type = { "AAAA" } + elseif remote_strategy == "ipv6_only" then + block_rule = api.clone(dns_rule) + block_rule.query_type = { "A" } + end + if block_rule then + block_rule.action = "predefined" + block_rule.rcode = "NOERROR" + block_rule.disable_cache = nil + block_rule.server = nil + block_rule.rewrite_ttl = nil + table.insert(dns.rules, block_rule) + end + end dns_rule.client_subnet = remote_dns_client_ip if value.outboundTag ~= COMMON.default_outbound_tag and remote_server.server and remote_dns_detour ~= "direct" then local remote_dns_server = api.clone(remote_server) @@ -2062,9 +2066,13 @@ function gen_config(var) end if value.fakedns then local fakedns_dns_rule = api.clone(dns_rule) - fakedns_dns_rule.query_type = { - "A", "AAAA" - } + if remote_strategy == "ipv4_only" then + fakedns_dns_rule.query_type = { "A" } + elseif remote_strategy == "ipv6_only" then + fakedns_dns_rule.query_type = { "AAAA" } + else + fakedns_dns_rule.query_type = { "A", "AAAA" } + end fakedns_dns_rule.server = fakedns_tag fakedns_dns_rule.disable_cache = true fakedns_dns_rule.client_subnet = nil @@ -2076,23 +2084,26 @@ function gen_config(var) end end if default_dns_flag == "remote" then + local dns_rule_query_type = { "A", "AAAA" } + if remote_strategy == "ipv4_only" then + dns_rule_query_type = { "A" } + elseif remote_strategy == "ipv6_only" then + dns_rule_query_type = { "AAAA" } + end if remote_dns_fake then -- When default is not direct and enable fakedns, default DNS use FakeDNS. local fakedns_dns_rule = { - query_type = { - "A", "AAAA" - }, + query_type = dns_rule_query_type, server = fakedns_tag, disable_cache = true, - rewrite_ttl = 30, - strategy = remote_strategy, + rewrite_ttl = 30 } table.insert(dns.rules, fakedns_dns_rule) else local remote_dns_rule = { + query_type = dns_rule_query_type, server = "remote", disable_cache = true, - strategy = remote_strategy, } table.insert(dns.rules, remote_dns_rule) end @@ -2328,156 +2339,7 @@ function gen_proto_config(var) return jsonc.stringify(config, 1) end -function gen_front_dns_config(var) - local dns_listen_port = var["dns_listen_port"] - local direct_dns_udp_server = var["direct_dns_udp_server"] - local direct_dns_udp_port = var["direct_dns_udp_port"] - local direct_dns_query_strategy = var["direct_dns_query_strategy"] - local default_dns_udp_server = var["default_dns_udp_server"] - local default_dns_udp_port = var["default_dns_udp_port"] - - local dns = { - servers = {}, - rules = {} - } - local inbounds = {} - local outbounds = {} - local route = {} - - local direct_strategy = "prefer_ipv6" - if direct_dns_query_strategy == "UseIPv4" then - direct_strategy = "ipv4_only" - elseif direct_dns_query_strategy == "UseIPv6" then - direct_strategy = "ipv6_only" - end - - table.insert(outbounds, { - type = "direct", - tag = "direct", - routing_mark = 255, - }) - - local direct_dns_shunt = uci:get(appname, "@global[0]", "direct_dns_shunt") or "" - if #direct_dns_shunt > 0 then - local dns_server = {} - string.gsub(direct_dns_shunt, '[^' .. "\r\n" .. ']+', function(w) - if w:find("#") == 1 then return end - local domain = sys.exec(string.format("echo -n $(echo %s | awk -F ' ' '{print $1}')", w)) - local dns = sys.exec(string.format("echo -n $(echo %s | awk -F ' ' '{print $2}')", w)) - if domain ~= "" and dns ~= "" then - local new_dns_server = parseDNS(dns) - if new_dns_server then - if not dns_server[dns] then - dns_server[dns] = {} - end - if not dns_server[dns].server then - dns_server[dns].server = new_dns_server - dns_server[dns].server.tag = dns - dns_server[dns].server.detour = "direct" - end - if not dns_server[dns].rule then - dns_server[dns].rule = { - action = "route", - server = dns, - domain = {}, - domain_suffix = {}, - domain_keyword = {} - } - end - if domain:find("full:") == 1 then - table.insert(dns_server[dns].rule.domain, domain:sub(1 + #"full:")) - elseif domain:find("domain:") == 1 then - table.insert(dns_server[dns].rule.domain_suffix, domain:sub(1 + #"domain:")) - else - table.insert(dns_server[dns].rule.domain_keyword, domain) - end - end - end - end) - for k, v in pairs(dns_server) do - table.insert(dns.servers, v.server) - if #v.rule.domain == 0 then v.rule.domain = nil end - if #v.rule.domain_suffix == 0 then v.rule.domain_suffix = nil end - if #v.rule.domain_keyword == 0 then v.rule.domain_keyword = nil end - table.insert(dns.rules, v.rule) - end - end - - if direct_dns_udp_server then - table.insert(dns.servers, { - tag = "direct", - type = "udp", - server = direct_dns_udp_server, - server_port = tonumber(direct_dns_udp_port) or 53, - detour = "direct" - }) - local node_domain = {} - local nodes_domain_text = sys.exec('uci show passwall2 | grep ".address=" | cut -d "\'" -f 2 | grep "[a-zA-Z]$" | sort -u') - string.gsub(nodes_domain_text, '[^' .. "\r\n" .. ']+', function(w) - w = (w or ""):lower() - table.insert(node_domain, w) - end) - if #node_domain > 0 then - table.insert(dns.rules, { - action = "route", - server = "direct", - domain = node_domain - }) - end - route.default_domain_resolver = { - server = "direct", - strategy = direct_strategy - } - end - - if default_dns_udp_server then - table.insert(dns.servers, { - tag = "default", - type = "udp", - server = default_dns_udp_server, - server_port = tonumber(default_dns_udp_port) or 53, - detour = "direct" - }) - dns.final = "default" - else - dns.final = "direct" - end - - local dns_in_inbound = { - type = "direct", - tag = "dns-in", - listen = "127.0.0.1", - listen_port = tonumber(dns_listen_port), - } - table.insert(inbounds, dns_in_inbound) - - route.rules = {} - table.insert(route.rules, { - action = "hijack-dns", - inbound = dns_in_inbound.tag - }) - table.insert(route.rules, { - action = "sniff", - inbound = dns_in_inbound.tag - }) - route.final = "direct" - - local config = { - log = { - disabled = true, - level = "debug", - timestamp = true, - }, - dns = dns, - inbounds = inbounds, - outbounds = outbounds, - route = route - } - return jsonc.stringify(config, 1) -end - _G.gen_config = gen_config -_G.gen_front_dns_config = gen_front_dns_config _G.gen_proto_config = gen_proto_config _G.geo_convert_srs = geo_convert_srs diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 530670c9..1df0c1a8 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -51,35 +51,6 @@ for i, v in ipairs(cipherSuites) do end ]]-- -function parseDNS(str) - local result_dns_server - -- [proto]://[ip] - -- [proto]://[ip]:[port] - -- https://[ip]/[path] - -- https://[ip]:[port]/[path] - local _a = api.parseURL(str) - if _a then - if _a.protocol == "tcp" or _a.protocol == "udp" or _a.protocol == "https" then - result_dns_server = { - address = str - } - if _a.protocol == "udp" then - result_dns_server.address = _a.hostname - end - if _a.port then - result_dns_server.port = _a.port - else - if _a.protocol == "https" then - result_dns_server.port = 443 - else - result_dns_server.port = 53 - end - end - end - end - return result_dns_server -end - function gen_outbound(flag, node, tag, proxy_table) local result = nil if node then @@ -2186,157 +2157,7 @@ function gen_proto_config(var) return jsonc.stringify(config, 1) end -function gen_front_dns_config(var) - local dns_listen_port = var["dns_listen_port"] - local direct_dns_udp_server = var["direct_dns_udp_server"] - local direct_dns_udp_port = var["direct_dns_udp_port"] - local default_dns_udp_server = var["default_dns_udp_server"] - local default_dns_udp_port = var["default_dns_udp_port"] - - local queryStrategy = "UseIP" - local dns = { - tag = "dns-global-direct", - disableCache = false, - disableFallback = true, - disableFallbackIfMatch = true, - queryStrategy = queryStrategy, - servers = {} - } - local inbounds = {} - local outbounds = {} - local routing = { - rules = {} - } - - table.insert(outbounds, { - tag = "direct", - protocol = "freedom", - settings = { - domainStrategy = queryStrategy - }, - streamSettings = { - sockopt = { - mark = 255 - } - } - }) - - if default_dns_udp_server then - table.insert(dns.servers, { - tag = "default", - address = default_dns_udp_server, - port = tonumber(default_dns_udp_port) or 53, - queryStrategy = queryStrategy, - }) - end - - local direct_dns_shunt = uci:get(appname, "@global[0]", "direct_dns_shunt") or "" - if #direct_dns_shunt > 0 then - local dns_server = {} - string.gsub(direct_dns_shunt, '[^' .. "\r\n" .. ']+', function(w) - if w:find("#") == 1 then return end - local domain = sys.exec(string.format("echo -n $(echo %s | awk -F ' ' '{print $1}')", w)) - local dns = sys.exec(string.format("echo -n $(echo %s | awk -F ' ' '{print $2}')", w)) - if domain ~= "" and dns ~= "" then - local new_dns_server = parseDNS(dns) - if new_dns_server then - if not dns_server[dns] then - dns_server[dns] = {} - end - dns_server[dns].tag = dns - dns_server[dns].queryStrategy = queryStrategy - dns_server[dns].address = new_dns_server.address - dns_server[dns].port = new_dns_server.port - dns_server[dns].finalQuery = true - if not dns_server[dns].domains then - dns_server[dns].domains = {} - end - table.insert(dns_server[dns].domains, domain) - end - end - end) - for k, v in pairs(dns_server) do - table.insert(dns.servers, v) - table.insert(routing.rules, { - inboundTag = { - v.tag - }, - outboundTag = "direct" - }) - end - end - - if direct_dns_udp_server then - local node_domain = {} - local nodes_domain_text = sys.exec('uci show passwall2 | grep ".address=" | cut -d "\'" -f 2 | grep "[a-zA-Z]$" | sort -u') - string.gsub(nodes_domain_text, '[^' .. "\r\n" .. ']+', function(w) - w = (w or ""):lower() - table.insert(node_domain, "full:" .. w) - end) - if #node_domain > 0 then - table.insert(dns.servers, { - tag = "dns-in-vpslist", - address = direct_dns_udp_server, - port = tonumber(direct_dns_udp_port) or 53, - queryStrategy = queryStrategy, - domains = node_domain, - finalQuery = true, - disableCache = false, - serveStale = true, - }) - end - end - - table.insert(inbounds, { - tag = "dns-in", - listen = "127.0.0.1", - port = tonumber(dns_listen_port), - protocol = "dokodemo-door", - settings = { - address = "0.0.0.0", - network = "tcp,udp" - } - }) - - table.insert(outbounds, { - tag = "dns-out", - protocol = "dns", - proxySettings = { - tag = "direct" - }, - settings = { - address = direct_dns_udp_server, - port = tonumber(direct_dns_udp_port) or 53, - network = "udp", - nonIPQuery = "skip", - blockTypes = { - 65 - } - } - }) - - table.insert(routing.rules, { - inboundTag = { - "dns-in" - }, - outboundTag = "dns-out" - }) - - local config = { - log = { - dnsLog = true, - loglevel = "debug" - }, - dns = dns, - inbounds = inbounds, - outbounds = outbounds, - routing = routing - } - return jsonc.stringify(config, 1) -end - _G.gen_config = gen_config -_G.gen_front_dns_config = gen_front_dns_config _G.gen_proto_config = gen_proto_config if arg[1] then diff --git a/luci-app-passwall2/po/fa/passwall2.po b/luci-app-passwall2/po/fa/passwall2.po index 0cbfa1a0..2e924b52 100644 --- a/luci-app-passwall2/po/fa/passwall2.po +++ b/luci-app-passwall2/po/fa/passwall2.po @@ -121,12 +121,6 @@ msgstr "0 به معنای عدم استفاده است" msgid "Current node: %s" msgstr "گره فعلی: %s" -msgid "Direct domain DNS routing" -msgstr "مسیریابی مستقیم DNS دامنه" - -msgid "Please note that the program will not start if the format is incorrect!" -msgstr "لطفا توجه داشته باشید که اگر قالب نادرست باشد، برنامه شروع نخواهد شد!" - msgid "IP:Port mode acceptable, multi value split with english comma." msgstr "حالت IP:Port قابل قبول است، مقادیر متعدد را با کاما انگلیسی جدا کنید." diff --git a/luci-app-passwall2/po/ru/passwall2.po b/luci-app-passwall2/po/ru/passwall2.po index 205665bf..2f7da3ee 100644 --- a/luci-app-passwall2/po/ru/passwall2.po +++ b/luci-app-passwall2/po/ru/passwall2.po @@ -118,12 +118,6 @@ msgstr "0 — отключить функцию" msgid "Current node: %s" msgstr "Текущий узел: %s" -msgid "Direct domain DNS routing" -msgstr "Прямая маршрутизация DNS домена" - -msgid "Please note that the program will not start if the format is incorrect!" -msgstr "Обратите внимание, что программа не запустится, если формат указан неверно!" - msgid "IP:Port mode acceptable, multi value split with english comma." msgstr "Допустим формат IP:Port. Несколько значений указывайте через запятую." diff --git a/luci-app-passwall2/po/zh-cn/passwall2.po b/luci-app-passwall2/po/zh-cn/passwall2.po index e6823a2e..8da8f7f7 100644 --- a/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/luci-app-passwall2/po/zh-cn/passwall2.po @@ -118,12 +118,6 @@ msgstr "0为不使用" msgid "Current node: %s" msgstr "当前节点:%s" -msgid "Direct domain DNS routing" -msgstr "直连域名 DNS 分流" - -msgid "Please note that the program will not start if the format is incorrect!" -msgstr "请注意,格式不正确将无法启动!" - msgid "IP:Port mode acceptable, multi value split with english comma." msgstr "接受 IP:Port 形式的输入,多个以英文逗号分隔。" diff --git a/luci-app-passwall2/po/zh-tw/passwall2.po b/luci-app-passwall2/po/zh-tw/passwall2.po index 57fc9b65..b012e0b6 100644 --- a/luci-app-passwall2/po/zh-tw/passwall2.po +++ b/luci-app-passwall2/po/zh-tw/passwall2.po @@ -118,12 +118,6 @@ msgstr "0為不使用" msgid "Current node: %s" msgstr "當前節點:%s" -msgid "Direct domain DNS routing" -msgstr "直連網域 DNS 分流" - -msgid "Please note that the program will not start if the format is incorrect!" -msgstr "請注意,格式不正確將無法啟動!" - msgid "IP:Port mode acceptable, multi value split with english comma." msgstr "接受 IP:Port 形式的輸入,多個以英文逗号分隔。" diff --git a/luci-app-passwall2/root/usr/share/passwall2/app.sh b/luci-app-passwall2/root/usr/share/passwall2/app.sh index 6c418286..ea032845 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -655,58 +655,13 @@ run_global() { set_cache_var "ACL_GLOBAL_redir_port" "$REDIR_PORT" } -run_front_dns() { - local switch=0 - direct_dns_shunt=$(config_t_get global direct_dns_shunt) - direct_dns_shunt=$(echo "${direct_dns_shunt}" | grep -v "^#") - [ -n "${direct_dns_shunt}" ] && switch=1 - [ "${switch}" == "1" ] && { - local config_file="${TMP_PATH}/direct_dns.json" - local log_file="${TMP_PATH}/direct_dns.log" - log_file="/dev/null" - local listen_port=$(get_new_port 10553) - json_init - json_add_string "dns_listen_port" "${listen_port}" - json_add_string "direct_dns_udp_server" "${DIRECT_DNS_UDP_SERVER}" - json_add_string "direct_dns_udp_port" "${DIRECT_DNS_UDP_PORT}" - json_add_string "direct_dns_query_strategy" "${DIRECT_DNS_QUERY_STRATEGY}" - [ -n "${ACL_GLOBAL_node}" ] && [ -n "${TUN_DNS_PORT}" ] && { - json_add_string "default_dns_udp_server" "127.0.0.1" - json_add_string "default_dns_udp_port" "${TUN_DNS_PORT}" - } - local _json_arg="$(json_dump)" - - local prefer_core="" - [ -n "${XRAY_BIN}" ] && prefer_core="xray" - [ -n "${SINGBOX_BIN}" ] && prefer_core="sing-box" - - if [ "${prefer_core}" = "xray" ]; then - lua $UTIL_XRAY gen_front_dns_config "${_json_arg}" > $config_file - ln_run 0 "$XRAY_BIN" "xray" "${log_file}" run -c "$config_file" - elif [ "${prefer_core}" = "sing-box" ]; then - lua $UTIL_SINGBOX gen_front_dns_config "${_json_arg}" > $config_file - ln_run 0 "$SINGBOX_BIN" "sing-box" "${log_file}" run -c "$config_file" - else - return 1 - fi - - FRONT_DNS_SERVER="127.0.0.1" - FRONT_DNS_PORT="${listen_port}" - } -} - run_global_dnsmasq() { - [ -z "${ACL_GLOBAL_node}" ] && [ -z "${FRONT_DNS_PORT}" ] && return + [ -z "${ACL_GLOBAL_node}" ] && return local RUN_NEW_DNSMASQ=1 RUN_NEW_DNSMASQ=${DNS_REDIRECT} DNSMASQ_DEFAULT_DNS="${AUTO_DNS}" DNSMASQ_LOCAL_DNS="${LOCAL_DNS:-${AUTO_DNS}}" DNSMASQ_TUN_DNS="${TUN_DNS}" - [ -n "${FRONT_DNS_PORT}" ] && { - DNSMASQ_DEFAULT_DNS="${FRONT_DNS_SERVER}#${FRONT_DNS_PORT}" - DNSMASQ_LOCAL_DNS="${DNSMASQ_DEFAULT_DNS}" - DNSMASQ_TUN_DNS="${DNSMASQ_DEFAULT_DNS}" - } if [ "${RUN_NEW_DNSMASQ}" == "0" ]; then #The old logic will be removed in the future. #Run a copy dnsmasq instance, DNS hijack that don't need a proxy devices. @@ -1194,7 +1149,6 @@ start() { fi mkdir -p ${GLOBAL_ACL_PATH} [ "$ENABLED_DEFAULT_ACL" == 1 ] && run_global - run_front_dns run_global_dnsmasq [ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start set_cache_var "USE_TABLES" "$USE_TABLES" diff --git a/luci-theme-footstrap/Makefile b/luci-theme-footstrap/Makefile index 1ff4ecb2..82de7b5c 100644 --- a/luci-theme-footstrap/Makefile +++ b/luci-theme-footstrap/Makefile @@ -17,7 +17,7 @@ LUCI_NAME:=luci-theme-footstrap FOOTSTRAP_VERSION?= ifneq ($(FOOTSTRAP_VERSION),) PKG_VERSION:=$(FOOTSTRAP_VERSION) -PKG_RELEASE:=9 +PKG_RELEASE:=10 endif LUCI_TITLE:=Footstrap Theme diff --git a/luci-theme-footstrap/htdocs/luci-static/resources/fs-router.js b/luci-theme-footstrap/htdocs/luci-static/resources/fs-router.js index 2f62bf5c..5318e358 100644 --- a/luci-theme-footstrap/htdocs/luci-static/resources/fs-router.js +++ b/luci-theme-footstrap/htdocs/luci-static/resources/fs-router.js @@ -381,6 +381,22 @@ function seed() { adoptEntry(); } +/* Does this document already carry the stylesheet a menu.d node names? + * + * The value is a path under /luci-static/resources (`view/foo/foo.css`), and head.ut prints it with + * a `?v=` cache key, so compare the PATH only and by suffix — the theme does not get to assume the + * resource base, and a re-hosted sheet keeps its element and its href (fs-sheets.js disables the + * , it never removes it), which is exactly the "already here" this asks about. */ +function documentHasSheet(css) { + const want = '/' + css.replace(/^\/+/, ''); + for (const link of document.querySelectorAll('link[rel~="stylesheet"][href]')) { + const href = (link.getAttribute('href') || '').split('?')[0]; + if (href.endsWith(want)) + return true; + } + return false; +} + /* Attempt an in-place navigation to `pathname`. Returns true if handled as a * SPA nav (caller should preventDefault), false to let the browser do a normal * full navigation. `push` adds a history entry (false when replaying popstate). @@ -402,6 +418,30 @@ function navigate(pathname, push, kbd) { const className = tree.viewClassFor(node); if (!className) return false; + + /* A PAGE WHOSE STYLESHEET ONLY THE SERVER CAN EMIT IS NOT OURS TO SWAP INTO. + * + * A menu.d node may name its own sheet (`"css": "view/foo/foo.css"`), and the server links it + * from on a full load (partials/head.ut). Nothing here can: a swap replaces #view's + * children, it does not re-render a document, so reaching such a page by CLICK would show it + * with the app's CSS missing — while reaching the same page by URL or F5 showed it styled. One + * page, two appearances, decided by how the user got there. + * + * So decline, exactly as the poisoned-document bail above does: speed is traded for + * correctness, never the other way. It costs ONE full load per such page — after it the + * is in the document, this test passes, and every later visit is a swap again (fs-sheets.js + * owns the sheet from then on and re-lights it per page). + * + * Injecting the here instead would work and is deliberately not done: it would put the + * theme in charge of fetching and ordering a foreign stylesheet, which is the job fs-sheets.js + * exists to keep out of the theme. The server already does it correctly. + * + * `node.css` reaches the client because /admin/menu serves the dispatcher's own tree and + * ui.js's scrubMenu() only rewrites `satisfied`. On a luci-base that predates the `css` schema + * entry the property is dropped server-side, so this is simply never true there. */ + if (typeof node.css === 'string' && node.css !== '' && !documentHasSheet(node.css)) + return false; + const rsegs = res.segs; /* from here on the navigation is committed */ diff --git a/luci-theme-footstrap/styles/pages/70-syslog.css b/luci-theme-footstrap/styles/pages/70-syslog.css index 5e1ce6d7..3fe8df4b 100644 --- a/luci-theme-footstrap/styles/pages/70-syslog.css +++ b/luci-theme-footstrap/styles/pages/70-syslog.css @@ -15,21 +15,26 @@ * cutting in half. The fields shrink instead of forcing that: `min-width: 0` undoes the field * box in theme/60-inputs.css for this row only. * - * Keyed on the controls' OWN ids rather than on the page: `data-page` differs between the system - * and the kernel log, and a third-party LogreadBox has neither, while ui.js gives these two rows - * the same ids wherever the widget is rendered. The inline `margin: 0 5px` LuCI writes on the - * labels stays as the horizontal spacing — only the ROW gap is ours, so nothing here has to - * fight an inline style. */ - div:has(> #logFacilitySelect), - div:has(> #logTextFilter) { + * Keyed on the ROW's SHAPE, not on the page and not on the controls' ids. `data-page` differs + * between the system and the kernel log and a third-party LogreadBox has neither — but the ids + * are no better: only the System Log is built by `tools/views.js`, and Status → Kernel Log is a + * view of its own (`view/status/dmesg.js`) whose four rows carry `logFromTime`, `logToTime`, + * `invertLogRangeTime`, `invertSeverity` and `invertAscendingSort`, of which an id list written + * against LogreadBox catches none — `logFacilitySelect` appears there only as a `for=`, on a + * label whose control is a time field. Both views wrap their rows in `#content_syslog`, and a + * filter row is exactly one that opens with a `