DNS与FakeIP排障:污染、副作用、TUN调优

1. GFW 旁路注入:你被怎么污染的

明文 DNS 经过国际出口时,GFW 站在光纤旁边偷看。每个查询包它瞥一眼里面的域名,命中黑名单(google.comyoutube.com 这类),立刻伪造一个回包,源地址写成你查的 DNS 服务器 IP,发回给你。

%%{init: {'theme': 'base', 'themeVariables': {'actorBkg': '#3B82F6', 'actorTextColor': '#000'}}}%%
sequenceDiagram
    autonumber
    participant App as "你的应用"
    participant DNS as "上游 DNS<br/>(8.8.8.8 / 阿里)"
    participant GFW as "GFW (旁路)"

    App->>DNS: "查 youtube.com (明文 UDP)"
    Note over GFW: "偷看到域名命中黑名单"

    par 正常应答
        DNS-->>App: "真实 IP (慢)"
    and GFW 抢答
        GFW-->>App: "伪造 IP 93.46.8.x (更快到)"
    end

    Note over App: "UDP 没法验证哪个真<br/>用先到的那个"
    App->>App: "连了 93.46.8.x (打不开)"

伪造包从 GFW 设备直接发出来,路径比 “ 真 DNS 服务器答复 “ 短得多,几乎总是先到。UDP 协议没法验证哪个是真,系统采信先到的那个。真答复后到时被当成 “ 重复包 “ 直接扔了。

“ 我换用 8.8.8.8 怎么也被污染 “? 因为 GFW 不管你查的是哪个 DNS,它只看请求里的域名。换 DNS 服务器没用,必须加密查询内容(让 GFW 看不到域名) 或绕开 UDP(用 TCP)。这就是为什么 DoH(DNS over HTTPS) 是默认推荐——HTTPS 加密之后 GFW 看不到里面查的是啥。

GFW 抢答的假 IP 不是随机的,集中在固定几段:

投毒 IP 段特征
93.46.8.x意大利
203.98.7.x新西兰
8.7.198.xLevel3 网段
240.0.0.0/4IANA 保留段(正常网络绝不会出现)

这个特征催生了第 3 章的 fallback-filter——“ 看到回来的是这几个段,当作被污染,用 fallback 的结果 “。

2. Fake-ip 副作用:局域网瘫痪 + 直连还原

fake-ip 撒了个 “ 谎 “——它给应用的不是真 IP。多数场景这无所谓,但有两类场景会翻车。

2.1 局域网打印机被瞬间废掉

家里的网络打印机叫 printer.local,NAS 叫 nas.lan,公司的代码服务器叫 gitlab.internal.company.com。它们都是域名。

fake-ip 模式下 Clash 不管三七二十一:你查 printer.local,我发个 198.18.0.7。电脑收到 198.18.0.7,真的把打印任务发到这个地址。Clash 截胡这个连接,查表知道 “ 这个 IP 对应 printer.local”,然后……然后它去哪?打印机在你局域网,Clash 既不知道它真实 IP,也没法用代理节点访问。结果是打印机连不上、Bonjour 设备发现失败、AirPlay 投屏没设备。

救法是告诉 fake-ip:” 这几个域名别给假 IP,放过 “。这就是 fake-ip-filter:

1
2
3
4
5
6
7
8
9
10
11
dns:
enhanced-mode: fake-ip
fake-ip-filter:
- "*.lan" # 路由器 / NAS 这种局域网域名
- "*.local" # mDNS / Bonjour
- "+.internal.company.com" # 公司内网
- "+.msftncsi.com" # Windows 检测网络是否通的探针
- "+.pool.ntp.org" # NTP 校时(fake-ip 会让校时失败)
- "+.stun.*" # WebRTC / 视频会议
- "*.music.163.com" # 网易云 IP 校验
- "*.srv.nintendo.net" # 任天堂游戏验证

匹配到这里的域名走 redir-host 路线——正常解析、拿到真 IP、走直连或代理规则。

