Linux 上如何检测并修复 VPN 的 DNS 泄漏
Linux 里有好几层决定 DNS 请求的去向。本文教你在 VPN 连接时查出到底是哪一层在应答,并在 systemd-resolved、NetworkManager 和 resolv.conf 上逐一修复。
阅读约 9 分钟更新于 2026年10月15日作者:XPASS Editorial Team

在 Linux 上,VPN 的 DNS 泄漏是一个很常见的现象:隧道看上去完全正常,ip addr 里能看到 VPN 接口,公网 IP 也变了,但咖啡馆的路由器、酒店网关或者运营商仍然在回答你的 DNS 查询,也就知道你访问了哪些网站。原因在于 Linux 并没有一个统一的地方来“做 DNS”,而是由多个组件协作完成,其中任何一个都可能继续使用旧的解析器。
本文是一份面向桌面和服务器用户的实操指南:怎样找出是哪一层在应答,怎样用抓包证明,以及在三种最常见的环境里怎样修复,分别是 systemd-resolved、NetworkManager 和普通的 /etc/resolv.conf。如果你想先了解概念,可以阅读 什么是 DNS 泄漏 和 DNS 是如何工作的。
为什么 Linux 上特别容易配错
Windows 和 macOS 基本只有一个主要的解析服务,而 Linux 的情况取决于发行版和网络的配置方式。一台典型的桌面机器大致有下面几层叠在一起。
- 应用程序与 C 库:程序调用 C 库,C 库先参考
/etc/nsswitch.conf,再读取/etc/resolv.conf。 - 存根解析器:在 Ubuntu、Fedora 等系统上,
/etc/resolv.conf指向127.0.0.53,这是 systemd-resolved 的本地监听地址。有些系统用的是 dnsmasq 或其他本地缓存。 - 网络管理器:NetworkManager、systemd-networkd 或 ifupdown 负责决定哪个接口用哪些 DNS 服务器,并通知解析器。
- 浏览器:Firefox 和 Chromium 系浏览器可以绕过系统解析器,直接向 DNS-over-HTTPS 服务器发问。
- 容器与虚拟机:Docker、Podman 和虚拟机往往带着自己的解析器设置。
VPN 客户端通常只动其中一层,有时一层都不动。用裸 ip link add 建立的隧道,或者没有 DNS = 这一行的最简 WireGuard 配置,只会改变路由,而解析器保持原样。这就是典型的泄漏:网页流量进了隧道,DNS 请求却仍然发给路由器。

