2.2 封包数据
在本书的语境中,封包数据实际上意味着libpcap的输出,这种输出可能是通过IDS或者tcpdump完成。libpcap最初由LBNL的网络研究组开发,是基本的网络捕捉工具,可以作为snort、bro和tcpdump等工具的采集器。
在封包捕捉数据中寻找有价值的信息如同大海捞针。这类数据的捕捉需要平衡海量的可捕捉数据和真正有意义的少数数据之间的关系。
2.2.1 封包和帧格式
在几乎所有现代化系统上,tcpdump将在以太网上捕捉IP,这意味着libpcap捕捉的数据实际上是包含了IP封包的以太网帧。虽然IP包含了超过80个不同的协议,但是在任何可用的网络上,绝大多数流量是从3个协议中产生的:TCP(协议 6)、UDP(协议17)和ICMP(协议 1)。
TCP、UDP和ICMP占据了IP流量的绝大部分,不过许多其他协议也可能出现在网络中,特别是在使用VPN的情况下。IANA有一个IP协议组的完整列表,其中重要的包括IPv6(协议 41)、GRE(协议 47)和ESP(协议 50)。GRE和ESP用于VPN通信。
完全的pcap捕捉往往不切实际。海量的冗余数据使得在合理的时间内保存网络流量中有意义的部分十分困难。封包捕捉数据的过滤和限制机制主要有3种:使用滚动缓存(Rolling buffers)保存同步的子样本;操纵快照长度,只捕捉固定长度的封包(例如报头);用BPF或者其他过滤规则过滤流量。每种方法都是分析上的一种妥协,各有优劣。
2.2.2 滚动缓存
滚动缓存(rolling buffer)是内存中的一个位置,数据在这里循环转储:信息被顺序丢弃,当缓冲区被填满时,数据被转储到缓冲区的开始位置,这一过程重复进行。例2-1给出了tcpdump使用滚动缓冲区的例子。在本例中,该过程向磁盘写入大约128MB数据,然后轮转到一个新的文件。当32个文件被填满(由-W开关指定),过程重新开始。
例2-1 在tcpdump中使用滚动缓存
host$ tcpdump -i en1 -s 0 -w result -C 128 -W 32
滚动缓存在流量分析上实现了一个时间范围:数据只能在缓冲区中读取。因此,建议使用较小的文件尺寸,因为当你发现异常现象时,必须快速地将其从缓存中取出。
2.2.3 限制每个封包中捕捉的数据
捕捉完整封包的替代方法是捕捉载荷的有限子集,在tcpdump中由快照长度(-s)参数控制。快照长度将封包限制在参数中指定的帧尺寸。如果你指定至少68个字节的帧尺寸,就能够记录TCP或者UDP报头(Header)1。这种解决方案不能很好地代替NetFlow(本章后面将作讨论)。
2.2.4 过滤特定类型封包
在交换机上进行过滤的替代方法之一是在镜像端口采集流量之后进行过滤。利用tcpdump和其他工具,这一方法很容易用伯克利封包过滤(Berkeley Packet Filtering,BPF)实现。BPF允许操作员指定任意的复杂过滤,因此你可以选择的范围非常广。本节将用实例说明一些有用的选项。图2-6提供了以太网帧、IP、UDP、ICMP和TCP报头的分解。
在我们介绍这些主要字段的时候,会指出描述和用于过滤这些字段的BPF宏。在大部分UNIX风格的系统中,pcap-filter manpage提供了BPF语法的汇总,Free BSD 的BPF manpage(http://bit.ly/bsd-manpages)中还总结了可用的命令。
在以太网帧中,最为关键的字段是两个MAC地址。这些48个字节的字段用于识别发送和接收流量的接口硬件地址。MAC地址被限制在一个冲突域中,并会在封包穿越多个网络时被修改(例见图2-5)。在BPF中,MAC地址用ether src和ether dst谓词访问。
tcpdump和MAC地址
大部分tcpdump实现需要一个命令行参数,才能显示链路级(以太网)信息。在Mac OS X中,-e开关将显示MAC地址。
在IP报头中,你最感兴趣的字段通常是IP地址、长度、TTL和协议。IP标识符、标志和用于涉及封包重新组装攻击的分段偏移——但是,它们也是以太网成为通用传输协议之前的历史遗迹。你可以用src host和dst host谓词访问IP地址,这些谓词还可以过滤网络掩码。
BPF中的地址过滤
BPF中的地址可以使用host和net谓词过滤。为了理解这些谓词的工作方式,我们来看一个简单的tcpdump输出。
host$ tcpdump -n -r sample.pcap | head -5
reading from file sample.pcap, link-type EN10MB (Ethernet)
20:01:12.094915 IP 192.168.1.3.56305 > 208.78.7.2.389: Flags [S],
seq 265488449, win 65535, options [mss 1460,nop, wscale 3,nop,
nop,TS val 1111716334 ecr 0,sackOK,eol], length 0
20:01:12.094981 IP 192.168.1.3.56302 > 192.168.144.18.389: Flags [S],
seq 1490713463, win 65535, options [mss 1460,nop,wscale 3,nop,
nop,TS val 1111716334 ecr 0,sackOK,eol], length 0
20:01:12.471014 IP 192.168.1.102.7600 > 192.168.1.255.7600: UDP, length 36
20:01:12.861101 IP 192.168.1.6.17784 > 255.255.255.255.17784: UDP, length 27
20:01:12.862487 IP 192.168.1.6.51949 > 255.255.255.255.3483: UDP, length 37
src host或者dst host将过滤准确的IP地址,下面过滤进出192.168.1.3的流量:
host$ tcpdump -n -r sample.pcap src host 192.168.1.3 | head -1
reading from file sample.pcap, link-type EN10MB (Ethernet)
20:01:12.094915 IP 192.168.1.3.56305 > 208.78.7.2.389: Flags [S],
seq 265488449, win 65535, options [mss 1460,nop,wscale 3,nop,
nop,TS val 1111716334 ecr 0,sackOK,eol], length 0
host$ tcpdump -n -r sample.pcap dst host 192.168.1.3 | head -1
reading from file sample.pcap, link-type EN10MB (Ethernet)
20:01:13.898712 IP 192.168.1.6.48991 > 192.168.1.3.9000: Flags [S],
seq 2975851986, win 5840, options [mss 1460,sackOK,TS val 911030 ecr 0,
nop,wscale 1], length 0
src net和dst net可以过滤网络地址块。下面的例子说明如何用地址或者CIDR标记法逐步过滤192.168.1 网络中的地址:
使用 src net 匹配8位字节,进行过滤
host$ tcpdump -n -r sample.pcap src net 192.168.1 | head -3
reading from file sample.pcap, link-type EN10MB (Ethernet)
20:01:12.094915 IP 192.168.1.3.56305 > 208.78.7.2.389: Flags [S],
seq 265488449, win 65535, options [mss 1460,nop,wscale 3,nop,nop,
TS val 1111716334 ecr 0,sackOK,eol], length 0
20:01:12.094981 IP 192.168.1.3.56302 > 192.168.144.18.389: Flags [S],
seq 1490713463, win 65535, options [mss 1460,nop,wscale 3,nop,
nop,TS val 1111716334 ecr 0,sackOK,eol], length 0
匹配一个地址
host$ tcpdump -n -r sample.pcap src net 192.168.1.5 | head -1
reading from file sample.pcap, link-type EN10MB (Ethernet)
20:01:13.244094 IP 192.168.1.5.50919 > 208.111.133.84.27017: UDP, length 84
使用CIDR地址块匹配
host$ tcpdump -n -r sample.pcap src net 192.168.1.64/26 | head -1
reading from file sample.pcap, link-type EN10MB (Ethernet)
20:01:12.471014 IP 192.168.1.102.7600 > 192.168.1.255.7600: UDP, length 36
使用ip proto谓词可以过滤协议。BPF还提供各种特定于协议的谓词,如tcp、udp和icmp。封包长度可以用less和greater谓词过滤,而TTL的过滤需要更高级的位操作,后面将讨论。
下面的代码片段过滤除了来自指定网络地址块(使用24位掩码的主机)之外的所有流量。
host$ tcpdump -i en1 -s 0 -w result src net 192.168.2.0/24
例2-2演示了tcpdump的过滤。
例2-2 使用tcpdump的过滤示例
host$ # 过滤内部流量之外的所有流量
host$ tcpdump -i en1 -s 0 -w result src net 192.168.2.0/24 && dst net \
192.168.0.0/16
host$ # 过滤由端口指定的Web流量之外的所有流量
host$ tcpdump -i en1 -s 0 -w result ((src port 80 || src port 443) && \
(src net 192.168.2.0))
在TCP中,端口号和标志最为关键。TCP标志用于维护TCP状态机制,而端口号用于区分会话和服务标识。端口号可以用src port和dst port开关过滤,也可以用src portrange和dst portrange开关过滤端口范围。BPF支持多种TCP标志谓词,包括tcp-fin、tcp-syn、tcp-rst、tcp-push、tcp-ack和 tcp-urg。
地址分类和CIDR地址块
IPv4地址是一个32位的整数。为方便起见,这些整数通常使用句点分隔四元组标记法,如o1.o2.o3.o4,所以0x000010FF代表的IP地址被写作0.0.16.255。3层路由几乎从来不是对单独的地址进行的,而是对一组地址—历史上曾称作分类(Class),现在称作网段(netblock)。
A类地址(0.0.0.0~127.255.255.255)的最高位设置为0,接下来的7位分配给某个实体,剩下的24位由所有者控制。这为所有者提供了224个地址。B类地址(128.0.0.0~191. 255.255.255)将16位分配给所有者,而C类(192.0.0.0~223.255.255.255)分配8位。这种方法导致地址很快耗尽,1993年开发的无类域际路由(Classless Inter-Domain Routing,CIDR)代替了原来的分类系统。在CIDR方案中,通过地址和一个网络掩码向用户分配网段。网络掩码表示地址中用户可以操纵的位数,根据惯例,这些位被设置为0。例如,拥有192.28.3.0~192.38.3.255的用户所得到的网段为192.28.3.0/24。
和TCP一样,UDP端口号也是最重要的,可以用和TCP相同的port和portrange开关访问。
因为ICMP是互联网的错误信息传递协议,ICMP消息包含的数据往往极其丰富。ICMP类型和代码最为重要,它们定义了后续载荷(如果有的话)的语法。BPF提供了各种特定于类型和代码的过滤器,包括icmp-echoreply、icmp-unreach、 icmptstamp和icmp-redirect。
2.2.5 如果不是以太网怎么办
为了简洁起见,本书专门针对以太网上的IP,但是你可能会经常遇到其他的传输和数据协议。大部分这类协议都是专用的,其中许多种协议除了在libpcap上构建的工具之外还需要其他的捕捉软件。
ATM
异步传输模式(Asynchronous Transfer Mode,ATM)是20世纪90年代重要的IP传输协议,现在大部分用于ISDN和PSTN传输,以及一些遗留的设备。
光纤通道
光纤通道(Fibre Channel)主要用于高速存储,是各种SAN实现的支柱。
CAN
CAN是Controller Area Network(控制器区域网络)的缩写,主要和车载网络等嵌入式系统有关,CAN是一种总线协议,用于在小型的隔离网络中发送消息。
任何形式的过滤都有性能方面的代价。在交换机或者路由上使用镜像端口会牺牲性能,交换机或者路由可能将这些性能用于通信。过滤器越复杂,过滤器软件增加的开销也就越大。在带宽较大的情况下,这可能是一个问题。