站点间 VPN 中的 NAT 何时值得使用
地址转换可以挽救重叠的前缀或单侧的返回路径,但它会改变每个策略看到的地址。请明确设计映射。
两个站点都使用同一个私有网段,隧道虽然建立起来,却没有有用的流量通过。地址转换是常见的答案,而且确实有效:向远端呈现不同的网段,可以解决地址重叠,或解决对端网络无法路由的返回路径。容易被忽略的一点是,转换会改变之后每一个决策所看到的地址。应把它当作有书面映射记录的设计决策,而不是不断添加规则直到 ping 成功。
决定重写哪个地址
源地址转换改变远端服务及其日志所看到的客户端,因此分支主机到达时会变成网关地址。目的地址转换或前缀转换则相反,为远端资源提供一个替代地址。有些部署需要两端协同转换,才能把两个原本相同的网络分开,而混乱大多从这种组合开始。
记下转换前的源地址、应用所称呼的目的地址,以及每个网关匹配的地址对。三列就够了,而第三列正是人们常漏掉的那一列。
选择器的顺序同样重要。IPsec 策略的选择与转换发生在特定阶段,因此 为转换前地址编写的选择器可能永远不会在你设想的阶段匹配数据包。要检查实际安装的策略,而不是你打算安装的策略,因为当一条规则被一个组件接受、被另一个组件忽略时,两者就会出现偏差:
ip xfrm policy show
ip xfrm state show
nft list ruleset | grep -A4 nat
跟随载荷与返回路径
如果服务器记录的是转换后的源地址而不是各个分支主机,任何以原始地址为键的规则或报表都会被破坏。在更改映射之前,先弄清下游是否有东西依据该字段做决定:访问列表、审计报表、速率限制、许可证检查。上述每一项,都是转换日后以“无法解释的故障”形式浮现的地方。
在载荷内部携带地址的协议需要单独规划,因为重写外层报头并不会触及内部引用。主动 FTP、SIP 以及某些远程访问产品就是典型例子;忽略它们的设计对 Web 流量可用,对真正重要的应用却会失败。
返回流量依赖有状态的映射。网关故障切换可能丢失该状态,非对称路由可能绕过它,重启可能在远端会话仍打开时清除它。因此,到达目的地的请求和真正完成的会话是两种不同的验收结果。
与重新编址站点相比较
对其中一个冲突站点重新编址可以彻底消除映射,留下无需转换表就能读懂的地址规划。它的运维代价很高:DNS 记录、静态分配、防火墙规则以及所有有文档的地址必须一起更改。代价只出现一次,在计划好的窗口内完成,终态清晰。你换来的是多年以后无需查表就能读懂抓包的能力。
地址转换避免了大部分本地改动,却创造出一个必须在 DNS、文档和排障中永久维护的映射。代价是持续发生的,形式就是每一位未来的工程师都得学会:某个前缀在隧道内部另有含义。
对于临时连接或你无法控制的合作方网络,持续代价通常值得付出。对于你拥有并将长期拥有的两个站点,只要如实计算迁移成本,重新编址往往是更便宜的决定。
用真实会话证明两个方向
要测试应用会话,而不是单次探测。一次成功的回显请求只能证明某个协议的一个方向可用,它与任何有状态流量都会失败的返回路径完全兼容。请使用促使你做出该设计的那个服务,并读取远端的日志,看它记录的是哪个源地址。
tcpdump -ni any host 10.40.9.20 and port 443
conntrack -L | grep 10.40.9.20
ip route get 10.40.9.20
然后确认只有预期的服务能通过映射访问。转换只改变编址,对授权毫无作用,因此允许什么仍然由防火墙策略决定。依赖一个晦涩的转换后前缀作为访问控制的设计,根本没有访问控制。
记录映射、测试过的会话以及双方各自观察到的地址。下一个调试这条隧道的人,比起配置文件,更需要这三项事实。