在折腾 HomeLab 的过程中,我们经常会遇到各种奇怪的网络现象。
最近我在调试 Proxmox VE (PVE) 网络时发现了一个非常有趣的案例:我的 LXC 容器配置了一个看似“错误”的 DNS,却在旁路由环境下跑得飞快;而一旦切换回主路由,网络瞬间断连。
这背后的原理,其实是一个关于“路径依赖”和“DNS 劫持”的精彩故事。
现象描述
我的网络环境是这样的:
- 宿主机:PVE,安装了 Tailscale。
- 容器:若干 LXC 容器(未安装 Tailscale)。
- 网关:指向旁路由(跑着 mihomo 核心组件)。
- DNS 设置:PVE 和 LXC 的 DNS 都填了
100.100.100.100。
奇怪的现象:
- 当网关指向旁路由时,LXC 容器可以正常上网,甚至可以访问外网。
- 一旦我将 LXC 的网关指向主路由(普通硬路由),LXC 立刻无法上网。
核心疑问
熟悉 Tailscale 的朋友都知道,100.100.100.100 是 Tailscale 的 MagicDNS 专用 IP。它只存在于安装了 Tailscale 的设备的虚拟网卡(tailscale0)上。
问题来了: 我的 LXC 容器根本没有安装 Tailscale,它没有虚拟网卡,理论上它根本不认识 100.100.100.100,也不可能 ping 通这个 IP。
那为什么在旁路由下,它居然能用这个 IP 解析域名并上网呢?
原理解析:一场完美的“欺骗”
真相是:你的 LXC 容器从来没有真正连接到 100.100.100.100,它只是被旁路由“劫持”了。
1. 旁路由模式下的数据流(The Hijack)
当你配置网关为旁路由时,DNS 解析过程是这样的:
- 发起请求:LXC 想访问
google.com,它根据配置,向100.100.100.100:53发送了一个 UDP 数据包。 - 路由查找:LXC 查路由表,发现自己不在
100.x.x.x网段,于是把包扔给了网关(旁路由)。 - 强制劫持:旁路由收到这个包。由于旁路由上运行着 mihomo,这类工具通常默认开启了 DNS 劫持 (DNS Hijacking) 功能(如 Redir-Host 或 Fake-IP 模式的配合)。
- mihomo 的逻辑是:“我不管你想发给谁,只要是 53 端口的 DNS 查询,统统扣下!”
- 代为解析:旁路由扣下请求,用它自己内置的 DNS 策略去解析
google.com。 - 伪造回复:旁路由拿到 IP 后,伪装成
100.100.100.100的身份,把结果发回给 LXC。
结果:LXC 以为是 MagicDNS 回答了它,实际上是旁路由演了一出戏。
2. 主路由模式下的数据流(The Crash)
当你把网关切回主路由(通常是光猫或普通路由器)时,保护层消失了:
- 发起请求:LXC 依然顽固地向
100.100.100.100:53发起请求。 - 路由转发:主路由收到包。它没有 mihomo 的 DNS 劫持功能,它很老实。它看着目标 IP
100.100.100.100(这属于 Carrier Grade NAT 保留段),以为你要访问公网上的某台机器。 - 丢弃/超时:主路由把包扔给运营商(ISP)。运营商一看这奇怪的内网保留 IP,直接丢弃(或者发出去也没人理)。
- 断连:LXC 等不到回应,DNS 解析超时(Timeout),导致无法上网。
为什么这很危险?
这种配置方式虽然能用,但它是一种脆弱的路径依赖。
你的网络可用性完全建立在“旁路由必须开启 mihomo 劫持”这个前提下。一旦旁路由挂了、mihomo 没启动,或者你想临时切回主路由排除故障,你的所有 LXC 容器网络会瞬间全崩。
这就像你的车其实没有轮子,全靠底下的传送带在拖着跑。一旦离开传送带,车就动不了了。
最佳实践方案
为了让网络更健壮,我们应该让 LXC 使用“真实存在”的 DNS。
方案一:回归通用(推荐)
将 LXC 的 DNS 修改为公共 DNS。这样无论走主路由还是旁路由,都能解析。
- 国内:
223.5.5.5(阿里云),119.29.29.29(腾讯云) - 国外:
8.8.8.8,1.1.1.1
效果:
- 走旁路由时:依然会被劫持去走 mihomo 代理(因为 53 端口劫持通常是全局的),不影响 mihomo 的分流规则。
- 走主路由时:正常连接阿里云 DNS,不影响国内上网。
方案二:指向局域网 DNS
如果你希望保留一些局域网解析功能,可以将 LXC 的 DNS 指向主路由的 LAN IP 或者 旁路由的 LAN IP(例如 192.168.1.1)(需要旁路由开启dns请求接受功能)。
方案三:只有一种情况该用 100.100.100.100
只有当你在 LXC 容器内部 也安装了 Tailscale 客户端,并且你确实需要使用 MagicDNS 解析 my-server.tailnet.ts.net 这种域名时,才应该在容器里填 100.100.100.100。
总结
看似玄学的网络故障,往往源于我们对数据包流向的误解。
- PVE 宿主机可以用
100.100.100.100,因为它真的装了 Tailscale。 - LXC 容器不该用
100.100.100.100,除非它也装了。 - 旁路由就像一个爱管闲事的中间人,它掩盖了配置错误,但也带来了脆弱性。
记住:不要依赖网络设备的“副作用”来维持网络的连通性。
Leave a comment