【提示】 本文所有技术内容仅用于授权渗透测试、安全学习和合规防御研究。未经授权对任何网络进行抓包、监听或入侵检测部署均属违法行为,作者及平台不承担任何法律责任。请确保在获得书面授权后开展所有测试活动,并严格遵守《网络安全法》《数据安全法》《个人信息保护法》等法律法规。文中涉及的 Wireshark、tcpdump、Snort、Suricata、Zeek 等工具均为公开开源工具,请仅在自建靶场或授权环境中使用。
1. 网络流量分析概述
网络流量分析是安全运营和威胁狩猎的核心能力。在企业网络中,所有攻击行为最终都会在网络上留下痕迹------无论是 C2 回连、数据外泄、横向移动还是端口扫描,都必然产生网络流量。掌握流量分析技术,意味着在终端日志和告警之外,获得了一双能看见网络全貌的"上帝之眼"。
网络流量分析的核心目标包括:识别异常通信模式、发现恶意行为痕迹、提取攻击指标(IOC)、还原攻击链路、构建检测规则。从工具层面看,流量分析涵盖了从单机抓包工具(Wireshark/tcpdump)到分布式入侵检测系统(Snort/Suricata/Zeek)再到企业级全流量回溯平台的完整技术栈。
本文将从网络协议基础讲起,逐步深入到 Wireshark 深度使用、命令行抓包、HTTP/DNS 协议分析、恶意流量识别、入侵检测系统构建、网络取证、加密流量分析、可视化与自动化,最终在靶场中串联完整分析链,形成"抓包---分析---检测---响应"闭环。
2. 网络流量基础
2.1 OSI七层与TCP/IP四层对照
理解协议栈分层是流量分析的前提。下表将 OSI 七层模型与工程中更常用的 TCP/IP 四层模型对照。
| OSI 层 | OSI 层名 | TCP/IP 层 | TCP/IP 层名 | 典型协议 | Wireshark 解析层 |
|---|---|---|---|---|---|
| 7 | 应用层 | 4 | 应用层 | HTTP/HTTPS/DNS/FTP/SSH/SMTP | Application |
| 6 | 表示层 | 4 | 应用层 | SSL/TLS/JPEG/GIF | Application |
| 5 | 会话层 | 4 | 应用层 | RPC/NetBION/SQL | Application |
| 4 | 传输层 | 3 | 传输层 | TCP/UDP/SCTP/QUIC | Transport |
| 3 | 网络层 | 2 | 网络层 | IP/ICMP/OSPF/ARP | Network |
| 2 | 数据链路层 | 1 | 网络接口层 | Ethernet/PPP/Frame Relay | Data Link |
| 1 | 物理层 | 1 | 网络接口层 | 电信号/光信号 | Physical |
【提示】 Wireshark 实际解析时会将 OSI 5-7 层合并显示为 Application 层,但在协议树中会按字段细分。分析时重点关注传输层(端口/会话)和应用层(协议内容),网络层主要负责路由寻址。
2.2 常见协议端口号速查
端口是流量分析中识别服务和检测异常的重要依据。下表汇总了安全分析中最常遇到的协议端口。
| 协议 | 端口 | 传输层 | 明文/加密 | 安全关注点 |
|---|---|---|---|---|
| HTTP | 80 | TCP | 明文 | Web 攻击、Webshell 通信 |
| HTTPS | 443 | TCP | 加密(TLS) | C2 隧道、证书异常 |
| DNS | 53 | TCP/UDP | 明文 | DNS 隧道、DNS 劫持 |
| FTP | 20/21 | TCP | 明文 | 匿名访问、凭据嗅探 |
| SSH | 22 | TCP | 加密 | 暴力破解、隧道穿透 |
| Telnet | 23 | TCP | 明文 | 凭据明文传输 |
| RDP | 3389 | TCP/UDP | 可加密 | 暴力破解、BlueKeep |
| SMB | 445 | TCP | 可加密 | 永恒之蓝、横向移动 |
| SMTP | 25/465/587 | TCP | 明文/加密 | 邮件伪造、外泄 |
| POP3 | 110/995 | TCP | 明文/加密 | 凭据嗅探 |
| IMAP | 143/993 | TCP | 明文/加密 | 凭据嗅探 |
| MySQL | 3306 | TCP | 可加密 | 未授权访问、注入 |
| Redis | 6379 | TCP | 明文 | 未授权访问、写SSH key |
| MQTT | 1883/8883 | TCP | 明文/加密 | IoT C2、未授权控制 |
| LDAP | 389/636 | TCP | 明文/加密 | 凭据枚举 |
| Kerberos | 88 | TCP/UDP | 加密 | Kerberoasting、黄金票据 |
| WinRM | 5985/5986 | TCP | 明文/加密 | 远程执行、横向移动 |
| VNC | 5900 | TCP | 可加密 | 弱口令、未授权访问 |
2.3 TCP三次握手与四次挥手
TCP 是面向连接的可靠传输协议,其连接建立和断开过程是流量分析的基础。
三次握手建立连接过程:
text
客户端 服务端
| |
| --- SYN (seq=x) -----------> | 第1次握手:客户端发送SYN,进入SYN_SENT
| | 服务端进入SYN_RCVD
| <== SYN+ACK (seq=y, ack=x+1) | 第2次握手:服务端回复SYN+ACK
| |
| --- ACK (ack=y+1) ---------> | 第3次握手:客户端回复ACK,连接建立
| | 双方进入ESTABLISHED
四次挥手断开连接过程:
text
客户端 服务端
| |
| --- FIN (seq=u) -----------> | 第1次挥手:主动方发送FIN,进入FIN_WAIT_1
| <== ACK (ack=u+1) ---------- | 第2次挥手:被动方回复ACK,进入CLOSE_WAIT
| | 主动方进入FIN_WAIT_2
| <== FIN (seq=v) ---------- | 第3次挥手:被动方发送FIN,进入LAST_ACK
| --- ACK (ack=v+1) ---------> | 第4次挥手:主动方回复ACK,进入TIME_WAIT
| | 等待2*MSL后关闭,被动方关闭
【提示】 在流量分析中,大量 SYN 包无后续 ACK 是 SYN 扫描或 SYN Flood 攻击的典型特征;大量 RST 包可能指示端口关闭或扫描;TIME_WAIT 堆积则暗示短连接过多。
2.4 UDP通信特点
UDP 是无连接的不可靠传输协议,不建立连接也不保证送达,但开销小、速度快。
| 特性 | TCP | UDP |
|---|---|---|
| 连接方式 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠(ACK重传) | 不可靠(不重传) |
| 顺序性 | 有序(序列号) | 无序 |
| 流量控制 | 滑动窗口 | 无 |
| 开销 | 较大(20字节头) | 较小(8字节头) |
| 速度 | 较慢 | 较快 |
| 典型应用 | HTTP/SSH/FTP/SMTP | DNS/DHCP/SNMP/QUIC/RTP |
UDP 在安全分析中的关注点:UDP 端口扫描(ICMP Port Unreachable 响应)、DNS 放大攻击(UDP 反射)、QUIC/HTTP3 流量识别困难。
2.5 数据包结构
网络数据包是分层封装的,每层添加自己的头部信息。以 Ethernet+IP+TCP+HTTP 为例。
| 层 | 头部字段 | 长度 | 关键分析点 |
|---|---|---|---|
| Ethernet | 目的MAC/源MAC/类型 | 14字节 | MAC地址溯源、VLAN标签 |
| IP | 版本/IHL/TTL/协议/源IP/目的IP | 20字节 | TTL异常(TTL=64 Linux/128 Windows)、IP分片 |
| TCP | 源端口/目的端口/序列号/标志位/窗口 | 20字节 | 标志位组合(SYN/FIN/RST/PSH/ACK/URG) |
| UDP | 源端口/目的端口/长度/校验和 | 8字节 | 端口识别、长度校验 |
| 应用层 | 协议特定头部+数据 | 可变 | 协议字段解析、载荷特征匹配 |
2.6 流量类型分类
| 流量类型 | 特征 | 检测难度 | 典型场景 | 分析手段 |
|---|---|---|---|---|
| 明文流量 | 载荷可直接读取 | 低 | HTTP/FTP/Telnet/DNS | 内容匹配、协议解析 |
| 加密流量 | 载荷加密不可读 | 高 | HTTPS/SSH/TLS 1.3 | 元数据分析、JA3指纹 |
| 隧道流量 | 协议封装嵌套 | 中高 | VPN/Tor/DNS隧道/ICMP隧道 | 行为分析、统计分析 |
| 恶意流量 | 含攻击载荷或异常行为 | 中 | Webshell/C2/扫描/外泄 | 特征匹配+行为分析 |
| 正常业务流量 | 符合预期通信模式 | 基线 | 日常办公/业务系统 | 基线对比、异常检测 |
2.7 协议栈速查表
| 分析需求 | 关注协议 | 关注字段 | 常见过滤器 |
|---|---|---|---|
| Web攻击 | HTTP | URI/UA/Host/Cookie | http.request |
| 凭据嗅探 | HTTP/FTP/POP3 | Authorization/USER/PASS | http.authorization |
| DNS异常 | DNS | 查询名/记录类型/响应 | dns.qry.name |
| C2通信 | HTTP/HTTPS/TLS | SNI/UA/证书/心跳 | tls.handshake |
| 端口扫描 | TCP | SYN标志/响应模式 | tcp.flags.syn==1 |
| 横向移动 | SMB/Kerberos/RPC | 会话/票据/接口 | smb2 |
| 数据外泄 | 所有 | 数据量/方向/时段 | tcp.port && tcp.len |
| 隧道检测 | DNS/ICMP/HTTP | 查询频率/载荷大小 | dns |
3. Wireshark深度使用
3.1 Wireshark界面与功能
Wireshark 是最强大的图形化网络协议分析工具,支持超过两千种协议的深度解析。
| 功能模块 | 位置 | 用途 | 常用操作 |
|---|---|---|---|
| 捕获选项 | Capture > Options | 选择网卡和捕获条件 | 设置BPF过滤器 |
| 显示过滤器 | 工具栏过滤栏 | 过滤显示的包 | 输入显示过滤表达式 |
| 数据包列表 | 主窗口 | 显示每个包摘要 | 点击查看详情 |
| 数据包详情 | 中间窗口 | 协议树逐层展开 | 展开各层协议字段 |
| 数据包字节 | 底部窗口 | 十六进制原始数据 | 查看原始字节 |
| 统计 | Statistics菜单 | 流量统计与分析 | IO Graph/Endpoints/Conversations |
| 分析 | Analyze菜单 | 专家信息/跟踪流 | Follow TCP Stream/Expert Info |
| 导出 | File > Export Objects | 导出重组文件 | 导出HTTP对象/TCP流 |
3.2 捕获过滤器语法(BPF)
捕获过滤器使用 BPF(Berkeley Packet Filter)语法,在抓包时过滤,减少采集量。注意:捕获过滤器与显示过滤器语法完全不同。
| 语法元素 | 示例 | 说明 |
|---|---|---|
| host | host 192.168.1.1 | 源或目的IP匹配 |
| src host | src host 10.0.0.5 | 源IP匹配 |
| dst host | dst host 8.8.8.8 | 目的IP匹配 |
| port | port 80 | 源或目的端口 |
| src port | src port 12345 | 源端口 |
| dst port | dst port 443 | 目的端口 |
| proto | tcp / udp / icmp / arp | 协议类型 |
| net | net 192.168.0.0/24 | 网段匹配 |
| and | tcp port 80 and host 10.0.0.1 | 逻辑与 |
| or | port 80 or port 443 | 逻辑或 |
| not | not port 22 | 逻辑非 |
| less/greater | less 100 | 包长小于100字节 |
常用捕获过滤器示例:
text
# 只抓80和443端口的HTTP/HTTPS流量
tcp port 80 or tcp port 443
# 抓取特定主机对之间的流量
host 192.168.1.100 and host 10.0.0.1
# 排除SSH管理流量,减少噪声
not port 22
# 只抓DNS查询
udp port 53
# 抓取某网段所有流量
net 192.168.1.0/24
# 抓取ICMP流量(ping探测)
icmp
# 组合:抓取非本地管理流量
not host 192.168.1.10 and (tcp port 80 or tcp port 443 or tcp port 445)
3.3 显示过滤器语法
显示过滤器使用 Wireshark 专有语法,功能远比 BPF 强大,可深入到协议字段级别过滤。
| 过滤类别 | 语法示例 | 说明 |
|---|---|---|
| IP地址 | ip.addr == 192.168.1.1 | 源或目的IP |
| 源IP | ip.src == 10.0.0.1 | 源IP |
| 目的IP | ip.dst == 8.8.8.8 | 目的IP |
| 端口 | tcp.port == 80 | 源或目的端口 |
| 源端口 | tcp.srcport == 12345 | 源端口 |
| TCP标志 | tcp.flags.syn == 1 | SYN标志位 |
| HTTP请求 | http.request.method == "POST" | HTTP POST请求 |
| HTTP URI | http.request.uri contains "admin" | URI含admin |
| HTTP头 | http.user_agent contains "curl" | UA含curl |
| TLS握手 | tls.handshake.type == 1 | ClientHello |
| SNI | tls.handshake.extensions_server_name == "evil.com" | SNI域名 |
| DNS查询 | dns.qry.name contains "malware" | 查询名含malware |
| 协议 | http or dns | HTTP或DNS |
| 包含 | frame contains "password" | 帧含password |
| 匹配 | http.request.uri matches "^/api/" | 正则匹配 |
常用显示过滤器组合:
text
# 查看所有HTTP POST请求(可能含表单提交)
http.request.method == "POST"
# 查找HTTP Basic认证凭据
http.authorization || http.request.method == "POST"
# 查看特定域名的DNS查询
dns.qry.name == "www.example.com"
# 查看特定SNI的TLS连接
tls.handshake.extensions_server_name == "c2.evil.com"
# 查找TCP重传(可能网络问题或扫描)
tcp.analysis.retransmission
# 查看所有HTTP 500错误响应
http.response.code == 500
# 查找包含特定字符串的包
frame contains "cmd.exe" || frame contains "/bin/sh"
# 查找非标准端口的TLS流量
tls && !tcp.port == 443
# 查找异常大的HTTP POST(可能数据外泄)
http.request.method == "POST" && http.content_length > 10000
3.4 常见协议过滤速查表
| 分析目标 | 显示过滤器 | 用途 |
|---|---|---|
| HTTP请求 | http.request | 所有HTTP请求包 |
| HTTP响应 | http.response | 所有HTTP响应包 |
| HTTP错误 | http.response.code >= 400 | 4xx/5xx错误 |
| HTTP重定向 | http.response.code == 302 | 跳转行为 |
| HTTPS握手 | tls.handshake | TLS握手全流程 |
| TLS证书 | tls.handshake.certificate | 证书内容 |
| DNS查询 | dns.flags.response == 0 | DNS查询包 |
| DNS响应 | dns.flags.response == 1 | DNS响应包 |
| TCP SYN | tcp.flags.syn == 1 && tcp.flags.ack == 0 | SYN包(无ACK) |
| TCP RST | tcp.flags.reset == 1 | 连接重置 |
| ICMP | icmp | 所有ICMP包 |
| SMB | smb2 | |
| Kerberos | kerberos | Kerberos认证 |
3.5 流量统计分析
Wireshark 的 Statistics 菜单提供了强大的流量统计功能。
| 统计工具 | 路径 | 用途 | 典型场景 |
|---|---|---|---|
| Capture File Properties | Statistics > Capture File Properties | 文件概要信息 | 查看抓包时间/包数/带宽 |
| Protocol Hierarchy | Statistics > Protocol Hierarchy | 协议分布树 | 发现异常协议占比 |
| Endpoints | Statistics > Endpoints | 各端点流量统计 | 定位流量异常主机 |
| Conversations | Statistics > Conversations | 会话统计 | 发现异常通信对 |
| I/O Graph | Statistics > I/O Graph | 时间-流量图 | 发现流量突增 |
| Flow Graph | Statistics > Flow Graph | 时序图 | 理解会话流程 |
| Packet Length | Statistics > Packet Length | 包长分布 | 小包过多可能扫描 |
| TCP Stream Graphs | Statistics > TCP Stream Graphs | TCP流图形 | 分析窗口/吞吐 |
【提示】 Protocol Hierarchy 是快速发现异常的第一站。如果发现 ICMP 占比异常高,或 UDP 流量远超基线,或出现不常见协议,都值得深入排查。Conversations 视图按字节数排序可以快速定位"谁在和谁大量通信"。
3.6 数据包导出与重组
Wireshark 可以从流量中重组和导出传输的文件对象。
| 导出功能 | 路径 | 支持协议 | 用途 |
|---|---|---|---|
| HTTP对象 | File > Export Objects > HTTP | HTTP | 导出下载的文件/图片 |
| TCP流 | Analyze > Follow > TCP Stream | TCP | 查看完整会话内容 |
| TLS流 | Analyze > Follow > TLS Stream | TLS | 查看解密后内容 |
| SMB对象 | File > Export Objects > SMB | SMB/SMB2 | 导出共享传输文件 |
| DICOM对象 | File > Export Objects > DICOM | DICOM | 导出医学影像 |
操作示例:
text
# 导出HTTP传输的文件
File > Export Objects > HTTP > Save All
# 跟踪TCP流,查看完整明文会话
右键数据包 > Follow > TCP Stream
# 导出特定字段值
File > Export Packet Dissections > As CSV
# 导出选中的数据包为新的pcap
File > Export Specified Packets
3.7 Wireshark高级功能
| 功能 | 路径 | 用途 | 实战技巧 |
|---|---|---|---|
| Follow Stream | Analyze > Follow | 重组完整会话 | 查看明文通信内容 |
| Expert Info | Analyze > Expert Information | 协议异常信息 | 发现重传/乱序/RST |
| 凭据提取 | Edit > Preferences > Protocols | 显示解码后密码 | HTTP/FTP/POP3凭据 |
| Decrypt TLS | Edit > Preferences > TLS | 解密TLS流量 | 需要SSLKEYLOGFILE |
| 着色规则 | View > Coloring Rules | 按规则着色包 | 可视化异常包 |
| 时间戳 | View > Time Display Format | 时间格式设置 | 改为绝对时间便于关联 |
| 过滤器宏 | Edit > Preferences > Macros | 保存常用过滤 | 提高分析效率 |
TLS解密配置步骤:
text
# 1. 设置环境变量,让浏览器导出TLS密钥
# Windows:
set SSLKEYLOGFILE=C:\tls_keys\sslkeys.log
# Linux/Mac:
export SSLKEYLOGFILE=/tmp/sslkeys.log
# 2. 启动浏览器(会自动写入密钥日志)
chrome 或 firefox
# 3. Wireshark中配置密钥文件
Edit > Preferences > Protocols > TLS >
(No TLS keys) > Edit > + >
Key file path: C:\tls_keys\sslkeys.log
# 4. 重新打开pcap,TLS流量已解密
# 在Follow TLS Stream中可看到明文
3.8 完整Wireshark分析流程
text
1. 确定分析目标 → 选择网卡/打开PCAP
2. 应用捕获过滤器 → 减少采集噪声
3. Protocol Hierarchy → 概览协议分布,发现异常
4. Conversations/Endpoints → 定位异常通信
5. I/O Graph → 发现流量突增时段
6. 显示过滤器 → 聚焦可疑协议/字段
7. Follow Stream → 查看完整会话
8. Expert Info → 发现协议异常
9. Export Objects → 提取传输文件
10. 保存过滤结果 → 导出报告
4. tcpdump与命令行抓包
4.1 tcpdump安装与基本语法
tcpdump 是 Linux 下最常用的命令行抓包工具,基于 libpcap 库,资源占用低,适合在服务器上长期运行。
bash
# 安装tcpdump
apt install tcpdump # Debian/Ubuntu
yum install tcpdump # CentOS/RHEL
# 基本语法
tcpdump [选项] [过滤表达式]
# 列出可用网卡
tcpdump -D
# 在eth0上抓包
tcpdump -i eth0
# 抓取指定端口
tcpdump -i eth0 port 80
4.2 tcpdump过滤器表
tcpdump 使用 BPF 语法进行过滤,与 Wireshark 捕获过滤器一致。
| 过滤类型 | 语法 | 示例 | 说明 |
|---|---|---|---|
| 地址 | host | host 192.168.1.1 | 源或目的IP |
| 源地址 | src host | src host 10.0.0.1 | 源IP |
| 目的地址 | dst host | dst host 8.8.8.8 | 目的IP |
| 端口 | port | port 80 | 源或目的端口 |
| 源端口 | src port | src port 12345 | 源端口 |
| 目的端口 | dst port | dst port 443 | 目的端口 |
| 协议 | proto | tcp/udp/icmp | 协议类型 |
| 网段 | net | net 192.168.0.0/24 | 网段 |
| 逻辑与 | and | tcp and port 80 | 同时满足 |
| 逻辑或 | or | port 80 or port 443 | 满足其一 |
| 逻辑非 | not | not port 22 | 排除 |
| 方向 | src/dst | src 10.0.0.1 and dst port 80 | 指定方向 |
4.3 tcpdump常用参数表
| 参数 | 全称 | 用途 | 示例 |
|---|---|---|---|
| -i | interface | 指定网卡 | tcpdump -i eth0 |
| -nn | 无名称解析 | 不解析主机名和端口名 | tcpdump -nn |
| -X | hex+ASCII | 十六进制和ASCII显示 | tcpdump -X |
| -w | write | 写入pcap文件 | tcpdump -w capture.pcap |
| -r | read | 读取pcap文件 | tcpdump -r capture.pcap |
| -c | count | 抓取指定包数 | tcpdump -c 100 |
| -s | snaplen | 设置抓包长度 | tcpdump -s 0(全包) |
| -v/vv/vvv | verbose | 详细输出 | tcpdump -vvv |
| -A | ASCII | ASCII显示内容 | tcpdump -A |
| -e | ethernet | 显示链路层头 | tcpdump -e |
| -q | quick | 简洁输出 | tcpdump -q |
| -t | timestamp | 不显示时间 | tcpdump -t |
| -G | rotate | 按时间轮转文件 | tcpdump -G 60(每60秒) |
| -W | count | 轮转文件数量 | tcpdump -W 10 |
4.4 tcpdump高级技巧
bash
# 组合过滤:抓取特定主机到特定端口的流量
tcpdump -i eth0 src host 10.0.0.5 and dst port 80 -nn
# 会话过滤:抓取两台主机之间的所有通信
tcpdump -i eth0 host 10.0.0.5 and host 192.168.1.100
# 内容匹配:查找包含特定字符串的包
tcpdump -i eth0 -A port 80 | grep "password"
tcpdump -i eth0 -AXs 0 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
# SYN扫描检测:只抓SYN包(无ACK)
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'
# DNS查询抓取
tcpdump -i eth0 -nn port 53
# 分片包处理
tcpdump -i eth0 'ip[6:2] & 0x1fff != 0' # 抓取分片包
# 写入文件并限制大小
tcpdump -i eth0 -w capture.pcap -C 100 -W 5 -G 3600
# -C 100: 每个文件最大100MB
# -W 5: 最多保留5个文件
# -G 3600: 每3600秒轮转
# 读取pcap并应用过滤
tcpdump -r capture.pcap -nn 'tcp port 80'
# 抓取ICMP Ping探测
tcpdump -i eth0 'icmp[icmptype] == icmp-echo'
# 抓取HTTP GET请求
tcpdump -i eth0 -s 0 -A 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
【提示】
tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420这个表达式通过计算 TCP 头部长度偏移,精确匹配载荷开头4字节为"GET "(0x47455420)。这是 BPF 底层字节匹配的经典用法。
4.5 tcpdump vs Wireshark对比
| 维度 | tcpdump | Wireshark |
|---|---|---|
| 界面 | 命令行 | 图形界面 |
| 资源占用 | 低 | 较高 |
| 协议解析 | 基础 | 深度解析2000+协议 |
| 过滤能力 | BPF(捕获级) | 显示过滤(字段级) |
| 导出重组 | 弱 | 强(HTTP对象/流跟踪) |
| 统计分析 | 基础 | 丰富(IO图/会话/协议树) |
| 远程使用 | 优秀 | 需X11或远程桌面 |
| 长期抓包 | 支持(轮转) | 不适合 |
| 适用场景 | 服务器/长期采集 | 深度分析/取证 |
最佳实践:服务器用 tcpdump 长期抓包存为 pcap,下载到本地用 Wireshark 深度分析。
4.6 tshark使用
tshark 是 Wireshark 的命令行版本,兼具 tcpdump 的轻量和 Wireshark 的深度解析能力。
bash
# 列出网卡
tshark -D
# 基本抓包
tshark -i eth0
# 使用显示过滤器(注意是显示过滤器语法)
tshark -i eth0 -f "port 80" # 捕获过滤器(BPF)
tshark -i eth0 -Y "http.request.method==POST" # 显示过滤器
# 提取特定字段
tshark -i eth0 -Y "http.request" -T fields -e http.host -e http.request.uri
# 统计HTTP状态码
tshark -r capture.pcap -Y "http.response" -T fields -e http.response.code | sort | uniq -c | sort -rn
# 提取所有DNS查询域名
tshark -r capture.pcap -Y "dns.qry.name" -T fields -e dns.qry.name | sort -u
# 提取TLS SNI
tshark -r capture.pcap -Y "tls.handshake.extensions_server_name" \
-T fields -e tls.handshake.extensions_server_name | sort -u
# 导出HTTP对象
tshark -r capture.pcap --export-objects http,./output/
# 统计IP会话
tshark -r capture.pcap -z conv,ip
# 统计协议分布
tshark -r capture.pcap -z io,phs
4.7 ngrep流量搜索
ngrep(network grep)可以在网络流量中按字符串或正则表达式搜索内容,适合快速查找特定模式。
bash
# 安装ngrep
apt install ngrep
# 搜索HTTP流量中的password
ngrep -i -d eth0 'password' port 80
# 搜索特定URL路径
ngrep -d eth0 '/admin' port 80
# 用正则匹配信用卡号模式
ngrep -d eth0 -W byline '[0-9]{16}' port 443
# 搜索所有HTTP User-Agent
ngrep -d eth0 'User-Agent' port 80
# 写入pcap同时搜索
ngrep -d eth0 -O capture.pcap 'session' port 80
4.8 完整命令行抓包流程
text
1. 确定目标 → 选择网卡(tcpdump -D / ip a)
2. 设置过滤器 → 减少采集量(-f BPF表达式)
3. 后台抓包 → 写入pcap(-w -C -G -W 轮转参数)
4. 实时监控 → 简洁输出(-nn -q)
5. 快速搜索 → ngrep/tshark过滤
6. 下载pcap → 传到分析机
7. tshark预处理 → 提取关键字段
8. Wireshark深度分析 → 图形化排查
5. HTTP/HTTPS流量分析
5.1 HTTP请求/响应结构
HTTP 是最常被分析和攻击的协议。理解其结构是 Web 流量分析的基础。
| HTTP组件 | 字段 | 示例 | 安全关注点 |
|---|---|---|---|
| Request Line | 方法 URI 版本 | GET /admin/ HTTP/1.1 | 方法异常/路径遍历 |
| Request Headers | Host/UA/Cookie/Auth | Host: example.com | UA异常/凭据泄露 |
| Request Body | POST数据 | user=admin&pass=123 | SQL注入/命令注入 |
| Status Line | 版本 状态码 原因 | HTTP/1.1 200 OK | 错误码分析 |
| Response Headers | Server/Location/Set-Cookie | Server: nginx | 服务器信息泄露 |
| Response Body | HTML/JSON/文件 | {"status":"ok"} | 敏感信息/恶意载荷 |
5.2 常见HTTP头字段分析
| 头字段 | 示例 | 安全分析价值 |
|---|---|---|
| Host | example.com | 识别目标站点,发现虚拟主机 |
| User-Agent | Mozilla/5.0... | 检测扫描器/爬虫/恶意软件UA |
| Cookie | sessionid=abc123 | 会话劫持/固定 |
| Referer | https://google.com | CSRF防护/来源追踪 |
| Authorization | Basic dXNlcjpwYXNz | 凭据提取(Base64解码) |
| X-Forwarded-For | 10.0.0.1 | 真实客户端IP,防伪造 |
| Set-Cookie | token=xyz; HttpOnly | Cookie安全属性检查 |
| Content-Type | application/json | 请求类型识别 |
| Accept-Language | zh-CN | 攻击者语言特征 |
| Server | Apache/2.4.41 | 指纹识别/版本漏洞 |
| X-Powered-By | PHP/7.4.3 | 技术栈识别 |
常见恶意User-Agent特征:
text
# 扫描器/工具UA
sqlmap/1.5
Nmap Scripting Engine
masscan/1.3
Nessus
Acunetix
Burp Suite
dirbuster
nikto
# 恶意软件常见UA
Mozilla/5.0 (compatible; <随机字符串>) # 伪装但格式异常
空UA或超短UA # 非浏览器行为
5.3 HTTP认证方式
| 认证方式 | 头字段 | 安全性 | 抓包可见性 |
|---|---|---|---|
| Basic | Authorization: Basic | 低(仅Base64编码) | 明文可解码 |
| Digest | Authorization: Digest <参数> | 中(MD5摘要) | 无法直接还原 |
| Bearer | Authorization: Bearer | 中(Token泄露风险) | Token可见 |
| Cookie | Cookie: sessionid= | 低(会话劫持) | 会话ID可见 |
| Session | Cookie: PHPSESSID= | 低(固定/劫持) | 会话ID可见 |
提取HTTP Basic认证凭据:
bash
# 使用tshark提取Authorization头
tshark -r capture.pcap -Y "http.authorization" \
-T fields -e http.authorization
# 解码Base64凭据
echo "dXNlcjpwYXNzMTIz" | base64 -d
# 输出:user:pass123
# Wireshark显示过滤器
http.authorization
5.4 HTTPS/TLS流量解密
HTTPS 流量因 TLS 加密无法直接查看内容,需要通过以下方式解密。
| 解密方式 | 原理 | 适用场景 | 限制 |
|---|---|---|---|
| SSLKEYLOGFILE | 浏览器导出密钥 | 分析自己浏览器流量 | 需要浏览器配合 |
| 中间人代理 | 代理充当CA签发证书 | 测试移动端/App | 需安装根证书 |
| 私钥解密 | 使用服务器私钥 | 分析服务器流量 | 仅RSA密钥交换有效 |
| 前向保密 | 临时密钥 | TLS 1.2/1.3默认 | 无法事后解密 |
SSLKEYLOGFILE方式(最常用):
text
# 1. 设置环境变量(让浏览器导出预主密钥)
# Windows CMD:
set SSLKEYLOGFILE=C:\keys\sslkeys.log
# Linux/Mac:
export SSLKEYLOGFILE=/tmp/sslkeys.log
# 2. 启动浏览器抓包
# Chrome/Firefox会自动将TLS密钥写入该文件
# 3. Wireshark配置密钥文件
Edit > Preferences > Protocols > TLS > (Pre)-Master-Secret log filename
选择 C:\keys\sslkeys.log
# 4. 抓包后TLS流量自动解密
# Follow TLS Stream 可看到明文HTTP内容
中间人代理方式(mitmproxy/burp):
bash
# 使用mitmproxy做HTTPS中间人
mitmproxy --mode transparent -p 8080
# 或使用mitmdump
mitmdump -w traffic.flow
# 受害端配置代理指向mitmproxy
# 安装mitmproxy的CA证书
# http://mitm.it 下载证书
5.5 HTTP/2与HTTP/3流量分析
| 协议 | 传输层 | 加密 | Wireshark解析 | 分析特点 |
|---|---|---|---|---|
| HTTP/1.1 | TCP | 可选(HTTPS) | 完整支持 | 文本协议,易读 |
| HTTP/2 | TCP | 默认TLS | 支持(需解密) | 多路复用/头部压缩HPACK |
| HTTP/3 | QUIC/UDP | 强制TLS 1.3 | 部分支持 | 无队头阻塞/0-RTT |
HTTP/2和HTTP/3分析挑战:
text
# HTTP/2过滤器(需先解密TLS)
http2.headers
http2.data.data
# HTTP/3/QUIC过滤器
quic
quic.version
# 挑战:
# 1. HTTP/2多路复用,一个TCP流承载多个请求
# 2. HTTP/3基于UDP+QUIC,传统TCP分析工具失效
# 3. 强制加密,无明文模式
# 4. 0-RTT重放攻击风险
5.6 完整HTTP流量分析流程
text
1. 过滤HTTP流量 → http || tls
2. 分析请求模式 → http.request.method / http.request.uri
3. 检查User-Agent → 异常UA特征匹配
4. 提取认证凭据 → http.authorization / Cookie
5. 检查POST载荷 → SQL注入/XSS/命令注入特征
6. 分析响应状态 → 4xx/5xx异常模式
7. 解密HTTPS → SSLKEYLOGFILE/中间人
8. 导出传输文件 → Export Objects > HTTP
9. 关联时间线 → 按时间排序还原攻击顺序
6. DNS流量分析
6.1 DNS报文结构
DNS 是网络基础协议,也常被用作隐蔽通信通道。理解其报文结构是检测 DNS 隧道的前提。
| DNS区域 | 字段 | 说明 | 安全分析点 |
|---|---|---|---|
| Header | Transaction ID | 事务ID | ID复用/欺骗检测 |
| Header | Flags | QR/Opcode/AA/TC/RD/RA/RCODE | 查询/响应标志 |
| Header | QDCOUNT | 问题数 | 通常为1 |
| Header | ANCOUNT | 回答数 | 响应记录数 |
| Header | NSCOUNT | 授权数 | 授权记录数 |
| Header | ARCOUNT | 附加数 | 附加记录数 |
| Question | QNAME | 查询域名 | 长度/字符异常检测 |
| Question | QTYPE | 查询类型 | TXT/NULL类型异常 |
| Question | QCLASS | 查询类 | IN/CH/HS |
| Answer | NAME | 域名 | CNAME链分析 |
| Answer | TYPE | 记录类型 | 记录类型异常 |
| Answer | TTL | 生存时间 | TTL异常短可能轮询 |
| Answer | RDATA | 资源数据 | TXT载荷过大 |
6.2 DNS记录类型
| 记录类型 | 代码 | 用途 | 安全关注点 |
|---|---|---|---|
| A | 1 | IPv4地址 | 域名解析IP,恶意域名检测 |
| AAAA | 28 | IPv6地址 | IPv6外泄通道 |
| CNAME | 5 | 别名记录 | CNAME链/CDN识别 |
| MX | 15 | 邮件交换 | 邮件服务器安全 |
| TXT | 16 | 文本记录 | DNS隧道载体/SPF/DKIM |
| NS | 2 | 域名服务器 | 委派异常/域劫持 |
| SOA | 6 | 起始授权 | 区域传输检测 |
| PTR | 12 | 反向解析 | 反向DNS异常 |
| SRV | 33 | 服务记录 | 服务发现/定位 |
| NULL | 10 | 空记录 | dnscat2隧道常用 |
| ANY | 255 | 所有记录 | 信息枚举 |
【提示】 DNS隧道通常使用 TXT 或 NULL 记录类型传输数据,因为这两种类型可承载较大的文本载荷。如果 DNS 流量中 TXT 记录占比异常高,值得重点排查。
6.3 DNS查询与响应分析
bash
# 提取所有DNS查询域名
tshark -r capture.pcap -Y "dns.qry.name" -T fields -e dns.qry.name | sort | uniq -c | sort -rn
# 提取DNS响应IP
tshark -r capture.pcap -Y "dns.a" -T fields -e dns.qry.name -e dns.a
# 查看TXT记录查询(可能DNS隧道)
tshark -r capture.pcap -Y "dns.qry.type == 16" -T fields -e dns.qry.name -e dns.txt
# 统计各记录类型分布
tshark -r capture.pcap -Y "dns" -T fields -e dns.qry.type | sort | uniq -c | sort -rn
# 查看NXDOMAIN响应(可能域名生成算法DGA)
tshark -r capture.pcap -Y "dns.flags.rcode == 3" -T fields -e dns.qry.name
6.4 DNS隧道检测
DNS 隧道是绕过网络安全设备的常用手段,其特征与传统 DNS 查询有显著差异。
| 检测维度 | 正常特征 | 隧道特征 | 检测方法 |
|---|---|---|---|
| 查询频率 | 低/中 | 极高(持续轮询) | 统计每秒查询数 |
| 域名长度 | 短(<20字符) | 长(>50字符) | 计算标签长度 |
| 子域名字符 | 正常单词 | Base32/Base64编码 | 熵值计算 |
| TXT记录占比 | 低 | 高 | 统计记录类型分布 |
| 查询模式 | 多样 | 规律(固定间隔) | 时间序列分析 |
| 响应大小 | 小 | 大(编码数据) | 响应包大小统计 |
| 子域名熵值 | 低 | 高(随机字符串) | 香农熵计算 |
DNS隧道检测脚本:
python
#!/usr/bin/env python3
"""DNS隧道检测脚本 - 基于统计特征分析"""
import math
from collections import defaultdict, Counter
def shannon_entropy(s):
"""计算字符串的香农熵"""
if not s:
return 0
freq = Counter(s)
length = len(s)
entropy = 0
for count in freq.values():
p = count / length
entropy -= p * math.log2(p)
return entropy
def analyze_dns_queries(queries):
"""
queries: [(timestamp, domain), ...]
返回可疑DNS隧道指标
"""
alerts = []
domain_stats = defaultdict(lambda: {"count": 0, "lengths": [], "entropies": []})
for ts, domain in queries:
# 取最长子域名标签
labels = domain.split(".")
longest_label = max(labels, key=len)
label_entropy = shannon_entropy(longest_label)
domain_stats[domain]["count"] += 1
domain_stats[domain]["lengths"].append(len(longest_label))
domain_stats[domain]["entropies"].append(label_entropy)
for domain, stats in domain_stats.items():
avg_len = sum(stats["lengths"]) / len(stats["lengths"])
avg_entropy = sum(stats["entropies"]) / len(stats["entropies"])
# 告警条件
if avg_len > 30:
alerts.append(f"[长子域名] {domain} 平均标签长度={avg_len:.1f}")
if avg_entropy > 3.5:
alerts.append(f"[高熵值] {domain} 平均熵={avg_entropy:.2f}")
if stats["count"] > 100:
alerts.append(f"[高频查询] {domain} 查询次数={stats['count']}")
return alerts
# 示例使用
test_queries = [
(1, "normal.example.com"),
(2, "a]!#$%@ tunnel.evil.com"),
(3, "normal.example.com"),
(4, "verylongbase32encodedlabel.evil.com"),
(5, "verylongbase32encodedlabel.evil.com"),
]
for alert in analyze_dns_queries(test_queries):
print(alert)
6.5 DNS隐蔽通道分析
常见DNS隧道工具及其流量特征:
| 工具 | 编码方式 | 记录类型 | 流量特征 | 检测规则 |
|---|---|---|---|---|
| dnscat2 | Base32/TXT | TXT/CNAME/A/MX | 子域名长/固定前缀 | 标签长度>50 |
| iodine | Base32 | NULL/TXT/CNAME | 非标端口/高熵 | NULL记录查询 |
| dns2tcp | Base64 | TXT/CNAME | 持续连接 | CNAME链异常 |
| Cobalt Strike | 随机 | A/AAAA | 轮询C2域名 | DGA特征 |
| DNSExfiltrator | Base64 | TXT/A | 大量子域名 | 子域名超长 |
6.6 DNS安全配置检查
bash
# 检查是否允许区域传输(信息泄露)
dig @ns.example.com example.com AXFR
# 检查是否开放递归解析(DNS放大攻击)
dig @target_ip google.com A
# 检查DNSSEC配置
dig +dnssec example.com A
# 检查是否使用DNS-over-HTTPS/TLS
# DoH: 端口443,特定路径
# DoT: 端口853
6.7 完整DNS流量分析流程
text
1. 过滤DNS流量 → dns
2. 统计查询域名 → 发现高频/异常域名
3. 记录类型分布 → TXT/NULL占比异常
4. 子域名长度分析 → 标签长度>30为可疑
5. 子域名熵值计算 > 香农熵>3.5为可疑
6. 查询频率分析 → 固定间隔轮询
7. 响应大小分析 → TXT响应过大
8. NXDOMAIN分析 → DGA域名特征
9. 关联威胁情报 → 恶意域名匹配
7. 恶意流量识别
7.1 恶意流量特征分类
| 攻击类别 | 流量特征 | 检测指标 | 典型工具/技术 |
|---|---|---|---|
| C2通信 | 规律性心跳/固定UA | 间隔/Jitter/信标 | Cobalt Strike/Metasploit |
| 数据外泄 | 大量出站/加密上传 | 数据量/方向/时段 | exfiltration detection |
| 端口扫描 | 大量SYN/无ACK | 单源多目的端口 | nmap/masscan |
| 暴力破解 | 短时大量认证请求 | 认证失败率 | hydra/medusa |
| Web攻击 | 攻击载荷/异常URI | 特征匹配 | SQLi/XSS/RCE |
| 横向移动 | 内网协议/SMB/RPC | 445/135/88通信 | PsExec/WMI |
| 隧道通信 | 协议封装异常 | 编码/频率/大小 | DNS/ICMP隧道 |
7.2 常见C2协议流量特征
| C2协议 | 传输方式 | 流量特征 | 检测要点 |
|---|---|---|---|
| HTTP C2 | 明文HTTP | 固定URI/UA/Jitter | URI模式/UA匹配 |
| HTTPS C2 | 加密TLS | 规律心跳/固定SNI | SNI/证书/时序 |
| DNS C2 | DNS查询 | 子域名编码/高频 | 熵值/标签长度 |
| ICMP C2 | ICMP载荷 | 非标准大小/内容 | 载荷大小>标准ping |
| TCP C2 | 原始TCP | 固定端口/心跳 | 非标准端口/模式 |
| 自定义C2 | 专有协议 | 非标准端口/格式 | 协议指纹/异常端口 |
7.3 Beacon行为分析
Beacon 是 Cobalt Strike 的核心通信模块,其行为模式有明显的流量特征。
| Beacon参数 | 说明 | 默认值 | 流量表现 |
|---|---|---|---|
| Beacon Type | 通信模式 | HTTP/HTTPS | 协议选择 |
| Sleep | 心跳间隔 | 60秒 | 固定间隔请求 |
| Jitter | 抖动比例 | 0-20% | 随机偏移 |
| MaxRetry | 最大重试 | 5 | 失败重连 |
| Server | C2地址 | 配置IP/域名 | 目的IP/SNI |
| User-Agent | 伪装UA | IE/Chrome | UA一致性检查 |
Beacon检测方法:
bash
# 1. 固定间隔检测:统计HTTP请求时间差
tshark -r capture.pcap -Y "http.request" -T fields -e frame.time_relative | \
awk 'NR>1{print $1-prev} {prev=$1}' | sort | uniq -c | sort -rn
# 2. 固定URI模式检测
tshark -r capture.pcap -Y "http.request.uri" -T fields -e http.request.uri | \
sort | uniq -c | sort -rn | head -20
# 3. 固定User-Agent检测
tshark -r capture.pcap -Y "http.user_agent" -T fields -e http.user_agent | \
sort | uniq -c | sort -rn
# 4. 心跳间隔分析(Python脚本)
# 见第13章自动化脚本集
7.4 恶意文件下载流量识别
bash
# 查找HTTP下载可执行文件
tshark -r capture.pcap -Y 'http.request.uri matches "\.(exe|dll|ps1|bat|vbs|jar)$"' \
-T fields -e http.host -e http.request.uri
# 查找MIME类型为可执行的响应
tshark -r capture.pcap -Y 'http.content_type contains "application/octet-stream"' \
-T fields -e http.host -e http.request.uri
# 导出HTTP对象进行恶意文件分析
tshark -r capture.pcap --export-objects http,./malware_files/
# 检查文件哈希(与威胁情报对比)
cd malware_files && for f in *; do sha256sum "$f"; done
7.5 数据外泄流量特征
| 外泄方式 | 流量特征 | 检测指标 | 检测方法 |
|---|---|---|---|
| HTTP POST | 大量POST/上传 | 请求大小>10KB | http.content_length统计 |
| DNS隧道 | 子域名编码数据 | 标签长度/熵值 | DNS频率分析 |
| ICMP隧道 | 大载荷ICMP | 载荷>64字节 | icmp.length统计 |
| FTP上传 | 大量FTP STOR | 上传文件数/大小 | ftp.request.command |
| 云存储上传 | HTTPS上传 | 大量出站/固定S3域名 | SNI/数据量统计 |
| 邮件外泄 | SMTP大附件 | 邮件大小/频率 | smtp/imap分析 |
7.6 扫描流量特征
| 扫描类型 | TCP标志 | 响应模式 | 检测过滤器 |
|---|---|---|---|
| SYN扫描 | SYN(无ACK) | 开放=SYN/ACK,关闭=RST | tcp.flags.syn1 && tcp.flags.ack0 |
| Connect扫描 | 完整三次握手 | 每端口建连 | tcp.flags.syn1 && tcp.flags.ack1 |
| FIN扫描 | FIN | 关闭=RST,开放=无响应 | tcp.flags.fin==1 |
| Null扫描 | 无标志 | 关闭=RST,开放=无响应 | tcp.flags==0 |
| Xmas扫描 | FIN+PSH+URG | 关闭=RST,开放=无响应 | tcp.flags.fin1 && tcp.flags.push1 && tcp.flags.urg==1 |
| UDP扫描 | UDP | 关闭=ICMP不可达 | udp && icmp.type==3 |
| ACK扫描 | ACK | RST=有防火墙 | tcp.flags.ack1 && tcp.flags.syn0 |
SYN扫描检测:
bash
# 统计各源IP的SYN包数(无后续ACK),识别扫描源
tshark -r capture.pcap -Y "tcp.flags.syn==1 && tcp.flags.ack==0" \
-T fields -e ip.src | sort | uniq -c | sort -rn | head -20
# 检测单源多目的端口扫描
tshark -r capture.pcap -Y "tcp.flags.syn==1 && tcp.flags.ack==0" \
-T fields -e ip.src -e ip.dst -e tcp.dstport | \
awk '{count[$1]++} END {for (ip in count) if (count[ip]>20) print ip, count[ip]}'
# 检测UDP端口扫描(ICMP不可达响应)
tshark -r capture.pcap -Y "icmp.type==3 && icmp.code==3" \
-T fields -e ip.src -e ip.dst | sort | uniq -c | sort -rn
7.7 完整恶意流量分析流程
text
1. 全局概览 → Protocol Hierarchy / Conversations
2. 定位异常主机 → Endpoints按字节数排序
3. 出站流量分析 → 非标准端口/异常目的IP
4. HTTP请求模式 → 固定URI/UA/间隔
5. DNS查询分析 → 子域名长度/熵值/频率
6. 扫描行为检测 → SYN/RST包统计
7. 凭据提取 → 明文协议/认证头
8. 文件提取 → Export Objects
9. 威胁情报关联 → IP/域名/哈希比对
10. 生成IOC列表 → IP/域名/UA/URI
8. 入侵检测系统(IDS/IPS)
8.1 IDS vs IPS
| 维度 | IDS(入侵检测) | IPS(入侵防御) |
|---|---|---|
| 部署方式 | 旁路镜像 | 串联部署 |
| 工作模式 | 被动监听 | 主动拦截 |
| 响应方式 | 告警/记录 | 丢弃/重置/阻断 |
| 性能影响 | 不影响网络 | 可能增加延迟 |
| 漏报影响 | 延迟发现 | 攻击可能成功 |
| 误报影响 | 告警噪声 | 误阻断正常业务 |
| 适用场景 | 审计/取证/分析 | 实时防护/关键节点 |
8.2 Snort架构与规则语法
Snort 是最经典的开源 IDS/IPS 系统,其规则语法已成为行业标准(Suricata 兼容)。
Snort架构由以下模块组成:
| 模块 | 功能 | 说明 |
|---|---|---|
| Packet Decoder | 数据包解码 | 解析Ethernet/IP/TCP/UDP等 |
| Preprocessors | 预处理器 | 流重组/HTTP解析/规则检查 |
| Detection Engine | 检测引擎 | 规则匹配核心 |
| Logging/Alerting | 日志告警 | 输出告警 |
| Output Modules | 输出模块 | 多种格式输出 |
Snort规则语法结构:
text
# 规则格式
[规则行为] [协议] [源IP] [源端口] [方向] [目的IP] [目的端口] ([规则选项])
# 方向操作符
-> 单向(源到目的)
<> 双向
# 规则选项
(msg: "告警消息";)
(content: "匹配内容";)
(pcre: "正则表达式";)
(sid: 规则ID;)
(rev: 修订版本;)
(classtype: 分类;)
(priority: 优先级;)
8.3 Snort规则编写示例集
以下规则覆盖常见攻击场景,可直接用于 Snort/Suricata 部署。
snort
# 1. 检测SQL注入 - UNION SELECT模式
alert tcp any any -> $HOME_NET any (msg:"SQL Injection - UNION SELECT"; \
content:"UNION"; nocase; content:"SELECT"; nocase; distance:0; within:20; \
sid:1000001; rev:1; classtype:web-application-attack;)
# 2. 检测XSS - script标签注入
alert tcp any any -> $HOME_NET any (msg:"XSS Attempt - Script Tag"; \
content:"<script"; nocase; \
sid:1000002; rev:1; classtype:web-application-attack;)
# 3. 检测命令注入 - 分号命令拼接
alert tcp any any -> $HOME_NET any (msg:"Command Injection - Semicolon"; \
content:";"; content:"/bin/sh"; nocase; distance:0; within:50; \
sid:1000003; rev:1; classtype:web-application-attack;)
# 4. 检测目录遍历 - ../路径
alert tcp any any -> $HOME_NET any (msg:"Directory Traversal - ../"; \
content:"../"; \
pcre:"/(\.\.\/){2,}/Ui"; \
sid:1000004; rev:1; classtype:web-application-attack;)
# 5. 检测SSH暴力破解 - 短时大量连接
alert tcp $EXTERNAL_NET any -> $HOME_NET 22 (msg:"SSH Brute Force Attempt"; \
flow:to_server,established; flags:A+; \
detection_filter:track by_src, count 5, seconds 30; \
sid:1000005; rev:1; classtype:attempted-admin;)
# 6. 检测Nmap SYN扫描
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"Nmap SYN Scan"; \
flags:S; \
detection_filter:track by_src, count 20, seconds 10; \
sid:1000006; rev:1; classtype:network-scan;)
# 7. 检测DNS隧道 - 超长子域名
alert udp any any -> $HOME_NET 53 (msg:"DNS Tunneling - Long Query"; \
content:"|00|"; offset:12; depth:255; \
pcre:"/[^\.]{40,}/"; \
sid:1000007; rev:1; classtype:trojan-activity;)
# 8. 检测ICMP隧道 - 大载荷
alert icmp any any -> $HOME_NET any (msg:"ICMP Tunneling - Large Payload"; \
dsize:>64; \
sid:1000008; rev:1; classtype:trojan-activity;)
# 9. 检测Metasploit Meterpreter - 特定URI
alert tcp any any -> $HOME_NET any (msg:"Meterpreter HTTP Communication"; \
content:"GET /"; content:"MIME"; distance:0; within:100; \
sid:1000009; rev:1; classtype:trojan-activity;)
# 10. 检测Cobalt Strike默认URI
alert http any any -> $HOME_NET any (msg:"Cobalt Strike Default Beacon URI"; \
content:"/dprom/"; content:"/submit.php"; distance:0; within:50; \
sid:1000010; rev:1; classtype:trojan-activity;)
# 11. 检测Webshell连接 - eval/base64
alert tcp any any -> $HOME_NET any (msg:"Webshell - eval base64"; \
content:"eval"; nocase; content:"base64_decode"; nocase; distance:0; within:30; \
sid:1000011; rev:1; classtype:web-application-attack;)
# 12. 检测文件下载 - 可执行文件
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"Executable Download"; \
content:"Content-Type|3a| application/octet-stream"; \
sid:1000012; rev:1; classtype:policy-violation;)
8.4 Suricata架构与多线程优势
Suricata 是新一代开源 IDS/IPS,兼容 Snort 规则语法,但采用多线程架构,性能更优。
| 维度 | Snort | Suricata |
|---|---|---|
| 架构 | 单线程 | 多线程 |
| 吞吐量 | 较低 | 高(可万兆级) |
| 规则兼容 | 自有语法 | 兼容Snort规则 |
| 协议解析 | 基础 | 更丰富(HTTP/2/QUIC) |
| 文件提取 | 不支持 | 内置支持 |
| 输出格式 | alert fast/full | EVE JSON(结构化) |
| 扩展功能 | 插件 | Lua脚本/文件存储 |
Suricata EVE JSON输出示例:
json
{
"timestamp": "2026-08-26T10:15:30.123456+0800",
"event_type": "alert",
"src_ip": "10.0.0.5",
"src_port": 54321,
"dest_ip": "192.168.1.100",
"dest_port": 80,
"proto": "TCP",
"alert": {
"action": "alert",
"gid": 1,
"signature_id": 1000001,
"signature": "SQL Injection - UNION SELECT",
"category": "web-application-attack",
"severity": 1
},
"http": {
"method": "GET",
"uri": "/page?id=1 UNION SELECT",
"hostname": "target.com"
}
}
8.5 Suricata规则编写
Suricata 规则与 Snort 语法兼容,但扩展了更多功能:
snort
# Suricata扩展规则 - 使用http关键字简化Web规则
alert http any any -> $HOME_NET any (msg:"SQL Injection via Suricata"; \
http.uri; content:"UNION"; nocase; \
http.uri; content:"SELECT"; nocase; distance:0; within:20; \
sid:2000001; rev:1;)
# 使用文件存储功能(Suricata特有)
alert http any any -> $HOME_NET any (msg:"Download executable"; \
fileext:exe; \
sid:2000002; rev:1; classtype:policy-violation;)
# 使用ja3指纹检测恶意TLS客户端
alert tls any any -> $HOME_NET any (msg:"Suspicious JA3 Fingerprint"; \
ja3.hash; content:"e7d705a3286e19ea42f587b344ee6865"; \
sid:2000003; rev:1;)
8.6 Zeek(Bro)脚本架构与日志分析
Zeek(原Bro)不同于 Snort/Suricata 的特征匹配范式,它通过脚本编程实现基于行为的网络分析,生成丰富的结构化日志。
| Zeek特性 | 说明 | 与Snort对比 |
|---|---|---|
| 分析范式 | 事件驱动/行为分析 | 特征匹配 |
| 编程能力 | Zeek脚本语言 | 无 |
| 日志输出 | 结构化TSV/JSON | 告警 |
| 误报率 | 低(行为驱动) | 较高(特征匹配) |
| 扩展性 | 脚本灵活定义 | 规则语法固定 |
8.7 IDS规则优化策略
| 优化维度 | 策略 | 方法 | 效果 |
|---|---|---|---|
| 性能优化 | 减少规则数 | 禁用过时规则 | 降低CPU占用 |
| 性能优化 | 使用fast_pattern | 指定快速匹配内容 | 提升匹配速度 |
| 性能优化 | 合理content顺序 | 高速内容在前 | 减少无效匹配 |
| 准确率优化 | 使用pcre细化 | 正则精确匹配 | 减少误报 |
| 准确率优化 | 添加上下文 | distance/within | 减少误报 |
| 误报优化 | 增加白名单 | pass规则 | 减少告警噪声 |
| 误报优化 | 阈值控制 | threshold/detection_filter | 避免单包告警 |
【提示】 规则优化核心原则:content匹配从最独特的特征开始,避免以常见字符串开头。使用
fast_pattern关键字指定最具区分度的content,Suricata会优先匹配该字段,大幅提升性能。
8.8 完整IDS部署方案
text
1. 需求评估 → 旁路IDS or 串联IPS
2. 硬件选型 → 吞吐量/CPU/内存
3. 网络部署 → SPAN镜像 or 串联接入
4. 规则集选择 → ET Open / ET Pro / 自定义
5. 策略调优 → 禁用不相关规则/添加白名单
6. 基线运行 → 收集误报/调整阈值
7. 告警对接 → SIEM/邮件/IM通知
8. 持续运营 → 规则更新/威胁狩猎
9. 网络流量取证
9.1 PCAP文件格式
| 格式 | 全称 | 特点 | 工具支持 |
|---|---|---|---|
| libpcap | pcap | 经典格式,单接口 | tcpdump/Wireshark |
| pcapng | pcap next generation | 现代格式,多接口/注释 | Wireshark/tshark |
| ERF | Extensible Record Format | Endace硬件格式 | 特定硬件 |
pcap文件结构:
text
# 文件头(24字节)
| 魔数(4) | 版本主(2) | 版本副(2) | 时区(4) | 精度(4) | 最大长度(4) | 链路类型(4) |
# 每个数据包记录头(16字节)
| 时间戳秒(4) | 时间戳微秒(4) | 包长度(4) | 原始长度(4) |
# 数据包内容(可变长度)
| Ethernet + IP + TCP/UDP + Payload |
9.2 PCAP文件处理工具
| 工具 | 功能 | 常用命令 |
|---|---|---|
| editcap | 编辑pcap | editcap -t input.pcap output.pcap |
| mergecap | 合并pcap | mergecap -w merged.pcap a.pcap b.pcap |
| capinfos | 查看信息 | capinfos capture.pcap |
| editcap切分 | 按时间/包数切分 | editcap -c 1000 input.pcap out |
| editcap去重 | 去除重复包 | editcap -d input.pcap output.pcap |
| dsniff | 协议嗅探 | dsniff -i eth0 |
| zeek | 日志生成 | zeek -r capture.pcap |
| tshark | 字段提取 | tshark -r capture.pcap -T fields |
bash
# 查看pcap文件基本信息
capinfos capture.pcap
# 按时间范围切分
editcap -A "2026-08-26 10:00:00" -B "2026-08-26 11:00:00" capture.pcap output.pcap
# 合并多个pcap
mergecap -w merged.pcap capture1.pcap capture2.pcap
# 去除重复包
editcap -d capture.pcap dedup.pcap
# 按包数切分
editcap -c 10000 capture.pcap output
# 修改时间戳(用于测试)
editcap -t +3600 capture.pcap time_adjusted.pcap
9.3 流量重组与会话还原
bash
# 使用tshark按会话分组
tshark -r capture.pcap -T fields -e tcp.stream | sort -u | wc -l
# 提取特定TCP流
tshark -r capture.pcap -Y "tcp.stream == 0" -w stream0.pcap
# 使用Wireshark Follow TCP Stream还原会话
# 右键 > Follow > TCP Stream
# 使用zeek生成会话日志
zeek -r capture.pcap local
# 生成conn.log,每行一个会话
9.4 文件提取
| 工具 | 提取方式 | 支持格式 | 特点 |
|---|---|---|---|
| foremost | 文件头特征 | 图片/文档/压缩包 | 基于文件雕刻 |
| binwalk | 固件/嵌入文件 | 固件/嵌入 | 递归提取 |
| NetworkMiner | PCAP解析 | 多种协议文件 | 图形化 |
| tshark | 协议导出 | HTTP/SMB | 按协议导出 |
| zeek | 脚本提取 | 所有传输文件 | 自动分析 |
bash
# 使用foremost提取文件
foremost -i capture.pcap -o ./extracted/
# 使用binwalk分析嵌入式文件
binwalk -e firmware.bin
# 使用tshark导出HTTP对象
tshark -r capture.pcap --export-objects http,./http_files/
# 使用tshark导出SMB对象
tshark -r capture.pcap --export-objects smb,./smb_files/
# 使用zeek提取文件
zeek -r capture.pcap local "LoadPKTS"
# 文件保存在extract_files目录
# NetworkMiner(图形化)
# 直接打开pcap,自动提取文件/凭据/图片
9.5 凭据提取
| 工具 | 提取协议 | 用法 |
|---|---|---|
| dsniff | HTTP/FTP/POP3/IMAP/Telnet | dsniff -i eth0 |
| PCredz | PCAP中凭据提取 | Pcredz -f capture.pcap |
| Ettercap | 中间人/嗅探 | ettercap -T -i eth0 |
| Wireshark | 图形化提取 | 凭据列表展示 |
| tshark | 命令行提取 | 字段提取 |
bash
# 使用dsniff嗅探明文凭据
dsniff -i eth0 -m
# 从pcap文件提取凭据
dsniff -r capture.pcap
# 使用PCredz从pcap提取凭据
python3 PCredz -f capture.pcap
# 使用tshark提取HTTP Basic认证
tshark -r capture.pcap -Y "http.authorization" \
-T fields -e http.authorization | \
while read auth; do echo "$auth" | sed 's/Basic //' | base64 -d; done
# 提取FTP凭据
tshark -r capture.pcap -Y "ftp.request.command==USER || ftp.request.command==PASS" \
-T fields -e ftp.request.arg
# 提取Cookie
tshark -r capture.pcap -Y "http.cookie" \
-T fields -e http.cookie
9.6 加密流量识别(JA3/JA3S)
JA3 是一种 TLS 客户端指纹技术,通过 ClientHello 中的字段生成 MD5 哈希,用于识别恶意软件的 TLS 通信。
JA3计算字段:
text
# JA3计算流程
ClientHello字段:
SSLVersion + CipherSuites + Extensions + EllipticCurves + EllipticCurvePointFormats
# 拼接为字符串,逗号分隔
# 例:771,4865-4866-4867,0-23-65281-10-11-35,29-23-24,0
# 计算MD5得到JA3指纹
echo -n "771,4865-4866-4867,0-23-65281-10-11-35,29-23-24,0" | md5sum
# 输出:e7d705a3286e19ea42f587b344ee6865
bash
# 使用tshark提取JA3指纹
tshark -r capture.pcap -Y "tls.handshake.type==1" \
-T fields -e ip.src -e tls.handshake.extensions_server_name \
-e tls.handshake.ciphersuite
# 使用Suricata生成JA3指纹(EVE JSON)
# suricata.yaml配置中启用:
# - ja3:
# enabled: yes
# JA3S(服务端指纹)提取
tshark -r capture.pcap -Y "tls.handshake.type==2" \
-T fields -e ip.src -e tls.handshake.ciphersuite
9.7 完整网络取证流程
text
1. 获取PCAP → tcpdump/Wireshark捕获
2. 文件信息 → capinfos查看概要
3. 预处理 → editcap去重/切分/时间修正
4. 协议概览 → tshark Protocol Hierarchy
5. 会话统计 → tshark conv统计
6. 凭据提取 → dsniff/PCredz/tshark
7. 文件提取 → tshark/foremost/zeek
8. 流量重组 → Follow TCP/TLS Stream
9. 加密分析 → JA3/JA3S指纹
10. 威胁关联 → IOC匹配
11. 取证报告 → 时间线/IOC列表/证据链
10. 加密流量分析
10.1 TLS握手流程
TLS握手是加密流量分析的核心,即使无法解密内容,握手过程也包含大量元数据。
text
客户端 服务端
| |
| --- ClientHello -----------------------> | 版本/密码套件/扩展/SNI
| <== ServerHello -------------------------| 选定密码套件/会话ID
| <== Certificate -------------------------| 服务器证书
| <== ServerKeyExchange(ECDHE)-----------| 密钥交换参数
| <== ServerHelloDone -------------------- | 握手结束
| |
| --- ClientKeyExchange ------------------> | 客户端密钥交换参数
| --- ChangeCipherSpec ------------------> | 切换加密
| --- Finished(加密)-------------------> | 完成验证
| |
| <== ChangeCipherSpec ------------------- | 切换加密
| <== Finished(加密)-------------------- | 完成验证
| |
| <== 应用数据(加密)====================> | 加密通信
10.2 JA3/JA3S指纹技术
| 指纹类型 | 分析对象 | 计算字段 | 用途 |
|---|---|---|---|
| JA3 | 客户端ClientHello | 版本/密码套件/扩展/曲线/点格式 | 识别恶意软件客户端 |
| JA3S | 服务端ServerHello | 版本/密码套件/扩展 | 识别C2服务器 |
| JA4 | 客户端(改进版) | 格式化字符串(非MD5) | 更可读/可比较 |
常见恶意软件JA3指纹:
| 恶意软件 | JA3指纹 | 特征 |
|---|---|---|
| Cobalt Strike | cd4c0a975e5f25f6... | 默认密码套件组合 |
| Metasploit | 5e2e6abb344c8d6b... | Meterpreter默认 |
| Emotet | 193d5d8a1c0c8b5f... | 特定扩展组合 |
| TrickBot | a0e9f5d64396d8b1... | 独特曲线选择 |
10.3 JA4指纹技术
JA4 是 JA3 的改进版本,使用格式化字符串而非MD5哈希,便于人工阅读和部分匹配。
text
# JA4格式:T(d/t)13d(版本)(密码套件数)(扩展数)(密码套件列表)(扩展列表)
# 例:t13d1516h2_8daaf6152771_b0da82dd1658
# JA4优势:
# 1. 不使用MD5,可直接阅读
# 2. 支持部分匹配(只匹配版本或密码套件)
# 3. 排序字段,消除顺序影响
# 4. 支持SNI关联分析
10.4 加密流量元数据分析
即使无法解密TLS内容,元数据依然能提供丰富的分析价值。
| 元数据类型 | 提取方法 | 分析价值 |
|---|---|---|
| SNI | tls.handshake.extensions_server_name | 目标域名/伪装检测 |
| 证书 | tls.handshake.certificate | 颁发者/有效期/自签名 |
| IP地址 | ip.src / ip.dst | 威胁情报关联 |
| 端口 | tcp.port | 非标准端口TLS |
| 数据量 | tcp.len统计 | 外泄检测 |
| 时序 | frame.time | 心跳模式检测 |
| 密码套件 | tls.handshake.ciphersuite | 指纹/异常组合 |
| 证书有效期 | cert证书字段 | 短期证书可C2 |
bash
# 提取所有TLS SNI
tshark -r capture.pcap -Y "tls.handshake.extensions_server_name" \
-T fields -e ip.src -e ip.dst -e tls.handshake.extensions_server_name | sort -u
# 提取TLS证书信息
tshark -r capture.pcap -Y "tls.handshake.certificate" \
-T fields -e x509sat.printableString
# 统计各SNI的连接频率(C2心跳检测)
tshark -r capture.pcap -Y "tls.handshake.extensions_server_name" \
-T fields -e frame.time -e tls.handshake.extensions_server_name | \
awk '{print $2}' | sort | uniq -c | sort -rn
# 检测自签名证书(C2常用)
tshark -r capture.pcap -Y "tls.handshake.certificate" \
-T fields -e x509sat.printableString | grep -i "self-signed"
# 统计TLS连接数据量(外泄检测)
tshark -r capture.pcap -Y "tls.record.content_type==23" \
-T fields -e ip.src -e ip.dst -e frame.len | \
awk '{sum[$1"->"$2]+=$3} END {for (k in sum) print k, sum[k]}' | sort -k2 -rn
10.5 加密C2流量识别
| 检测维度 | C2特征 | 正常特征 | 检测方法 |
|---|---|---|---|
| 通信模式 | 规律心跳 | 随机访问 | 时间间隔分析 |
| 数据量 | 固定大小 | 变化大 | 包长标准差分析 |
| SNI | 异常/不存在 | 合法域名 | SNI与IP关联验证 |
| 证书 | 自签名/短期 | 合法CA | 证书链验证 |
| JA3 | 恶意指纹 | 浏览器指纹 | 指纹库匹配 |
| 流量方向 | 客户端为主 | 双向均衡 | 方向性分析 |
10.6 TLS 1.3流量分析挑战
| 挑战 | 原因 | 应对策略 |
|---|---|---|
| 握手加密 | ServerHello后加密 | 依赖ClientHello元数据 |
| 0-RTT | 会话恢复数据 | 无法区分新旧会话 |
| ESNI/ECH | 加密SNI | SNI不可见,依赖IP |
| 前向保密 | 临时密钥 | 无法事后解密 |
| 会话票据 | 加密票据 | 无法关联会话 |
10.7 完整加密流量分析方案
text
1. 提取TLS元数据 → SNI/证书/密码套件/JA3
2. JA3/JA4指纹 → 恶意软件指纹库匹配
3. SNI分析 → 域名信誉/异常检测
4. 证书分析 → 颁发者/有效期/自签名
5. 时序分析 → 心跳间隔/Beacon模式
6. 数据量分析 → 上行/下行不对称
7. IP关联 → SNI与IP一致性验证
8. 流量基线 → 对比正常TLS模式
9. 威胁情报 → IP/域名/指纹关联
11. Zeek(Bro)日志分析
11.1 Zeek日志类型
Zeek 自动生成丰富的结构化日志,是网络行为分析的宝贵数据源。
| 日志文件 | 类型 | 核心字段 | 分析用途 |
|---|---|---|---|
| conn.log | 连接 | uid/时间/源目IP/端口/协议/字节/状态 | 会话分析/基线 |
| dns.log | DNS | uid/查询域名/记录类型/响应IP | DNS隧道/DGA |
| http.log | HTTP | uid/方法/URI/UA/状态码/Host | Web攻击/异常 |
| ssl.log | TLS | uid/SNI/版本/密码套件/证书 | C2检测/证书异常 |
| files.log | 文件 | uid/源/类型/大小/MD5/SHA1 | 文件传输/恶意文件 |
| x509.log | 证书 | 证书指纹/颁发者/有效期 | 证书分析 |
| weird.log | 异常 | uid/异常类型/描述 | 协议异常检测 |
| notice.log | 告警 | 时间/类型/描述/源 | Zeek内置告警 |
| ssh.log | SSH | 版本/认证方法/方向 | SSH异常 |
| smb_files.log | SMB | 路径/大小/操作 | 横向移动 |
| kerberos.log | Kerberos | 请求类型/服务/客户端 | Kerberos攻击 |
11.2 conn.log字段详解
conn.log 是 Zeek 最核心的日志,记录所有网络连接。
| 字段 | 说明 | 分析价值 |
|---|---|---|
| ts | 时间戳 | 时间线分析 |
| uid | 连接唯一ID | 关联其他日志 |
| id.orig_h | 源IP | 溯源/统计 |
| id.orig_p | 源端口 | 客户端行为 |
| id.resp_h | 目的IP | 目标分析 |
| id.resp_p | 目的端口 | 服务识别 |
| proto | 传输层协议 | tcp/udp/icmp |
| service | 应用层协议 | http/dns/ssl |
| duration | 连接时长 | 长连接/Beacon |
| orig_bytes | 源发字节 | 上行流量 |
| resp_bytes | 响应字节 | 下行流量 |
| conn_state | 连接状态 | S0/SF/REJ等 |
| orig_pkts | 源发包数 | 包计数 |
| resp_pkts | 响应包数 | 包计数 |
conn_state状态码:
| 状态 | 含义 | 安全分析 |
|---|---|---|
| S0 | 未完成连接(无SYN-ACK) | SYN扫描/SYN Flood |
| SF | 正常完成 | 正常会话 |
| REJ | 连接被拒(RST) | 端口关闭/防火墙 |
| S1 | 连接建立无数据 | 可能扫描 |
| S2 | 连接建立,源先断 | 异常终止 |
| S3 | 连接建立,目先断 | 异常终止 |
| RSTO | 源发RST | 异常关闭 |
| RSTR | 目发RST | 异常关闭 |
| OTH | 无SYN的流量 | 畸形包 |
bash
# 分析conn.log
# 统计各IP的连接数
cat conn.log | zeek-cut id.orig_h | sort | uniq -c | sort -rn | head -20
# 查找Beacon行为(固定间隔连接)
cat conn.log | zeek-cut id.orig_h id.resp_h duration | \
awk '$3>0 && $3<2 {print $1, $2}' | sort | uniq -c | sort -rn | head
# 查找未完成连接(SYN扫描)
cat conn.log | zeek-cut id.orig_h conn_state | grep S0 | \
zeek-cut id.orig_h | sort | uniq -c | sort -rn
# 统计各端口连接数
cat conn.log | zeek-cut id.resp_p | sort | uniq -c | sort -rn
11.3 http.log与ssl.log分析
bash
# HTTP分析
# 统计User-Agent(检测异常UA)
cat http.log | zeek-cut user_agent | sort | uniq -c | sort -rn
# 提取所有请求URI(检测攻击载荷)
cat http.log | zeek-cut uri | sort | uniq -c | sort -rn | head -30
# 查找异常大POST请求(数据外泄)
cat http.log | zeek-cut method uri request_body_len | \
awk '$1=="POST" && $3>10000 {print $2, $3}'
# SSL/TLS分析
# 提取SNI(检测C2域名)
cat ssl.log | zeek-cut server_name | sort | uniq -c | sort -rn
# 查找无SNI的TLS连接(可能C2)
cat ssl.log | zeek-cut server_name | grep -c "^$"
# 查找自签名证书
cat x509.log | zeek-cut certificate_subject issuer | \
grep -i "self\|unknown\|empty"
11.4 Zeek脚本编写
Zeek 脚本使用事件驱动模型,可以在特定网络事件发生时执行自定义逻辑。
zeek
# 自定义脚本:检测特定UA的HTTP请求
# 保存为 detect_scanner.zeek
module HTTP_SCANNER;
export {
redef enum Notice::Type += {
Suspicious_User_Agent
};
}
# 可疑UA列表
const suspicious_uas: set[string] = {
"sqlmap/1.5",
"Nmap Scripting Engine",
"masscan",
"Nessus",
"dirbuster",
"nikto",
} &redef;
# HTTP请求事件
event http_request(c: connection, method: string, unescaped_uri: string)
{
if ( c$http$user_agent in suspicious_uas )
{
NOTICE([$note=Suspicious_User_Agent,
msg=fmt("Suspicious UA: %s from %s",
c$http$user_agent, c$id$orig_h),
conn=c,
sub=c$http$user_agent]);
}
}
# 自定义脚本:检测DNS隧道
# 保存为 detect_dns_tunnel.zeek
module DNS_TUNNEL;
export {
redef enum Notice::Type += {
DNS_Tunnel_Long_Query,
DNS_Tunnel_High_Frequency,
};
}
# 记录各源IP的DNS查询数
global dns_query_count: table[addr] of count &default=0;
# DNS请求事件
event dns_request(c: connection, msg: dns_msg, query: string)
{
# 检测超长子域名
local labels = split_string(query, /\./);
for ( label in labels )
{
if ( |labels[label]| > 40 )
{
NOTICE([$note=DNS_Tunnel_Long_Query,
msg=fmt("Long DNS label (%d chars): %s from %s",
|labels[label]|, query, c$id$orig_h),
conn=c,
sub=query]);
}
}
# 检测高频查询
dns_query_count[c$id$orig_h] += 1;
if ( dns_query_count[c$id$orig_h] > 100 )
{
NOTICE([$note=DNS_Tunnel_High_Frequency,
msg=fmt("High DNS frequency: %d queries from %s",
dns_query_count[c$id$orig_h], c$id$orig_h),
conn=c]);
}
}
运行Zeek脚本:
bash
# 对pcap运行Zeek
zeek -r capture.pcap local ./detect_scanner.zeek ./detect_dns_tunnel.zeek
# 查看告警
cat notice.log | zeek-cut ts note msg | column -t
# 实时监听网卡
zeek -i eth0 local ./detect_scanner.zeek
11.5 Zeek与ELK集成
text
# Zeek输出JSON格式(便于ELK采集)
# 在local.zeek中配置:
@load policy/tuning/json-logs.zeek
# 或在zeek配置文件中设置:
# LogAscii::use_json=T
# Filebeat采集Zeek日志
# filebeat.yml
filebeat.inputs:
- type: log
paths:
- /opt/zeek/logs/current/*.log
fields:
zeek: true
multiline:
pattern: '^{'
negate: true
match: after
output.elasticsearch:
hosts: ["localhost:9200"]
indices:
- index: "zeek-conn-%{+yyyy.MM.dd}"
when.contains:
zeek_log_type: "conn"
- index: "zeek-dns-%{+yyyy.MM.dd}"
when.contains:
zeek_log_type: "dns"
11.6 完整Zeek分析流程
text
1. 运行Zeek → zeek -r capture.pcap local
2. 查看日志列表 → ls *.log
3. 分析conn.log → 连接统计/Beacon检测
4. 分析dns.log → DNS隧道/DGA检测
5. 分析http.log → Web攻击/异常UA
6. 分析ssl.log → TLS/SNI/证书分析
7. 分析files.log → 文件提取/哈希
8. 查看notice.log → 内置告警
9. 加载自定义脚本 → 特定检测逻辑
10. 导入ELK → 可视化分析
12. 网络流量可视化
12.1 流量可视化工具
| 工具 | 类型 | 特点 | 适用场景 |
|---|---|---|---|
| Kibana | 通用可视化 | ELK组件/灵活看板 | SIEM/日志分析 |
| Grafana | 监控可视化 | 实时监控/多数据源 | 流量监控/告警 |
| Arkime(Moloch) | 全流量分析 | PCAP+元数据索引 | 全流量回溯/狩猎 |
| RITA | 威胁分析 | Zeek日志分析 | Beacon/C2检测 |
| Malcolm | 一体化平台 | Zeek+Arkime+ELK | 企业级流量分析 |
| VAST | 大数据分析 | 高速查询 | 大规模流量 |
| Moloch | 老牌工具 | Arkime前身 | 全流量存储 |
12.2 Arkime(Moloch)部署与使用
Arkime 是全流量捕获与索引平台,将 PCAP 存储与结构化元数据索引结合,支持快速检索和回溯。
bash
# 安装Arkime(Ubuntu)
apt install arkime
# 配置网卡监听
# 编辑config.ini
[default]
pcapDir = /opt/arkime/raw
interface = eth0
elasticsearch = http://localhost:9200
# 启动抓包
/opt/arkime/bin/capture -c /opt/arkime/etc/config.ini
# 启动Web界面
/opt/arkime/bin/viewer -c /opt/arkime/etc/config.ini
# 访问Web界面
# http://localhost:8005
# Arkime查询语法
# ip.dst:8.8.8.8 按目的IP过滤
# port.dst: == 443 按目的端口
# protocols == "http" 按协议
# http.uri == "/admin" 按HTTP URI
# tls.sni == "evil.com" 按TLS SNI
12.3 RITA使用
RITA(Real Intelligence Threat Analysis)专门分析 Zeek 日志,自动检测 Beacon 行为和 C2 通信。
bash
# 安装RITA
# 需要Go和MongoDB
# 导入Zeek日志
rita import /opt/zeek/logs/ analysis_set
# 查看分析结果
rita show-beacons analysis_set
# 输出Beacon连接列表(间隔/Jitter/分数)
rita show-exploded-dns analysis_set
# 输出DNS子域名统计(隧道检测)
rita show-strobes analysis_set
# 输出高频重复连接
rita show-long-connections analysis_set
# 输出长连接
rita show-useragents analysis_set
# 输出User-Agent统计
# RITA检测逻辑
# Beacon检测:固定间隔+低Jitter+持续连接
# 隧道检测:超长子域名+高频查询
# 外泄检测:大量出站+异常端口
12.4 Malcolm流量分析平台
Malcolm 是集成了 Zeek、Arkime、ELK、Suricata 的一体化流量分析平台。
text
# Malcolm部署(Docker Compose)
git clone https://github.com/cisagov/Malcolm.git
cd Malcolm
docker-compose up -d
# Malcolm组件
# - Zeek:流量解析与日志生成
# - Arkime:全流量PCAP存储
# - Suricata:IDS规则检测
# - Elasticsearch:日志索引
# - Kibana:可视化看板
# - Logstash/Filebeat:日志采集
# - Arkime Viewer:Web界面
# 访问界面
# Kibana: https://localhost:5601
# Arkime: https://localhost:443
12.5 ELK Stack网络流量看板
Kibana 网络流量看板常用可视化组件:
| 看板组件 | 数据源 | 可视化类型 | 分析价值 |
|---|---|---|---|
| 协议分布 | Zeek conn.log | 饼图 | 流量组成概览 |
| Top IP | Zeek conn.log | 柱状图 | 异常主机定位 |
| 流量趋势 | Zeek conn.log | 折线图 | 流量突增检测 |
| DNS查询 | Zeek dns.log | 表格 | 异常域名发现 |
| HTTP请求 | Zeek http.log | 表格 | Web攻击检测 |
| TLS SNI | Zeek ssl.log | 表格 | C2域名发现 |
| IDS告警 | Suricata EVE | 时间线 | 攻击事件分析 |
| 文件传输 | Zeek files.log | 表格 | 文件活动监控 |
12.6 完整可视化方案
text
1. 数据采集 → Zeek/Suricata/NetFlow
2. 日志传输 → Filebeat/Logstash
3. 数据存储 → Elasticsearch
4. 全流量存储 → Arkime PCAP
5. 可视化展示 → Kibana/Grafana
6. 威胁分析 → RITA自动检测
7. 一体化部署 → Malcolm
8. 告警联动 → 邮件/IM/工单
13. 自动化流量分析
13.1 Python Scapy包构造与解析
Scapy 是 Python 最强大的网络数据包操作库,支持包构造、发送、嗅探和解析。
| Scapy函数 | 用途 | 示例 |
|---|---|---|
| sniff() | 嗅探数据包 | sniff(iface="eth0", count=10) |
| sr() | 发送并接收(多响应) | sr(IP(dst="8.8.8.8")/ICMP()) |
| sr1() | 发送并接收(单响应) | sr1(IP(dst="8.8.8.8")/ICMP()) |
| send() | 只发送(不接收) | send(IP(dst="8.8.8.8")/ICMP()) |
| PcapReader | 读取PCAP | PcapReader("capture.pcap") |
| wrpcap | 写入PCAP | wrpcap("out.pcap", packets) |
python
#!/usr/bin/env python3
"""Scapy基础:包构造与解析"""
from scapy.all import (
IP, TCP, UDP, ICMP, DNS, DNSQR, Raw,
sniff, sr1, send, PcapReader, wrpcap
)
# 1. 构造并发送ICMP Ping
response = sr1(IP(dst="8.8.8.8")/ICMP(), timeout=2)
if response:
print(f"收到响应: {response[IP].src}")
# 2. 构造TCP SYN包
syn_packet = IP(dst="192.168.1.1")/TCP(dport=80, flags="S")
response = sr1(syn_packet, timeout=2)
if response and response.haslayer(TCP):
if response[TCP].flags == "SA":
print("端口开放")
elif response[TCP].flags == "RA":
print("端口关闭")
# 3. 构造DNS查询
dns_query = IP(dst="8.8.8.8")/UDP(dport=53)/DNS(
id=1, qd=DNSQR(qname="example.com", qtype="A")
)
response = sr1(dns_query, timeout=2)
if response and response.haslayer(DNS):
for i in range(response[DNS].ancount):
print(f"DNS响应: {response[DNS].an[i].rdata}")
# 4. 嗅探数据包
def packet_handler(pkt):
if pkt.haslayer(TCP) and pkt.haslayer(Raw):
payload = pkt[Raw].load.decode('utf-8', errors='ignore')
if "password" in payload.lower():
print(f"[凭据] {pkt[IP].src} -> {pkt[IP].dst}: {payload[:100]}")
sniff(iface="eth0", filter="tcp port 80", prn=packet_handler, count=100)
# 5. 读取PCAP文件分析
with PcapReader("capture.pcap") as reader:
for pkt in reader:
if pkt.haslayer(DNS) and pkt.haslayer(DNSQR):
query_name = pkt[DNSQR].qname.decode()
print(f"DNS查询: {query_name}")
13.2 自定义流量分析脚本
python
#!/usr/bin/env python3
"""协议解析与特征检测脚本"""
from scapy.all import IP, TCP, UDP, DNS, DNSQR, Raw, PcapReader
from collections import defaultdict, Counter
import re
class TrafficAnalyzer:
"""网络流量分析器"""
def __init__(self):
self.ip_stats = defaultdict(int)
self.port_stats = defaultdict(int)
self.protocol_stats = Counter()
self.http_requests = []
self.dns_queries = []
self.syn_sources = defaultdict(int)
self.bytes_sent = defaultdict(int)
self.bytes_recv = defaultdict(int)
def analyze_pcap(self, pcap_file):
"""分析PCAP文件"""
with PcapReader(pcap_file) as reader:
for pkt in reader:
self._process_packet(pkt)
def _process_packet(self, pkt):
"""处理单个数据包"""
if not pkt.haslayer(IP):
return
ip = pkt[IP]
self.ip_stats[ip.src] += 1
self.protocol_stats[ip.proto] += 1
self.bytes_sent[ip.src] += len(pkt)
self.bytes_recv[ip.dst] += len(pkt)
# TCP分析
if pkt.haslayer(TCP):
tcp = pkt[TCP]
self.port_stats[tcp.dport] += 1
# SYN扫描检测
if tcp.flags == "S":
self.syn_sources[ip.src] += 1
# HTTP请求分析
if pkt.haslayer(Raw) and tcp.dport == 80:
payload = pkt[Raw].load.decode('utf-8', errors='ignore')
if re.match(r'^(GET|POST|PUT|DELETE|HEAD)', payload):
method = payload.split(' ')[0]
uri = payload.split(' ')[1] if ' ' in payload else ''
self.http_requests.append({
'src': ip.src,
'dst': ip.dst,
'method': method,
'uri': uri,
'time': float(pkt.time)
})
# DNS查询分析
if pkt.haslayer(DNS) and pkt.haslayer(DNSQR):
query_name = pkt[DNSQR].qname.decode().rstrip('.')
self.dns_queries.append({
'src': ip.src,
'query': query_name,
'qtype': pkt[DNSQR].qtype,
'time': float(pkt.time)
})
def detect_port_scan(self, threshold=20):
"""检测端口扫描"""
print("\n[端口扫描检测]")
for ip, count in sorted(self.syn_sources.items(),
key=lambda x: x[1], reverse=True):
if count > threshold:
print(f" {ip}: {count} 个SYN包(疑似扫描)")
def detect_dns_tunnel(self, max_label_len=40, min_entropy=3.5):
"""检测DNS隧道"""
import math
from collections import Counter
print("\n[DNS隧道检测]")
for query in self.dns_queries:
labels = query['query'].split('.')
for label in labels:
if len(label) > max_label_len:
print(f" [超长标签] {query['src']} -> {query['query']}")
break
# 计算熵值
if len(label) > 10:
freq = Counter(label)
entropy = -sum(c/len(label) * math.log2(c/len(label))
for c in freq.values())
if entropy > min_entropy:
print(f" [高熵值] {query['src']} -> {query['query']} (熵={entropy:.2f})")
break
def detect_data_exfiltration(self, threshold=100000):
"""检测数据外泄"""
print("\n[数据外泄检测]")
for ip, bytes_out in sorted(self.bytes_sent.items(),
key=lambda x: x[1], reverse=True):
if bytes_out > threshold:
print(f" {ip}: 上传 {bytes_out/1024:.1f} KB(疑似外泄)")
def generate_report(self):
"""生成分析报告"""
print("=" * 60)
print("网络流量分析报告")
print("=" * 60)
print(f"\n总IP数: {len(self.ip_stats)}")
print(f"总HTTP请求: {len(self.http_requests)}")
print(f"总DNS查询: {len(self.dns_queries)}")
print("\n[Top 10 源IP]")
for ip, count in Counter(self.ip_stats).most_common(10):
print(f" {ip}: {count} 包")
print("\n[Top 10 目的端口]")
for port, count in Counter(self.port_stats).most_common(10):
print(f" 端口 {port}: {count} 包")
self.detect_port_scan()
self.detect_dns_tunnel()
self.detect_data_exfiltration()
# 使用示例
if __name__ == "__main__":
analyzer = TrafficAnalyzer()
analyzer.analyze_pcap("capture.pcap")
analyzer.generate_report()
13.3 自动化恶意流量检测脚本
python
#!/usr/bin/env python3
"""自动化恶意流量检测脚本集"""
import re
import math
from collections import defaultdict, Counter
from scapy.all import IP, TCP, UDP, DNS, DNSQR, Raw, PcapReader
# 恶意UA特征库
MALICIOUS_UA = [
r'sqlmap', r'nmap', r'masscan', r'nessus', r'acunetix',
r'nikto', r'dirbuster', r'gobuster', r'wpscan', r'burp',
r'metasploit', r'curl', r'python-requests'
]
# SQL注入特征
SQLI_PATTERNS = [
r'union\s+select', r'or\s+1=1', r'and\s+1=1',
r"'\s*or\s*'", r'--', r'/\*.*\*/',
r'concat\s*\(', r'sleep\s*\(', r'benchmark\s*\(',
]
# XSS特征
XSS_PATTERNS = [
r'<script', r'javascript:', r'onerror=', r'onload=',
r'<img[^>]+src', r'<iframe', r'alert\s*\(',
]
# 命令注入特征
CMDI_PATTERNS = [
r';\s*/bin/', r'\|\s*/bin/', r'`.*`',
r'\$\(', r'&&\s*\w', r'\|\|\s*\w',
]
def detect_malicious_http(pcap_file):
"""检测HTTP恶意流量"""
findings = []
with PcapReader(pcap_file) as reader:
for pkt in reader:
if not (pkt.haslayer(IP) and pkt.haslayer(TCP) and pkt.haslayer(Raw)):
continue
payload = pkt[Raw].load.decode('utf-8', errors='ignore')
src_ip = pkt[IP].src
# 检测恶意UA
for pattern in MALICIOUS_UA:
if re.search(pattern, payload, re.IGNORECASE):
findings.append({
'type': 'Malicious UA',
'src': src_ip,
'detail': f"匹配: {pattern}",
'payload': payload[:200]
})
# 检测SQL注入
for pattern in SQLI_PATTERNS:
if re.search(pattern, payload, re.IGNORECASE):
findings.append({
'type': 'SQL Injection',
'src': src_ip,
'detail': f"匹配: {pattern}",
'payload': payload[:200]
})
# 检测XSS
for pattern in XSS_PATTERNS:
if re.search(pattern, payload, re.IGNORECASE):
findings.append({
'type': 'XSS',
'src': src_ip,
'detail': f"匹配: {pattern}",
'payload': payload[:200]
})
# 检测命令注入
for pattern in CMDI_PATTERNS:
if re.search(pattern, payload, re.IGNORECASE):
findings.append({
'type': 'Command Injection',
'src': src_ip,
'detail': f"匹配: {pattern}",
'payload': payload[:200]
})
return findings
def detect_beacon_behavior(pcap_file, min_connections=10, max_jitter=0.3):
"""检测Beacon行为"""
connections = defaultdict(list)
with PcapReader(pcap_file) as reader:
for pkt in reader:
if not (pkt.haslayer(IP) and pkt.haslayer(TCP)):
continue
key = f"{pkt[IP].src}->{pkt[IP].dst}:{pkt[TCP].dport}"
connections[key].append(float(pkt.time))
beacons = []
for key, times in connections.items():
if len(times) < min_connections:
continue
times.sort()
intervals = [times[i+1] - times[i] for i in range(len(times)-1)]
if not intervals:
continue
avg_interval = sum(intervals) / len(intervals)
if avg_interval == 0:
continue
# 计算Jitter(标准差/均值)
variance = sum((x - avg_interval) ** 2 for x in intervals) / len(intervals)
std_dev = math.sqrt(variance)
jitter = std_dev / avg_interval if avg_interval > 0 else 1
if jitter < max_jitter:
beacons.append({
'connection': key,
'connections': len(times),
'avg_interval': avg_interval,
'jitter': jitter
})
return beacons
# 使用示例
if __name__ == "__main__":
print("[恶意HTTP检测]")
findings = detect_malicious_http("capture.pcap")
for f in findings:
print(f" [{f['type']}] {f['src']}: {f['detail']}")
print("\n[Beacon行为检测]")
beacons = detect_beacon_behavior("capture.pcap")
for b in beacons:
print(f" {b['connection']}: {b['connections']}次, "
f"间隔={b['avg_interval']:.1f}s, Jitter={b['jitter']:.2f}")
13.4 流量基线与异常检测
python
#!/usr/bin/env python3
"""流量基线与异常检测"""
from collections import defaultdict
from scapy.all import IP, TCP, UDP, PcapReader
import statistics
class TrafficBaseline:
"""流量基线模型"""
def __init__(self):
self.hourly_bytes = defaultdict(int)
self.ip_pairs = defaultdict(int)
self.port_usage = defaultdict(int)
self.packet_sizes = []
def build_baseline(self, pcap_file):
"""从正常流量构建基线"""
with PcapReader(pcap_file) as reader:
for pkt in reader:
if not pkt.haslayer(IP):
continue
hour = int(float(pkt.time)) // 3600
self.hourly_bytes[hour] += len(pkt)
self.packet_sizes.append(len(pkt))
src, dst = pkt[IP].src, pkt[IP].dst
self.ip_pairs[f"{src}->{dst}"] += 1
if pkt.haslayer(TCP):
self.port_usage[pkt[TCP].dport] += 1
elif pkt.haslayer(UDP):
self.port_usage[pkt[UDP].dport] += 1
def get_baseline_stats(self):
"""获取基线统计"""
return {
'avg_packet_size': statistics.mean(self.packet_sizes),
'std_packet_size': statistics.stdev(self.packet_sizes),
'avg_hourly_bytes': statistics.mean(self.hourly_bytes.values()),
'top_ip_pairs': sorted(self.ip_pairs.items(),
key=lambda x: x[1], reverse=True)[:10],
'top_ports': sorted(self.port_usage.items(),
key=lambda x: x[1], reverse=True)[:10]
}
def detect_anomalies(self, pcap_file, threshold=3.0):
"""检测异常流量(Z-score方法)"""
baseline = self.get_baseline_stats()
anomalies = []
current_traffic = defaultdict(int)
with PcapReader(pcap_file) as reader:
for pkt in reader:
if not pkt.haslayer(IP):
continue
src, dst = pkt[IP].src, pkt[IP].dst
current_traffic[f"{src}->{dst}"] += 1
# 检测异常通信对
for pair, count in current_traffic.items():
baseline_count = self.ip_pairs.get(pair, 0)
if baseline_count == 0:
anomalies.append(f"新通信对: {pair} ({count}包)")
else:
z_score = (count - baseline_count) / baseline_count
if abs(z_score) > threshold:
anomalies.append(
f"异常通信: {pair} ({count}包, 基线={baseline_count}, Z={z_score:.2f})"
)
return anomalies
# 使用示例
if __name__ == "__main__":
baseline = TrafficBaseline()
baseline.build_baseline("normal_traffic.pcap")
stats = baseline.get_baseline_stats()
print("基线统计:")
print(f" 平均包大小: {stats['avg_packet_size']:.1f}")
print(f" 平均每小时流量: {stats['avg_hourly_bytes']:.1f}")
anomalies = baseline.detect_anomalies("suspicious_traffic.pcap")
print("\n异常检测:")
for a in anomalies:
print(f" {a}")
13.5 完整自动化分析脚本集
python
#!/usr/bin/env python3
"""综合流量分析工具 - 集成所有检测模块"""
import argparse
import json
from scapy.all import PcapReader, IP, TCP, UDP, DNS, DNSQR, Raw
from collections import defaultdict, Counter
class ComprehensiveAnalyzer:
def __init__(self, pcap_file):
self.pcap_file = pcap_file
self.results = {
'summary': {},
'port_scans': [],
'dns_tunnels': [],
'beacons': [],
'malicious_http': [],
'data_exfiltration': [],
'credentials': []
}
def run_all(self):
"""运行所有检测模块"""
print(f"[*] 分析文件: {self.pcap_file}")
self.analyze_summary()
self.detect_port_scans()
self.detect_dns_tunnels()
self.detect_beacons()
self.detect_malicious_http()
self.detect_data_exfiltration()
self.extract_credentials()
return self.results
def analyze_summary(self):
"""基础统计"""
packet_count = 0
ip_count = set()
protocol_count = Counter()
with PcapReader(self.pcap_file) as reader:
for pkt in reader:
packet_count += 1
if pkt.haslayer(IP):
ip_count.add(pkt[IP].src)
if pkt.haslayer(TCP):
protocol_count['TCP'] += 1
elif pkt.haslayer(UDP):
protocol_count['UDP'] += 1
self.results['summary'] = {
'total_packets': packet_count,
'unique_ips': len(ip_count),
'protocols': dict(protocol_count)
}
print(f" 总包数: {packet_count}, 独立IP: {len(ip_count)}")
def detect_port_scans(self, threshold=20):
"""端口扫描检测"""
syn_sources = defaultdict(int)
with PcapReader(self.pcap_file) as reader:
for pkt in reader:
if pkt.haslayer(IP) and pkt.haslayer(TCP):
if pkt[TCP].flags == 'S':
syn_sources[pkt[IP].src] += 1
for ip, count in syn_sources.items():
if count > threshold:
self.results['port_scans'].append({
'source': ip, 'syn_count': count
})
print(f" 端口扫描: {len(self.results['port_scans'])} 个")
def detect_dns_tunnels(self, max_label_len=40):
"""DNS隧道检测"""
with PcapReader(self.pcap_file) as reader:
for pkt in reader:
if pkt.haslayer(DNS) and pkt.haslayer(DNSQR):
query = pkt[DNSQR].qname.decode().rstrip('.')
labels = query.split('.')
for label in labels:
if len(label) > max_label_len:
self.results['dns_tunnels'].append({
'source': pkt[IP].src,
'query': query,
'label_length': len(label)
})
print(f" DNS隧道: {len(self.results['dns_tunnels'])} 个")
def detect_beacons(self, min_conn=10, max_jitter=0.3):
"""Beacon行为检测"""
connections = defaultdict(list)
with PcapReader(self.pcap_file) as reader:
for pkt in reader:
if pkt.haslayer(IP) and pkt.haslayer(TCP):
key = f"{pkt[IP].src}->{pkt[IP].dst}:{pkt[TCP].dport}"
connections[key].append(float(pkt.time))
import math
for key, times in connections.items():
if len(times) < min_conn:
continue
times.sort()
intervals = [times[i+1]-times[i] for i in range(len(times)-1)]
avg = sum(intervals)/len(intervals)
if avg == 0:
continue
std = math.sqrt(sum((x-avg)**2 for x in intervals)/len(intervals))
jitter = std/avg
if jitter < max_jitter:
self.results['beacons'].append({
'connection': key,
'count': len(times),
'avg_interval': round(avg, 2),
'jitter': round(jitter, 3)
})
print(f" Beacon行为: {len(self.results['beacons'])} 个")
def detect_malicious_http(self):
"""恶意HTTP检测"""
import re
patterns = [
(r'union\s+select', 'SQLi'),
(r'<script', 'XSS'),
(r'/bin/sh', 'CmdInjection'),
(r'\.\./', 'DirTraversal'),
]
with PcapReader(self.pcap_file) as reader:
for pkt in reader:
if not (pkt.haslayer(Raw) and pkt.haslayer(TCP)):
continue
payload = pkt[Raw].load.decode('utf-8', errors='ignore')
for pattern, atk_type in patterns:
if re.search(pattern, payload, re.IGNORECASE):
self.results['malicious_http'].append({
'type': atk_type,
'source': pkt[IP].src,
'payload': payload[:200]
})
print(f" 恶意HTTP: {len(self.results['malicious_http'])} 个")
def detect_data_exfiltration(self, threshold=100000):
"""数据外泄检测"""
bytes_sent = defaultdict(int)
with PcapReader(self.pcap_file) as reader:
for pkt in reader:
if pkt.haslayer(IP):
bytes_sent[pkt[IP].src] += len(pkt)
for ip, total in bytes_sent.items():
if total > threshold:
self.results['data_exfiltration'].append({
'source': ip, 'bytes': total
})
print(f" 数据外泄: {len(self.results['data_exfiltration'])} 个")
def extract_credentials(self):
"""凭据提取"""
import re
cred_patterns = [
(r'Authorization:\s*Basic\s+(\S+)', 'HTTP Basic'),
(r'USER\s+(\S+)', 'FTP User'),
(r'PASS\s+(\S+)', 'FTP Pass'),
(r'Cookie:\s*(\S+)', 'Cookie'),
]
with PcapReader(self.pcap_file) as reader:
for pkt in reader:
if not pkt.haslayer(Raw):
continue
payload = pkt[Raw].load.decode('utf-8', errors='ignore')
for pattern, cred_type in cred_patterns:
match = re.search(pattern, payload, re.IGNORECASE)
if match:
self.results['credentials'].append({
'type': cred_type,
'value': match.group(1)[:100]
})
print(f" 凭据: {len(self.results['credentials'])} 个")
def to_json(self):
"""输出JSON报告"""
return json.dumps(self.results, indent=2, ensure_ascii=False)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="综合流量分析工具")
parser.add_argument("pcap", help="PCAP文件路径")
parser.add_argument("-o", "--output", help="JSON报告输出路径")
args = parser.parse_args()
analyzer = ComprehensiveAnalyzer(args.pcap)
results = analyzer.run_all()
report = analyzer.to_json()
if args.output:
with open(args.output, 'w', encoding='utf-8') as f:
f.write(report)
print(f"\n[*] 报告已保存: {args.output}")
else:
print("\n" + report)
14. 企业级流量监控方案
14.1 全流量监控架构
企业级流量监控需要从采集、存储、分析到告警响应的完整体系。
| 架构层 | 功能 | 组件选型 | 关键指标 |
|---|---|---|---|
| 采集层 | 流量获取 | SPAN镜像/网络TAP/NetFlow/sFlow | 覆盖率/丢包率 |
| 存储层 | 数据保存 | PCAP存储/日志存储/索引 | 容量/查询速度 |
| 分析层 | 检测分析 | Suricata/Zeek/自定义脚本 | 检测率/延迟 |
| 告警层 | 告警生成 | SIEM/邮件/IM/工单 | 响应时间 |
| 响应层 | 处置响应 | 阻断/隔离/取证 | MTTR |
14.2 NetFlow/sFlow/IPFIX
| 技术 | 原理 | 优势 | 适用场景 |
|---|---|---|---|
| NetFlow | Cisco协议,记录流摘要 | 低开销/摘要信息 | 路由器流量统计 |
| sFlow | 采样流统计 | 多厂商支持/低开销 | 交换机流量监控 |
| IPFIX | NetFlow标准化版本 | 标准化/可扩展 | 跨厂商统一采集 |
NetFlow采集配置示例:
bash
# 路由器端配置(Cisco示例)
flow exporter FLOW_EXPORTER
destination 10.0.0.100
source Loopback0
transport udp 2055
template data timeout 60
flow monitor FLOW_MONITOR
record netflow ipv5 original-input
exporter FLOW_EXPORTER
cache timeout active 60
cache timeout inactive 15
# 采集端(nfcapd/nfdump)
nfcapd -l 10.0.0.100 -p 2055 -D
# 分析NetFlow数据
nfdump -R /var/log/nfcapd/ -s srcip -n 20
nfdump -r /var/log/nfcapd/nfcapd.202608261200 -s ip
14.3 SPAN/Mirror端口配置
text
# Cisco交换机SPAN配置
monitor session 1 source interface Gi0/1 both
monitor session 1 destination interface Gi0/24
# 华为交换机镜像配置
observe-port 1 interface GigabitEthernet0/0/24
port-mirroring observe-port 1
# 网络TAP(硬件分流器)
# - 主动TAP:需要供电,不丢包
# - 被动TAP:无需供电,可能丢包
# - 适用场景:核心链路/全流量监控
14.4 流量探针部署
| 部署位置 | 监控范围 | 探针类型 | 典型场景 |
|---|---|---|---|
| 互联网出口 | 出入站流量 | 全流量+NetFlow | 外泄/C2检测 |
| 数据中心核心 | 东西向流量 | 全流量 | 横向移动检测 |
| DMZ边界 | DMZ出入站 | 全流量+IDS | Web攻击检测 |
| 办公网核心 | 办公流量 | NetFlow | 异常行为检测 |
| 分支机构 | 分支流量 | NetFlow | 远程办公监控 |
14.5 全流量回溯分析
PCAP存储策略:
| 存储层 | 保存时间 | 压缩率 | 用途 |
|---|---|---|---|
| 热存储 | 7天 | 无压缩 | 快速回溯 |
| 温存储 | 30天 | 轻度压缩 | 事件调查 |
| 冷存储 | 90天 | 高压缩 | 合规审计 |
| 归档 | 1年+ | 极高压缩 | 长期保存 |
bash
# 全流量存储策略(基于tcpdump轮转)
tcpdump -i eth0 -w /data/pcap/capture_%Y%m%d_%H%M.pcap \
-G 3600 -C 1000 -W 48 -U
# 定期清理旧文件(保留90天)
find /data/pcap/ -name "*.pcap" -mtime +90 -delete
# 压缩归档旧PCAP
find /data/pcap/ -name "*.pcap" -mtime +7 -exec gzip {} \;
14.6 SIEM集成与告警联动
text
# Suricata EVE JSON → SIEM
# Filebeat采集Suricata告警
filebeat.inputs:
- type: log
paths:
- /var/log/suricata/eve.json
json.keys_under_root: true
json.add_error_key: true
# 告警分级
# P1(严重):C2通信/数据外泄 → 电话+短信+工单
# P2(高):Web攻击/扫描 → 短信+工单
# P3(中):异常行为 → 工单
# P4(低):信息告警 → 日志记录
# 自动响应(SOAR联动)
# 1. 告警触发 → SIEM推送
# 2. 自动研判 → 关联威胁情报
# 3. 自动处置 → 防火墙封锁IP
# 4. 工单派发 → 安全团队跟进
14.7 完整企业级方案
text
1. 网络规划 → 确定监控关键节点
2. 流量采集 → SPAN/TAP/NetFlow
3. 探针部署 → 全流量+摘要双模式
4. IDS部署 → Suricata/Snort旁路
5. Zeek部署 → 行为分析日志
6. 全流量存储 → PCAP分层保留
7. SIEM集成 → 告警集中管理
8. SOAR联动 → 自动响应
9. 可视化看板 → Kibana/Grafana
10. 持续运营 → 规则更新/威胁狩猎
15. 靶场实战:完整流量分析链
15.1 靶场环境搭建
docker
# docker-compose.yml - 流量分析靶场
version: '3'
services:
# 被攻击靶机
victim:
image: webgoat/goatandwolf:v2023.8
ports:
- "8080:8080"
- "9001:9001"
networks:
analysis_net:
ipv4_address: 10.0.0.10
# C2服务器
c2-server:
image: h4ck3rt3ch/c2-server:latest
ports:
- "443:443"
- "50050:50050"
networks:
analysis_net:
ipv4_address: 10.0.0.20
# Suricata IDS
suricata:
image: jasonish/suricata:latest
cap_add:
- NET_ADMIN
network_mode: host
volumes:
- ./suricata/rules:/etc/suricata/rules
- ./suricata/logs:/var/log/suricata
command: suricata -i eth0 -c /etc/suricata/suricata.yaml
# Zeek
zeek:
image: zeek/zeek:latest
cap_add:
- NET_ADMIN
network_mode: host
volumes:
- ./zeek/logs:/usr/local/zeek/logs
command: zeek -i eth0 local
# Elasticsearch
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.10.0
environment:
- discovery.type=single-node
ports:
- "9200:9200"
# Kibana
kibana:
image: docker.elastic.co/kibana/kibana:8.10.0
ports:
- "5601:5601"
depends_on:
- elasticsearch
networks:
analysis_net:
driver: bridge
ipam:
config:
- subnet: 10.0.0.0/24
15.2 PCAP样本集
公开PCAP样本资源用于练习:
| 样本集 | 来源 | 特征 | 练习目标 |
|---|---|---|---|
| Malware Traffic Exchange | malware-traffic-analysis.net | 真实恶意流量 | 恶意流量识别 |
| PCAP Files for Testing | wiki.wireshark.org | 各类协议样本 | 协议分析 |
| Stratosphere IPS | stratosphereips.org | APT/恶意通信 | C2检测 |
| MalShare | malshare.com | 恶意文件+流量 | 文件提取 |
| CICIDS2017 | unb.ca | 标注攻击流量 | IDS规则验证 |
15.3 从抓包到威胁发现的完整流程
以下是在靶场中模拟的完整攻击链与对应流量分析步骤。
text
攻击链模拟:
1. 攻击者(10.0.0.5) → SYN扫描靶机(10.0.0.10)开放端口
2. 攻击者 → HTTP扫描Web应用漏洞
3. 攻击者 → SQL注入获取数据
4. 攻击者 → 上传Webshell
5. Webshell → 反弹Shell到C2(10.0.0.20)
6. C2 → Beacon心跳维持连接
7. 攻击者 → 通过C2横向扫描内网
8. 攻击者 → 数据外泄到C2
15.4 逐步演示
步骤1:基础抓包
bash
# 启动tcpdump抓包
tcpdump -i eth0 -w attack_chain.pcap -G 3600 not port 22
# 实时监控
tcpdump -i eth0 -nn port 80 or port 443
步骤2:协议分析
bash
# 协议概览
tshark -r attack_chain.pcap -z io,phs
# 会话统计
tshark -r attack_chain.pcap -z conv,ip
# 按IP统计
tshark -r attack_chain.pcap -T fields -e ip.src -e ip.dst | \
sort | uniq -c | sort -rn
步骤3:恶意识别
bash
# SYN扫描检测
tshark -r attack_chain.pcap -Y "tcp.flags.syn==1 && tcp.flags.ack==0" \
-T fields -e ip.src | sort | uniq -c | sort -rn
# SQL注入检测
tshark -r attack_chain.pcap -Y 'http.request.uri contains "UNION"' \
-T fields -e ip.src -e http.request.uri
# Webshell上传检测
tshark -r attack_chain.pcap -Y 'http.request.method==POST && http.request.uri contains "upload"' \
-T fields -e ip.src -e ip.dst -e http.request.uri
步骤4:IDS告警
bash
# 启动Suricata
suricata -c /etc/suricata/suricata.yaml -r attack_chain.pcap \
-l /var/log/suricata/
# 查看告警
cat /var/log/suricata/fast.log
# 提取告警JSON
cat /var/log/suricata/eve.json | jq 'select(.event_type=="alert")'
步骤5:取证提取
bash
# 提取Webshell文件
tshark -r attack_chain.pcap --export-objects http,./extracted_files/
# 提取凭据
tshark -r attack_chain.pcap -Y "http.authorization" \
-T fields -e http.authorization | while read auth; do \
echo "$auth" | sed 's/Basic //' | base64 -d; echo; done
# 提取C2通信内容
tshark -r attack_chain.pcap -Y "tcp.stream eq 5" -z follow,tcp,ascii,0
步骤6:加密分析
bash
# 提取TLS SNI
tshark -r attack_chain.pcap -Y "tls.handshake.extensions_server_name" \
-T fields -e ip.src -e ip.dst -e tls.handshake.extensions_server_name | sort -u
# JA3指纹提取
tshark -r attack_chain.pcap -Y "tls.handshake.type==1" \
-T fields -e ip.src -e tls.handshake.ciphersuite
# 证书分析
tshark -r attack_chain.pcap -Y "tls.handshake.certificate" \
-T fields -e x509sat.printableString
步骤7:自动化检测
bash
# 运行综合分析脚本
python3 comprehensive_analyzer.py attack_chain.pcap -o report.json
# 查看JSON报告
cat report.json | python3 -m json.tool
步骤8:可视化看板
bash
# 导入Zeek日志到ELK
zeek -r attack_chain.pcap local
filebeat -c filebeat.yml # 采集Zeek日志
# Kibana查看
# 访问 http://localhost:5601
# 创建Discover视图
# 创建Dashboard看板
步骤9:企业级方案验证
text
验证清单:
□ 全流量采集覆盖率 > 95%
□ IDS规则检出率 > 90%
□ 告警延迟 < 5分钟
□ PCAP回溯能力 > 30天
□ 自动响应联动正常
□ 可视化看板数据准确
16. 总结与参考资源
16.1 流量分析检查清单
| 检查项 | 具体内容 | 工具 |
|---|---|---|
| 协议概览 | Protocol Hierarchy无异常协议 | Wireshark/tshark |
| 流量统计 | 无异常流量突增 | IO Graph |
| 主机通信 | 无未知异常通信对 | Conversations |
| DNS分析 | 无超长子域名/高频查询 | dns.log |
| HTTP分析 | 无攻击载荷/异常UA | http.log |
| TLS分析 | 无异常SNI/自签名证书 | ssl.log |
| 端口扫描 | 无大量SYN包 | conn.log |
| 数据外泄 | 无异常大量出站 | 字节统计 |
| 凭据泄露 | 无明文传输凭据 | dsniff/tshark |
| 文件传输 | 无可疑可执行文件下载 | files.log |
| IDS告警 | 无未处理告警 | Suricata EVE |
| 威胁情报 | 无已知恶意IP/域名 | IOC匹配 |
16.2 Wireshark过滤器速查表
| 分析场景 | 显示过滤器 |
|---|---|
| HTTP请求 | http.request |
| HTTP POST | http.request.method == "POST" |
| HTTP错误 | http.response.code >= 400 |
| HTTP认证 | http.authorization |
| HTTP Cookie | http.cookie |
| TLS握手 | tls.handshake |
| TLS SNI | tls.handshake.extensions_server_name |
| TLS证书 | tls.handshake.certificate |
| DNS查询 | dns.qry.name |
| DNS TXT | dns.qry.type == 16 |
| SYN包 | tcp.flags.syn == 1 && tcp.flags.ack == 0 |
| RST包 | tcp.flags.reset == 1 |
| ICMP | icmp |
| SMB | smb2 || smb |
| 包含字符串 | frame contains "keyword" |
| 正则匹配 | http.request.uri matches "pattern" |
| TCP重传 | tcp.analysis.retransmission |
16.3 tcpdump命令速查表
| 分析场景 | 命令 |
|---|---|
| 基本抓包 | tcpdump -i eth0 -nn |
| 写入PCAP | tcpdump -i eth0 -w out.pcap |
| 指定端口 | tcpdump -i eth0 port 80 |
| 指定主机 | tcpdump -i eth0 host 10.0.0.1 |
| 排除端口 | tcpdump -i eth0 not port 22 |
| 组合过滤 | tcpdump -i eth0 'src host 10.0.0.1 and dst port 80' |
| SYN包 | tcpdump 'tcptcpflags & tcp-syn != 0' |
| 显示内容 | tcpdump -i eth0 -A port 80 |
| 十六进制 | tcpdump -i eth0 -X port 80 |
| 轮转存储 | tcpdump -i eth0 -w out.pcap -C 100 -W 5 -G 3600 |
| 读取PCAP | tcpdump -r out.pcap -nn |
16.4 Snort/Suricata规则速查表
| 检测场景 | 规则关键字 |
|---|---|
| 内容匹配 | content:"pattern"; |
| 不区分大小写 | nocase; |
| 正则匹配 | pcre:"/pattern/i"; |
| 距离限制 | distance:0; within:10; |
| HTTP URI | http.uri; content:"path"; |
| HTTP UA | http.user_agent; content:"sqlmap"; |
| HTTP方法 | http.method; content:"POST"; |
| TLS SNI | tls.handshake.extensions_server_name; |
| JA3指纹 | ja3.hash; content:"hash"; |
| 文件扩展名 | fileext:exe; |
| 流方向 | flow:to_server,established; |
| 包大小 | dsize:>100; |
| 频率检测 | detection_filter:track by_src, count 5, seconds 30; |
| 阈值控制 | threshold:type both, track by_src, count 10, seconds 60; |
16.5 Zeek日志速查表
| 分析场景 | 日志文件 | 关键字段 |
|---|---|---|
| 连接分析 | conn.log | id.orig_h/id.resp_h/id.resp_p/conn_state |
| DNS分析 | dns.log | query/qtype_name/answers |
| HTTP分析 | http.log | method/uri/user_agent/status_code |
| TLS分析 | ssl.log | server_name/version/cipher |
| 文件分析 | files.log | source/mime_type/sha1 |
| 证书分析 | x509.log | certificate_subject/issuer |
| 异常检测 | weird.log | name/addl |
| 告警 | notice.log | note/msg/sub |
| SSH分析 | ssh.log | version/auth_success |
| SMB文件 | smb_files.log | name/size/action |
16.6 参考资源
| 资源类型 | 名称 | 链接 |
|---|---|---|
| 工具文档 | Wireshark用户指南 | wireshark.org/docs |
| 工具文档 | tcpdump手册 | tcpdump.org/manpages |
| IDS文档 | Snort规则手册 | snort.org/documents |
| IDS文档 | Suricata用户指南 | suricata.readthedocs.io |
| IDS文档 | Zeek文档 | docs.zeek.org |
| 流量样本 | Malware Traffic Analysis | malware-traffic-analysis.net |
| 流量样本 | Wireshark Sample Captures | wiki.wireshark.org/SampleCaptures |
| 流量样本 | Stratosphere IPS | stratosphereips.org |
| 指纹库 | JA3指纹库 | ja3er.com |
| 指纹库 | JA4项目 | github.com/FoxIO-LLC/ja4 |
| 规则集 | ET Open Rules | rules.emergingthreats.net |
| 规则集 | Snort Community Rules | snort.org/rules |
| 可视化 | Arkime项目 | arkime.com |
| 可视化 | RITA项目 | github.com/activecm/rita |
| 可视化 | Malcolm平台 | github.com/cisagov/Malcolm |
| 学习 | 网络流量分析实战 | 书籍 |
| 学习 | Wireshark网络分析 | 书籍 |
【提示】 本文所有技术内容仅用于授权渗透测试、安全学习和合规防御研究。未经授权对任何网络进行抓包、监听或入侵检测部署均属违法行为,作者及平台不承担任何法律责任。请确保在获得书面授权后开展所有测试活动,并严格遵守《网络安全法》《数据安全法》《个人信息保护法》等法律法规。文中涉及的 Wireshark、tcpdump、Snort、Suricata、Zeek、Scapy 等工具均为公开开源工具,请仅在自建靶场或授权环境中使用。

