tcpdump 实现原理【整理】
参考:http://blog.sina.com.cn/s/blog_523491650101au7f.html
一、tcpdump
默认情况下,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, int protocol)
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)
goto drop_n_restore;
……
if (skb_shared(skb)) {
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);自己复制一份。
if (nskb == NULL)
goto drop_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) {
case BPF_ALU|BPF_ADD|BPF_X:
A += X;
continue;
case BPF_ALU|BPF_ADD|BPF_K:
A += fentry->k;
continue;
……
switch (k-SKF_AD_OFF) {
case SKF_AD_PROTOCOL:
A = ntohs(skb->protocol);
continue;
case SKF_AD_PKTTYPE:
A = skb->pkt_type;
continue;
case SKF_AD_IFINDEX:
A = skb->dev->ifindex;
continue;
default:
return 0;
}
这个函数是执行了一个自己定义的指令集和。用户通过sockopt来注册这段指令,内核在内核态执行这些指令,完成匹配,其中包含了报文某些字段的加载,条件跳转、加减乘除以及返回等指令。当转包套接口接收到报文之后,对这个报文执行这段虚拟程序,直到遇到ret指令作为自己的返回值。通过tcpdump -d 可以显示出编译之后生成的指令,下面是一个测试输出
[root@Harry bash-4.1]# tcpdump -d host 1.2.3.4
tcpdump: WARNING: eth0: no IPv4 address assigned
(000) ldh [12]
(001) jeq #0x800 jt 2 jf 6
(002) ld [26] 加载接收到报文的第26个字节开始的一个int类型,
(003) jeq #0x1020304 jt 12 jf 4 如果和0x1234相等,跳转到12跳指令,不等继续第四条指令。
(004) ld [30]
(005) jeq #0x1020304 jt 12 jf 13
(006) jeq #0x806 jt 8 jf 7
(007) jeq #0x8035 jt 8 jf 13
(008) ld [28]
(009) jeq #0x1020304 jt 12 jf 10
(010) ld [38]
(011) jeq #0x1020304 jt 12 jf 13
(012) ret #65535
(013) ret #0
[root@Harry bash-4.1]#
五、tcpdump的处理
对于tcpdump来说,命令行输入中除了选项之外的参数都将作为一个语法文件来处理。libcap中定义了自己的词法分析器和语法分析器。其词法分析器为scanner.l,语法分析文件为scanner.l,可见该语言的定义使用了通用的bison和flex的帮助。但是如果使用了这些工具,就意味着一个配置文件就可以写的很复杂,例如syslog-ng配置、ld连接配置脚本、bash脚本等各种语法。
这个语法文件如果感兴趣可以看看说明文档即可。
其中pcap库中没有对网卡的配置,而且tcpdump的命令处理对于-i是覆盖的,所以一次tcpdump只能侦听一个端口。如果命令行没有指定网络设备,pcap会枚举系统中所有的网络设备,然后取出第一个设备(这个顺序在不通的系统有不同排列顺序,看一下tcpdump的输出即可确定是在那个端口)
六、本地报文处理
if (res.type == RTN_LOCAL) {
if (!fl.fl4_src)
fl.fl4_src = fl.fl4_dst;
if (dev_out)
dev_put(dev_out);
dev_out = &loopback_dev;
dev_hold(dev_out);
fl.oif = dev_out->ifindex;
if (res.fi)
fib_info_put(res.fi);
res.fi = NULL;
flags |= RTCF_LOCAL;
goto make_route;
}
struct net_device loopback_dev = {
.name = "lo",
tcpdump 实现原理【整理】的更多相关文章
- 3星|《结构思考力》:用金字塔原理整理PPT的思路,案例偏简单
结构思考力 名义上全书是讲结构化思考,实际内容是用结构化思考的方法来整理PPT的思路,让PPT的逻辑更清晰.少部分提到如何修改标题更吸引人,如何做图表设计. 书中结构化思考的基本思路,重要的有两个:1 ...
- dynamic-load-apk插件原理整理
因为当前项目功能越来越多,编译速度越来越慢(公司电脑配置也挺差的...),并且方法数已超出65535的限制了,虽然通过multidex暂时解决了,但是这并不是一个好的解决方式.所以通过插件来加快编译速 ...
- 字符串匹配--kmp算法原理整理
kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...
- Java的HashMap实现原理整理总结
通过Debug 探寻Java-HashMap 实现原理: 一个简单的例子,代码如下, 测试方法 main: public static void main(String[] args) { KeyOb ...
- Binder 原理整理
linux进程间通信方式 1. 管道 管道的实质是一个内核缓冲区,管道的作用正如其名,需要通信的两个进程在管道的两端,进程利用管道传递信息.管道对于管道两端的进程而言,就是一个文件,但是这个文件比较特 ...
- 跳出初学MySQL知识的原理整理(一)
一.基础架构 MySQL 可以分为 Server 层和存储引擎层两部分. Server 层包括连接器.查询缓存.分析器.优化器.执行器等,所有跨存储引擎 的功能都在这一层实现,比如存储过程.触发器.视 ...
- Spring Boot常用注解和原理整理
一.启动注解 @SpringBootApplication @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documen ...
- vue响应式原理整理
vue是数据响应性,这是很酷的一个地方.本文只为理清逻辑.详细请看官方文档 https://cn.vuejs.org/v2/guide/reactivity.html vue的data在处理数据时候, ...
- Storm Topology及分组原理
Storm的通信机制,需要满足如下一些条件以满足Storm的语义. 1.建立数据传输的缓冲区.在通信连接没有建立之前把发送的数据缓存起来.数据发送方可以在连接建立之前发送消息,而不需要等连接建立起来, ...
随机推荐
- Java spring mvc多数据源配置
1.首先配置两个数据库<bean id="dataSourceA" class="org.apache.commons.dbcp.BasicDataSource&q ...
- 【css a标签 鼠标悬浮时变手型】
<a href="#" style="cursor:pointer">
- vue.js(四)
由于组件内容太多又特别关键,我决定在官网教程的基础上,加上自己的理解,针对每个内容详细记录一下 1.注册组件 ①全局注册 //首先创建组件 Vue.component('blog-post', { ...
- Linux下如何执行Shell脚本
Linux下你可以有两种方式执行Shell脚本: 1.用shell程序执行脚本:根据你的shell脚本的类型,选择shell程序,常用的有sh,bash,tcsh等(一般来说第一行#!/bin/bas ...
- Yarn之ResourceManager详细分析
一.概述 本文将介绍ResourceManager在Yarn中的功能作用,从更细的粒度分析RM内部组成的各个组件功能和他们相互的交互方式. 二.ResourceManager的交互协议与基本职 ...
- (转)通过HTTP RESTful API 操作elasticsearch搜索数据
样例数据集 这是编造的JSON格式银行客户账号信息文档,文档schema如下: { “account_number”: 0, “balance”: 16623, “firstname”: “Brads ...
- scikit-learn 中常用的评估模型
一,scikit-learn中常用的评估模型 1.评估分类模型: 2.评估回归模型: 二.常见模型评估解析: •对于二分类问题,可将样例根据其真实类别和分类器预测类别划分为:(T,F表示预测的 ...
- JDK eclipse selenium的安装以及环境变量的配置
未经允许,禁止转载!!! 未经允许,禁止转载!!! 首先下载安装JDK: 然后双击进行安装 选着第一个:开发工具!点击next 一定要记住:Install to: C:\Program Files\ ...
- 在GUI程序中使用控制台的两种方法
win32程序启用控制台(控制台文件名:conout$,conin$,conerr$) //添加控制台,加入在程序构造函数中 AllocConsole(); freopen("conin$& ...
- Keras实践:模型可视化
Keras实践:模型可视化 安装Graphviz 官方网址为:http://www.graphviz.org/.我使用的是mac系统,所以我分享一下我使用时遇到的坑. Mac安装时在终端中执行: br ...