2. 网络流量基础
好,咱们正式开始第二讲。说实话,很多搞安全的朋友,一上来就急着分析攻击流量,结果连数据包长什么样都说不清楚。我个人习惯是,先把地基打牢。这一章,我们就来聊聊网络流量的那些“底层逻辑”。
2.1 TCP/IP协议栈:别把它想得太复杂
TCP/IP协议栈,说白了就是一套“网络通信的规矩”。你想想看,两台电脑要说话,总得有个统一的语言吧?这个协议栈就是那个语言。
它分四层,我习惯从上往下记:
- 应用层:你直接用的软件,比如浏览器(HTTP)、邮件客户端(SMTP)、(自定义协议)。这一层只管“我要发什么内容”。
- 传输层:负责“怎么可靠地发”。TCP保证不丢包,UDP只管快。我在项目中遇到过,有人用UDP传重要数据,结果丢包了还不知道,排查了半天。
- 网络层:负责“路怎么走”。IP协议在这里,它决定数据包从你的电脑到服务器,中间要经过哪些路由器。
- 网络接口层:负责“物理上怎么传”。比如网线、Wi-Fi信号,还有MAC地址。
2.2 数据包结构:拆开来看,其实很简单
一个网络数据包,就像一封信。信封上写着地址(IP头),里面还有一层信封写着怎么确认收到(TCP头),最里面才是信纸(数据)。
咱们重点看两个最常用的头:IP头和TCP头。
2.2.1 IP头(网络层)
IP头里最重要的几个字段,我列个表给你看:
| 字段 | 长度(位) | 说明 |
|---|---|---|
| 版本号 | 4 | IPv4还是IPv6。现在大部分还是IPv4。 |
| 源IP地址 | 32 | 谁发的。比如192.168.1.100 |
| 目的IP地址 | 32 | 发给谁。比如8.8.8.8 |
| 协议号 | 8 | 上层是什么协议。6代表TCP,17代表UDP。 |
| 生存时间(TTL) | 8 | 防止数据包在网络里无限循环。每过一个路由器减1,减到0就丢弃。 |
嗯,这里要注意:TTL值在异常流量分析里很有用。我曾经遇到过一种攻击,攻击者伪造源IP,但TTL值没改好,一看就知道是假的。因为正常Windows发的包TTL是128,Linux是64,攻击者伪造的包TTL是255,明显不对劲。
2.2.2 TCP头(传输层)
TCP头更关键,因为大部分攻击都跟它有关。核心字段如下:
| 字段 | 长度(位) | 说明 |
|---|---|---|
| 源端口 | 16 | 发起方的端口,比如浏览器随机分配一个高位端口。 |
| 目的端口 | 16 | 目标服务的端口,比如HTTP是80,HTTPS是443。 |
| 序列号(SEQ) | 32 | 保证数据顺序。第一次握手时随机生成。 |
| 确认号(ACK) | 32 | 告诉对方“我收到你的数据了,下一个该发这个序号”。 |
| 标志位 | 9 | 最常用的:SYN(发起连接)、ACK(确认)、FIN(结束)、RST(重置)。 |
2.3 PCAP文件格式解析:你每天都在用的东西
做流量分析,离不开PCAP文件。Wireshark、tcpdump抓下来的包,默认就是PCAP格式。说白了,它就是一个“数据包的容器”,把抓到的每个包按顺序存起来。
PCAP文件的整体结构,我画个图给你描述一下:
+-------------------+
| 全局文件头 (24字节) |
+-------------------+
| 数据包1头 (16字节) |
| 数据包1数据 |
+-------------------+
| 数据包2头 (16字节) |
| 数据包2数据 |
+-------------------+
| ... |
+-------------------+
全局文件头只有24字节,但信息量很大。我挑几个重要的说:
- Magic Number(4字节):固定为0xA1B2C3D4。如果字节序反了,就是0xD4C3B2A1。这用来判断文件是大端还是小端。
- Major Version / Minor Version(各2字节):版本号,目前主流是2.4。
- Timezone(4字节):时区偏移。说实话,这个字段在实际中经常不准,我一般忽略它。
- Snaplen(4字节):每个包最大抓取长度。比如设为65535,就是抓完整包;设为96,就只抓前96字节。
- Link Type(4字节):链路层类型。1代表以太网,最常见的。如果是Linux的loopback接口,值是0。
每个数据包的头是16字节,记录了这个包的基本信息:
struct pcap_pkthdr {
struct timeval ts; // 时间戳,8字节(秒+微秒)
bpf_u_int32 caplen; // 实际抓取的长度(4字节)
bpf_u_int32 len; // 原始包的长度(4字节)
};
这里有个坑:caplen和len可能不一样。如果Snaplen设得小,caplen就是Snaplen的值,但len是原始包的真实长度。我在写解析工具时,曾经忘了处理这个差异,结果读出来的数据全是截断的,排查了半天才发现。
2.4 实战:用Python解析PCAP文件
光说不练假把式。咱们写几行Python代码,手动解析一个PCAP文件。这样你就能真正理解它的结构了。
import struct
def parse_pcap(filepath):
with open(filepath, 'rb') as f:
# 读取全局文件头
magic = struct.unpack('<I', f.read(4))[0]
if magic == 0xA1B2C3D4:
print("字节序:大端")
elif magic == 0xD4C3B2A1:
print("字节序:小端")
else:
print("不是合法的PCAP文件")
return
# 跳过其他全局头字段
f.read(20) # 版本、时区、snaplen、链路类型
packet_count = 0
while True:
# 读取数据包头
header_data = f.read(16)
if len(header_data) < 16:
break # 文件结束
# 解析时间戳和长度
ts_sec, ts_usec, caplen, orig_len = struct.unpack('<IIII', header_data)
print(f"包 {packet_count}: 时间={ts_sec}.{ts_usec:06d}, "
f"抓取长度={caplen}, 原始长度={orig_len}")
# 跳过数据部分(这里不解析具体内容)
f.read(caplen)
packet_count += 1
print(f"共解析 {packet_count} 个数据包")
# 使用示例
# parse_pcap('example.pcap')
这段代码虽然简单,但能让你看到PCAP文件的“骨架”。你想想看,Wireshark那么强大的工具,底层也就是这样一层层解析的。只不过它把每个字段都展示出来了。
2.5 本章小结
这一章我们干了三件事:
- 回顾了TCP/IP四层模型,重点放在传输层和网络层。
- 拆解了IP头和TCP头的关键字段,特别是那些跟攻击检测相关的(TTL、标志位)。
- 解析了PCAP文件格式,从全局头到数据包头,最后用Python代码验证了理解。