两个蜂窝站点没有入站端口:搭建一个可用的中心节点
当两个站点都不接受入站 IPv4 连接时,让双方都主动连接到一个可到达的中心节点。按此顺序执行路由、转发和回退步骤。
两条蜂窝上行链路上的两个站点在双向都遇到同一个问题:任何一方都无法接受未经请求的 IPv4 连接,因此任何一方都无法在直连隧道中充当服务器。可行的架构是在中间放置一个可达的第三方:每个站点向外发起连接,中间只转发你批准的那部分流量。这个中间方可以是你自己运营的路由器,也可以是负责介绍对端的产品,两者并不相同。下面的步骤安排成每一步都先产出证据,再让下一步依赖它。
两边都无法被试拨,所以双方都必须向外发起
在围绕它设计之前先确认这个限制。如果运营商给 WAN 接口分配的是私有地址,那么站点自身路由器上的任何端口映射都不会让它可达,因为地址转换发生在更上游。同一条链路上也可能存在公网 IPv6 地址,从而彻底改变设计,所以检查要覆盖两个地址族。把每个站点的结论写下来,因为即便共用同一家运营商,两者的限制也很少完全相同。
常见的蜂窝场景看起来像是来自运营商转换后地址段的地址,并有一条默认路由从中穿过。这不是需要修复的故障;这正是中心节点存在的原因。你要找的是第三方在站点尚未主动开口之前就能到达的任何地址。
两条命令就能回答你面前这个站点的编址问题。请在站点的路由器上执行,而不是它后面的笔记本电脑:
ip -4 addr show scope global
ip -6 addr show scope global谁负责介绍对端,谁负责承载数据包
介绍与承载是两件不同的事,产品常常把它们捆在一起却不把界线显露出来。会合机制帮助两个对端找到候选路径;当没有直连路径时,中继负责承载它们的数据包。购买一项介绍对端的服务并不会给你路由器,而这一区别决定了设计到底需不需要中心节点。
穿透有其专用术语,这些词描述的是角色,而不是保证。 ICE 规范 描述了候选与连通性检查,STUN 描述了一种了解地址转换的方式,TURN 则描述了供实现它的应用使用的中继传输。这些机制都不会出现在常规网关里,因为你只是把它指向了一个发现地址。请把穿透当作产品能力来验证,并在测试证明相反之前假定存在中继。
每个站点一条路由,由对端持有
中心节点需要每个站点一条隧道、各自背后一个独立的 LAN 前缀,以及为每个前缀指定其持有者的一条路由。示例中中心节点是 10.61.0.1,站点 A 是 10.61.0.11,其 LAN 为 10.60.10.0/24,站点 B 是 10.61.0.12,其 LAN 为 10.60.20.0/24。下面每条路由都指向持有该前缀的对端,而不是隧道接口:
ip route add 10.60.10.0/24 via 10.61.0.11 dev wg0
ip route add 10.60.20.0/24 via 10.61.0.12 dev wg0
sysctl net.ipv4.ip_forward
ip route get 10.60.20.55 from 10.60.10.77必须开启转发,否则数据包会停在中心节点,而且不会有任何错误指向原因。最后一条命令回答的是真正的问题,因为它把源地址纳入查找,询问数据包从站点 A 的 LAN 到站点 B 的 LAN 会走哪条路。把指名隧道接口的查找当作证据,把落回默认路由的查找当作缺失的路由,而不是谜团。然后有意识地限制过境流量,因为一个在所有对端之间转发的中心节点会把两个站点变成一张扁平网络,你以为拥有的访问策略就不再适用。
还要决定加密在哪里终止。当中心节点同时持有隧道两端时,那台机器的运营者及其工作负载就进入了信任与可用性模型,它的带宽也成为路径的一部分。
通过运营商让每个映射保持存活
每个站点各自发起隧道,而且每个站点都必须让转换映射保持存活,否则运营商就会忘记它。发起侧的保活消息在两次握手之间保住这个映射。把允许的前缀限定为中心节点地址和远端 LAN,这样被攻陷的对端就无法声称一个并不属于它的前缀:
[Peer]
PublicKey = <hub public key>
Endpoint = 192.0.2.10:51820
AllowedIPs = 10.61.0.1/32, 10.60.20.0/24
PersistentKeepalive = 25在另一个站点上用该站点自己的远端前缀复制这个配置块,并且抵制允许整段隧道的冲动。握手停下又从新的源端口继续,是映射过期的特征,而握手时间戳就是它发生过的证据。比运营商超时更短的间隔能防止过期,而不是事后修复。当运营商改变转换行为时,这些时间也会随之改变。
先证明两个方向,再证明恢复能力
验证是有方向的,所以 从 A 到 B 的 ping 只证明了设计的一半,对回程路径一无所知。用同一条考虑源地址的查找在中心节点上检查回程,然后从另一侧重复测试。新的握手同样属于证据,因为闲置一小时的隧道可能正在检验一个旧映射:
wg show wg0 latest-handshakes
ping -c 3 10.60.20.55
traceroute -n 10.60.20.55然后测试你预期的故障,而不是你想要的顺利。重启一个站点的上行链路,确认隧道在两端都没有人动手的情况下恢复,因为每次运营商变动之后都需要运维人员的设计还没有完成。记录主路径、存在时的 IPv6 备选,以及中心节点不可用时的行为。中心节点现在是你可用性模型的一部分,所以要把它写下来,而不是在故障发生时才去发现。