在配置文件中加上 redirect-gateway 后连接,你机器的默认路由可能消失、可能一分为二,也可能原封不动,取决于没人会读两遍的那些标志。这个选项只改路由状态,别的什么都不动,所以唯一可信的证据是客户端随后装进表里的路由。下面依次是连接后的路由表、让隧道自身保持连通的那条路由,以及该指令从不声称覆盖的 IPv6 流量。每一步都是隧道在线时你可以在客户端执行的命令。

每个标志对默认路由做了什么

一个标志都不加时,该选项会删掉普通默认路由,把隧道放到它的位置,于是连接期间旧网关从表中消失。加上 def1,那条默认路由仍留在表里,由两条更窄的路由干活。加上 bypass-dhcp,DHCP 路由也会保留,这在客户端仍需访问本地 DHCP 服务器的网络里很重要。OpenVPN 2.6 手册页上的标志列表短到读一遍就够,而每一条都会改变最终进入表里的路由。

推送下来的选项到达后行为相同,所以客户端配置文件里可能什么都没有,表却看起来已被完全重定向。这很正常:服务器发了标志,客户端应用了它们,本地文件从未提到该指令。当推送看起来毫无作用时,检查客户端那一侧接受或丢弃拉取选项的过滤器,因为被丢弃的选项在两头都不会报错。

def1 靠更具体取胜,且不动你的默认路由

两条半默认路由合起来覆盖 IPv4 空间,0.0.0.0/1 与 128.0.0.0/1。它们都比 0.0.0.0/0 更具体,所以查找会优先命中它们,而真正的默认路由仍留在表里,供那些要求最不具体匹配的查询使用。

读表而不是读配置文件,因为只有表能说明你处在哪种情况。两行就足以区分:

ip route show default
ip route show | grep -E '^(0\.0\.0\.0/1|128\.0\.0\.0/1)'

注意每一行的接口和度量值,而不只是目的网络。指向隧道的默认路由与一对指向隧道的半默认路由表达的是同一个意图,但隧道断开时的失败方式不同,因为其中一种情况下备用路径仍然存在。把这两个字段都写进变更记录。残留的备用路径有时正是让远程会话撑到修复隧道的原因,而当意图是完整隧道时,泄漏流量的也正是它。

让隧道对端保持可达

客户端需要一条通往隧道远端、且本身不经过隧道的路由。OpenVPN 在改动其他任何东西之前先装上这条主机路由,而手工改路由或第二个 VPN 客户端都可能把它弄掉。之后的症状是:连接报告已连接,却什么都过不去。

在隧道在线时问内核,它会为对端地址选用哪个接口。答案必须指出物理接口及其网关,绝不该是 tun0:

ip route get 198.51.100.20

如果这次查询返回的是隧道设备,说明隧道在承载自己的传输,只要有包需要外出就会崩塌。本地前缀、第二块网卡和策略路由在这里依然重要,这也是为什么在干净笔记本上有效的重定向,到了带管理接口和两条默认路由的主机上会失败。人们通常怪配置文件,实际动手的却是地址规划。

IPv6 流量继续使用自己的表

重定向 IPv4 不会动 IPv6,两个协议族由不同的标志控制。在 v6 默认路由正常的双栈主机上,v4 流量可以完全待在隧道里,而每个支持 v6 的目的地却从物理链路出去。在一张表里看起来正确的主机,在另一张表里正在泄漏。

连接后检查 v6 表,而不是假定隧道覆盖了它。该指令携带地址族标志正是为此,而省略它们的配置文件会继承平台的默认行为:

ip -6 route show default
ip -6 route get 2001:db8::10

证明应用到底用了哪个接口

已连接不等于已拦截,路由变更也不等于 kill switch。如果隧道断开时必须切断直连流量,那条策略住在防火墙里,需要单独测试。

测应用真正走的路径,而不是配置文件描述的路径。先查路由,再依次把请求绑定到每个接口,比较对端报告的结果:

ip route get 203.0.113.10
curl -s --interface tun0 https://ifconfig.me
curl -s --interface eth0 https://ifconfig.me

如果两个请求返回同一个地址,应用就没走隧道,尽管路由表说它应该走。如果只有绑定隧道的请求成功,说明该目的地被物理路径过滤,隧道正在按你的要求工作。把标志、装进表的路由、对端查询和两次出口结果都写进变更记录,让下一个人继承事实而不是截图。

相关文章