隧道买的是拓扑,不是加密或延迟
隧道给你一条逻辑路径,也许还有一个独立的转发上下文。它本身不加密,也不承诺延迟。
这个假设是:隧道是一条私有、快速的线路——你建好它,里面的流量就被加密了,路径更短,链路表现得像两个站点之间的一根电缆。这个假设的每一部分都是彼此独立的属性,而隧道只给了你要的第一样东西,也就是一条逻辑路径。其余的一切都必须刻意选择和配置。把属性混为一谈,设计就会落得一条没人能排查故障的加密链路,外加一个没人能兑现的延迟承诺。
迷思:一条隧道,三重保证
隧道可靠地只做一件事。它让两个并未直接相连的端点,为了某个目的表现得像彼此相邻,而中间的网络负责承载外层数据包。这是一种拓扑改变,本身确实有用。
加密、协议承载和转发隔离是叠加在它之上的独立决定。GRE 隧道在密码学意义上三者皆无,IP-in-IP 隧道则是一个完全不带机密性的有效设计。两者都不是错误;它们只是隧道在做隧道该做的事。图上的标签并不会告诉你具备哪些属性。
一旦把属性分开,问题就变得可以回答:这条隧道承载路由邻接吗,承载帧吗,隐藏内部地址吗,对延迟作出任何承诺吗?这是四个不同的答案,对应四种不同的配置后果。
隧道究竟给地图添了什么
端点得到了一条此前没有的路径。这条路径是表现得像被路由的一跳,还是像一段以太网,完全取决于封装;而这一区别会改变两个站点能用它做什么。被路由的隧道给你下一跳和前缀;以太网延伸给你广播行为和远为庞大的故障域。
IP 隧道不会自动让远端站点成为同一子网的一部分,也不会让路由协议在其上运行,除非实现支持这种邻接。多播是另一个独立问题,有它自己的答案。
ip -d link show type gre ip route get 10.20.0.5 traceroute -n -T -p 443 10.20.0.5 mtr -n --report -c 20 10.20.0.5
这些命令回答的是问题的不同部分。第一条说明存在什么类型的接口,第二条说明内核会选择哪条路径,最后两条展示的是底层链路的实际行为,而不是标签的承诺。
承载是与可达性分开的决定
隧道可以承载底层不转发的协议。IPv6 走 IPv4 路径是经典案例,它能成立是因为两端都理解两个协议族,而中间的只负责投递外层数据包。底层只需要一条通往隧道端点的可用路径,仅此而已。
但端点需要完整支持:转发、地址,以及一个真正使用内部协议族的应用。给隧道分配 IPv6 前缀,并不会让只支持 IPv4 的服务能通过 IPv6 访问,也不会让底层变成双栈。
帧承载比协议承载是更大的承诺。把广播域延伸过隧道,会连带搬走生成树行为、ARP 和故障传播,这是设计决定,而不是功能开关。
隔离不是机密性
运营商 VPN 把客户路由和流量放在各自的转发上下文里,这种分离真实而有价值。它不是加密。BGP/MPLS VPN 规范明确指出,它的私密性来自转发模型而非密码学,而这恰恰就是在一张只写着 VPN 的幻灯片里丢失的区别。
如果你需要机密性,你需要带认证和密钥管理的密码学机制,并且需要知道它在哪里终止。提供隔离的隧道和提供加密的隧道可以是同一条隧道,但只有在有人把两者都配置了的时候。
实际后果是,「它在 VPN 里」回答的是路由上下文的问题,而对谁能读到路径上的字节只字不提。两个团队可能都正确,却仍在描述不同的事情。当安全问题出现时,要问加密在哪里终止以及什么在认证对端,而不是问有没有隧道。
延迟和 QoS 跟随底层
逻辑边不是更短的物理路径。外层数据包仍然经过同样的链路、队列和运营商,而封装会在两端增加逐包开销和处理。隧道可以快,是因为底层好,绝不是因为它是隧道。
服务质量的待遇更糟,因为它取决于你可能无法控制的行政域。内部标记必须刻意映射到外部标记,路径上的每个运营商都必须提供你期望的待遇。加密不会创造优先级;它只是隐藏了中间盒本来可以用来给流分类的字段。
在承诺任何东西之前,先测量底层。一份显示外层路径延迟稳定、没有丢包的报表是证据;一张画着隧道的图不是。
为所需的网络关系选择隧道,然后分别规定加密、访问策略、数据包大小和性能。四项决定、四份证据,没有任何一个标签可以代替其中任何一项。