记录一次ping不通问题的分析过程
1. 背景描述
同一网段的机器A、B,机器B上部署有虚拟机b,期望通过机器A能ping通虚拟机b。
2. 分析过程
2.1. 配置路由
由于A、B在同一网段,但是和虚拟机b并不在同一网段,因此当从机器A上ping虚拟机b的ip时,其网络报文并不会被路由到机器B。
解决方案,在A上增加一条到虚拟机b的路由配置,示例如下:
route add -host ip_b/32 gw ip_B dev eth0
2.2. 报文转发
路由配置成功后,在机器B上就可以抓到机器A发送的ping报文了,但是此时仍然ping不通。
原因在于报文从机器B到其上的虚拟机b,还需要经过网桥转发报文,因此需要开启机器B上的报文转发功能,示例如下。
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.conf.virbr0.forwarding=1
2.3. 网络过滤
配置完报文转发后,预期在虚拟机b上就已经可以抓到来自机器A的ping报文了,但实际上并没有看到。
2.3.1. 首先确认机器B上路由配置
发现有从机器B到其上虚拟机b的路由,且从机器B上也能ping通b,因此确定机器B上的路由配置并无问题。
2.3.2. 其次确认机器B上的iptables配置
如下图所示,通过iptabels –nL查看机器B上的iptables配置如下,发现该报文并没有被丢弃。
2.3.3. 抓取ip_forward内核执行流程
通过tcpdump很容易确认,上述ping报文确实已经到机器B,且未送达虚拟机b,且未发现明显的iptables过滤配置。
因此推测还是ip报文转发流程出了问题,通过ftrace抓取ip_forward执行流程如下图所示,能明显看到该报文被iptables过滤掉了。
2.3.4. 再次确认机器B上的iptables配置
通过iptables –nvL再次确认iptables的详细配置信息,如下图所示:
上文看到的LIBVIRT_FWX规则配置,指定了报文转发的入口网卡virbr0,且该接口明显不是机器A到B的网卡eth0,因此并不会命中。
继续往后分析,在LIBVIRT_FWI规则第1行配置中,虽然出/入网卡接口和源目的地址都匹配,但针对的是已建立链接,因此也不会命中。
再往后分析,在LIBVIRT_FWI规则第2行配置中,所有匹配规则均满足,且目标处理方式为REJECT,因此会命中该规则,进而导致ping报文被丢弃。
2.3.5. 修改iptables配置
在机器B上执行如下命令,使得通向虚拟机b的报文均能通过,之后在虚拟机b上,能正常监控到来自机器A的ping报文。
iptables -I LIBVIRT_FWI -d ip_b/32 -j ACCEPT
3. 最终结果
至此,在机器A上可以正常的ping通,机器B上的虚拟机b。