tcpdump程序是由Van Jacobson、Craig Leres和Steven McCanne编写的,他们都来自加利福尼亚大学伯克利分校的劳伦斯伯克利实验室。
tcpdump通过将网络接口卡设置为混杂模式( promiscuous mode)来截获经过网络接口
的每一个分组。正常情况下,用于诸如以太网媒体的接口卡只截获送往特定接口地址或广播
地址的链路层的帧。
底层的操作系统必须允许将一个接口设置成混杂模式,并且允许一个用户进程截获帧。
下列的操作系统可以支持tcpdump,或者可以加入对tcpdump的支持: 4.4BSD、BSD/386、SunOS、Ultrix和HP-UX。可以参考随着tcpdump发布的README文件,了解它支持哪些操作系统以及哪些版本。
除了tcpdump还有其他一些选择。例如:可以使用Solaris 2.2的程序snoop来查
看一些分组。AIX 3.2.2提供了iptrace程序,该程序也提供了类似的功能。
1 BSD 分组过滤器
当前由BSD演变而来的Unix内核提供了BSD 分组过滤器BPF (BSD Packet Filter) ,
tcpdump用它来截获和过滤来自一个被置为混杂模式的网络接口卡的分组。B P F也可以工作在点对点的链路上,如SLIP,不需要什么特别的处理就可以截获所有通过接口的分组。BPF还可以工作在环回接口上。
BPF有一个很长的历史。1980年卡耐基梅隆大学的Mike Accetta和Rick Rashid创造
了Enet分组过滤程序。斯坦福的Jeffrey Mogul将代码移植到BSD,从1983年开始继续开
发。从那以后,它演变为DEC的Ultrix分组过滤器、SunOS 4.1下的一个STREAMS NIT
模
块和B P F。劳伦斯伯克利实验室的Steven McCanne在1 9 9 0年的夏天实现了B P F。其中很多设计来自于Van
Jacobson。[McCanne and Jacobson 1993] 给出了最新版本的细节以及与Sun的NIT的一个比较。
图A - 1显示了用于以太网的B P F的特征。
BPF将以太网设备驱动程序设置为混杂模式,然后从驱动程序那里接收每一个收到的分组
和传输的分组。这些分组要通过一个用户指明的过滤器,使得只有那些用户进程感兴趣的分
组才会传递给用户进程。
多个进程可以同时监视一个接口,每个进程指明了一个自己的过滤器。图A - 1显示了
tcpdump的两个实例进程和一个RARP守护进程监视同样的以太网接口。tcpdump
的每个实例指明了一个自己的过滤器。tcpdump的过滤器可以由用户在命令行指明,而
rarpd总是使用只截获RARP请求的过滤器。
除了指明一个过滤器, BPF的每个用户还指明了一个超时定时器的值。因为网络的数据传
输
率可以很容易地超过CPU的处理能力,而且一个用户进程从内核中只读小块数据的代价昂贵,因此,
BPF试图将多个帧装载进一个读缓存,只有缓存满了或者用户指明的超时到期才将读缓存保存的帧返回。tcpdump将超时定时器置为1秒,因为它一般从
BPF收到很多数据。而RARP守护进程收到的帧很少,所以rarpd将超时置为0(收到一个帧就返回)
用户指明的过滤器告诉BPF用户进程对什么帧感兴趣,过滤器是对一个假想机器的一组指
令。这些指令被内核中的BPF过滤器解释。在内核中过滤,而不在用户进程中,减少了必须
从内核传递到用户进程的数据量。RARP守护进程总是使用绑定在程序里的、同样的过滤程序。
另一方面,tcpdump在每次运行时,让用户在命令行指明一个过滤表达式。tcpdump将用户
指明的表达式转换为相应的B P F的指令序列。tcpdump表达式的例子如下:
% tcpdump tcp port 25
% tcpdump icmp [0] != 8 and icmp[0] != 0
第一个只打印源端口和目的端口为25的TCP报文段。第二个只打印不是回送请求和回送
应
答的I C M
P报文(也就是非ping的分组)。这个表达式指明了ICMP报文的第一个字节,type字段,不等于8或0,即图6-3中的回送请求和回送应答。正像你
所看到的,设计过滤器需要有底层分组结构的知识。第二个例子中的表达式被放在一对单引号中,防止Unix外壳程序解释特殊字符。
参考tcpdump(1) 的手册,了解用户可以指明的表达式的全部细节。bpf(4) 的手册详细
描述了B P F使用的假想机器指令。[McCanne and Jacobson 1993] 比较了这个假想机器方法与
其他方法的设计与性能。
2 SunOS的网络接口分接头
SunOS
4.1.x提供了一个STREAMS伪设备驱动程序(pseudo-device driver),称为网络接口分接头(Network
Interface Tap )或者NIT([Rago 1993]
包含了流设备驱动程序的其他细节。我们把这种特征叫作“流”)。NIT类似于BSD分组过滤器,但不如后者功能强大和效率高。图A - 2显示了使用N
I T所用到的流模块。这个图与图A -
1之间的一个不同点在于BPF可以截获网络接口收到的和传送的分组,而NIT只能截获接口收到的分组。将tcpdump与NIT结合起来意味着我们只能看
见由网络中其他主机发送来的分组—即根本不可能看见我们自己主机发送的分组(尽管BPF可以工作在SunOS
4.1.x上,但它需要对以太网设备驱动程序的源代码进行改变,大多数的用户没有权限访问源代码,因而这是不可能的)。
当
设备/dev/nit被打开时,流驱动程序nit_if就会被打开。既然NIT是使用流来构造的,处理模块可以放在nit_if驱动程序之上。
tcpdump将模块nit_buf放在STREAM之上。这个模块将多个网络帧聚集在一个读缓存中,允许用户进程指明一个超时的值。这种情况类似于我们
在BPF中所描述的。RARP守护进程没有把这个模块放在它的流之上,因为它只处理了一小部分分组。
用户指明的过滤由流模块nit_pf处理。在图A - 2中,我们注意到这个模块被RARP守护
进程所用,但没有被tcpdump使用。在SunOS操作系统中,tcpdump代之以在用户进程中完
成自己的过滤操作。这么做的理由是nit_pf使用的假想机器的指令与BPF所支持的指令不同(不如BPF所支持的功能强大)。这就意味着当用户对tcpdump指明了一个过滤表达式时,与BPF相比较,使用NIT就会有更多的数据在内核与用户进程之间交换。
SVR4数据链路提供者接口
SVR4支持数据链路提供者接口DLPI (Data Link Provider Interface),它是OSI数据链路服务定义的一个流实现。SVR4的大多数版本支持第1版的DLPI,SVR4.2同时支持第1版和第2版,
Sun的Solaris 2.x支持第2版,但是增强了一些功能。
像tcpdump的网络监视程序必须使用D L P I来直接访问数据链路设备驱动程序。在Solaris 2.x中,分组过滤的流模块被改名为pfmod,缓存模块被改名为bufmod。
4 tcpdump的输出
tcpdump的输出是“原始的”。在本书中包含它的输出时,我们对它进行了修改以便阅读。
首先,它总是输出它正在监听的网络接口的名字。我们把这一行给删去了。
其
次,tcpdump输出的时间戳在一个微秒精度的系统中采用如同09:11:22.642008的格式,在一个10
ms时钟精度的系统中则如同09:11:22.64一样。在任何一种情况下,
HH:MM:SS的格式都不是我们想要的。我们感兴趣的是每个分组与开始监听的相对时间以及与下面分组的时间差。我们修改了输出以显示这两个时间差。第1
个差值在微秒精度的系统中打印到十进制小数点后面6位(对于只有10
ms精度的系统打印到小数点后面2位),第2个差值打印到十进制小数点后面4位或2位(依赖于时钟精度)。
5 安全性考虑
很明显,截获网络中传输的数据流使我们可以看到很多不应该看到的东西。例如,Telnet和FTP用户输入的口令在网络中传输的内容和用户输入的一样(与口令的加密表示相
比,这称为口令的明文表示。在Unix口令文件中,一般是/etc/passwd或/etc/shadow,
存储的是加密的表示)。然而,很多时候一个网络管理员需要使用一个类似于tcpdump的工
具来分析网络中出现的问题。
我
们是把tcpdump作为一个学习的工具,用来查看网络中实际传输的东西。对tcpdump以及其他厂商提供的类似工具的访问权限依赖于具体系统。例如,
在SunOS,对NIT设备的访问只限于超级用户。BSD的分组过滤器使用了一种不同的技术:通过对/dev/bpfXX设备
的授权来控制访问。一般来说,只有属主才能读写这些设备(属主应该是超级用户),对于同组用户是可读的(经常是系统管理组)。这就是说如果系统管理员不对程序设置用户的I D,一般的用户是不能运行类似于tcpdump的程序的。
6 插口排错选项
查看一个TCP连接上发生的事情的另一种方法是使能插口排错选项,当然是在支持这一特征的系统中。这个特征只能工作在TCP上(其他协议都不行),并且需要应用程序支持(当
应用程序启动时,使能一个插口排错选项)。
大多数伯克利演变的实现都支持这个特征,包括SunOS、4.4BSD和SVR4。
程序使能了一个插口选项,内核就会保留在那个连接上发生的事情的一个痕迹记录。在这之
后,所有记录的信息都可以使用trpt( 8 )程序打印出来。使能一个插口排错选项不需要特别的许可,但是因为trpt程序访问了内核的内存,所以运行trpt需要特别的权限。
阅读(1756) | 评论(0) | 转发(0) |