一次 k3s 容器无法访问外网分析

问题现象

k3s 边缘集群容器无法与 [cc-rancher-xxx.xeewo.com] 建连,导致 rancher 无法启动。现象是发出去的 SYN 包没有收到回复 SYN+ACK 的包,但在物理机上一切正常,ping 和 curl 都可以成功。

经确认,实际上不止这个域名无法建连,其实是容器压根无法访问外网,ping 和 tcp 建连都是不行的,ping 显示 100% lost。

分析过程

首先先解决 ping 都不通的问题,经确认我们用的是 flannel 网络模型,在 pod 内发起目标地址为外网的 icmp 包会依次经经过 pod/eth0 -> cni0 -> node/eth0

于是分别在这三个网卡上抓包,发现 icmp 包正常通过宿主机的 eth0 发了出去,且 eth0 也收到了 ICMP 的响应,但是,eth0 没有将 ICMP 响应包进一步发送给 cni0,pod 中自然是收不到的 ICMP 的响应包,因此 ping 一直都是 100% lost。

正常网络包丢了,本能怀疑是 iptables 规则导致,经过一番查找和对比,没有发现什么异常的规则会丢弃,于是去查看 icmp 的包,之前 tcpdump 没有加 -v,没发现宿主机收到的 icmp 包的 ttl 变为了 1。同时还发现,宿主机回复了一个「time exceed in-transit」的 icmp 消息。

TTL 的设计初衷是为了防止数据包在互联网上无限制地循环下去。每当一个数据包经过一个路由器,该路由器都会将数据包的 TTL 值减少 1。当 TTL 达到 0 时,路由器会丢弃该数据包,并通常发送一个 ICMP "Time Exceeded" 消息给原始发送者。

当 ICMP 或 IP 头中的 TTL 变为 1,意味着数据包要么到达目标,要么经过下一个路由器后被丢弃。

那是不是确实经过的网络设备太多,导致 ttl 不够用了呢?在容器内,把 ttl 先改大为 255,再试下,发现回复的 ttl 依然是 1,看来是有什么路由器在把包发给边缘节点的时候,强制把 ttl 改为了 1。

如果是这个问题,那可以通过 iptables 来把宿主机收到的 ttl 改大一点,比如改为 64。

shell 复制代码
iptables -t mangle -A PREROUTING -p icmp --icmp-type echo-reply -m ttl --ttl-eq 1 -j TTL --ttl-set 64

改完 ping 命令就都可以成功了。

那 ping 能成功,是不是 tcp 请求就能成功呢?

会发现 telnet 和 curl 都会超时,此时再来抓包看看。

发现 tcp 包里的 IP 头里的 TTL 也被设置为了 1。IP 头的 TTL 变为 1,不会把包继续传给容器内下一跳,容器就收不到服务器回复的 SYN+ACK 了。

于是我们再通过 iptables 将 IP 头的 ttl 也设置为 64。

css 复制代码
iptables -t mangle -A PREROUTING -m ttl --ttl-eq 1 -j TTL --ttl-set 64

再次请求就成功返回了。

小结

目前为什么 ttl 被设置为了 1,还需要跟边缘节点部署方确认。暂时可以通过此方法 hack 绕过。

css 复制代码
iptables -t mangle -A PREROUTING -p icmp --icmp-type echo-reply -m ttl --ttl-eq 1 -j TTL --ttl-set 64
iptables -t mangle -A PREROUTING -m ttl --ttl-eq 1 -j TTL --ttl-set 64

另外,上面 iptables 规则的改动,重启会丢失,需要做持久化。

相关推荐
一路向北North12 分钟前
Spring Security OAuth2.0(20):完善环境配置
java·后端·spring
从零开始的代码生活_27 分钟前
C++ string 详解:常用接口、字符串算法与深拷贝实现
开发语言·c++·后端·学习·算法
65岁退休Coder1 小时前
LangChain v1.3.4 笔记 - 01 模型的连接/输出、消息、提示词模板
后端
笃行3501 小时前
数据库优化深度科普向|外连接消除底层原理,国产数据库优化器设计思路拆解
后端
苍何2 小时前
耗时 7 天,我们开源了腾讯 WorkBuddy 实战蓝皮书(建议收藏)
前端·后端
青山木2 小时前
Redis 高可用的最后一公里:Cluster 分片、Gossip 与故障转移全流程
数据库·redis·后端·缓存
老孙讲技术2 小时前
巡店系统笔记:listDeviceDetailsByPage 台账 + bindDeviceLive 辅码流最小闭环
后端·物联网
Dong先生2 小时前
Harness vibecoding:从 PRD 到可交付代码的结构化工法
后端
拾光师3 小时前
HDFS 深度解析:大数据存储的“硬盘不够、单盘坏了怎么办“
后端
雪隐3 小时前
用Flutter做背单词APP-03为了给单词库塞满数据,我让AI给我打了上万份工
前端·人工智能·后端