精心型机场订阅会写一份很全的 filter。敷衍型订阅没写,这就是为什么开了 TUN 之后 printer.local 突然找不到——不是 Clash 的锅,是订阅没写 filter。

2.2 翻车现场:Navicat 连 AWS RDS 被错代理到 Netflix

上一节讲了直连分支怎么 “ 反查域名拿真 IP” 的机制,听起来 fake-ip + 域名规则配合得很好。但当分流规则用的是 IP 段而不是域名时,会出一类特别隐蔽的翻车。

实例:你用 Navicat 连 AWS 中国区的 RDS,域名长这样:

1
xxx.cn-northwest-1.rds.amazonaws.com.cn

明明是国内服务(IP 在国内宁夏机房),却莫名其妙连不上。打开 Clash 日志一看:

1
2
[TCP] 198.18.0.1:51627(Navicat) --> 34.208.231.7:22
match IPCIDR(34.208.0.0/12) using Netflix

34.208.0.0/12 这条 IP 段规则把它当成了海外服务,丢给了 Netflix 节点。Netflix 节点在洛杉矶,绕地球半圈回宁夏,能连上才奇怪。

为什么会这样

  1. Navicat 拿到的是 fake-ip 198.18.0.x,真正去连接时 Clash 反查到 amazonaws.com.cn
  2. 但分流规则没有 DOMAIN-SUFFIX,amazonaws.com.cn,DIRECT,只有按 IP 段写的 IP-CIDR,34.208.0.0/12,Netflix
  3. Clash 为了匹配 IP 段规则,调用本地 DNS 解析 amazonaws.com.cn,拿到 34.208.231.7 (AWS 在全球用一张 IP 表)
  4. 这个 IP 命中了 34.208.0.0/12,被分给 Netflix

根因:AWS 在全球用一张 IP 表,34.208.x.x 在多数规则集里被划进 “ 海外 AWS”。但 AWS 中国是合资公司单独运营、用了另一套 IP 段——规则维护者不可能穷举,必然漏。

救场方法 1(推荐):给目标 IP 加一条精确直连:

1
IP-CIDR,34.208.231.7/32,DIRECT,no-resolve

no-resolve 这个尾巴的意思是:” 这条规则按 IP 匹配,不要为了它去做 DNS 查询“。两个好处:

  • 对方本来就是 IP 连接(Navicat 配的就是 IP)——免去无意义解析
  • 对方是域名连接时,也不会因为这条 IP 规则触发反向解析,导致 fake-ip 的 198.18.x.x 被错误地交给 DNS 模块去查

救场方法 2(更通用):给域名加一条直连,优先级放在 IP 规则之前:

1
2
3
4
DOMAIN-SUFFIX,amazonaws.com.cn,DIRECT
DOMAIN-SUFFIX,aliyuncs.com,DIRECT
DOMAIN-SUFFIX,myqcloud.com,DIRECT
# 在所有 IP-CIDR 规则之前

域名规则优先级高、不依赖 GeoIP 数据库,是最稳的方法。

反面教材:很多人遇到这种情况会去切 Global 模式想 “ 全代理总行了吧 “,但 Global 反而把这台 RDS 强制扔到 Netflix,更连不上。Global ≠ 解决一切,见 第一篇 ch.8 的澄清。

2.3 Navicat 连 AWS RDS 凭什么直连

Navicat 用域名连国内 AWS RDS,需要直连。fake-ip 模式下,Navicat 拿到的是 198.18.0.x 这种假 IP,怎么直连?

关键在分流引擎做了一次 “ 反查 “:

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6', 'primaryTextColor': '#fff', 'lineColor': '#60A5FA'}}}%%
flowchart TD
    A["Navicat 查 xxx.rds.amazonaws.com.cn"] --> B["Clash 发 198.18.0.9"]
    B --> C["Navicat 连 198.18.0.9:3306"]
    C --> D["Clash 截胡 → 查表知道是 amazonaws.com.cn"]
    D --> E{"匹配规则"}
    E -->|"DOMAIN-SUFFIX,amazonaws.com.cn,DIRECT"| F["调本地 nameserver<br/>查真实 IP"]
    F --> G["拿到 161.189.x.x"]
    G --> H["直连 161.189.x.x:3306"]

    classDef key fill:#F59E0B,stroke:#D97706,color:#000
    classDef ok fill:#10B981,stroke:#059669,color:#fff
    class F key
    class H ok

