Amazon Linux 2023:Bug 还是特性?

背景

在 AWS 的一个 VPC 内部的一台 EC2 上搭了一个 OpenVPN 服务器,对,就是 从 Client VPN endpoint 迁移到 EC2 上的 OpenVPN 提到的这件事。然后我有台 PC 通过 OpenVPN 客户端软件连了过来。以下是基本信息。

NOTE: IP 地址都不是实际真实情况

  • EC2(A)
    • 公网 IP:1.1.1.1(本地并没有,这个是防火墙或其他设备给做的一对一 map)
    • 私网 IP:10.0.0.2/24
    • 私网网关:10.0.0.1
    • 私网网卡:enX0
    • tun 设备名:tun0
    • tun 设备 IP:172.16.0.1/24
  • PC(B)
    • tun 设备名:tun0
    • tun 设备 IP:172.16.0.2/24

问题描述

问题的核心是:B 无法 ping 通 A 的私网 IP。换句话说,当我在 B 上执行 ping 10.0.0.2 命令时,无法得到响应。俗话就是 ping 不通 10.0.0.2。

问题排查

初步排查

我对 AWS EC2 的网络问题进行了深入的排查,包括各种路由表、安全组、网络 ACL,甚至本地的防火墙配置等等。然而,我并没有找到问题的所在。我可以访问 VPC 内部的私网里的 RDS 资源,也可以在 A 上明显看到有接收到数据包。

ICMP 包的追踪

我继续深入,发现在 A 上可以接收到 B 发送的 icmp 包,而且 A 也确实有回包,但是奇怪的是,回包并没有通过 tun0 设备,而是直接从 enX0 设备发送出去!

不是路由的问题(?)

马上怀疑本地路由有问题,直接在 A 上执行

1
ip r get 172.16.0.2

发现没问题呀,是从设备 tun0 走的呀?这下就完全把我给整不会了。再此之后,我还做了好些努力,比如:

继续检测排查

  • 在 A 上 ping B 的 VPN 地址(tun0 设备上):
    • ping 172.16.0.2,当然是通的
    • ping -I 10.0.0.2 172.16.0.2,这种指定源 IP 的方式 ping,当然是不通的,同样问题,听包发现包没往 tun0 设备上走,而是往 enX0 上走了
  • 跟各种 AI 掰扯,也被告知过 n 多需要检查的地方,比如 kernel 参数 rp_filter 啥的,都对,但都没啥意义,都查过 n 多遍了。
  • 还在微信朋友圈里发了这个问题,看看朋友圈的卧龙凤雏有没有啥好一点的建议方法。回复基本上都有道理,但没有一个能给我灵感的。

问题原因

多番努力,虽然没有结果,但是慢慢还是明白了问题所在就是为什么从 10.0.0.2 出去按路由表应该往 tun0 上走的包却走到了 enX0 上?“这还是路由的问题“,我盖棺定论。

老想想不出为什么,于是就上网找了找 Linux 高级路由的资料看了看,突然想起来:Linux 系统里,路由选择上比路由表级别更高的还有一个:路由策略!柳暗花明呀。

我立马起来,登录上 EC2,

1
ip rule s

果然有一条记录:

10000: from 10.0.0.2 lookup 10000 proto static

果然有货,再接着看这条 id 是 10000 的路由表里有什么:

1
ip r s table 10000

系统显示:

default via 10.0.0.1 dev enX0 proto dhcp metric 512
10.0.0.0/24 dev enX0 proto static scope link

这一下子逻辑就清晰了,源地址是 10.0.0.2、目标地址是 172.16.0.2 的数据包之所以会往 enX0 上走是因为路由策略 10000: from 10.0.0.2 lookup 10000 proto static,这个策略规定了源地址是 10.0.0.2 的数据包怎么走要看路由表 10000,而在 10000 这张路由表又是这样的:

default via 10.0.0.1 dev enX0 proto dhcp metric 512
10.0.0.0/24 dev enX0 proto static scope link

按照这个路由表,去往 172.16.0.2 的数据包不妥妥的要往 enX0 上发吗?

问题验证

最后,我还要做最后一个测试,以验证我的结论:

1
2
3
4
sudo ip r add 172.16.0.0/24 \
dev tun0 \
src 172.16.0.1 \
table 10000

然后,那边在 B 上 ping 10.0.0.2 马上就通了。

最后的最后,我把刚加的这条路由删掉了,因为我还没想好要不要修以及怎么修这个问题。

1
sudo ip r del 172.16.0.0/24 table 10000

结论

由于 Amazon Linux 2023 中在策略路由里将从 EC2 私网地址为源地址的数据包强制走了另外一张路由表,在那张表里源地址为 EC2 私网地址的数据包会走 enX0,而我的 OpenVPN 服务启动时只修改了缺省的路由表:main,故而导致从 OpenVPN 的客户端不能通 EC2 的私网地址。

所以,这到底是 Amazon Linux 2023 的 bug 呢,还是 OpenVPN 的 bug 呢?这个问题还需要进一步的探讨和研究。