linux下 tcpdump实现原理
来源:互联网 发布:淘宝网冬装女装 编辑:程序博客网 时间:2024/05/22 13:15
linux下抓包实现原理
一、tcpdump
对于本机中进程的系统行为调用跟踪,strace是一个很好的工具,而在网络问题的调试中,tcpdump应该说是一个必不可少的工具,和大部分linux下优秀工具一样,它的特点就是简单而强大。
默认情况下,tcpdump不会抓取本机内部通讯的报文。根据网络协议栈的规定,对于报文,即使是目的地是本机,也需要经过本机的网络协议层,所以本机通讯肯定是通过API进入了内核,并且完成了路由选择。
二、linux下抓包原理
linux下的抓包是通过注册一种虚拟的底层网络协议来完成对网络报文(准确的说是网络设备)消息的处理权。当网卡接收到一个网络报文之后,它会遍历系统中所有已经注册的网络协议,例如以太网协议、x25协议处理模块来尝试进行报文的解析处理,这一点和一些文件系统的挂载相似,就是让系统中所有的已经注册的文件系统来进行尝试挂载,如果哪一个认为自己可以处理,那么就完成挂载。
当抓包模块把自己伪装成一个网络协议的时候,系统在收到报文的时候就会给这个伪协议一次机会,让它来对网卡收到的报文进行一次处理,此时该模块就会趁机对报文进行窥探,也就是把这个报文完完整整的复制一份,假装是自己接收到的报文,汇报给抓包模块。
先看一下网络层对于接收到的报文的处理方法
static int process_backlog(struct net_device *backlog_dev, int*budget)---netif_receive_skb
list_for_each_entry_rcu(ptype, &ptype_all, list) {
if(!ptype->dev || ptype->dev == skb->dev) {
if(pt_prev)
ret= deliver_skb(skb, pt_prev,orig_dev) ;
pt_prev =ptype;
}
}
三、协议族的注册
对于这种协议,也只有在需要的时候才注册,因为它毕竟增加了系统报文的处理速度并且会消耗大量的系统skb。当抓包开始的时候,它会创建一个对应的网络套接口,这种套接口的类型就是af_packet类型。相关实现为
linux-2.6.21\net\packet\af_packet.c
static int packet_create(struct socket *sock, intprotocol)
sk->sk_family = PF_PACKET;
po->num= proto ;
……
po->prot_hook.func = packet_rcv;
……
if (proto){
po->prot_hook.type = proto;
dev_add_pack(&po->prot_hook);这个接口会将prot_hook注册到前面看到的ptype_all队列中
sock_hold(sk);
po->running = 1;
}
当一个网卡上真正有报文到来的时候,它就会调用这里注册的packet_rcv函数
……
res= run_filter(skb, sk,snaplen);如果说filter过滤失败,说明是抓包不关心的报文,直接放行,返回值非零表示不关心。
if(!res)
gotodrop_n_restore;
……
if(skb_shared(skb)) {
structsk_buff *nskb = skb_clone(skb, GFP_ATOMIC);自己复制一份。
if (nskb ==NULL)
gotodrop_n_acct;
if (skb_head!= skb->data) {
skb->data= skb_head;
skb->len= skb_len;
}
kfree_skb(skb);
skb =nskb;
}
四、filter的执行
run_filter--->>sk_run_filter
……
for (pc = 0;pc < flen; pc++) {
fentry =&filter[pc];
switch(fentry->code) {
caseBPF_ALU|BPF_ADD|BPF_X:
A +=X;
continue;
caseBPF_ALU|BPF_ADD|BPF_K:
A +=fentry->k;
continue;
……
switch(k-SKF_AD_OFF) {
默认情况下,tcpdump不会抓取本机内部通讯的报文。根据网络协议栈的规定,对于报文,即使是目的地是本机,也需要经过本机的网络协议层,所以本机通讯肯定是通过API进入了内核,并且完成了路由选择。
二、linux下抓包原理
linux下的抓包是通过注册一种虚拟的底层网络协议来完成对网络报文(准确的说是网络设备)消息的处理权。当网卡接收到一个网络报文之后,它会遍历系统中所有已经注册的网络协议,例如以太网协议、x25协议处理模块来尝试进行报文的解析处理,这一点和一些文件系统的挂载相似,就是让系统中所有的已经注册的文件系统来进行尝试挂载,如果哪一个认为自己可以处理,那么就完成挂载。
当抓包模块把自己伪装成一个网络协议的时候,系统在收到报文的时候就会给这个伪协议一次机会,让它来对网卡收到的报文进行一次处理,此时该模块就会趁机对报文进行窥探,也就是把这个报文完完整整的复制一份,假装是自己接收到的报文,汇报给抓包模块。
先看一下网络层对于接收到的报文的处理方法
static int process_backlog(struct net_device *backlog_dev, int*budget)---netif_receive_skb
三、协议族的注册
对于这种协议,也只有在需要的时候才注册,因为它毕竟增加了系统报文的处理速度并且会消耗大量的系统skb。当抓包开始的时候,它会创建一个对应的网络套接口,这种套接口的类型就是af_packet类型。相关实现为
linux-2.6.21\net\packet\af_packet.c
static int packet_create(struct socket *sock, intprotocol)
……
……
当一个网卡上真正有报文到来的时候,它就会调用这里注册的packet_rcv函数
……
……
四、filter的执行
run_filter--->>sk_run_filter
……
……