注意第 6 步——直连分支会临时绕开 fake-ip,真去解析一次。这就是为什么直连场景下,本地 nameserver 也得配对(多数机场订阅会指向国内 DNS 比如阿里)。

如果日志报 “ 直连域名解析失败 “,通常是机场的 nameserver 全配的是境外 DNS(比如 8.8.8.8),国内域名走不通。解法是用脚本(见第 5 章)把 nameserver-policygeosite:cn 单独指给国内 DNS。

3. Fallback / Fallback-filter / Nameserver-policy 三件套

精心型机场的 dns: 块通常长成这样,理解了这三件套就能看懂大部分配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
dns:
nameserver: # 主用:国内 DNS,解析国内域名快
- https://dns.alidns.com/dns-query

fallback: # 备胎:境外 DNS,解析被污染域名
- https://1.1.1.1/dns-query
- https://8.8.8.8/dns-query

fallback-filter: # 什么时候采用 fallback 的结果
geoip: true
geoip-code: CN # 主用返回的 IP 不在 CN → 当作被污染,用 fallback
ipcidr:
- 240.0.0.0/4 # 主用返回这些段 → 必是污染,用 fallback
domain:
- "+.google.com" # 这些域名永远直接走 fallback
- "+.youtube.com"

nameserver-policy: # 指定特定域名走特定 DNS
"geosite:cn": "https://dns.alidns.com/dns-query"
"+.internal.company.com": "10.0.0.1" # 公司内网域名走内网 DNS

工作流程:

  1. nameserverfallback 并发发查询(不是串行)
  2. nameserver 先回,用 fallback-filter 判断:可信吗?
  3. 可信 → 用 nameserver 的结果(快)
  4. 不可信 → 等 fallback 的结果用(保险)
  5. nameserver-policy 优先级最高,命中就跳过上面整套流程

这套设计的核心思想:国内域名走国内 DNS(快),境外域名走境外 DNS(防污染)。判断 “ 这个域名是国内还是境外 “ 不靠你列名单,靠 GeoIP——看主用 DNS 给你的 IP 是不是中国。

4. TUN 三档力度:gVisor / Mixed / System

Clash Verge 里 TUN 不止一个开关。点进 “ 虚拟网卡模式 “ 的齿轮,能选 “ 堆栈 “(stack)。这就是 TUN 的接管力度:

堆栈接管什么什么时候要代价
gVisor(增强,默认)TCP 全管,UDP 基础管日常浏览 + 终端 + IDE几乎无
Mixed(混合)TCP + UDP 都更彻底需要 UDP 的应用:部分游戏 NAT、WebRTC、视频会议偶发兼容问题
System(系统栈 / 游戏档)直接用操作系统的网络栈,接管最狠上面两档都搞不定的极端情况macOS 上偶尔崩、对系统侵入大

底层原理差异:

  • gVisor:Google 出的用户态 TCP/IP 协议栈,Clash 自己解析 IP 包、TCP 握手、流量控制。优点是隔离性好、不依赖系统、跨平台。缺点是 UDP 性能一般、某些 UDP 协议(如 QUIC、游戏的自定义 UDP)兼容性差
  • Mixed:TCP 用 gVisor、UDP 用更激进的接管。多数 UDP 场景能跑,代价是出问题难定位
  • System:直接调用操作系统的 socket(macOS 上是 utun 设备 + PF 路由),等于让 Clash 用宿主机的协议栈。性能最好,但崩了可能影响系统网络栈,且不同 macOS 版本行为不一致

兜底建议:默认用 gVisor,别折腾。除非:

  • 打游戏 NAT 卡了(典型:交换机 / Switch 上联机 NAT 受限)→ 升级 Mixed
  • WebRTC 视频会议有问题 → 升级 Mixed
  • Mixed 也搞不定 → 试 System(自己评估系统稳定性风险)

