我有一个主机,该主机有一个接口,该接口具有 ip 10.0.10.5/28
。主机有一个容器,其接口为 cali02ad7e68ce1 , ip 为10.42.1.2/26
。这是主机的主路由表:
$> ip r list table main
default via 10.0.10.1 dev eth0 proto dhcp metric 100
10.0.10.0/28 dev eth0 proto kernel scope link src 10.0.10.5 metric 100
10.42.1.2 dev cali02ad7e68ce1 scope link
这是 IP 规则列表:
$> ip rule
0: from all lookup local
30400: from 10.0.10.5 lookup 30400
32766: from all lookup main
32767: from all lookup default
这是路由表 30400:
$> ip r list table 30400
default via 10.0.10.1 dev eth0 proto static metric 10
10.0.10.1 dev eth0 proto static scope link metric 10
当我尝试 ping 容器时ping 10.42.1.2
,没有收到任何数据包。但是,如果我在容器的接口上使用 tcpdump,我可以看到回显请求和回显答复。
$> sudo tcpdump -eni cali02ad7e68ce1
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on cali02ad7e68ce1, link-type EN10MB (Ethernet), capture size 262144 bytes
15:57:24.589384 ee:ee:ee:ee:ee:ee > 4e:b1:cd:f0:62:82, ethertype IPv4 (0x0800), length 98: 10.0.10.5 > 10.42.1.2: ICMP echo request, id 34667, seq 1, length 64
15:57:24.589405 4e:b1:cd:f0:62:82 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.42.1.2 > 10.0.10.5: ICMP echo reply, id 34667, seq 1, length 64
15:57:25.637186 ee:ee:ee:ee:ee:ee > 4e:b1:cd:f0:62:82, ethertype IPv4 (0x0800), length 98: 10.0.10.5 > 10.42.1.2: ICMP echo request, id 34667, seq 2, length 64
15:57:25.637216 4e:b1:cd:f0:62:82 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 98: 10.42.1.2 > 10.0.10.5: ICMP echo reply, id 34667, seq 2, length 64
一旦我删除规则30400
,ping 就可以正常工作。我很困惑,因为我不明白该规则如何使 echo 回复永远不会到达 ping 过程。据我所知,该规则只适用于10.0.10.5
源 ip。任何帮助或猜测都将不胜感激!
更新
根据评论的要求添加桥梁信息:
$> ip -br link; ip -br address`
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
eth0 UP 06:e4:85:e5:1b:94 <BROADCAST,MULTICAST,UP,LOWER_UP>
cali02ad7e68ce1@if3 UP ee:ee:ee:ee:ee:ee <BROADCAST,MULTICAST,UP,LOWER_UP>
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP 10.0.10.5/28
cali02ad7e68ce1@if3 UP fe80::ecee:eeff:feee:eeee/64
$> ip -br link show type bridge
$> ip -br link show type bridge_slave
$>
更新2
$> ping 10.42.1.2 &
[1] 1645713
$> PING 10.42.1.2 (10.42.1.2) 56(84) bytes of data.
$> sudo nstat -az TcpExtIPReversePathFilter
#kernel
TcpExtIPReversePathFilter 0 0.0
$> sudo nstat -az TcpExtIPReversePathFilter
#kernel
TcpExtIPReversePathFilter 0 0.0
$> ip route get 10.0.10.5 from 10.42.1.2 iif cali02ad7e68ce1
local 10.0.10.5 from 10.42.1.2 dev lo table local
cache <local> iif cali02ad7e68ce1
答案1
这似乎是反向路径检查问题。请使用 检查计数器nstat -az TcpExtIPReversePathFilter
。如果计数器正在增加,则使用命令检查这些数据包到源的路由
ip route get 10.0.10.5 from 10.42.1.2 iif cali02ad7e68ce1
您很可能会收到错误。
反向路径过滤器检查传入数据包源的路由,并可能丢弃在意外接口上收到的数据包。操作取决于 sysctl 变量的值net.ipv4.conf.<iface>.rp_filter
。
解决方案:
- 禁用 rp_filter 或将其设置为松散模式 (值为
2
)net.ipv4.conf.<iface>.rp_filter
- 请参阅 sysctl 文档。 - 在路由表中设置给容器的附加路由
30400
。
更新:
命令的输出显示反向路径过滤器没有丢弃任何数据包(SNMP 计数器为零,路由有效)。因此问题的原因在于其他方面。使用iptables-save -c
命令检查防火墙规则。它显示了带有命中计数器的完整规则集。可能是某些规则阻止了回复数据包。