尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

也谈tcpdump抓包

也谈tcpdump抓包 shixudong163.com一、tcpdump和netfilter数据包接收环节的抓包点位于内核函数__netif_receive_skb_core此时数据包已经过GRO合并处理但尚未进入rx_handler环节如bridge至于netfilterPREROUTING被hook在协议层ip_rcv更是在rx_handler 环节之后。所以在收包环节DNAT以及netfilter 过滤规则并不会影响 tcpdump抓包譬如tcpdump只能抓到接收包DNAT前的目标IP而非DNAT后的目标IP。数据包发送环节的抓包点位于内核函数dev_queue_xmit_nit正好在网卡发包函数ndo_start_xmit之前此时数据包早已经过OUTPUT/DNAT和POSTROUTING/SNAT。因此在发包环节netfilter 过滤规则以及DNAT/SNAT必然影响tcpdump抓包譬如tcpdump只能抓到外出包SNAT后的源IP而非SNAT前的源IP对于OUTPUT/DNATtcpdump也只能抓到外出包DNAT后的目标IP而非DNAT前的目标IP。二、tcpdump和bridge如前所述数据包在接收环节首次抓包时尚未进入bridge属于物理网卡上的抓包。数据包经bridge处理后对于需要继续移交上层处理的数据包bridge将调用netif_receive_skb也意味着数据包再次进入接收环节抓包点即bridge网卡接收环节抓包点此时属于逻辑网卡上的抓包。至于那些经bridge处理后直接在二层转发出去的数据包除非bridge网卡开启PROMISC否则永远不会经过bridge网卡接收环节抓包点。数据包在发送环节将先后两次调用dev_queue_xmit_nit第一次将进入bridge网卡发送环节抓包点第二次将进入物理网卡发送环节抓包点。对于先前那些经bridge处理后直接在二层转发出去的数据包同样也永远不会经过bridge网卡发送环节抓包点。在bridge环境下如启用了br_netfilter将在二层提前进行三层netfilter处理经过bridge各种处理后包括netfilter处理只有需要继续移交上层处理的数据包才会进入bridge网卡接收环节抓包点。此时在bridge网卡接收方向上抓包也必然受到DNAT以及netfilter 过滤规则的影响譬如tcpdump只能抓到接收包DNAT后的目标IP而非DNAT前的目标IP以及抓不到那些本应在三层才被内核隐式DROP的数据包。因此为了便于精确跟踪调试数据包流向在bridge网卡上抓包时建议临时关闭br_netfilter或者直接在bridge下挂的物理网卡上抓包。三、tcpdump和PROMISC在《Linux二层包类型对网络功能的影响分析》一文中提到如网卡不开启PROMISC目标MAC为非本网卡MAC的数据包在网卡固件层面就被DROP压根不会进入接收环节。tcpdump抓包时默认开启被抓包网卡的PROMISC网卡开启PROMISC后网卡固件允许接收目标MAC为非本网卡MAC的数据包内核将其包类型标记为PACKET_OTHERHOST并被tcpdump抓包对于HUB环境该功能可以嗅探其他机器之间的数据包。但对于Switch环境即使网卡已开启PROMISC也压根收不到目标MAC为非本网卡MAC的数据包此时tcpdump抓包的主要目的是为了跟踪调试数据包流向。对于linux bridge来说加入bridge的物理网卡都强制开启了PROMISC用于接收和转发PACKET_OTHERHOST数据包。通常情况下这些 PACKET_OTHERHOST数据包并不会进入上层协议栈但如bridge网卡本身不小心也开启了PROMISC这些已二层直接转发出去的数据包还会同时提交上层协议栈由于ip_rcv将直接丢弃PACKET_OTHERHOST包此类数据包最终并不能被linux三层处理。显然在bridge网卡上开启PROMISC将对数据包流向产生一定影响不利于后续精确跟踪调试数据包流向因此针对bridge网卡本身抓包时建议使用-p参数non-promiscuous mode此后tcpdump就能精确抓取那些真正需要经由bridge和上层协议交互的数据包而不再抓取经由物理网卡直接转发出去的PACKET_OTHERHOST数据包。顺便提一下在已开启PROMISC的bridge物理网卡上使用-p参数抓包并不会关闭PROMISC。在Switch环境下linux bridge下挂的物理网卡因强制开启了PROMISC会出现PACKET_OTHERHOST数据包bridge网卡本身如手动开启了PROMISC后也会出现PACKET_OTHERHOST数据包。除此之外包括非桥接物理网卡以及bond在内的其他逻辑网卡即便主动开启了PROMISC理论上也不会出现PACKET_OTHERHOST数据包tcpdump在这些网卡上抓包时是否使用-p参数对抓包效果无任何影响。四、tcpdump和DNAT/SNAT对于PREROUTING/DNAT和POSTROUTING/SNAT如一所述虽然netfilter规则能够影响到发送环节tcpdump抓包例如数据包外出时发生了SNAT只能抓取SNAT后的源IP但返回包抓取发生在DNAT前抓包时返回包目标IP尚未经过DNAT转换仍是SNAT后的源IP这两个IP一致。也就是说通常情形下在数据包经过的任意一块网卡上抓包所抓数据包在进出两个方向上的IP地址和PORT都保持对称。如二所述bridge环境下启用br_netfilter后如发生了DNAT在bridge接收方向上只能抓到DNAT后的目标IP和PORT, 在bridge发送方向上则抓到SNAT后的源IP和PORT这两组IP和PORT是不一致的。这意味着对于需要DNAT的数据包来说在tcpdump看来数据包在bridge网卡进出两个方向上的IP地址和PORT将不再保持对称。抓包条件还必须额外匹配数据包DNAT后的目标IP和PORT才能抓全进出方向上的不对称包。如直接在bridge下挂的物理网卡上抓包则不存在该问题仍可通过常规匹配条件抓取进出方向上的对称包。对于OUTPUT/DNAT和INPUT/SNAT情形则略有不同发送环节抓包点同样只能抓取DNAT后的目标IP而返回包的源IP需要抵达三层INPUT链处才做相应的SNAT转换故不受bridge和br_netfilter影响。在bridge网卡接收环节抓包点由于返回包源IP尚未经过INPUT/SNAT转换只能抓到返回包SNAT前的源IP即发送包DNAT后的目标IP。这两个IP一致保证了所抓数据包在bridge网卡进出两个方向上IP地址和PORT的对称性。五、tcpdump和lo当对本机外出数据包进行OUTPUT/REDIRECT时全程使用lo网卡并不涉及bridge和br_netfilter但同样会出现如四所述现象即lo网卡上抓取REDIRECT的数据包来回链路上的IP地址和PORT也不对称。原因分析如下Linux在进行本机单播通信时使用lo网卡数据包同样需要经过发送和接收环节的抓包点。理论上在lo网卡上抓包时数据包一来一回之间应能抓到4个包但在显示抓包结果时会有一半的数据包看起来明显冗余因此tcpdump抓包库libpcap专门针对lo网卡进行了过滤仅在接收环节显示抓包结果所以tcpdump实际上只显示来回链路上2个接收环节的数据包去除了不必要的冗余。对于经过OUTPUT/REDIRECT处理的本机外出数据包实际上早在外出包的发送环节抓包点目标IP已更改lo网卡在接收环节显示抓包结果时自然也显示为REDIRECT后的目标IP。至于返回包源IP的SNAT转换由于为本机自发自收返回包在其发送环节POSTROUTING链处能匹配到先前外出包的DNAT记录并在此处完成了相应的SNAT转换而无需像第四部分OUTPUT链DNAT目标非本机那样直到INPUT链处才做SNAT转换。因此在返回包的接收环节抓包点显然只能抓到SNAT后的源IP对应外出包REDIRECT前的目标IP导致来回之间看起来也不对称。当lo网卡上有很多流量时也必须额外匹配外出包REDIRECT后的目标IP和PORT才能抓全来回链路上的不对称包。考虑到TPROXY也是全程使用lo网卡并且无需修改目标IP因此可用TPROXY取代REDIRECT即可在lo网卡上通过常规匹配条件抓取来回链路上的对称包。Linux为实现本机组播/广播通信在通过ip_mc_output对外发送组播/广播包时顺手调用dev_loopback_xmit发给自己一份在该函数中将包类型设置为PACKET_LOOPBACK然后直接调用netif_rx收包。因此对于本机组播/广播来说相当于跳过了发送环节抓包点虽然后续netif_rx收包时需要经过接收环节抓包点但内核抓包环节并不处理PACKET_LOOPBACK所以发给自己的组播/广播包全程无法抓包并且dev_loopback_xmit和netif_rx也只使用发送组播/广播IP时选定的网卡全程不使用lo网卡。六、tcpdump和数据包方向通常情况下tcpdump在指定网卡上抓包可通过源IPPORT和目标IPPORT的组合大致识别数据包流向无需刻意关注数据包在网卡上的进出方向。接口“any”可用于捕获来自所有网卡的数据包鉴于同一组合的数据包可在不同网卡上同时出现从v4.99起tcpdump支持LINKTYPE_LINUX_SLL2-iany能显示数据包在不同网卡上的进出方向之前版本无法显示网卡信息。此外tcpdump还可指定-Qin\out\inout来抓取特定方向的数据包。在《Linux二层包类型对网络功能的影响分析》一文中提到Linux网卡在接收数据包时网卡驱动调用eth_type_trans对数据包进行预处理该函数通过比较目标MAC地址判断二层包类型并进行标记PACKET_BROADCAST二层广播地址、PACKET_MULTICAST二层多播地址、PACKET_OTHERHOST目标MAC非本网卡MAC、PACKET_HOST目标MAC为本网卡MAC二层包类型标记将影响数据包在二层的后续流向和三层的后续处理。Linux网卡发送数据包时无需关心二层包类型标记但内核在数据包发送环节的抓包点dev_queue_xmit_nit针对外发数据包的二层包类型专门为抓包程序标记了PACKET_OUTGOING。Tcpdump在使用-iany显示数据包方向时对Linux二层包类型进行了转换In对应PACKET_HOSTB对应PACKET_BROADCASTM对应PACKET_MULTICASTP对应PACKET_OTHERHOSTOut对应PACKET_OUTGOING。根据前面分析In、B、M和P实际上都表示网卡的接收方向只有Out才表示网卡的发送方向。tcpdump在使用-Q参数指定数据包方向时-Qin也是包含了In、B、M和P。Linux的KVM在桥接外部网络时直接加入Linux网桥虚拟机之间以及虚拟机和外部网络的通信完全遵从linux网桥行为譬如在主机桥接网卡上抓包时就无法抓取虚拟机之间不经过该网卡的数据包。然而Linux上的Vmware或Virtualbox在桥接外部网络时没有使用linux网桥技术而是采用Hub技术直接桥接到主机网卡在主机桥接网卡上不仅能抓到虚拟机和外部网络的数据包还能抓到虚拟机之间的数据包并且这两种情形下都存在重复包。这些重复包实际上是虚拟机将数据包同时发到了主机网卡的发送和接收方向此时就可以借助-iany并结合源IPPORT、目标IPPORT的组合来识别虚拟机数据包在主机网卡上的进出方向。本文第五部分提到Linux在进行本机单播通信时使用lo网卡在使用-ilo进行抓包时一般情形下本机通信使用相同的源IP和目标IP127.0.0.1或本机网卡IP但源端口和目标端口并不相同抓包数据看起来有来有往宾主相欢。在使用TPROXY的情形下源IP和目标IP也不相同抓包数据就更加好看。然而当使用-iany加其他限定条件抓包后lo网卡上的数据包流向顿时原形毕露全部表现为清一色的In方向。当然事实上并非如此诚如第五部分所言只是为了去除不必要的显示冗余以及libpcap的处理方便针对lo网卡libpcap仅处理接收环节的数据包而已。
返回列表