blackhole 路由与 VPN 断网开关:各自的作用
blackhole 路由会丢弃匹配的流量,并在故障时强制走封闭路径。将它覆盖的范围与盲区,与基于包过滤的断网开关做比较。
一个数据包离开笔记本,从未到达 VPN 网关,防火墙计数器也毫无变化。路由表早已决定了它的命运:一条 blackhole 条目匹配了它,内核在任何接口看到它之前就把它丢弃了。当某个目的地应当以关闭方式失败时,这种行为很有用,但它是一项范围很窄的路由操作。把它当作完整的断网开关,正是设计出错的地方。
丢弃操作究竟匹配什么
路由查找先选定一张表,然后在表中选出 最长的匹配前缀。blackhole 路由是动作等于丢弃的普通条目,因此它只影响在完整决策之后会选中该条目的数据包。用策略规则换一张表,或添加更具体的前缀,丢弃就不再适用。
正因如此,blackhole 的覆盖范围精确且容易表述:它覆盖该地址族在这张表中的这个前缀。它不覆盖会被另一张表胜出的目的地,也不会仅仅因为丢弃了 IPv4 前缀就覆盖 IPv6。
ip route get 会在部署任何东西之前显示决策,包括所用表和路由类型。读这段输出,比从一次失败的请求去推断哪条规则或前缀生效要快。
blackhole 与 unreachable 或 prohibit 并不相同
Linux 提供三种类似丢弃的路由类型,它们的区别在于发送方观察到什么。blackhole 不回复直接丢弃数据包,客户端看到的是超时。unreachable 路由返回 ICMP unreachable 消息,连接很快以主机或网络错误失败。prohibit 路由返回管理性禁止错误,更接近有意的策略拒绝。
选择你希望应用看到的行为。不想暴露策略时,静默丢弃是合适的;需要让用户理解目的地为何不可用时,立即报错更好。在同一张网络里混用这些类型,会产生把同一条策略描述成三种不同故障的支持工单。
诊断连接时,不要以为每条丢弃条目都可以互换。错误文本、时序和抓包结果都不同,而表中的路由类型会告诉你正在看哪一种。ip-route 手册列出了这些类型及其出错时的行为。
它与断网开关相比如何
断网开关是包过滤:一条防火墙规则,丢弃本会离开隧道的出站流量。blackhole 路由则是在协议栈更早阶段做出的转发决定。两者都能阻断流量,但它们看到的东西不同,漏掉的场景也不同。
| Mechanism | What it blocks | What it misses | How failure looks |
|---|---|---|---|
| Blackhole route | Destinations matching the prefix and table | Other tables, other address families, traffic with a different route | Silent timeout |
| Firewall kill switch | Egress not bound to the tunnel interface | Rules that are too broad can break the endpoint or DHCP | Dropped packets with counters |
| WireGuard AllowedIPs | Destinations not routed into the interface | Traffic that never enters the interface at all | No tunnel route, direct egress |
覆盖范围才是比较的关键。防火墙可以匹配属主、端口或接口,在保持端点可达的同时阻断某个应用;路由做不到。反过来,路由可以在完全不加载任何包过滤的情况下把整个前缀送进丢弃,这在最小化系统上很有用。
WireGuard 的 AllowedIPs 是密码密钥路由,而不是防火墙。它决定哪些目的前缀被接受到接口中,只列出隧道子网的配置文件,会把其他目的地交给普通默认路由。这就是全网隧道配置使用 0.0.0.0/0 的原因,也是 wg-quick 在可能时还会安装防火墙规则的原因。
把隧道端点留在丢弃范围之外
端点的外部地址必须能通过物理接口到达。若丢弃同时捕获了该地址,握手就发不出去,隧道永远起不来,看起来像 VPN 故障而不是路由策略。变更前后都要检查到端点的路由。
管理访问也属于同一次审查。如果通往路由器或客户端的唯一路径就是隧道,过宽的丢弃会把你锁在那台本可让你删除它的机器之外。保留有记录的带外路径、控制台或定时回滚。
IPv6 需要自己的条目和自己的审查。把 IPv4 丢进 blackhole 却把 IPv6 留在默认路由上的设计,恰好泄漏了这条策略本想拦住的流量,而这个错误在只测 IPv4 的环境里看不出来。
用定时器和回滚分阶段实施
应用路由时附带一次短暂自动删除,这样错误不会跨越重启继续存在。下面的命令使用文档专用网段;请换成你的设计实际丢弃的前缀:
sudo ip route replace blackhole 10.0.0.0/8
ip route get 10.1.2.3
sudo systemd-run --on-active=60 /sbin/ip route del blackhole 10.0.0.0/8第二条命令应当报告 blackhole 路由以及它来自哪张表。第三条会安排在一分钟后删除,这个时间足够确认策略,也足够短,能在远程主机上从失误中恢复。行为确认之后,再用管理其他路由的同一套配置管理把该条目持久化。
收尾时记录前缀、表、地址族和回滚方式。丢弃是路由设计中刻意保留的例外,下一位工程师在判断它是否仍然适用之前,需要知道它当初要拦住哪些流量。