Homelab 网络系列:透明代理 VIP、VRRP 和 Fallback DNS
系列导航
- Homelab 网络系列:开篇 - 家庭网络为什么会变复杂
- Homelab 网络系列:RouterOS 主网关和 WRT 旁路由为什么要分工
- Homelab 网络系列:透明代理 VIP、VRRP 和 Fallback DNS
- Homelab 网络系列:NetBird ACL:Mobile Devices / MacBook 如何访问 Homelab / Hometown / Office 网络
- Homelab 网络系列:Backup Path:ZeroTier P2P 和 Sing-box Inbound 为什么还留着
- Homelab 网络系列:自动化和可恢复性:订阅生成、健康检查、配置同步、回滚
背景
上一篇讲 RouterOS 和 WRT 为什么要分工:RouterOS 是主网关,负责稳定底座和日常主要访问;WRT 是额外策略层,负责海外访问分流、Sing-box、NetBird Peer 和一些 Backup Path。
这篇继续拆 WRT 这层里最容易出问题的一块:透明代理 VIP、VRRP 和 Fallback DNS。
我想解决的问题不是“所有设备都强制走代理”,而是:
- 普通设备继续走 RouterOS,不受 WRT 策略层影响
- 需要海外访问分流的设备,通过 DHCP 进入代理策略组
- 代理策略组看到的是稳定的网关和 DNS
- WRT 上的 Sing-box 挂了之后,代理设备至少不要完全断网
- Fallback DNS 能兜普通解析,但不要变成公网服务入口 Rewrite 中心
所以最后就变成了一个代理 VIP:客户端只认这个 VIP,背后由 WRT 或 RouterOS 根据健康状态接管。
为什么需要一个 VIP
最直接的方案,是让需要代理的设备把默认网关和 DNS 都指向 WRT。
这个方案短期很简单,但问题也很直接:一旦 WRT 或 Sing-box 有问题,客户端拿到的网关和 DNS 就一起失效。对手机、平板、电视这类设备来说,这种故障通常很难现场解释,也很难要求每台设备自己切回普通网络。
所以我没有让客户端直接绑定 WRT 的真实地址,而是让 DHCP 下发一个代理 VIP:
- 普通客户端:默认网关是
10.1.1.1,DNS 是10.1.1.100 - 代理客户端:默认网关和 DNS 都指向代理 VIP
10.1.1.253 - WRT 健康时:WRT
10.1.1.254持有 VIP,后面接 Sing-box DNS / TUN / Route Policy,DNS Backend 是10.1.1.254:53 - WRT 基础健康失败时:RouterOS
10.1.1.1接管 VIP,提供普通 LAN/WAN Fallback
这样客户端配置是稳定的,故障切换发生在网关侧。
这里的重点不是“无感高可用”,而是把故障结果从“完全不可用”降级成“只失去代理策略”。
地址和路径先摊开
这套设计如果只讲“VIP”和“Fallback”,很容易听起来像抽象概念。实际地址关系是这样:
| 场景 | 客户端网关 | 客户端 DNS | VIP 持有者 | DNS 后端 |
|---|---|---|---|---|
| 普通客户端 | 10.1.1.1 |
10.1.1.100 |
不经过代理 VIP | AdGuardHome 10.1.1.100:53 |
| 代理健康 | 10.1.1.253 |
10.1.1.253 |
WRT 10.1.1.254 |
WRT Sing-box DNS 10.1.1.254:53 |
| 代理 Fallback | 10.1.1.253 |
10.1.1.253 |
RouterOS 10.1.1.1 |
RouterOS Firewall Redirect 到 AdGuardHome 10.1.1.100:53 |
sequenceDiagram
participant Client as Normal / Proxy Clients
participant RouterOS as RouterOS 10.1.1.1
participant WRT as WRT 10.1.1.254
participant SingBox as Sing-box 10.1.1.254:53
participant ADG as AdGuardHome 10.1.1.100:53
participant WAN as WAN / Proxy Nodes
rect rgb(245, 248, 255)
Note over Client,ADG: 普通客户端路径
Client->>RouterOS: GW 10.1.1.1
Client->>ADG: DNS 10.1.1.100
RouterOS->>WAN: Ordinary WAN/NAT
end
rect rgb(240, 250, 244)
Note over Client,WAN: 代理健康路径,VIP 10.1.1.253 在 WRT
Client->>WRT: GW/DNS 10.1.1.253
WRT->>SingBox: Backend 10.1.1.254
SingBox->>ADG: dns-local
SingBox->>WAN: Direct or Proxy Egress
end
rect rgb(255, 248, 230)
Note over WRT,RouterOS: WRT L1 健康检查失败
WRT-->>RouterOS: RouterOS Becomes VRRP MASTER for 10.1.1.253
Client->>RouterOS: DNS to 10.1.1.253:53
RouterOS->>ADG: VRRP MASTER Hook Redirects to 10.1.1.100:53
ADG-->>Client: Ordinary/Local/Cache DNS
ADG-->>Client: GFWList matched domains return REFUSED
Client->>RouterOS: Default Traffic via 10.1.1.253
RouterOS->>WAN: Ordinary LAN/WAN Fallback
end
sequenceDiagram
participant Client as Normal / Proxy Clients
participant RouterOS as RouterOS 10.1.1.1
participant WRT as WRT 10.1.1.254
participant SingBox as Sing-box 10.1.1.254:53
participant ADG as AdGuardHome 10.1.1.100:53
participant WAN as WAN / Proxy Nodes
rect rgb(245, 248, 255)
Note over Client,ADG: 普通客户端路径
Client->>RouterOS: GW 10.1.1.1
Client->>ADG: DNS 10.1.1.100
RouterOS->>WAN: Ordinary WAN/NAT
end
rect rgb(240, 250, 244)
Note over Client,WAN: 代理健康路径,VIP 10.1.1.253 在 WRT
Client->>WRT: GW/DNS 10.1.1.253
WRT->>SingBox: Backend 10.1.1.254
SingBox->>ADG: dns-local
SingBox->>WAN: Direct or Proxy Egress
end
rect rgb(255, 248, 230)
Note over WRT,RouterOS: WRT L1 健康检查失败
WRT-->>RouterOS: RouterOS Becomes VRRP MASTER for 10.1.1.253
Client->>RouterOS: DNS to 10.1.1.253:53
RouterOS->>ADG: VRRP MASTER Hook Redirects to 10.1.1.100:53
ADG-->>Client: Ordinary/Local/Cache DNS
ADG-->>Client: GFWList matched domains return REFUSED
Client->>RouterOS: Default Traffic via 10.1.1.253
RouterOS->>WAN: Ordinary LAN/WAN Fallback
end
sequenceDiagram
participant Client as Normal / Proxy Clients
participant RouterOS as RouterOS 10.1.1.1
participant WRT as WRT 10.1.1.254
participant SingBox as Sing-box 10.1.1.254:53
participant ADG as AdGuardHome 10.1.1.100:53
participant WAN as WAN / Proxy Nodes
rect rgb(245, 248, 255)
Note over Client,ADG: 普通客户端路径
Client->>RouterOS: GW 10.1.1.1
Client->>ADG: DNS 10.1.1.100
RouterOS->>WAN: Ordinary WAN/NAT
end
rect rgb(240, 250, 244)
Note over Client,WAN: 代理健康路径,VIP 10.1.1.253 在 WRT
Client->>WRT: GW/DNS 10.1.1.253
WRT->>SingBox: Backend 10.1.1.254
SingBox->>ADG: dns-local
SingBox->>WAN: Direct or Proxy Egress
end
rect rgb(255, 248, 230)
Note over WRT,RouterOS: WRT L1 健康检查失败
WRT-->>RouterOS: RouterOS Becomes VRRP MASTER for 10.1.1.253
Client->>RouterOS: DNS to 10.1.1.253:53
RouterOS->>ADG: VRRP MASTER Hook Redirects to 10.1.1.100:53
ADG-->>Client: Ordinary/Local/Cache DNS
ADG-->>Client: GFWList matched domains return REFUSED
Client->>RouterOS: Default Traffic via 10.1.1.253
RouterOS->>WAN: Ordinary LAN/WAN Fallback
endsequenceDiagram
participant Client as Normal / Proxy Clients
participant RouterOS as RouterOS 10.1.1.1
participant WRT as WRT 10.1.1.254
participant SingBox as Sing-box 10.1.1.254:53
participant ADG as AdGuardHome 10.1.1.100:53
participant WAN as WAN / Proxy Nodes
rect rgb(245, 248, 255)
Note over Client,ADG: 普通客户端路径
Client->>RouterOS: GW 10.1.1.1
Client->>ADG: DNS 10.1.1.100
RouterOS->>WAN: Ordinary WAN/NAT
end
rect rgb(240, 250, 244)
Note over Client,WAN: 代理健康路径,VIP 10.1.1.253 在 WRT
Client->>WRT: GW/DNS 10.1.1.253
WRT->>SingBox: Backend 10.1.1.254
SingBox->>ADG: dns-local
SingBox->>WAN: Direct or Proxy Egress
end
rect rgb(255, 248, 230)
Note over WRT,RouterOS: WRT L1 健康检查失败
WRT-->>RouterOS: RouterOS Becomes VRRP MASTER for 10.1.1.253
Client->>RouterOS: DNS to 10.1.1.253:53
RouterOS->>ADG: VRRP MASTER Hook Redirects to 10.1.1.100:53
ADG-->>Client: Ordinary/Local/Cache DNS
ADG-->>Client: GFWList matched domains return REFUSED
Client->>RouterOS: Default Traffic via 10.1.1.253
RouterOS->>WAN: Ordinary LAN/WAN Fallback
end
这张图里有三个细节很重要。
第一,10.1.1.100 不是只在故障时才出现。普通客户端本来就通过 RouterOS 侧的普通 LAN DNS 策略使用它,所以 Fallback 状态下,代理客户端只是回到同一套 AdGuardHome 本地解析和 LAN Cache。
第二,健康代理路径和 Fallback 路径的客户端配置是一样的,都是 10.1.1.253 做网关和 DNS。差别只在 Backend:健康时是 WRT 10.1.1.254 / Sing-box DNS 10.1.1.254:53,Fallback 时是 RouterOS 10.1.1.1 / AdGuardHome 10.1.1.100:53。
第三,RouterOS 接管 VIP 后,Fallback DNS 不是靠客户端改配置完成的,而是 RouterOS 的 VRRP MASTER Hook 使用 Firewall Redirect,把发往 10.1.1.253:53 的 DNS 流量转到 10.1.1.100:53。
VRRP 负责谁持有 VIP
VIP 的归属用 VRRP 做。
健康状态正常时,WRT 是 MASTER。代理客户端发到 VIP 的 DNS 和默认路由流量,都会进入 WRT。WRT 上的 Sing-box 再根据规则决定直连、代理、DNS 策略和 TUN 路由。
RouterOS 则保持 BACKUP。它不是日常代理路径,只是在 WRT 基础能力失败时接管 VIP。
这个边界很重要:
- WRT 负责完整策略能力
- RouterOS 负责 Fallback 能力
- VRRP 只决定 VIP 属于谁
- 客户端不需要知道当前是谁在接管
也就是说,VRRP 不是为了让 RouterOS 也实现一份完整代理能力。RouterOS 接管时,它提供的是普通网络兜底,不是 Sing-box 的替代品。
实现上,RouterOS 成为 10.1.1.253 的 MASTER 后,会进入对应的 VRRP 接管逻辑。这里的 Fallback DNS 动作就是 Firewall Redirect:把目的地址仍然写着 10.1.1.253:53 的请求转给 10.1.1.100:53。客户端仍然只知道 VIP,不需要知道背后已经从 WRT 切到了 RouterOS + AdGuardHome。
L1 健康检查决定是否切走
WRT 什么时候应该交出 VIP?我的判断标准是 L1 基础能力失败。
这里的 L1 不是“海外网络是否好用”,而是 WRT 作为代理网关还是否具备基本服务能力:
- Sing-box 进程还在不在
- Sing-box 的 DNS 配置是否符合代理路径预期
- 本地或国内 DNS 探测是否可用
- TUN 和转发规则是否存在
- 必要时再加国内 HTTP 探测
这些检查失败,说明 WRT 已经不适合作为客户端的网关和 DNS。此时让 RouterOS 接管 VIP 是合理的,因为至少能把客户端带回普通网络。
这个设计也避免了一个常见误区:不要因为“海外探测失败”就立刻切 VIP。
L2 海外退化为什么不切 VIP
海外访问失败和 WRT 基础能力失败不是一回事。
如果只是海外 DNS 或 HTTP 探测失败,但 Sing-box 进程、配置、本地 DNS、TUN、转发规则都还正常,那么 WRT 仍然应该持有 VIP。
原因很简单:切回 RouterOS 并不能修好海外访问。
RouterOS Fallback 提供的是普通 LAN/WAN 出口。它没有完整的 Sing-box 选择器、远端 DNS 策略和海外分流能力。海外路径本身退化时,把 VIP 切走只会让客户端立刻失去策略层,反而扩大影响。
所以我把海外探测放在 L2:
- L2 失败只记录状态
- L2 失败不改变 VRRP 退出码
- L2 慢探测不能卡住 VRRP 主循环
- L2 恢复后再把状态写回 Healthy
这会带来一个看起来不够“自动化”的结果:海外不可用时,VIP 仍然可能留在 WRT。
但这是有意为之。L2 是观测信号,不是接管信号。
Fallback DNS 能兜什么
RouterOS 接管 VIP 后,需要处理一个现实问题:代理客户端的 DNS 仍然指向 VIP。
如果 RouterOS 只是接管了 VIP,却没有处理 DNS,那么客户端会从“网关不可用”变成“DNS 不可用”,体验还是断的。
所以 RouterOS 上保留一条 Fallback DNS Redirect:当它成为 VIP MASTER 时,通过 Firewall Redirect 把发往 10.1.1.253:53 的 DNS 请求转给本地 DNS 服务。
这个本地 DNS 服务不是 RouterOS 自己跑的递归解析,而是 PVE Host 上 Docker 里的 AdGuardHome。RouterOS 只负责在 Fallback 状态下把 DNS 流量转过去。
更准确地说,这个 AdGuardHome 平时也是 RouterOS 普通客户端的 Upstream DNS。普通客户端没有进代理策略组时,DNS 解析已经会走到这里;Fallback 只是让代理客户端在 WRT 失效后,也回到同一套本地 DNS 语义里。
这个设计有两个好处:
- 普通客户端和 Fallback 状态下的代理客户端,看到的本地别名和基础解析行为一致
- LAN 内已经缓存过的解析结果可以继续复用,不会因为 VIP 接管就换一套 DNS 行为
这里的 Fallback DNS 不是一个“尽量帮你解析所有东西”的宽松 Resolver。它会主动用 Filter 对 GFWList 命中的域名做 Reject。
这个取舍是故意的:当代理路径已经失败时,我不希望 Fallback DNS 继续把明显需要代理策略的域名拿去普通 DNS 路径解析。那样虽然短期看起来更“可用”,但会泄露真实访问意图,也增加 DNS Leak 的可能。
所以 Fallback 状态下,某些本来应该走代理 DNS 的域名被拒绝是预期行为。它的目标是保住普通网络和本地解析,而不是在降级路径里继续假装完整代理策略还存在。
这条 Fallback 能兜的是:
- 普通域名解析
- 本地别名
- 和普通 RouterOS 客户端一致的 LAN 内 DNS Cache
- 国内访问需要的基础解析
- WRT 重启或 Sing-box 挂掉时的临时网络恢复
它不能兜的是:
- 完整的 Sing-box DNS 分流
- 海外远端 DNS 策略
- GFWList 命中域名的普通 DNS 解析
- 代理选择器
- 特定代理规则带来的访问偏好
所以 Fallback DNS 的目标不是“和正常代理路径等价”,而是“别让客户端因为 DNS 完全断掉”。
DNS 不负责公网入口分流
这里还要强调一个边界:Fallback DNS 不是公网服务入口 Rewrite 层。
Homelab 里有些服务既要从外面访问,也要在 LAN 里用同一套公网视角访问。我不希望这些服务在 LAN 内靠 DNS 改写到内网地址。
原因上一篇已经讲过:DNS 只能按名字分流,但入口问题经常和端口、协议、鉴权、后端服务有关。
所以公网服务入口继续由 RouterOS Hairpin NAT 解决:
- WAN 访问走公网入口 DNAT
- LAN 访问同一公网入口走 Hairpin
- 后端回复路径由 RouterOS 保证回流
- DNS 视角保持一致
WRT 的透明代理 DNS 和 RouterOS 的公网入口 Hairpin 是两条边界。混在一起,排障会很痛苦。
验证
这类设计不能只看配置,要看故障切换。
我比较关心几种状态:
- 正常状态下,代理 VIP 在 WRT 上,代理客户端通过 WRT 走 Sing-box
- 停掉 Sing-box 后,WRT 释放 VIP,RouterOS 接管
- RouterOS 接管后,VRRP MASTER Hook/Firewall Redirect 把 VIP DNS 转到
10.1.1.100:53 - RouterOS 接管后,代理客户端至少能获得普通 DNS 和普通出口
- Sing-box 恢复并通过 L1 检查后,WRT 重新接管 VIP
- 海外 L2 探测失败时,状态记录退化,但 VIP 不应该因为这个单独切走
这里最容易误判的是“探测慢”和“探测失败”。
VRRP 的健康检查必须短、硬、可预期。慢探测应该异步化,否则会把 Keepalived 的 Track Script 卡住,最后造成不必要的主备抖动。
最后的结论
透明代理 VIP 解决的是客户端稳定入口问题。
VRRP 解决的是 WRT 和 RouterOS 谁来持有这个入口。
L1 健康检查决定是否真的需要切走。
L2 海外探测只提供退化状态,不直接触发接管。
Fallback DNS 解决的是降级时的基础可用性,不是完整代理能力,也不是公网服务入口分流。它在 RouterOS 成为 VRRP MASTER 后,通过 Firewall Redirect 把 10.1.1.253:53 转到 PVE Host Docker 上的 AdGuardHome 10.1.1.100:53;这个 AdGuardHome 同时也是普通 RouterOS 客户端的 Upstream DNS,所以 Fallback 后仍然复用同一套本地解析和 LAN Cache。它也会主动 Reject GFWList 命中域名,避免在降级路径里泄露真实访问意图。
这套设计的目标不是把代理路径做成完美 HA,而是让 WRT 这层额外能力失败时,损失范围保持清楚:普通网络还能走,代理策略可以降级,排障时知道问题卡在哪一层。