第一步:查出谁在应答 DNS
动手修改之前,先在 VPN 已连接的状态下取得基线。
- 运行
resolvectl status。它会列出每个接口(称为 link)的 DNS 服务器、搜索域,以及一行Default Route。如果物理接口例如wlp3s0显示Default Route: yes,而 VPN 接口显示no,说明普通请求正从物理接口发出。 - 运行
resolvectl query example.com。最后几行会说明由哪个 link 应答,例如link: wlp3s0或link: wg0。你希望看到的是 VPN 接口。 - 运行
cat /etc/resolv.conf。如果里面是nameserver 127.0.0.53,说明 systemd-resolved 在管理;如果是192.168.1.1这样的私有地址,说明系统在直接和路由器对话。 - 运行
ip route get 1.1.1.1。输出会给出内核访问该目标时选用的接口。如果显示的是物理接口,说明连普通流量都还没有进隧道,你面对的是路由问题,而不仅仅是 DNS 问题。
如果你没有使用 systemd-resolved,resolvectl 会提示服务未运行,请直接跳到下面关于 NetworkManager 和 resolv.conf 的部分。
第二步:在网线上取证
配置只能告诉你“应该发生什么”,抓包才能告诉你“实际发生了什么”。打开两个终端。
第一个终端运行:
sudo tcpdump -ni any 'udp port 53 or tcp port 53'
第二个终端请求几个最近没访问过的域名:
resolvectl flush-caches
getent hosts example.org
dig +short example.net
留意抓包结果里的接口名称列。出现在 wg0 或 tun0 上的请求已在隧道内,在物理接口上只会表现为加密流量。出现在 wlp3s0 或 eth0 上、目的地是路由器或公共解析器的请求,则是通过普通网络发出的,这些就是泄漏。
有两个细节可避免误判。第一,存根地址 127.0.0.53 永远出现在 lo 接口上,它只是本机内部通信,无害。第二,隧道里的 DNS 由隧道加密,所以一切正常时你在物理接口上根本看不到 53 端口,只会看到加密的 VPN 数据包。最后可以再用浏览器里的在线泄漏检测交叉验证,其余检查可参考 如何测试 VPN。
如何解读结果
| 你看到的现象 | 含义 | 下一步 |
|---|---|---|
| 请求只出现在 VPN 接口 | 这条路径没有泄漏 | 继续测试 IPv6 和浏览器 |
| 请求在物理接口上发往路由器 | 解析器仍跟随旧接口 | 按接口设置 DNS,并让 VPN 接口成为默认路由 |
| 请求在物理接口上发往公共解析器 | 浏览器 DoH 或硬编码的服务器 | 检查浏览器与应用配置 |
| 请求在两个接口上交替出现 | 存在多个默认路由接口 | 从物理接口移除 DNS,或使用路由域 |
| 修复后什么都没有 | 解析可能已失效 | 确认 VPN 的 DNS 地址能通过隧道访问 |
修复方案一:systemd-resolved 按接口设置 DNS
这是最干净的做法,因为 systemd-resolved 本来就是为多接口设计的。思路是给 VPN 接口配置专属的 DNS 服务器,并让它负责所有域名。
- 在 VPN 接口上设置服务器:
sudo resolvectl dns wg0 10.0.0.1。请使用你的 VPN 配置所提供的解析器地址。 - 用通配路由域让它负责所有名称:
sudo resolvectl domain wg0 '~.'。波浪号表示把这个域的查询路由到这里,而不把它加入搜索列表。 - 关闭物理接口的默认路由,让它只回答自己的本地名称:
sudo resolvectl default-route wlp3s0 no。 - 再次用
resolvectl status和resolvectl query example.com检查。
这些设置只在接口存在期间有效。要让 WireGuard 的设置长期生效,可以在配置文件里写 DNS = 10.0.0.1,接口启动时 wg-quick 会把它交给解析器工具。在 resolvconf 由 systemd 提供的系统上,这个调用最终会变成上面的命令。每次重启后请用 resolvectl status 实际验证,不要凭想象。
修复方案二:NetworkManager
由 NetworkManager 管理连接时,应在连接配置文件上修改 DNS,这样重新连接后设置仍然有效。
- 给 VPN 配置文件一个负优先级:
nmcli connection modify "my-vpn" ipv4.dns-priority -50 ipv4.ignore-auto-dns yes。负值会让 NetworkManager 只使用该配置文件里的服务器。 - 对 Wi-Fi 或以太网配置文件,告诉它在 VPN 期间不要使用路由器的 DNS:
nmcli connection modify "Home Wi-Fi" ipv4.ignore-auto-dns yes,然后重新连接。 - 如果网络通告了 IPv6 解析器,也要加上
ipv6.ignore-auto-dns yes。 - 对修改过的配置文件执行
nmcli connection down再up。
代价是断开 VPN 之后,物理连接的配置文件如果没有自己的 DNS 就无法解析。很多人会为同一个 Wi-Fi 保留两份配置文件,或者在退出 VPN 时临时手动改一下。
修复方案三:普通 resolv.conf 与其他解析器
在精简的服务器或较旧的发行版上,/etc/resolv.conf 可能只是一个普通文件。你可以把 VPN 的解析器写进去,但任何会重写该文件的程序(例如 DHCP 客户端)都会抹掉你的修改。更稳妥的做法有两种:
- 交给 VPN 脚本管理。
resolvconf、openresolv这类工具会保存多个来源的列表并按优先级合并,隧道启动期间 VPN 的条目会取代路由器的条目,隧道关闭后又会自动撤销。 - 如果非要固定文件,请把它当作有意识的决定并留下记录。用
chattr +i冻结文件,也会冻结此后所有正当的变更,下次开机或换网络时常常导致断网。笔记本电脑上不建议这样做。
如果你运行了 dnsmasq 或 unbound 这样的本地缓存解析器,应修改它的上游服务器而不是那个文件,并在隧道启停时重启它。

