「Network」- 关于 TCPDUMP 和 IPTABLES 的先后顺序

问题背景

当 Host-A 无法访问 Host-B 时,我们可以在 Host-B 上使用 tcpdump 抓包,检查 Host-B 是否收到了数据包。

但是 Host-B 上通常都配置了防火墙,那在 Host-B 上数据包是先被 tcpdump 捕获呢,还是先被 iptables 过滤调了?

实际情况

事实上它们的关系是这样子的:

Wire -> NIC -> tcpdump -> netfilter -> applications -> netfilter -> tcpdump -> NIC -> Wire

因此,使用 tcpdump 后,可以看到流入网卡的全部数据包,也可以看到流出网卡的所有数据包,但是不一定能看到应用程序返回的数据包。

详细说明

在 Linux 中,当「网络栈」中接收到「常规数据包」时,「内核」首先检查是否存在对「常规数据包」感兴趣的「数据包套接字」,如果有,则将「常规数据包」转发到该「数据包套接字」。如果使用了选项 ETH_P_ALL,则所有协议都通过数据包套接字。

命令 tcpdump 基于 libpcap 库,而该库用于创建「数据包套接字」。libpcap 使用 ETH_P_ALL 选项实现一个这样的「数据包套接字」,将「常规数据包」保留一个副本供自己分析使用,并将「常规数据包」复制回「网络栈」中,然后内核就可以以通常的方式处理它,这包括首先将它传递给 netfilter(iptables 的内核空间对应物)。同样的事情,在发送数据包的情况下,以相反的顺序发生(即,第一个 netfilter,然后通过「数据包套接字」)。

所以,在某些 rootkit 中,可以使用 libpacp 来绕过防火墙。

参考文献

Will tcpdump see packets that are being dropped by iptables?
Does tcpdump bypass iptables?
Iptables FORWARD chain traffic not seen by tcpdump
Debugging iptables rules with tcpdump and wireshark