5. 实战配置模板:用脚本注入完整 Dns 块

如果你的订阅是上一篇 ch.6.3 里的 “ 中等型 “ 或 “ 敷衍型 “,直接开 DNS 覆写会把订阅里仅有的几行也盖掉。更好的做法是用 Verge 的全局扩展脚本注入——既补全缺失字段,又保留订阅原有的(比如机场专属 nameserver-policy)。

操作位置:Clash Verge 订阅页底部 → “ 全局扩展脚本 “ → 点编辑图标 → 粘贴下面这段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
function main(config) {
const cnDns = [
"https://223.5.5.5/dns-query",
"https://1.12.12.12/dns-query",
];
const trustDns = [
"https://1.1.1.1/dns-query",
"https://8.8.8.8/dns-query",
];

// 合并而非替换:保留订阅原有的 nameserver-policy 等
const existing = config.dns || {};
const existingPolicy = existing["nameserver-policy"] || {};
const existingFilter = existing["fake-ip-filter"] || [];

config.dns = {
...existing,
enable: true,
"prefer-h3": true,
"enhanced-mode": "fake-ip",
"fake-ip-range": "198.18.0.1/15",
"fake-ip-filter": [
...existingFilter, // 保留订阅自带的 filter
"*.lan", "*.local", "*.direct",
"+.msftncsi.com", "+.msftconnecttest.com",
"+.ntp.org", "+.pool.ntp.org",
"+.stun.*", "+.stun.*.*",
"*.music.163.com", "*.126.net",
"localhost.ptlogin2.qq.com",
// 这里加你自己的内网域名
"+.internal.your-company.com",
],
"default-nameserver": ["223.5.5.5", "119.29.29.29"],
nameserver: cnDns,
fallback: trustDns,
"fallback-filter": {
geoip: true,
"geoip-code": "CN",
ipcidr: ["240.0.0.0/4", "0.0.0.0/32"],
},
"nameserver-policy": {
...existingPolicy, // 保留订阅自带的 policy
"geosite:cn": cnDns,
"geosite:geolocation-!cn": trustDns,
},
};
return config;
}

要点:

  • default-nameserver 必须是纯 IP(不能是 https:// 域名),因为它专门用来解析其他 DNS 服务器的域名,鸡和蛋问题
  • prefer-h3: true 优先用 DoH3(最快的加密 DNS,见附录)
  • nameserver-policy 用 GeoSite 把国内外域名分给不同 DNS,避免国内域名走境外 DNS 慢
  • fake-ip-filter 用 spread 语法保留订阅原有条目,再追加你自己关心的
  • DNS 覆写开关要保持关——脚本注入和覆写是两条互斥路径,开覆写会让脚本白注

保存后右键订阅 → “ 重新激活订阅 “ 才会生效。

6. 常见问题速查

现象原因解决
ping 域名返回 198.18.x.x,以为代理坏了ping 用 ICMP 不走代理,看到的是 fake-ip。用 curl -I https://xxx 验代理不用解决,这是正常的
内网打印机 / NAS 找不到mDNS / .local 被分配了假 IP加进 fake-ip-filter
双重 DNS 拦截,解析异常路由器 OpenClash + 设备 Verge 都接管了二选一,别套娃
WebRTC 泄漏真实 IP浏览器 P2P 绕过代理浏览器装 WebRTC 防泄漏插件
Verge 重启后短暂断网映射表清空,应用缓存的假 IP 失效store-fake-ip: true
银行 / 金融 App 无法登录应用校验 IP 归属地,假 IP 不通过把该 App 域名加 fake-ip-filter
nslookup xxx 114.114.114.114 返回 198.18.x.xTUN 已经截胡所有 DNS,你指定的 DNS 服务器没用想看真 IP 把域名加 fake-ip-filter
国内域名访问慢、走了境外节点机场 nameserver 全是境外 DNS,国内域名也走 fallback用第 5 章脚本,给 geosite:cn 单独指国内 DNS
直连域名报 “ 解析失败 “同上,机场 nameserver 配置不当同上