读路由表并算一算
目标
读取地址、计算子网,并直接询问内核数据包会从哪条路径发出。 防火墙规则和网络策略全都建立在这些计算之上。
为什么重要
“只有某个网段无法访问”这类报告几乎总是路由或掩码计算问题。 但如果不会读取路由表,甚至不知道应该查看什么。
第 4 步尤其重要。ip route get 不需要阅读表格后自行推断,而是
直接询问内核。它比人的推断更准确,而且能立即得到答案。
步骤
- 为什么我的地址是 /32 →
/root/net/01-addr.txt - 计算给定三个网段的子网 →
/root/net/02-subnet.txt - 路由表 →
/root/net/03-route.txt - 执行两次
ip route get→/root/net/04-get.txt - 解释最长前缀匹配 →
/root/net/05-longest.txt - 判断私有/公共地址 →
/root/net/08-private.txt
参考
- 此 Pod 没有内核权限,因此无法使用
ip route add更改路由。 目标是读取和计算。 - Pod 地址为
/32是正常现象。Cilium 只为每个 Pod 分配一个地址, 并通过单独的 on-link 路由告知出站路径。因此,Pod 中不存在“同一子网内的 邻居”,所有通信都会经过网关。 python3的ipaddress模块有助于核对计算结果。- 172 私有网段的边界和
100.64.0.0/10是陷阱。
我的地址前缀看起来很奇怪
使用 ip -o addr show eth0 查看地址。前缀应该是 /32——这不是笔误。
在 /root/net/01-addr.txt 中写入两行:(1)原样写入地址/前缀;(2)用一行说明为什么是 /32。提示:此集群的 CNI 是 Cilium,它不会为 Pod 分配子网,而是只分配一个地址,再通过单独的 on-link 路由告知出站路径。因此,Pod 从根本上就没有“同一子网内的邻居”这一概念。
计算子网
此 Pod 的地址是 /32,没有需要计算的内容,因此使用给定网段练习。在 /root/net/02-subnet.txt 中写入三行,每行格式为 <CIDR> <네트워크주소> <브로드캐스트> <호스트개수>。
需要计算的网段:192.168.219.0/26、10.10.0.0/20、172.16.5.128/25
先手动计算,再使用 python3 -c "import ipaddress; n=ipaddress.ip_network('192.168.219.0/26'); print(n.network_address, n.broadcast_address, n.num_addresses-2)" 核对。
路由表
将 ip route 的完整输出保存到 /root/net/03-route.txt。其中必须包含 default 行。
直接询问内核
询问两次。ip route get 8.8.8.8(外部)和 ip route get <게이트웨이 주소>(on-link)。网关地址位于第 3 步保存的 default via ... 行中。
将两个结果保存到 /root/net/04-get.txt。一个带有 via,另一个没有——这一区别表示“经过网关”和“直接发送”。
最长前缀匹配
在 /root/net/05-longest.txt 中写入两行。(1)同时存在 10.0.0.0/8 和 10.244.0.0/16 时,10.244.1.5 会走哪一条路由;(2)为什么。请在答案中写出规则名称。
区分名称与连接
这是将“无法访问”按层次拆分的训练。在 /root/net/06-dns.txt 中写入两行。(1)getent hosts localhost 的结果;(2)用一行说明尝试 getent hosts nowhere.invalid 时会发生什么。名称无法解析与无法连接是不同的问题,但在用户看来都只是同样的“不可用”。
哪些端口正在监听
使用 ss -ltnp 查看处于 LISTEN 状态的 TCP 端口。将结果保存到 /root/net/07-ports.txt。此 Pod 没有相应权限,因此可能看不到进程名称,这也是正常现象——只要有端口列表即可。
判断私有网段
在 /root/net/08-private.txt 中写入五行。每行格式为 <주소> <private|public>。需要判断的地址:10.1.2.3 / 172.20.5.6 / 172.32.0.1 / 192.168.100.1 / 100.100.1.1。172 网段的边界和 CGNAT 网段是陷阱。