IPv6 与浏览器的 DNS-over-HTTPS
有两种泄漏即便是谨慎的用户也容易忽略。第一种是 IPv6。如果路由器通告了 IPv6 的 DNS 服务器,而 VPN 只覆盖 IPv4,请求可能从 IPv6 路径泄出。请在 resolvectl status 中检查物理接口下是否有 IPv6 地址,然后让 IPv6 也走隧道,或在测试期间用 NetworkManager 的 ipv6.method disabled 关闭该连接的 IPv6。IPv6 泄漏 一文有更深入的说明。
第二种是浏览器。Firefox 可以使用自带的提供商列表进行 DNS-over-HTTPS,Chromium 系浏览器则可能跟随系统设置,也可能使用自己的设置。这些请求封装在访问 443 端口的 HTTPS 连接里,因此不会出现在你对 53 端口的抓包中,也不理会你刚刚修好的解析器。请有意识地做决定:要么让浏览器使用系统解析器,要么在知情的前提下选定某个 DoH 服务器。DNS over HTTPS 与 VPN 的比较 解释了两者的关系。
用防火墙规则堵住漏网的请求
设置正确之后,再加一道保险,让将来的配置失误以“关闭”的方式失败,而不是泄漏。下面这张小小的 nftables 表会丢弃试图从隧道和回环以外的接口发出的明文 DNS:
table inet dnsguard {
chain output {
type filter hook output priority 0; policy accept;
oifname != "wg0" oifname != "lo" udp dport 53 drop
oifname != "wg0" oifname != "lo" tcp dport 53 drop
}
}
用 sudo nft -f dnsguard.nft 加载,用 sudo nft delete table inet dnsguard 删除。有两点要注意。第一,规则生效且隧道断开时,DNS 会完全失效,这正是目的,却常让人意外。建议把加载和删除绑定到接口的启停上,例如使用 PostUp 与 PostDown。第二,VPN 客户端仍需要解析服务器的名称,所以请把 endpoint 写成确切的 IP 地址,或者只在首次连接成功后再加载规则。这一思路的整体介绍见 VPN 断线保护(Kill Switch)是什么。
常见错误
- 只用网站上的泄漏检测,从不看抓包结果。
- 修改了
/etc/resolv.conf,却不明白为什么休眠唤醒后又恢复原样。 - 在 VPN 配置里写了
DNS =,但系统没有resolvconf或相应的解析器集成,这一行被悄悄忽略。 - 忘记容器,它们保留自己的解析器,可能绕过主机的设置。
- 只修了 IPv4,路由器仍在通告 IPv6。
- 以为公网 IP 变了就等于修好了。地址和解析器是两个独立的问题。
总结
Linux 上的 DNS 泄漏几乎从来不是隧道本身的问题,而是解析器栈、网络管理器、浏览器或 IPv6 仍然沿用旧路径。先用 resolvectl 找到应答的那一层,用 tcpdump 取证,再通过按接口设置 DNS 或调整连接优先级来修复,最后加上防火墙规则让失误以关闭方式收场。每次重启和更换网络后都要重新测试一遍。
如果你使用免费的 VPNclient 应用连接,Linux 设置指南 介绍了安装方法,准备好之后也可以到 价格页面 了解选项。
常见问题
隧道明明正常,为什么 Linux 上的 VPN 还会发生 DNS 泄漏?
隧道只负责承载被路由表送进去的数据包。DNS 请求由另一层解析器产生,如果这一层仍然指向路由器的地址,请求就会走普通网络,即使你的网页流量已经走了 VPN。
哪条命令能看出我的 DNS 请求去了哪里?
使用 systemd-resolved 的系统可以运行 resolvectl status 查看各接口的 DNS 服务器,再用 resolvectl query example.com 查看由哪个 link 应答。想在网线上取证,可以在浏览时运行 sudo tcpdump -ni any port 53。
手动修改 /etc/resolv.conf 是个好办法吗?
通常不是。多数现代发行版的这个文件由 systemd-resolved 或 NetworkManager 生成,网络一变化你的修改就会被覆盖。应当在连接配置或接口上设置 DNS。
DNS 泄漏还需要考虑 IPv6 吗?
需要。如果网络下发了 IPv6 解析器,而 VPN 只覆盖 IPv4,请求可能从 IPv6 路径泄出。用 resolvectl status 检查有没有 IPv6 服务器,然后让 IPv6 也走隧道,或在该连接上关闭 IPv6。
参考资料
关于作者

Bob Kanokphon Thongdee
- XPASS VPN 创始人
- eSIMonline.asia 联合创始人
- 7 年以上网络营销经验
- Cojourney Visa 与 Cojourney Travel 创始人
继续阅读

VPN 安全
VPN 的 Split DNS(分流 DNS)是什么
Split DNS 让设备按域名选择不同的解析器:内部名称走 VPN,其他名称走平时的解析器。本文介绍原理、使用场景和检查方法。
阅读约 9 分钟

设备指南
如何修复 Windows 上的 VPN DNS 泄漏
为什么 Windows 会把 DNS 查询发到 VPN 之外,如何用系统自带工具确认泄漏,以及对大多数电脑有效的修复顺序。
阅读约 10 分钟


