TPROXY DNS 冲突详解 | AI生成和翻译

Home 2026.03

问题: 在 Clash TPROXY 设置中,我们可以设置 dns: enable: false 并使用 systemd-resolved 代替吗?

答案:

简短回答:技术上是的,但这会破坏基于域名的路由规则。 原因如下。


为什么在 TPROXY 模式下不能简单禁用 Clash DNS

核心问题:TPROXY 看到的是 IP,而不是域名

当 iPad 流量到达 TPROXY 端口时,Clash 只看到带有 IP addresses 的原始 TCP/UDP 数据包。它不知道最初请求的域名。例如:

Clash sees:  192.168.201.136:54321 → 142.250.80.46:443
Clash needs: "this is google.com → route via proxy"

如果没有自己的 DNS 拦截原始查询,Clash 无法匹配基于域名的规则,例如:

- DOMAIN-SUFFIX,google.com,Proxy
- DOMAIN-SUFFIX,baidu.com,DIRECT
- GEOSITE,cn,DIRECT

DNS 查询通过 UDP 发送,无法通过标准的 iptables 规则重定向,这可能导致不正确的结果。这就是为什么使用 Clash 的内置 DNS 来替换 systemd-resolved —— 它记住从域名到 IP 的映射,因此 Clash 知道重定向连接的域名,并可以应用与域名相关的规则。


各种场景下会发生什么

场景 A:dns: enable: false + systemd-resolved

iPad → DNS query → systemd-resolved → returns real IP (e.g. 142.250.80.46)
iPad → connects to 142.250.80.46:443
iptables TPROXY → Clash receives packet
Clash: "What domain is this? I don't know." → can only match by IP/GEOIP
→ Domain rules like DOMAIN-SUFFIX,google.com ALL FAIL
→ Only IP-CIDR and GEOIP rules still work

你的代理路由变得非常粗糙——一切要么走 DIRECT 要么 PROXY,没有域名级控制。

场景 B:dns: enable: true + Clash DNS(当前推荐)

iPad → DNS query → Clash DNS (port 53) → Clash records "198.18.0.5 = google.com"
iPad → connects to 198.18.0.5:443 (real IP in redir-host mode)
iptables TPROXY → Clash receives packet
Clash: "I know 142.250.80.46 = google.com" → matches DOMAIN rules correctly
→ Full domain-based rule matching works ✅

端口 53 冲突问题

人们想要禁用 Clash DNS 的真正原因是 systemd-resolved 已经占用了端口 53,导致 Clash 无法启动。在 Clash 的 DNS 模块工作之前,你可能需要杀死 systemd-resolved 和任何占用 UDP 端口 53 的其他进程。

正确的修复不是禁用 Clash DNS,而是释放端口 53:

# Stop systemd-resolved from occupying port 53
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved

# Point resolv.conf to Clash directly
sudo rm /etc/resolv.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf

# Now Clash can listen on 0.0.0.0:53

或者,更优雅的方法——让 Clash 监听 127.0.0.53:53(systemd-resolved 使用的确切地址),然后将 systemd-resolved 的上游指向 Clash:

# Clash config: listen on systemd-resolved's stub address
dns:
  enable: true
  listen: 127.0.0.53:53     # takes over systemd-resolved's slot
  enhanced-mode: redir-host
  nameserver:
    - 223.5.5.5
    - 119.29.29.29

配置 Clash 监听 127.0.0.53:53 后,使用 dnsmasq 作为 DNS 缓存层,server=127.0.0.53 指向 Clash,并将 /etc/resolv.conf 设置为使用 dnsmasq 作为本地解析器。


决策树:何时可以禁用 Clash DNS?

你的规则 可以禁用 Clash DNS 吗?
IP-CIDRGEOIP 规则 ✅ 是的,工作正常
DOMAIN-SUFFIXDOMAIN-KEYWORD 规则 ❌ 否,域名匹配会中断
GEOSITE 规则(例如 cn 站点 DIRECT) ❌ 否,GEOSITE 需要域名数据
MATCH 捕获所有 ✅ 是的(一切走一个代理)

对于你的用例(中国站点 DIRECT,其他一切通过 Hysteria2),你必须保持 Clash DNS 启用,因为你依赖基于域名的路由决策。


推荐设置(干净地避免端口冲突)

# 1. Disable systemd-resolved stub listener (but keep the service)
sudo mkdir -p /etc/systemd/resolved.conf.d/
sudo tee /etc/systemd/resolved.conf.d/no-stub.conf << EOF
[Resolve]
DNSStubListener=no
EOF
sudo systemctl restart systemd-resolved

# 2. Now Clash can freely take port 53
# In Clash config:
# dns:
#   enable: true
#   listen: 0.0.0.0:53

这保持 systemd-resolved 运行(用于笔记本电脑自身的名称解析),但让 Clash 拥有端口 53 用于面向 iPad 的接口。

引用:


Back Donate