4、Python流量分析入门:Scapy库安装与基础、读取PCAP文件、解析数据包字段
好,咱们进入实战环节了。前面聊了那么多理论,现在终于要亲手碰一碰真正的网络流量了。这一章,我带你搞定Python里最强大的流量分析工具——Scapy。说实话,我当年刚接触网络分析时,被各种二进制格式搞得头大,直到遇见了Scapy,才觉得「原来流量分析可以这么爽」。
4.1 Scapy库的安装与环境配置
先说说安装。Scapy的安装其实很简单,但有几个坑我得提前告诉你。
推荐用pip安装,干净利落:
# 基础安装
pip install scapy
# 如果你需要图形界面(我个人很少用)
pip install scapy[complete]
# 验证安装
python -c "from scapy.all import *; print('Scapy安装成功')"
嗯,这里要注意:Scapy需要管理员/root权限才能发送原始数据包。如果只是读取PCAP文件做分析,普通用户权限就够了。我平时做分析时,90%的时间都在读PCAP,只有做主动探测时才需要提权。
4.2 Scapy的核心数据结构
Scapy最牛的地方,是它把网络协议栈变成了Python对象。你想想看,一个数据包就是一个多层嵌套的字典,每一层协议都可以直接访问。
我个人习惯把Scapy的数据包想象成一个「洋葱」:
- 最外层:Ethernet帧(MAC地址)
- 中间层:IP层(源/目标IP)
- 内层:TCP/UDP等传输层(端口号)
- 核心:Payload(实际数据)
看个例子就明白了:
from scapy.all import *
# 手动构造一个数据包
pkt = IP(src="192.168.1.1", dst="10.0.0.1")/TCP(sport=12345, dport=80)/"GET / HTTP/1.1"
# 查看数据包结构
pkt.show()
# 输出类似这样:
# ###[ IP ]###
# src = 192.168.1.1
# dst = 10.0.0.1
# ###[ TCP ]###
# sport = 12345
# dport = 80
# ###[ Raw ]###
# load = 'GET / HTTP/1.1'
看到了吗?用/符号就能把不同协议层「叠」在一起。这个设计太优雅了,我第一次用的时候就觉得:这才叫符合直觉的API设计。
4.3 读取PCAP文件
实际工作中,我们很少手动构造数据包。更多时候是分析现成的PCAP文件。比如从Wireshark导出的抓包文件,或者从IDS/IPS系统里拿到的流量样本。
读取PCAP文件就一行代码:
from scapy.all import *
# 读取PCAP文件
packets = rdpcap("sample.pcap")
# 看看有多少个包
print(f"总共 {len(packets)} 个数据包")
# 查看第一个包
packets[0].show()
# 遍历所有包
for i, pkt in enumerate(packets[:5]): # 只看前5个
print(f"包 {i+1}: {pkt.summary()}")
from scapy.all import PcapReader
for pkt in PcapReader("large_file.pcap"):
# 逐包处理,内存友好
process_packet(pkt)
4.4 解析数据包关键字段
读进来只是第一步,关键是怎么提取我们想要的字段。我在做异常流量分析时,最常关注这几个维度:
| 协议层 | 关键字段 | 常见用途 |
|---|---|---|
| Ethernet | src, dst, type | 识别MAC地址、判断协议类型 |
| IP | src, dst, ttl, len | 追踪源/目标、检测TTL异常 |
| TCP | sport, dport, flags, seq | 端口扫描检测、连接状态分析 |
| UDP | sport, dport, len | DNS查询、NTP放大攻击 |
| ICMP | type, code | ping扫描、Traceroute |
来看看实际怎么提取:
from scapy.all import *
packets = rdpcap("sample.pcap")
for pkt in packets:
# 检查是否有IP层
if pkt.haslayer(IP):
ip_layer = pkt[IP]
src_ip = ip_layer.src
dst_ip = ip_layer.dst
ttl = ip_layer.ttl
# 检查是否有TCP层
if pkt.haslayer(TCP):
tcp_layer = pkt[TCP]
sport = tcp_layer.sport
dport = tcp_layer.dport
flags = tcp_layer.flags
# 输出关键信息
print(f"{src_ip}:{sport} -> {dst_ip}:{dport} [Flags: {flags}]")
# 检测SYN扫描(只有SYN标志位)
if flags == 0x02: # SYN标志
print(f"⚠️ 发现SYN扫描行为: {src_ip} -> {dst_ip}:{dport}")
4.5 常用过滤与统计技巧
实际分析时,我们往往不需要所有包,而是关注特定类型的流量。Scapy提供了很灵活的过滤方式:
from scapy.all import *
from collections import Counter
packets = rdpcap("capture.pcap")
# 1. 过滤特定协议
tcp_packets = [p for p in packets if p.haslayer(TCP)]
udp_packets = [p for p in packets if p.haslayer(UDP)]
# 2. 统计目标端口分布
dst_ports = [p[TCP].dport for p in tcp_packets if p.haslayer(TCP)]
port_counts = Counter(dst_ports)
print("Top 10 目标端口:")
for port, count in port_counts.most_common(10):
print(f" 端口 {port}: {count} 次")
# 3. 提取HTTP请求(80端口)
http_packets = [p for p in tcp_packets
if p.haslayer(TCP) and
(p[TCP].dport == 80 or p[TCP].sport == 80)]
# 4. 查看数据包大小分布
sizes = [len(p) for p in packets]
print(f"最小包: {min(sizes)} bytes")
print(f"最大包: {max(sizes)} bytes")
print(f"平均包: {sum(sizes)/len(sizes):.0f} bytes")
- 统计协议分布(TCP/UDP/ICMP各占多少)
- 找出Top 10通信IP
- 检查是否有异常端口(比如非标准端口上的服务)
4.6 实战:快速分析一个PCAP样本
来,咱们把上面学的串起来,写一个完整的分析脚本:
#!/usr/bin/env python3
"""
快速PCAP分析工具
用法: python analyze_pcap.py sample.pcap
"""
from scapy.all import *
import sys
from collections import Counter
def analyze_pcap(filename):
print(f"[*] 正在分析: {filename}")
# 读取PCAP
packets = rdpcap(filename)
print(f"[*] 总数据包数: {len(packets)}")
# 统计协议
proto_count = Counter()
ip_src = Counter()
ip_dst = Counter()
tcp_ports = Counter()
for pkt in packets:
if pkt.haslayer(IP):
ip = pkt[IP]
ip_src[ip.src] += 1
ip_dst[ip.dst] += 1
if pkt.haslayer(TCP):
proto_count['TCP'] += 1
tcp = pkt[TCP]
tcp_ports[tcp.dport] += 1
elif pkt.haslayer(UDP):
proto_count['UDP'] += 1
elif pkt.haslayer(ICMP):
proto_count['ICMP'] += 1
else:
proto_count['Other'] += 1
# 输出结果
print("\n=== 协议分布 ===")
for proto, count in proto_count.most_common():
print(f" {proto}: {count} ({count/len(packets)*100:.1f}%)")
print("\n=== Top 5 源IP ===")
for ip, count in ip_src.most_common(5):
print(f" {ip}: {count}")
print("\n=== Top 5 目标IP ===")
for ip, count in ip_dst.most_common(5):
print(f" {ip}: {count}")
print("\n=== Top 10 目标端口 ===")
for port, count in tcp_ports.most_common(10):
print(f" 端口 {port}: {count}")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("用法: python analyze_pcap.py ")
sys.exit(1)
analyze_pcap(sys.argv[1])
好了,这一章的内容就到这里。说白了,Scapy就是一把瑞士军刀,能切能砍能撬。你只要掌握了读取PCAP和提取字段这两个基本功,后面那些高级玩法——流量重放、协议伪造、自动化检测——就都水到渠成了。
下一章,我会带你用Scapy做更深入的流量分析,比如检测端口扫描、识别DDoS攻击。到时候你会发现,原来网络安全分析可以这么「Pythonic」。