diff --git a/clashoo/Makefile b/clashoo/Makefile index 9630b569..ee112b7b 100644 --- a/clashoo/Makefile +++ b/clashoo/Makefile @@ -5,7 +5,7 @@ PKG_SHORT_SHA:=4aa9cc1 PKG_COMMIT_DATE:=2026.09.10 PKG_VERSION:=$(PKG_COMMIT_DATE)~$(PKG_SHORT_SHA) -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-alpha-$(PKG_SHORT_SHA).tar.gz PKG_SOURCE_SUBDIR:=$(PKG_NAME)-alpha-$(PKG_SHORT_SHA) diff --git a/clashoo/files/etc/config/clashoo b/clashoo/files/etc/config/clashoo index 905e873b..1f2112ff 100644 --- a/clashoo/files/etc/config/clashoo +++ b/clashoo/files/etc/config/clashoo @@ -47,6 +47,9 @@ config clashoo 'config' option fallback_filter_geoip '0' list fallback_filter_ipcidr '240.0.0.0/4' option dns_respect_rules '1' + option dns_loopback_compat '0' + list dns_loopback_compat_resolver 'udp://223.5.5.5:53' + list dns_loopback_compat_resolver 'udp://119.29.29.29:53' option dns_migrated '1' option block_quic '0' option singbox_independent_cache '0' diff --git a/clashoo/files/etc/init.d/clashoo b/clashoo/files/etc/init.d/clashoo index f63e05ac..5a1cd15f 100755 --- a/clashoo/files/etc/init.d/clashoo +++ b/clashoo/files/etc/init.d/clashoo @@ -1089,6 +1089,55 @@ _dns_nameserver_inherit_mode() { printf '%s' inherit } +_adapt_dns_loopback_resolver() { + local filter listen host host_pattern old_port servers replacement tmp + [ "$(uci -q get clashoo.config.dns_loopback_compat 2>/dev/null)" = "1" ] || return 0 + command -v yq >/dev/null 2>&1 || return 0 + [ -s "$CONFIG_YAML" ] || return 0 + + filter="${CLASHOO_DNS_LOOPBACK_FILTER:-/usr/share/clashoo/runtime/dns_loopback_adapter.yq}" + [ -r "$filter" ] || return 0 + [ "$(yq -M e '(.dns."proxy-server-nameserver" | type)' "$CONFIG_YAML" 2>/dev/null)" = "!!seq" ] || return 0 + + listen="$(yq -M e -r '.dns.listen // ""' "$CONFIG_YAML" 2>/dev/null)" + old_port="${listen##*:}" + host="${listen%:*}" + printf '%s' "$old_port" | grep -Eq '^[0-9]+$' || return 0 + host="$(printf '%s' "$host" | tr 'A-Z' 'a-z')" + case "$host" in + ""|0.0.0.0|'[::]'|::) + host_pattern='(localhost|127(\.[0-9]{1,3}){3}|\[?::1\]?)' ;; + localhost) + host_pattern='localhost' ;; + 127.*) + printf '%s' "$host" | grep -Eq '^127(\.[0-9]{1,3}){3}$' || return 0 + host_pattern="$(printf '%s' "$host" | sed 's/\./\\./g')" ;; + '[::1]'|::1) + host_pattern='\[?::1\]?' ;; + *) + return 0 ;; + esac + + servers="$(yq -M e -r '.dns."proxy-server-nameserver"[]' "$CONFIG_YAML" 2>/dev/null)" + printf '%s\n' "$servers" | grep -Eiq "^([A-Za-z][A-Za-z0-9+.-]*://)?(${host_pattern}):${old_port}($|[/#?])" || return 0 + + replacement="$(uci -q get clashoo.config.dns_loopback_compat_resolver 2>/dev/null)" + [ -n "$replacement" ] || replacement='udp://223.5.5.5:53 udp://119.29.29.29:53' + tmp="$(mktemp "${CONFIG_YAML}.dns-loopback.XXXXXX" 2>/dev/null)" || return 0 + export CLASHOO_DNS_OLD_PORT="$old_port" + export CLASHOO_DNS_HOST_PATTERN="$host_pattern" + export CLASHOO_DNS_REPLACEMENT="$replacement" + if yq -M e --from-file "$filter" "$CONFIG_YAML" > "$tmp" 2>/dev/null && + mv -f "$tmp" "$CONFIG_YAML"; then + log_msg "Adapted stale loopback proxy DNS" "已适配失效的回环节点 DNS" + else + rm -f "$tmp" + log_msg "Loopback proxy DNS adaptation failed; preserved source settings" "回环节点 DNS 适配失败,已保留原配置" + fi + unset CLASHOO_DNS_OLD_PORT CLASHOO_DNS_HOST_PATTERN CLASHOO_DNS_REPLACEMENT + return 0 +} + backfill_custom_sniffer_overrides() { [ "$CLASHOO_KEEP_SNIFFER" = "1" ] || return 0 [ "$(uci -q get clashoo.config.sniffer_streaming 2>/dev/null)" = "1" ] || return 0 @@ -1935,6 +1984,7 @@ _start_prepare_config() { if command -v yq >/dev/null 2>&1 && grep -q '<<[[:space:]]*:' "$CONFIG_YAML" 2>/dev/null; then yq e -i 'explode(.)' "$CONFIG_YAML" 2>/dev/null || true fi + _adapt_dns_loopback_resolver >/dev/null 2>&1 # stage bundled cn.mrs into the core dir; mihomo rejects rule-set paths outside /etc/clashoo if [ -f /usr/share/clashoo/ruleset/cn.mrs ]; then if [ ! -f /etc/clashoo/ruleset/cn.mrs ] || [ /usr/share/clashoo/ruleset/cn.mrs -nt /etc/clashoo/ruleset/cn.mrs ]; then diff --git a/clashoo/files/usr/share/clashoo/runtime/dns_loopback_adapter.yq b/clashoo/files/usr/share/clashoo/runtime/dns_loopback_adapter.yq new file mode 100644 index 00000000..12d5851e --- /dev/null +++ b/clashoo/files/usr/share/clashoo/runtime/dns_loopback_adapter.yq @@ -0,0 +1,17 @@ +. as $document | +strenv(CLASHOO_DNS_OLD_PORT) as $old_port | +strenv(CLASHOO_DNS_HOST_PATTERN) as $host_pattern | +(strenv(CLASHOO_DNS_REPLACEMENT) | split(" ") | map(select(length > 0))) as $replacement | +("(?i)^(?:[a-z][a-z0-9+.-]*://)?(?:" + $host_pattern + "):" + $old_port + "(?:$|[/#?])") as $old_loopback | +( + $document | + select((.dns."proxy-server-nameserver" | type) == "!!seq") | + ([.dns."proxy-server-nameserver"[] | select(type == "!!str" and test($old_loopback))] | length) as $match_count | + select($match_count > 0) | + .dns."proxy-server-nameserver" = + ([ + .dns."proxy-server-nameserver"[] | + select((type == "!!str" and test($old_loopback)) | not) | + select(. as $server | ($replacement | contains([$server])) | not) + ] + $replacement) +) // $document diff --git a/luci-app-clashoo/Makefile b/luci-app-clashoo/Makefile index 52d19c8e..fc2fadfe 100644 --- a/luci-app-clashoo/Makefile +++ b/luci-app-clashoo/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-clashoo PKG_VERSION:=1.30.0 -PKG_RELEASE:=12 +PKG_RELEASE:=13 PKG_MAINTAINER:=kenzok8 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) diff --git a/luci-app-clashoo/htdocs/luci-static/resources/view/clashoo/config.js b/luci-app-clashoo/htdocs/luci-static/resources/view/clashoo/config.js index 159cf86c..0eee7506 100644 --- a/luci-app-clashoo/htdocs/luci-static/resources/view/clashoo/config.js +++ b/luci-app-clashoo/htdocs/luci-static/resources/view/clashoo/config.js @@ -1357,6 +1357,14 @@ return view.extend({ o = s.option(form.Flag, 'dns_respect_rules', _("DNS Respect Rules")); o.default = '1'; o.description = _("DNS queries follow the routing rules, so overseas domains resolve through the proxy instead of a polluted result. Requires proxy-server-nameserver."); + o = s.option(form.Flag, 'dns_loopback_compat', _("OpenClash/Nikki Loopback DNS Compatibility")); + o.default = '0'; + o.description = _("Optional compatibility for normal managed mode. At runtime, replace only proxy node resolvers that point back to the imported configuration's own DNS listener. Core Only mode stays verbatim; the source configuration and unrelated local DNS services remain unchanged."); + o.depends('enable_dns', '1'); + o = s.option(form.DynamicList, 'dns_loopback_compat_resolver', _("Loopback DNS Replacement")); + o.placeholder = 'udp://223.5.5.5:53'; + o.description = _("Used only when the compatibility switch detects a stale self-reference. When empty, udp://223.5.5.5:53 and udp://119.29.29.29:53 are used. Plain IP DNS is recommended to avoid bootstrap loops."); + o.depends('dns_loopback_compat', '1'); o = s.option(form.Value, 'dns_ecs', _("ECS Client Subnet")); o.placeholder = _("Recommended blank"); o.description = _("mihomo writes the ecs parameter to DNS URLs; sing-box writes dns.client_subnet. Leave empty to skip."); diff --git a/luci-app-clashoo/po/templates/clashoo.pot b/luci-app-clashoo/po/templates/clashoo.pot index 423f8051..db1f757a 100644 --- a/luci-app-clashoo/po/templates/clashoo.pot +++ b/luci-app-clashoo/po/templates/clashoo.pot @@ -902,9 +902,18 @@ msgstr "" msgid "OpenClash is enabled; disable it first to avoid rule conflicts" msgstr "" +msgid "OpenClash/Nikki Loopback DNS Compatibility" +msgstr "" + msgid "Operation failed: " msgstr "" +msgid "Loopback DNS Replacement" +msgstr "" + +msgid "Optional compatibility for normal managed mode. At runtime, replace only proxy node resolvers that point back to the imported configuration's own DNS listener. Core Only mode stays verbatim; the source configuration and unrelated local DNS services remain unchanged." +msgstr "" + msgid "Other Configuration Files (upload / overwrite output)" msgstr "" @@ -1502,6 +1511,9 @@ msgstr "" msgid "User-Agent (UA)" msgstr "" +msgid "Used only when the compatibility switch detects a stale self-reference. When empty, udp://223.5.5.5:53 and udp://119.29.29.29:53 are used. Plain IP DNS is recommended to avoid bootstrap loops." +msgstr "" + msgid "Username" msgstr "" diff --git a/luci-app-clashoo/po/zh-cn/clashoo.po b/luci-app-clashoo/po/zh-cn/clashoo.po index 0767b07c..4d376654 100644 --- a/luci-app-clashoo/po/zh-cn/clashoo.po +++ b/luci-app-clashoo/po/zh-cn/clashoo.po @@ -909,6 +909,18 @@ msgstr "TCP 或 UDP 任意一个选择 TUN 时,该栈设置才会生效。" msgid "OpenClash is enabled; disable it first to avoid rule conflicts" msgstr "OpenClash 已启用,请先停用以避免规则冲突" +msgid "OpenClash/Nikki Loopback DNS Compatibility" +msgstr "OpenClash/Nikki 回环 DNS 兼容" + +msgid "Loopback DNS Replacement" +msgstr "回环 DNS 替换地址" + +msgid "Optional compatibility for normal managed mode. At runtime, replace only proxy node resolvers that point back to the imported configuration's own DNS listener. Core Only mode stays verbatim; the source configuration and unrelated local DNS services remain unchanged." +msgstr "用于普通接管模式的可选兼容功能。运行时仅替换指回导入配置自身 DNS 监听的节点解析器;仅内核模式保持原样,源配置和其他本地 DNS 服务不受影响。" + +msgid "Used only when the compatibility switch detects a stale self-reference. When empty, udp://223.5.5.5:53 and udp://119.29.29.29:53 are used. Plain IP DNS is recommended to avoid bootstrap loops." +msgstr "仅在兼容开关检测到失效自引用时使用。留空则使用 udp://223.5.5.5:53 和 udp://119.29.29.29:53。建议使用纯 IP DNS,避免启动解析死循环。" + msgid "Operation failed: " msgstr "操作失败: " diff --git a/luci-app-kaiplus/Makefile b/luci-app-kaiplus/Makefile index b84597fa..dbdc5fe7 100644 --- a/luci-app-kaiplus/Makefile +++ b/luci-app-kaiplus/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=KaiPlus -PKG_VERSION:=1.0.7 -PKG_RELEASE:=2 +PKG_VERSION:=1.0.8 +PKG_RELEASE:=1 LUCI_DEPENDS:=+kaiplus +luci-compat +luci-lib-linkeaseauth LUCI_MINIFY_CSS:=0 LUCI_MINIFY_JS:=0 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 a3655af1..68a72d4a 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 @@ -181,9 +181,7 @@ o:value("1:65535", translate("All")) o:depends("mode", "1") o.validate = port_validate -o = s:taboption("Main", DummyValue, "_hide_node_option", "") -o.template = m:template_path("/cbi/hidevalue") -o.value = "1" +o = s:taboption("Main", HideValue, "_hide_node_option", "") o:depends("mode", "0") o:depends({ tcp_no_redir_ports = "1:65535", udp_no_redir_ports = "1:65535" }) if TCP_NO_REDIR_PORTS == "1:65535" and UDP_NO_REDIR_PORTS == "1:65535" then @@ -208,19 +206,14 @@ if node_value then end current_node = current_node_id and m:get(current_node_id) or {} -o = s:taboption("Main", DummyValue, "node_save_before", "") -o.template = m:template_path("/cbi/hidevalue") +o = s:taboption("Main", HideValue, "node_save_before", "") o.value = current_node[".name"] o.cbid = function(self, section) return "node_save_before" end -o = s:taboption("Main", DummyValue, "_acl_node_bool", "") -o.template = m:template_path("/cbi/hidevalue") -o.value = "1" +o = s:taboption("Main", HideValue, "_acl_node_bool", "") o:depends({ node = "", ['!reverse'] = true }) -o = s:taboption("Main", DummyValue, "_diff_global_node", "") -o.template = m:template_path("/cbi/hidevalue") -o.value = "1" +o = s:taboption("Main", HideValue, "_diff_global_node", "") if NODE ~= "" then o:depends({ node = NODE, ['!reverse'] = true }) else @@ -319,14 +312,10 @@ o.template = m:template_path("/global/proxy") o:depends({ _acl_node_bool = "1", _diff_global_node = "1" }) -- Node → DNS Depends Settings -o = s:taboption("Main", DummyValue, "_node_sel_shunt", "") -o.template = m:template_path("/cbi/hidevalue") -o.value = "1" +o = s:taboption("Main", HideValue, "_node_sel_shunt", "") o:depends({ node = "__always__" }) -o = s:taboption("Main", DummyValue, "_node_sel_other", "") -o.template = m:template_path("/cbi/hidevalue") -o.value = "1" +o = s:taboption("Main", HideValue, "_node_sel_other", "") o:depends({ _node_sel_shunt = "1", ['!reverse'] = true }) ---- DNS 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 b43d7209..c41f64d4 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -162,25 +162,18 @@ o = s:taboption("Main", Flag, "node_socks_bind_local", translate("Node") .. " So o.default = "1" o:depends("_node", "1") -o = s:taboption("Main", DummyValue, "node_save_before", "") -o.template = m:template_path("/cbi/hidevalue") +o = s:taboption("Main", HideValue, "node_save_before", "") o.value = current_node[".name"] o.cbid = function(self, section) return "node_save_before" end -o = s:taboption("Main", DummyValue, "_node", "") -o.template = m:template_path("/cbi/hidevalue") -o.value = "1" +o = s:taboption("Main", HideValue, "_node", "") o:depends({ node = "", ['!reverse'] = true }) -- Node → DNS Depends Settings -o = s:taboption("Main", DummyValue, "_node_sel_shunt", "") -o.template = m:template_path("/cbi/hidevalue") -o.value = "1" +o = s:taboption("Main", HideValue, "_node_sel_shunt", "") o:depends({ node = "__always__" }) -o = s:taboption("Main", DummyValue, "_node_sel_other", "") -o.template = m:template_path("/cbi/hidevalue") -o.value = "1" +o = s:taboption("Main", HideValue, "_node_sel_other", "") o:depends({ _node_sel_shunt = "1", ['!reverse'] = true }) -- [[ DNS Settings ]]-- diff --git a/luci-app-passwall/luasrc/passwall/api.lua b/luci-app-passwall/luasrc/passwall/api.lua index c0f60b46..1204da36 100644 --- a/luci-app-passwall/luasrc/passwall/api.lua +++ b/luci-app-passwall/luasrc/passwall/api.lua @@ -1517,11 +1517,111 @@ function set_default_cbi() return cbi.AbstractValue.write(self, section, new_val) end end + if true then + --HideValue + local HideValue = util.class(cbi.DummyValue) + function HideValue.__init__(self, ...) + cbi.DummyValue.__init__(self, ...) + self.template = self.map:template_path("/cbi/hidevalue") + self.value = "1" + end + cbi.HideValue = HideValue + end +end + +function set_type_cbi(s) + local cbi = require "luci.cbi" + local s1 = s.parent + function s.option(s_self, class, option, ...) + local obj = class(s_self.map, s_self, option, ...) + obj.config_option = option + obj.option_prefix = s_self.option_prefix + obj.option = s_self.option_prefix .. option + obj.cfgvalue = function(self, section) + if self.rewrite_option then + return self.map:get(section, self.rewrite_option) + else + return self.map:get(section, self.config_option) + end + end + obj.write = function(self, section, value) + if s1.fields["type"]:formvalue(s_self.section) == s_self.type_name then + 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 + self.map:set(section, self.rewrite_option, new_val) + else + self.map:set(section, self.config_option, new_val) + end + end + end + obj.remove = function(self, section) + if s1.fields["type"]:formvalue(s_self.section) == s_self.type_name then + if self.rewrite_option then + self.map:del(section, self.rewrite_option) + else + self.map:del(section, self.config_option) + end + end + end + obj.deplist2json = function(self, section, deplist) + local deps, i, d = { } + if type(self.deps) == "table" then + if not next(self.deps) then + self:depends({ type = s.type_name }) + end + local list = deplist or self.deps + for i, d in ipairs(list) do + if s.type_name and not d["type"] then + d["type"] = s.type_name + end + local a, k, v = { } + for k, v in pairs(d) do + if k:find("!", 1, true) then + a[k] = v + elseif k:find("^", 1, true) then + a[k:sub(2)] = v + elseif k:find(".", 1, true) then + a['cbid%s' % k] = v + elseif s_self.fields[k] then + a['cbid.%s.%s.%s' %{ self.config, section, s_self.fields[k].option }] = v + else + a['cbid.%s.%s.%s' %{ self.config, section, k }] = v + end + end + deps[#deps+1] = a + end + end + return util.serialize_json(deps) + end + s_self:append(obj) + s_self.fields[option] = obj + return obj + end +end + +function type_cbi_section(s, s2) + for i, v in ipairs(s2.children) do + local o = s2.children[i] + s:append(o) + s.fields[o.option] = o + end end function return_map(map) local cbi = require "luci.cbi" - local api = require "luci.passwall.api" if true then -- header local header = cbi.Template(appname .. "/cbi/header") @@ -1537,91 +1637,6 @@ function return_map(map) return map end -function set_type_cbi(s) - local cbi = require "luci.cbi" - local s1 = s.parent - function s.option(self, class, option, ...) - local obj = class(self.map, self, option, ...) - obj.config_option = option - obj.option_prefix = self.option_prefix - obj.option = self.option_prefix .. option - obj.cfgvalue = function(o_self, section) - if o_self.rewrite_option then - return o_self.map:get(section, o_self.rewrite_option) - else - return o_self.map:get(section, o_self.config_option) - end - end - obj.write = function(o_self, section, value) - if s1.fields["type"]:formvalue(self.section) == self.type_name then - local new_val = value - if util.instanceof(o_self, cbi.DynamicList) then - local new_t = {} - if type(value) == "table" then - new_t = table_remove_duplicates(value) - else - new_t = { value } - end - if o_self.cast == "string" then - new_val = table.concat(new_t, " ") - else - new_val = new_t - end - end - if o_self.rewrite_option then - o_self.map:set(section, o_self.rewrite_option, new_val) - else - o_self.map:set(section, o_self.config_option, new_val) - end - end - end - obj.remove = function(o_self, section) - if s1.fields["type"]:formvalue(self.section) == self.type_name then - if o_self.rewrite_option then - o_self.map:del(section, o_self.rewrite_option) - else - o_self.map:del(section, o_self.config_option) - end - end - end - obj.depends = function(o_self, field, value) - local deps - if type(field) == "string" then - deps = {} - deps[field] = value - else - deps = field - end - local new_deps = {} - for k, v in pairs(deps) do - local n_k = k - if self.fields[k] then - n_k = self.fields[k].option - end - new_deps[n_k] = v - end - new_deps["type"] = self.type_name - if next(new_deps) then - table.insert(o_self.deps, new_deps) - end - end - self:append(obj) - self.fields[option] = obj - return obj - end -end - -function type_cbi_section(s, s2) - for i, v in ipairs(s2.children) do - local o = s2.children[i] - if #o.deps == 0 then - o:depends({ type = s2.type_name }) - end - s:append(o) - s.fields[o.option] = o - end -end - function get_std_domain(domain) domain = trim(domain) if domain == "" then return "" end diff --git a/luci-app-passwall/root/usr/share/passwall/app.sh b/luci-app-passwall/root/usr/share/passwall/app.sh index b71296d5..5c9c5f88 100755 --- a/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/luci-app-passwall/root/usr/share/passwall/app.sh @@ -337,10 +337,10 @@ run_socks() { [ -n "$config_file" ] && [ -z "$(echo ${config_file} | grep $TMP_PATH)" ] && config_file=$TMP_PATH/$config_file [ -n "$http_port" ] || http_port=0 [ -n "$http_config_file" ] && [ -z "$(echo ${http_config_file} | grep $TMP_PATH)" ] && http_config_file=$TMP_PATH/$http_config_file - if [ -n "$log_file" ] && [ "$log_file" != "/dev/null" ] && [ -z "$(echo ${log_file} | grep $TMP_PATH)" ]; then - log_file=$TMP_PATH/$log_file - else + if [ -z "$log_file" ] || [ "$log_file" = "/dev/null" ]; then log_file="/dev/null" + elif [ "${log_file#"$TMP_PATH/"}" = "$log_file" ]; then + log_file=$TMP_PATH/$log_file fi local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') @@ -1475,23 +1475,21 @@ acl_app() { esac } } - dns_cache_key="${dns_mode}_${remote_dns}_${v2ray_dns_mode:-none}_${remote_dns_client_ip:-0}_${remote_fakedns:-0}_${remote_rewrite_ttl:-30}" - ([ "$v2ray_dns_mode" = "doh" ] || [ "$v2ray_dns_mode" = "http3" ]) && { - dns_cache_key="${dns_mode}_${remote_dns_doh:-https://1.1.1.1/dns-query}_${v2ray_dns_mode:-doh}_${remote_dns_client_ip:-0}_${remote_fakedns:-0}_${remote_rewrite_ttl:-30}" - } + + local dns_cache_str="${dns_mode}_${v2ray_dns_mode}_${remote_dns}_${remote_dns_doh}_${remote_dns_client_ip}_${remote_fakedns}_${remote_rewrite_ttl}" + dns_cache_key="$(echo -n "${dns_cache_str}" | md5sum | cut -d " " -f1)" if [ "$remote_fakedns" = "1" ] || ([ "$protocol" = "_shunt" ] && [ "$(config_n_get $node fakedns)" = "1" ]); then use_fakedns=1 fi run_dns() { - local _dns_port - [ -n $1 ] && _dns_port=$1 - [ -z ${_dns_port} ] && { + local dns_fwd_port=$1 + [ -z "$dns_fwd_port" ] && { dns_port=$(get_new_port $(expr $dns_port + 1)) - _dns_port=$dns_port + dns_fwd_port=$dns_port if [ "$dns_mode" = "dns2socks" ]; then - run_dns2socks flag=acl_${sid} socks_address=127.0.0.1 socks_port=$socks_port listen_address=0.0.0.0 listen_port=${_dns_port} dns=$remote_dns cache=1 + run_dns2socks flag=acl_${sid} socks_address=127.0.0.1 socks_port=$socks_port listen_address=0.0.0.0 listen_port=$dns_fwd_port dns=$remote_dns cache=1 elif [ "$dns_mode" = "sing-box" ] || [ "$dns_mode" = "xray" ]; then config_file=$TMP_ACL_PATH/${node}_SOCKS_${socks_port}_DNS.json remote_dns_doh=${remote_dns_doh:-https://1.1.1.1/dns-query} @@ -1499,10 +1497,15 @@ acl_app() { [ "${dns_mode}" = "sing-box" ] && type="singbox" dnsmasq_filter_proxy_ipv6=0 remote_dns_query_strategy="UseIP" - [ "$filter_proxy_ipv6" = "1" ] && remote_dns_query_strategy="UseIPv4" - run_${type} flag=acl_${sid} type=$dns_mode dns_socks_address=127.0.0.1 dns_socks_port=$socks_port dns_listen_port=${_dns_port} remote_dns_protocol=${v2ray_dns_mode} remote_dns_udp_server=${remote_dns} remote_dns_tcp_server=${remote_dns} remote_dns_doh="${remote_dns_doh}" remote_dns_query_strategy=${remote_dns_query_strategy} remote_dns_client_ip=${remote_dns_client_ip} config_file=$config_file + [ "$filter_proxy_ipv6" = "1" ] && { + remote_dns_query_strategy="UseIPv4" + set_cache_var "node_${node}_${dns_cache_key}_ipv6" "0" + } + run_${type} flag=acl_${sid} type=$dns_mode dns_socks_address=127.0.0.1 dns_socks_port=$socks_port dns_listen_port=$dns_fwd_port \ + remote_dns_protocol=${v2ray_dns_mode} remote_dns_udp_server=${remote_dns} remote_dns_tcp_server=${remote_dns} remote_dns_doh="${remote_dns_doh}" \ + remote_dns_query_strategy=${remote_dns_query_strategy} remote_dns_client_ip=${remote_dns_client_ip} config_file=$config_file fi - set_cache_var "node_${node}_$(echo -n "${dns_cache_key}" | md5sum | cut -d " " -f1)" "${_dns_port}" + set_cache_var "node_${node}_${dns_cache_key}" "$dns_fwd_port" } [ "$dns_shunt" = "chinadns-ng" ] && [ -n "$(first_type chinadns-ng)" ] && { @@ -1531,7 +1534,7 @@ acl_app() { _flag="$sid" \ _listen_port=${chinadns_port} \ _dns_local=${_chinadns_local_dns} \ - _dns_trust=127.0.0.1#${_dns_port} \ + _dns_trust=127.0.0.1#${dns_fwd_port} \ _no_ipv6_trust=${filter_proxy_ipv6} \ _use_direct_list=${use_direct_list} \ _use_proxy_list=${use_proxy_list} \ @@ -1548,33 +1551,34 @@ acl_app() { use_default_dns="chinadns_ng" } + ([ "$filter_proxy_ipv6" = "1" ] && [ "$dnsmasq_filter_proxy_ipv6" = "1" ]) && { + dnsmasq_filter_proxy_ipv6=$(get_cache_var "node_${node}_${dns_cache_key}_ipv6") + dnsmasq_filter_proxy_ipv6=${dnsmasq_filter_proxy_ipv6:-1} + } + dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1)) local dnsmasq_conf=${acl_path}/dnsmasq.conf local dnsmasq_conf_path=${acl_path}/dnsmasq.d lua $APP_PATH/helper_dnsmasq.lua add_rule -FLAG ${sid} -TMP_DNSMASQ_PATH ${dnsmasq_conf_path} -DNSMASQ_CONF_FILE ${dnsmasq_conf} \ -LISTEN_PORT ${dnsmasq_port} -DEFAULT_DNS ${DEFAULT_DNS} -LOCAL_DNS $LOCAL_DNS \ -USE_DIRECT_LIST "${use_direct_list}" -USE_PROXY_LIST "${use_proxy_list}" -USE_BLOCK_LIST "${use_block_list}" -USE_GFW_LIST "${use_gfw_list}" -CHN_LIST "${chn_list}" \ - -TUN_DNS "127.0.0.1#${_dns_port}" -USE_DEFAULT_DNS "${use_default_dns:-direct}" -CHINADNS_DNS ${_china_ng_listen:-0} \ + -TUN_DNS "127.0.0.1#${dns_fwd_port}" -USE_DEFAULT_DNS "${use_default_dns:-direct}" -CHINADNS_DNS ${_china_ng_listen:-0} \ -NODE $node -DEFAULT_PROXY_MODE ${tcp_proxy_mode} -NO_PROXY_IPV6 ${dnsmasq_filter_proxy_ipv6:-0} -NFTFLAG ${nftflag:-0} \ -NO_LOGIC_LOG 1 ln_run "$(first_type dnsmasq)" "dnsmasq_${sid}" "/dev/null" -C ${dnsmasq_conf} -x ${acl_path}/dnsmasq.pid set_cache_var "ACL_${sid}_dns_port" "${dnsmasq_port}" - set_cache_var "node_${node}_$(echo -n "${tcp_proxy_mode}_${dns_cache_key}" | md5sum | cut -d " " -f1)" "${dnsmasq_port}" #dhcp.leases to hosts $APP_PATH/lease2hosts.sh > /dev/null 2>&1 & } - _redir_port=$(get_cache_var "node_${node}_redir_port") - _socks_port=$(get_cache_var "node_${node}_socks_port") - if [ -n "${_socks_port}" ] && [ -n "${_redir_port}" ]; then + local _redir_port=$(get_cache_var "node_${node}_redir_port") + local _socks_port=$(get_cache_var "node_${node}_socks_port") + local _enable_log=$(get_cache_var "node_${node}_enable_log") + local _dns_port + if [ -n "${_socks_port}" ] && [ -n "${_redir_port}" ] && [ "${_enable_log}" != "1" ] && [ "${log}" != "1" ]; then socks_port=${_socks_port} node_port=${_redir_port} - _dnsmasq_port=$(get_cache_var "node_${node}_$(echo -n "${tcp_proxy_mode}_${dns_cache_key}" | md5sum | cut -d " " -f1)") - if [ -z "${_dnsmasq_port}" ]; then - _dns_port=$(get_cache_var "node_${node}_$(echo -n "${dns_cache_key}" | md5sum | cut -d " " -f1)") - run_dns ${_dns_port} - else - [ -n "${_dnsmasq_port}" ] && set_cache_var "ACL_${sid}_dns_port" "${_dnsmasq_port}" - fi + _dns_port=$(get_cache_var "node_${node}_${dns_cache_key}") + run_dns ${_dns_port} else socks_port=$(get_new_port $(expr $socks_port + 1)) set_cache_var "node_${node}_socks_port" "${socks_port}" @@ -1582,7 +1586,10 @@ acl_app() { set_cache_var "node_${node}_redir_port" "${redir_port}" node_port=$redir_port local log_file="/dev/null" - [ "${log}" = "1" ] && log_file="${TMP_ACL_PATH}/${sid}/node.log" + [ "${log}" = "1" ] && { + log_file="${TMP_ACL_PATH}/${sid}/node.log" + set_cache_var "node_${node}_enable_log" "1" + } if [ "${type}" = "sing-box" ] || [ "${type}" = "xray" ]; then config_file="acl/${node}_${redir_port}.json" @@ -1592,7 +1599,10 @@ acl_app() { _dns_port=$dns_port dnsmasq_filter_proxy_ipv6=0 remote_dns_query_strategy="UseIP" - [ "$filter_proxy_ipv6" = "1" ] && remote_dns_query_strategy="UseIPv4" + [ "$filter_proxy_ipv6" = "1" ] && { + remote_dns_query_strategy="UseIPv4" + set_cache_var "node_${node}_${dns_cache_key}_ipv6" "0" + } remote_dns_doh=${remote_dns_doh:-https://1.1.1.1/dns-query} _extra_param="${_extra_param} dns_listen_port=${_dns_port} remote_dns_protocol=${v2ray_dns_mode} remote_dns_udp_server=${remote_dns} remote_dns_tcp_server=${remote_dns}" _extra_param="${_extra_param} remote_dns_doh=${remote_dns_doh} remote_dns_query_strategy=${remote_dns_query_strategy} remote_fakedns=${remote_fakedns:-0} remote_dns_client_ip=${remote_dns_client_ip}" diff --git a/luci-app-passwall/root/usr/share/passwall/iptables.sh b/luci-app-passwall/root/usr/share/passwall/iptables.sh index eeead0c2..af52ec30 100755 --- a/luci-app-passwall/root/usr/share/passwall/iptables.sh +++ b/luci-app-passwall/root/usr/share/passwall/iptables.sh @@ -417,7 +417,7 @@ load_acl() { [ "$_ipv4" != "1" ] && $ip6t_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} 2>/dev/null $ipt_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} [ "$_ipv4" != "1" ] && $ip6t_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} 2>/dev/null - [ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}使用与全局配置不相同节点,已将DNS强制重定向到专用 DNS 服务器。" + [ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}与全局配置不同节点,DNS 重定向到专用 DNS 服务器 [${dns_redirect}]。" fi [ -n "$tcp_port" ] || [ -n "$udp_port" ] && { diff --git a/luci-app-passwall/root/usr/share/passwall/nftables.sh b/luci-app-passwall/root/usr/share/passwall/nftables.sh index 95b29a6c..4e69e59d 100755 --- a/luci-app-passwall/root/usr/share/passwall/nftables.sh +++ b/luci-app-passwall/root/usr/share/passwall/nftables.sh @@ -478,7 +478,7 @@ load_acl() { #nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :${dns_redirect} comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :${dns_redirect} comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :${dns_redirect} comment \"$remarks\"" - [ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}使用与全局配置不相同节点,已将DNS强制重定向到专用 DNS 服务器。" + [ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}与全局配置不同节点,DNS 重定向到专用 DNS 服务器 [${dns_redirect}]。" fi [ -n "$tcp_port" ] || [ -n "$udp_port" ] && { diff --git a/luci-lib-linkeaseauth/Makefile b/luci-lib-linkeaseauth/Makefile index c2165cfe..b2f25004 100644 --- a/luci-lib-linkeaseauth/Makefile +++ b/luci-lib-linkeaseauth/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI shared OpenWrt auth bridge for LinkEase apps LUCI_PKGARCH:=all -PKG_VERSION:=1.0.1 -PKG_RELEASE:=2 +PKG_VERSION:=1.0.3 +PKG_RELEASE:=1 include $(TOPDIR)/feeds/luci/luci.mk diff --git a/shortcut-fe/shortcut-fe/Makefile b/shortcut-fe/shortcut-fe/Makefile index 9c1c0de4..26feaeed 100644 --- a/shortcut-fe/shortcut-fe/Makefile +++ b/shortcut-fe/shortcut-fe/Makefile @@ -16,7 +16,7 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=shortcut-fe -PKG_RELEASE:=10 +PKG_RELEASE:=11 include $(INCLUDE_DIR)/package.mk @@ -70,7 +70,6 @@ define Build/Compile $(KERNEL_MAKE_FLAGS) \ $(PKG_MAKE_FLAGS) \ M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS+="-DSFE_SUPPORT_IPV6" \ SFE_SUPPORT_IPV6=y \ modules endef diff --git a/shortcut-fe/shortcut-fe/src/Makefile b/shortcut-fe/shortcut-fe/src/Makefile index 991a20ec..85545bad 100644 --- a/shortcut-fe/shortcut-fe/src/Makefile +++ b/shortcut-fe/shortcut-fe/src/Makefile @@ -10,6 +10,8 @@ endif obj-m += shortcut-fe-cm.o +ccflags-$(SFE_SUPPORT_IPV6) += -DSFE_SUPPORT_IPV6 + shortcut-fe-objs := \ sfe_ipv4.o