网络流量分析是安全运维和故障排查的核心技能。通过抓包工具捕获和分析网络数据包,可以发现异常通信、诊断网络问题、检测恶意行为和验证安全策略。本文将深入讲解 tcpdump 和 Wireshark 两款最重要的抓包分析工具的使用方法,并通过实战场景演示流量分析技巧。
网络抓包原理
混杂模式(Promiscuous Mode)
网络接口默认只接收目标为自身 MAC 地址的数据帧。开启混杂模式后,网卡会接收经过接口的所有数据帧,这是网络抓包的基础。在交换网络中,通常需要配合端口镜像(Port Mirroring / SPAN)才能捕获其他主机的流量。
# 手动开启混杂模式
sudo ip link set eth0 promisc on
# 查看接口是否处于混杂模式
ip link show eth0 | grep PROMISC
BPF 过滤器(Berkeley Packet Filter)
BPF 是 BSD 系统引入的内核级包过滤机制。tcpdump 和 Wireshark 的捕获过滤器都基于 BPF 语法。BPF 在内核层面进行过滤,只将匹配的数据包复制到用户空间,大幅减少了性能开销。
BPF 过滤表达式由**原语(Primitives)**组合而成,支持逻辑运算符 and(&&)、or(||)、not(!)。
tcpdump 常用命令与过滤表达式
tcpdump 是 Linux/Unix 环境下最经典的命令行抓包工具,几乎所有服务器都预装了它。
基础命令
# 监听指定接口(默认只显示摘要)
sudo tcpdump -i eth0
# 指定接口,显示详细信息(-v 详细,-vv 更详细)
sudo tcpdump -i eth0 -vv
# 不解析主机名和端口名(提高速度)
sudo tcpdump -i eth0 -nn
# 显示数据包的十六进制和 ASCII 内容
sudo tcpdump -i eth0 -XX
# 限制捕获数量
sudo tcpdump -i eth0 -c 100
# 保存为 pcap 文件
sudo tcpdump -i eth0 -w capture.pcap
# 读取 pcap 文件
sudo tcpdump -r capture.pcap
# 旋转保存文件(每100MB一个文件,最多10个文件)
sudo tcpdump -i eth0 -w capture_%Y%m%d_%H%M%S.pcap -C 100 -W 10
# 设置抓包缓冲区大小(高流量环境防丢包)
sudo tcpdump -i eth0 -B 4096 -w capture.pcap
IP 地址和网段过滤
# 捕获源IP为指定地址的流量
sudo tcpdump -i eth0 -nn src host 192.168.1.100
# 捕获目的IP为指定地址的流量
sudo tcpdump -i eth0 -nn dst host 10.0.0.1
# 捕获与指定IP相关的所有流量(源或目的)
sudo tcpdump -i eth0 -nn host 192.168.1.100
# 捕获指定网段的流量
sudo tcpdump -i eth0 -nn net 192.168.1.0/24
# 捕获两个主机之间的流量
sudo tcpdump -i eth0 -nn host 192.168.1.100 and host 10.0.0.1
# 排除特定IP
sudo tcpdump -i eth0 -nn not host 192.168.1.1
端口过滤
# 捕获指定端口的流量
sudo tcpdump -i eth0 -nn port 80
# 捕获端口范围
sudo tcpdump -i eth0 -nn portrange 8000-9000
# 捕获源端口为22的流量
sudo tcpdump -i eth0 -nn src port 22
# 捕获多个端口
sudo tcpdump -i eth0 -nn port 80 or port 443 or port 8080
# 捕获非SSH流量(排除SSH避免干扰)
sudo tcpdump -i eth0 -nn not port 22
协议过滤
# 仅捕获 TCP 流量
sudo tcpdump -i eth0 -nn tcp
# 仅捕获 UDP 流量
sudo tcpdump -i eth0 -nn udp
# 仅捕获 ICMP 流量
sudo tcpdump -i eth0 -nn icmp
# 仅捕获 ARP 流量
sudo tcpdump -i eth0 -nn arp
# 捕获 DNS 查询(UDP 53端口)
sudo tcpdump -i eth0 -nn udp port 53
# 捕获 DHCP 流量
sudo tcpdump -i eth0 -nn port 67 or port 68
TCP 标志位过滤
# 捕获 SYN 包(连接发起)
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0'
# 仅捕获 SYN 包(不含 SYN-ACK)
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] == tcp-syn'
# 捕获 SYN-ACK 包
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] == (tcp-syn|tcp-ack)'
# 捕获 RST 包(连接异常重置)
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'
# 捕获 FIN 包(连接关闭)
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-fin != 0'
# 捕获 PSH-ACK(数据传输包)
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-push|tcp-ack) == (tcp-push|tcp-ack)'
高级组合过滤
# 捕获来自外部的 SYN 扫描(大量 SYN 但无 ACK)
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] == tcp-syn and not src net 192.168.1.0/24'
# 捕获 HTTP GET 请求
sudo tcpdump -i eth0 -nn -A 'tcp dst port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
# 捕获包含特定内容的数据包
sudo tcpdump -i eth0 -nn -A 'tcp port 80' | grep -i "password"
# 捕获大于1000字节的数据包
sudo tcpdump -i eth0 -nn 'greater 1000'
# 捕获分片数据包(可能的攻击指标)
sudo tcpdump -i eth0 -nn 'ip[6:2] & 0x3fff != 0'
Wireshark 过滤器详解
Wireshark 是最强大的图形化抓包分析工具,支持两种不同的过滤器。
捕获过滤器(Capture Filter)
在捕获前设置,使用 BPF 语法,作用于内核层面。与 tcpdump 语法完全相同。
# 常用捕获过滤器示例
host 192.168.1.100
port 80 or port 443
tcp and not port 22
src net 10.0.0.0/8
icmp
显示过滤器(Display Filter)
在捕获后对已抓取的数据包进行过滤显示,语法更丰富、更强大。
# IP 地址过滤
ip.addr == 192.168.1.100
ip.src == 10.0.0.1
ip.dst == 172.16.0.0/16
ip.addr == 192.168.1.100 && ip.addr == 10.0.0.1
# 端口过滤
tcp.port == 80
tcp.dstport == 443
tcp.srcport == 22
udp.port == 53
tcp.port in {80, 443, 8080, 8443}
# 协议过滤
http
dns
tls
icmp
arp
dhcp
ftp
smtp
# HTTP 协议深度过滤
http.request.method == "GET"
http.request.method == "POST"
http.request.uri contains "/admin"
http.host == "example.com"
http.response.code == 200
http.response.code >= 400
http.content_type contains "json"
http.user_agent contains "curl"
http.cookie contains "session"
# DNS 过滤
dns.qry.name == "example.com"
dns.qry.type == 1 # A 记录
dns.qry.type == 28 # AAAA 记录
dns.flags.rcode != 0 # DNS 查询失败
# TLS/SSL 过滤
tls.handshake.type == 1 # Client Hello
tls.handshake.type == 2 # Server Hello
tls.handshake.extensions_server_name == "example.com"
tls.record.version == 0x0303 # TLS 1.2
# TCP 标志位过滤
tcp.flags.syn == 1 && tcp.flags.ack == 0 # SYN 包
tcp.flags.rst == 1 # RST 包
tcp.flags.fin == 1 # FIN 包
# TCP 分析过滤
tcp.analysis.retransmission # 重传包
tcp.analysis.duplicate_ack # 重复 ACK
tcp.analysis.zero_window # 零窗口
tcp.analysis.window_full # 窗口满
# 数据包大小过滤
frame.len > 1500
tcp.len > 0
udp.length > 512
# 时间过滤
frame.time >= "2025-01-01 00:00:00" && frame.time <= "2025-01-01 23:59:59"
# 逻辑组合
(http or dns) && ip.src == 192.168.1.100
tcp.port == 80 && !(ip.src == 192.168.1.1)
实战流量分析场景
分析 TCP 三次握手
# 显示过滤器:查看特定连接的三次握手
tcp.flags.syn == 1 && ip.addr == 192.168.1.100 && tcp.port == 80
正常的三次握手过程:
- SYN:客户端 → 服务器,
Seq=0, Flags=[S] - SYN-ACK:服务器 → 客户端,
Seq=0, Ack=1, Flags=[S,A] - ACK:客户端 → 服务器,
Seq=1, Ack=1, Flags=[A]
异常情况识别:
- 大量 SYN 无 SYN-ACK 响应:可能遭受 SYN Flood 攻击
- SYN 后立即 RST:端口关闭或被防火墙拒绝
- SYN 无响应:可能被丢弃或主机不可达
分析 HTTP 流量
# tcpdump 捕获 HTTP 流量并显示内容
sudo tcpdump -i eth0 -nn -A -s0 'tcp port 80'
# 提取 HTTP 请求的 URL
sudo tcpdump -i eth0 -nn -A -s0 'tcp dst port 80' | grep -oP 'GET \K[^ ]+'
Wireshark 中分析 HTTP:
# 查看所有 HTTP 请求
http.request
# 查看包含敏感关键词的请求
http.request.uri contains "passwd" or http.request.uri contains "admin"
# 查看非200响应
http.response.code != 200
# 追踪完整 HTTP 会话:右键 → Follow → HTTP Stream
分析 DNS 查询
# tcpdump 捕获 DNS 流量
sudo tcpdump -i eth0 -nn port 53
# 提取 DNS 查询的域名
sudo tcpdump -i eth0 -nn port 53 -l | awk '/A\?/ {print $NF}'
Wireshark 显示过滤器:
# 查看所有 DNS 查询
dns.flags.response == 0
# 查看 DNS 查询失败(NXDOMAIN)
dns.flags.rcode == 3
# 查看查询特定域名
dns.qry.name contains "suspicious-domain"
# 检测 DNS 隧道(超长域名查询)
dns.qry.name.len > 50
TLS 加密流量分析
虽然 TLS 流量内容已加密,但仍可以从握手阶段获取有价值的信息:
# 查看 TLS Client Hello(获取 SNI 域名)
tls.handshake.type == 1
# 提取 SNI(Server Name Indication)
tls.handshake.extensions_server_name
# 查看使用的 TLS 版本
tls.record.version
# 查看使用的密码套件
tls.handshake.ciphersuite
# 检测弱加密套件
tls.handshake.ciphersuite == 0x002f # TLS_RSA_WITH_AES_128_CBC_SHA
# 查看证书信息
tls.handshake.type == 11 # Certificate 消息
tls.handshake.certificate
使用 SSLKEYLOGFILE 解密 TLS 流量(调试用途):
# 设置环境变量让浏览器导出会话密钥
export SSLKEYLOGFILE=~/sslkeys.log
# 在 Wireshark 中加载密钥:
# Edit → Preferences → Protocols → TLS → (Pre)-Master-Secret log filename
# 指向 ~/sslkeys.log 文件
流量异常识别方法
端口扫描检测
# tcpdump:检测 SYN 扫描特征
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] == tcp-syn' -c 1000 -w syn_scan.pcap
# Wireshark:识别端口扫描
tcp.flags.syn == 1 && tcp.flags.ack == 0 && tcp.window_size <= 1024
特征:同一源 IP 在短时间内向大量不同端口发送 SYN 包。
ARP 欺骗检测
# Wireshark 显示过滤器
arp.duplicate-address-detected
arp.opcode == 2 # ARP Reply 泛洪
特征:同一 IP 地址对应多个不同的 MAC 地址,或大量无请求的 ARP Reply。
DNS 隧道检测
# 异常长度的 DNS 查询
dns.qry.name.len > 50
# TXT 记录查询(常用于DNS隧道)
dns.qry.type == 16
# 高频 DNS 查询
dns && ip.src == 192.168.1.100
特征:异常长的域名查询、高频 TXT 记录查询、大量 NXDOMAIN 响应。
数据外泄检测
# 检测大量外发数据
sudo tcpdump -i eth0 -nn 'src net 192.168.1.0/24 and dst net not 192.168.1.0/24 and greater 1000' -c 500
# Wireshark:大数据量外发
ip.src == 192.168.1.0/24 && !ip.dst == 192.168.1.0/24 && tcp.len > 1000
实用 tcpdump 脚本
#!/bin/bash
# network_monitor.sh - 网络流量监控脚本
INTERFACE="eth0"
LOG_DIR="/var/log/network_capture"
mkdir -p "$LOG_DIR"
# 捕获可疑的 SYN 扫描
echo "[*] Monitoring SYN scans..."
sudo tcpdump -i $INTERFACE -nn 'tcp[tcpflags] == tcp-syn' \
-G 3600 -w "$LOG_DIR/syn_scan_%Y%m%d_%H%M%S.pcap" &
# 捕获 DNS 流量
echo "[*] Monitoring DNS traffic..."
sudo tcpdump -i $INTERFACE -nn port 53 \
-G 3600 -w "$LOG_DIR/dns_%Y%m%d_%H%M%S.pcap" &
# 捕获非标准端口的 HTTP 流量
echo "[*] Monitoring non-standard HTTP..."
sudo tcpdump -i $INTERFACE -nn 'tcp dst portrange 8000-9999 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420 or tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354)' \
-G 3600 -w "$LOG_DIR/http_nonstandard_%Y%m%d_%H%M%S.pcap" &
echo "[+] Monitoring started. Logs in $LOG_DIR"
wait
安全建议
- 最小化抓包范围:使用精确的 BPF 过滤器,避免全量抓包对系统性能的影响。高流量环境下全量抓包可能导致丢包。
- 保护 pcap 文件:抓包文件可能包含敏感信息(凭证、会话令牌等),必须妥善存储并控制访问权限。
- 合规合法:网络抓包在许多地区受法律约束,确保在授权范围内进行,遵守数据隐私法规。
- 定期抓包审计:在关键网络节点定期进行流量采样分析,建立正常流量基线,及时发现异常。
- 结合 IDS 使用:将 pcap 文件导入 Snort/Suricata 进行离线分析,获得更深层次的威胁检测。
- 加密流量监控:虽然无法解密 TLS 内容,但通过 JA3/JA3S 指纹、SNI 信息和流量模式仍可识别恶意通信。
- 自动化分析:使用 tshark(Wireshark 命令行版)编写自动化分析脚本,提高效率。
# tshark 示例:自动提取HTTP请求的URL
tshark -r capture.pcap -Y "http.request" -T fields -e http.host -e http.request.uri
# tshark:统计TCP会话
tshark -r capture.pcap -q -z conv,tcp
# tshark:统计HTTP响应码分布
tshark -r capture.pcap -q -z http,stat,
# tshark:提取 TLS SNI 信息
tshark -r capture.pcap -Y "tls.handshake.type == 1" -T fields -e tls.handshake.extensions_server_name
总结
网络抓包与流量分析是网络安全和运维工作中不可或缺的技能。tcpdump 以其轻量级和命令行特性适合服务器端实时捕获和快速排查,Wireshark 凭借强大的图形界面和协议解析能力适合深度分析和取证。掌握 BPF 捕获过滤器和 Wireshark 显示过滤器的语法,能够帮助你快速定位目标流量。在实际工作中,建议将两者结合使用:在服务器端用 tcpdump 捕获并保存 pcap 文件,然后在本地用 Wireshark 进行详细分析,形成完整的流量分析工作流。