tcpdump
tcpdump 是一个功能强大的命令行网络抓包工具, 广泛应用于网络故障诊断、安全审计和协议分析等场景。它基于 libpcap 库实现, 能够捕获和分析网络流量, 是网络工程师和安全研究人员必备的工具之一。
基础用法
抓包命令格式
tcpdump 的基本命令格式如下:
bash
tcpdump [选项] [表达式]常用选项
-i interface: 指定监听的网络接口, 如-i eth0, 使用-i any监听所有接口-n: 不进行 DNS 解析, 直接显示 IP 地址, 避免 DNS 查询带来的延迟-nn: 不解析主机名和端口名, 显示数字形式的地址和端口-v: 输出更详细的信息, 包括 TTL、 TOS 等-vv: 更详细的输出-c count: 捕获指定数量的数据包后退出-w file: 将抓取的包保存为 pcap 格式文件, 供后续分析-r file: 从 pcap 文件读取数据包进行离线分析-e: 显示数据链路层 (MAC) 头部信息-x: 以十六进制格式显示数据包内容-xx: 以十六进制格式显示数据包内容, 包括链路层头部-X: 同时以十六进制和 ASCII 格式显示数据包内容-XX: 同时以十六进制和 ASCII 格式显示数据包内容, 包括链路层头部
常用选项示例:
bash
# 监听 eth0 接口, 不解析 DNS
tcpdump -i eth0 -n
# 监听所有接口, 显示详细输出
tcpdump -i any -vv
# 捕获 100 个数据包后退出
tcpdump -i eth0 -c 100
# 保存为 pcap 文件
tcpdump -i eth0 -w capture.pcap
# 读取 pcap 文件
tcpdump -r capture.pcap基本表达式
tcpdump 使用 BPF (Berkeley Packet Filter) 语法, 表达式用于过滤特定的数据包。表达式可以是协议类型、主机地址、端口号等。
bash
# 抓取 TCP 包
tcpdump -i eth0 tcp
# 抓取 UDP 包
tcpdump -i eth0 udp
# 抓取 ICMP 包
tcpdump -i eth0 icmp
# 抓取特定主机的数据包
tcpdump -i eth0 host 192.168.1.100
# 抓取来源或目标是特定主机的数据包
tcpdump -i eth0 host 192.168.1.100过滤器表达式
tcpdump 的过滤器表达式是其核心功能之一, 通过组合不同的过滤条件, 可以精准地捕获所需的网络流量。
协议过滤
通过协议类型进行过滤:
bash
# 只抓 TCP 包
tcpdump -i eth0 tcp
# 只抓 UDP 包
tcpdump -i eth0 udp
# 只抓 ICMP 包
tcpdump -i eth0 icmp
# 只抓 ARP 包
tcpdump -i eth0 arp
# 只抓 IP 包
tcpdump -i eth0 ip主机过滤
通过 IP 地址进行过滤:
bash
# 抓取与特定主机相关的所有数据包
tcpdump -i eth0 host 192.168.1.100
# 抓取来自特定主机的数据包 (src)
tcpdump -i eth0 src host 192.168.1.100
# 抓取发往特定主机的数据包 (dst)
tcpdump -i eth0 dst host 192.168.1.100
# 抓取来自特定网段的数据包
tcpdump -i eth0 src net 192.168.1.0/24
# 抓取发往特定网段的数据包
tcpdump -i eth0 dst net 192.168.1.0/24端口过滤
通过端口号进行过滤:
bash
# 抓取特定端口的数据包
tcpdump -i eth0 port 80
# 抓取来源或目的端口为 80 的数据包
tcpdump -i eth0 port 80
# 抓取来源端口为 80 的数据包
tcpdump -i eth0 src port 80
# 抓取目的端口为 80 的数据包
tcpdump -i eth0 dst port 80
# 抓取端口范围内的数据包
tcpdump -i eth0 portrange 8000-9000逻辑运算符
使用逻辑运算符组合多个过滤条件:
bash
# and (或者使用 &&): 两个条件同时满足
tcpdump -i eth0 host 192.168.1.100 and port 80
tcpdump -i eth0 'host 192.168.1.100 && port 80'
# or (或者使用 ||): 任意一个条件满足
tcpdump -i eth0 tcp or udp
tcpdump -i eth0 'host 192.168.1.100 or host 192.168.1.200'
# not (或者使用 !): 条件取反
tcpdump -i eth0 not port 22
tcpdump -i eth0 '! port 22'
# 组合使用
tcpdump -i eth0 'host 192.168.1.100 and (port 80 or port 443)'
# 复杂组合
tcpdump -i eth0 'tcp and ((host 192.168.1.100 and port 80) or (host 192.168.1.200 and port 443))'常用抓包场景
抓取 HTTP 流量
bash
# 抓取 HTTP 流量 (80 端口)
tcpdump -i eth0 port 80
# 抓取 HTTP 请求头信息
tcpdump -i eth0 -nn -tttt port 80
# 抓取特定主机的 HTTP 流量
tcpdump -i eth0 -nn host 192.168.1.100 and port 80
# 抓取 HTTP 请求和响应
tcpdump -i eth0 -A 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'抓取 TCP SYN/FIN/RST 包
使用 tcpflags 过滤器抓取特殊的 TCP 控制报文:
bash
# 抓取 SYN 包 (连接建立)
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0'
# 抓取 FIN 包 (连接关闭)
tcpdump -i eth0 'tcp[tcpflags] & tcp-fin != 0'
# 抓取 RST 包 (连接重置)
tcpdump -i eth0 'tcp[tcpflags] & tcp-rst != 0'
# 抓取 SYN-ACK 包
tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0'
# 抓取所有 TCP 控制报文 (排除 ACK)
tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0'抓取特定端口数据
bash
# 抓取 SSH 连接 (22 端口)
tcpdump -i eth0 port 22
# 抓取 DNS 查询 (53 端口)
tcpdump -i eth0 port 53
# 抓取 FTP 数据 (21 端口控制, 20 端口数据)
tcpdump -i eth0 port 21
# 抓取 SMTP 邮件 (25 端口)
tcpdump -i eth0 port 25
# 抓取 MySQL 数据库 (3306 端口)
tcpdump -i eth0 port 3306
# 抓取 Redis (6379 端口)
tcpdump -i eth0 port 6379保存和读取 pcap 文件
bash
# 保存抓包结果到文件
tcpdump -i eth0 -w capture.pcap
# 保存特定条件的抓包结果
tcpdump -i eth0 -w capture.pcap host 192.168.1.100 and port 80
# 读取 pcap 文件
tcpdump -r capture.pcap
# 读取并显示详细信息
tcpdump -r capture.pcap -vv
# 读取并应用过滤器
tcpdump -r capture.pcap 'tcp port 80'
# 保存多个文件, 每个文件 100MB
tcpdump -i eth0 -W 10 -C 100 -w capture.pcap
# 按包数量轮转文件
tcpdump -i eth0 -W 5 -C 100 -w capture.pcap输出格式解析
tcpdump 的输出包含丰富的信息, 理解这些信息对于分析网络问题至关重要。
包头信息
典型的 tcpdump 输出格式:
12:34:56.789012 IP 192.168.1.100.443 > 192.168.1.200.52345: Flags [P.], seq 1:100, ack 1, win 502, length 99各字段含义:
12:34:56.789012: 时间戳 (小时:分钟:秒.微秒)IP: 网络层协议192.168.1.100.443: 源 IP 和端口>: 数据流向符号192.168.1.200.52345: 目标 IP 和端口Flags [P.]: TCP 标志位seq 1:100: TCP 序列号ack 1: 确认号win 502: 窗口大小length 99: 数据载荷长度
TCP 标志位说明
[S]: SYN - 连接建立请求[S.]: SYN-ACK - SYN 响应[P.]: PUSH - 数据推送[F]: FIN - 连接关闭请求[R]: RST - 连接重置[.]: ACK - 确认[P.] [.]: PSH-ACK 组合
时间戳含义
bash
# 默认时间戳格式
tcpdump -i eth0 port 80
# 输出: 12:34:56.789012 IP 192.168.1.100.80 > 192.168.1.200.52345: ...
# 人类可读时间戳 (-tttt)
tcpdump -i eth0 -tttt port 80
# 输出: 2024-01-15 12:34:56.789012 IP 192.168.1.100.80 > 192.168.1.200.52345: ...
# Unix 时间戳 (-t)
tcpdump -i eth0 -t port 80
# 输出: 1705312496 IP 192.168.1.100.80 > 192.168.1.200.52345: ...
# 不显示时间戳 (-t)
tcpdump -i eth0 -tt port 80
# 输出: IP 192.168.1.100.80 > 192.168.1.200.52345: ...高级用法
表达式组合
bash
# 抓取特定主机和端口组合
tcpdump -i eth0 'host 192.168.1.100 and port 80 and tcp'
# 排除特定端口
tcpdump -i eth0 'tcp and not port 22'
# 抓取特定网段但排除特定主机
tcpdump -i eth0 'net 192.168.1.0/24 and not host 192.168.1.50'
# 抓取长度大于特定值的包
tcpdump -i eth0 'ip[2:2] > 1000'
# 抓取 TCP 特定端口范围
tcpdump -i eth0 'tcp and (port 80 or port 443 or port 8080)'
# 抓取 ICMP 特定类型 (ping 请求/响应)
tcpdump -i eth0 'icmp and (icmp[0] = 8 or icmp[0] = 0)'抓取特定标志位
tcpdump 支持通过 tcpflags 关键字和偏移量来抓取 TCP 标志位:
bash
# TCP 头结构偏移量
# - tcp[0] & 0x12 提取标志位
# - 0x02 = SYN, 0x10 = ACK, 0x01 = FIN, 0x04 = RST
# 抓取 SYN 包
tcpdump -i eth0 'tcp[0] & 0x02 != 0'
# 抓取 RST 包
tcpdump -i eth0 'tcp[0] & 0x04 != 0'
# 抓取 SYN-ACK 包
tcpdump -i eth0 'tcp[0] = 0x12'
# 抓取只有 SYN 标志的包 (不含 ACK)
tcpdump -i eth0 'tcp[13] = 2'
# 抓取包含 RST 标志的包
tcpdump -i eth0 'tcp[13] & 4 != 0'
# tcpflags 关键字方式 (更易读)
tcpdump -i eth0 'tcpflags tcp-syn'
tcpdump -i eth0 'tcpflags tcp-rst'
tcpdump -i eth0 'tcpflags tcp-fin'十六进制输出
bash
# 十六进制输出 (-x)
tcpdump -i eth0 -x port 80
# 输出:
# 0x0000: 4500 0054 0011 4000 4006 1234 0a00 000f
# 0x0010: 0a00 000a c1a8 0050 8c9a 7b5a 1f8e a9cc
# 十六进制输出包含链路层 (-xx)
tcpdump -i eth0 -xx port 80
# 十六进制+ASCII 输出 (-X)
tcpdump -i eth0 -X port 80
# 输出:
# 0x0000: 4500 0054 0011 4000 4006 1234 0a00 000f E..T..@.@.......
# 0x0010: 0a00 000a c1a8 0050 8c9a 7b5a 1f8e a9cc .......P..{[....
# 十六进制+ASCII 输出包含链路层 (-XX)
tcpdump -i eth0 -XX port 80
# 完整十六进制输出查看包内容
tcpdump -i eth0 -nn -XX 'tcp port 80 and tcp[32:4] = 0x47455420'
# 0x47455420 = "GET " ASCII其他高级选项
bash
# 监听特定 VLAN 的流量
tcpdump -i eth0 vlan 100
# 监听 IPv6 流量
tcpdump -i eth0 ip6
# 显示相对序列号 (相对于 TCP 握手)
tcpdump -i eth0 -S port 80
# 打印包过滤代码
tcpdump -i eth0 -d 'tcp and port 80'
# 打印编译后的 BPF 代码
tcpdump -i eth0 -dd 'tcp and port 80'
# 设置快照长度 (snaplen)
tcpdump -i eth0 -s 100 port 80
# 不截断输出 (完整抓取)
tcpdump -i eth0 -s 0 port 80与 Wireshark 配合
tcpdump 和 Wireshark 是网络分析的双剑合璧。tcpdump 负责高效抓包, Wireshark 负责深度分析。
工作流程
bash
# 1. 在服务器或路由器上使用 tcpdump 抓包
# 优点: 资源占用少, 可远程抓包, 保存完整数据
# 抓取特定条件的包并保存
tcpdump -i eth0 -s 0 -w /tmp/capture.pcap 'host 192.168.1.100 and port 80'
# 后台持续抓取, 每小时轮转一次
tcpdump -i eth0 -s 0 -G 3600 -w /tmp/capture_%H.pcap 'tcp'
# 按文件大小轮转 (每个文件 100MB)
tcpdump -i eth0 -s 0 -C 100 -w /tmp/capture.pcap
# 2. 将 pcap 文件传输到分析主机
scp user@remote:/tmp/capture.pcap /tmp/
# 3. 使用 Wireshark 图形界面分析
wireshark /tmp/capture.pcap
# 或者使用 tshark (命令行版 Wireshark) 分析
tshark -r /tmp/capture.pcap -Y 'http' | less
# 提取 HTTP 请求
tshark -r /tmp/capture.pcap -Y 'http.request' -T fields -e http.host -e http.request.uritcpdump 与 tshark 配合
bash
# 使用 tcpdump 预处理, 再用 tshark 分析
tcpdump -i eth0 -nn -c 1000 'tcp port 80' -w - | tshark -r - -Y 'http'
# 提取特定字段
tcpdump -i eth0 -nn -c 100 'tcp port 80' -w - | tshark -r - -T fields -e ip.src -e tcp.srcport -e ip.dst -e tcp.dstport常见分析场景
bash
# 分析 TCP 连接问题
tcpdump -i eth0 -nn -tttt 'tcp port 80' > tcpdump.txt
# 然后在 Wireshark 中:
# 1. 筛选 tcp.flags.syn == 1 查看 SYN 包
# 2. 筛选 tcp.flags.reset == 1 查看 RST 包
# 3. 查看专家信息 (Expert Information)
# 分析 HTTP/HTTPS 问题
tcpdump -i eth0 -nn -A 'tcp port 80 or tcp port 443' > http.txt
# 对于 HTTPS, 需要结合私钥解密
# openssl s_client -connect site:443 -key keyfile -cert certfile性能优化
tcpdump 在高流量环境中可能丢包, 以下是一些优化建议:
bash
# 使用缓冲区
tcpdump -i eth0 -B 4096 port 80
# 选择空闲接口
tcpdump -i eth0 -p # 不进入混杂模式
# 缩短表达式
tcpdump -i eth0 -nn 'tcp port 80'
# 使用 -c 限制数量
tcpdump -i eth0 -nn -c 10000 'tcp port 80'
# 避免 DNS 解析
tcpdump -i eth0 -nn port 80
# 内核过滤 (早期过滤, 减少用户空间拷贝)
tcpdump -i eth0 -f 'tcp port 80'注意事项
- 权限: 抓包通常需要 root 权限, 或者使用
setcap授予 tcpdump 特定权限 - 磁盘空间: 长时间抓包会生成大文件, 注意监控磁盘使用
- 性能影响: 在高流量环境中抓包会影响网络性能
- 隐私: 抓包可能包含敏感信息, 确保数据安全
- 法規: 在某些场景下抓包可能涉及法律问题, 请确保合规使用
bash
# 授予 tcpdump 永久抓包权限 (谨慎使用)
sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump