用户态 tcpdump 如何实现抓到内核网络包的?
时间:2021-09-23 15:40:53
手机看文章
扫描二维码
随时随地手机看文章
[导读]大家好,我是飞哥!今天聊聊大家工作中经常用到的tcpdump。在网络包的发送和接收过程中,绝大部分的工作都是在内核态完成的。那么问题来了,我们常用的运行在用户态的程序tcpdump是那如何实现抓到内核态的包的呢?有的同学知道tcpdump是基于libpcap的,那么libpcap...
大家好,我是飞哥!今天聊聊大家工作中经常用到的 tcpdump。在网络包的发送和接收过程中,绝大部分的工作都是在内核态完成的。那么问题来了,我们常用的运行在用户态的程序 tcpdump 是那如何实现抓到内核态的包的呢?有的同学知道 tcpdump 是基于 libpcap 的,那么 libpcap 的工作原理又是啥样的呢。如果让你裸写一个抓包程序,你有没有思路?按照飞哥的风格,不搞到最底层的原理咱是不会罢休的。所以我对相关的源码进行了深入分析。通过本文,你将彻底搞清楚了以下这几个问题。找到 tcpdump 抓包点
我们在网络设备层的代码里找到了 tcpdump 的抓包入口。在 __netif_receive_skb_core 这个函数里会遍历 ptype_all 上的协议。还记得上文中我们提到 tcpdump 在 ptype_all 上注册了虚拟协议。这时就能执行的到了。来看函数:
- tcpdump 是如何工作的?
- netfilter 过滤的包 tcpdump 是否可以抓的到?
- 让你自己写一个抓包程序的话该如何下手?
一、网络包接收过程
在图解Linux网络包接收过程一文中我们详细介绍了网络包是如何从网卡到达用户进程中的。这个过程我们可以简单用如下这个图来表示。找到 tcpdump 抓包点
我们在网络设备层的代码里找到了 tcpdump 的抓包入口。在 __netif_receive_skb_core 这个函数里会遍历 ptype_all 上的协议。还记得上文中我们提到 tcpdump 在 ptype_all 上注册了虚拟协议。这时就能执行的到了。来看函数://file: net/core/dev.c
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
{
......
//遍历 ptype_all (tcpdump 在这里挂了虚拟协议)
list_for_each_entry_rcu(ptype, 




