Linux命令-tcpdump(网络数据包捕获)
tcpdump 是 Linux 下最强大的命令行网络抓包工具,常被称为"命令行版 Wireshark"。它能实时捕获和分析网络接口上的数据包,支持强大的 BPF(Berkeley Packet Filter)过滤表达式,是网络故障排查、安全分析和协议调试的必备工具。
快速参考
bash
tcpdump [选项] [BPF过滤表达式]
权限提示 :
tcpdump需要 root 权限或CAP_NET_RAW能力。抓取生产环境流量时,应使用-c限制包数或-w写入文件后在本地分析,避免长时间占用接口。
安装
bash
# Debian/Ubuntu
sudo apt-get install tcpdump
# RHEL/CentOS
sudo yum install tcpdump
# Fedora
sudo dnf install tcpdump
# 验证安装
which tcpdump
tcpdump --version
# 检查权限(非 root 需要 setcap)
sudo setcap cap_net_raw+ep $(which tcpdump)
基本抓包
bash
# 抓取默认接口的所有流量
sudo tcpdump
# 指定接口
sudo tcpdump -i eth0
# 列出可用接口
sudo tcpdump -D
sudo tcpdump --list-interfaces
# 限制抓包数量
sudo tcpdump -c 100 -i eth0
# 不解析主机名(加速显示)
sudo tcpdump -n -i eth0
# 不解析端口和服务名
sudo tcpdump -nn -i eth0
# 详细输出
sudo tcpdump -v -i eth0
sudo tcpdump -vv -i eth0 # 更详细
sudo tcpdump -vvv -i eth0 # 极其详细
BPF 过滤表达式
bash
# 按主机过滤
sudo tcpdump -n host 192.168.1.100
sudo tcpdump -n src host 192.168.1.100 # 源地址
sudo tcpdump -n dst host 192.168.1.100 # 目标地址
# 按端口过滤
sudo tcpdump -n port 80
sudo tcpdump -n src port 80
sudo tcpdump -n dst port 443
sudo tcpdump -n portrange 8000-9000 # 端口范围
# 按协议过滤
sudo tcpdump -n icmp
sudo tcpdump -n tcp
sudo tcpdump -n udp
sudo tcpdump -n arp
sudo tcpdump -n arp or icmp
# 逻辑组合
sudo tcpdump -n "tcp port 80 and host 192.168.1.1"
sudo tcpdump -n "tcp port 443 and host 1.2.3.4"
sudo tcpdump -n "host 10.0.0.1 and not port 22"
sudo tcpdump -n "(port 80 or port 443) and host example.com"
sudo tcpdump -n "tcp[tcpflags] & (tcp-syn) != 0" # SYN 包
sudo tcpdump -n "tcp[tcpflags] & (tcp-fin) != 0" # FIN 包
# 按网段过滤
sudo tcpdump -n net 192.168.1.0/24
sudo tcpdump -n src net 10.0.0.0/8
# 按包大小过滤
sudo tcpdump -n greater 1000 # 大于 1000 字节
sudo tcpdump -n less 100 # 小于 100 字节
输出格式
bash
# ASCII 输出(查看 HTTP 等文本协议)
sudo tcpdump -A -n -s 0 port 80
# 十六进制 + ASCII 输出
sudo tcpdump -X -n -s 0 port 80
# 仅十六进制输出
sudo tcpdump -xx -n -s 0 port 53
# 时间戳格式
sudo tcpdump -n -tt port 80 # Unix 时间戳
sudo tcpdump -n -tttt port 80 # 可读时间(含日期)
sudo tcpdump -n -T iso8601 port 80 # ISO 8601 格式
# 打印以太网头
sudo tcpdump -e -n -i eth0
# 仅打印 IP 地址和端口号
sudo tcpdump -n -t port 80 # 不打印时间戳
写入与读取文件
bash
# 抓包写入文件(可用 Wireshark 打开)
sudo tcpdump -w capture.pcap -i eth0
sudo tcpdump -w capture.pcap -c 1000 -i eth0 # 限制包数
# 读取 pcap 文件
sudo tcpdump -r capture.pcap
sudo tcpdump -r capture.pcap -n port 80 # 读取时过滤
# 从文件中按条件读取
sudo tcpdump -r capture.pcap -n "host 10.0.0.1"
sudo tcpdump -r capture.pcap -n "tcp port 443"
sudo tcpdump -r capture.pcap -A -n "tcp port 80 and http"
# 抓包同时写入文件并显示
sudo tcpdump -w capture.pcap -i eth0 -c 500
# 另一个终端:
sudo tcpdump -r capture.pcap -n
实战:HTTP 抓包分析
bash
# 抓取 HTTP 请求和响应(ASCII 模式)
sudo tcpdump -A -n -s 0 "tcp port 80 and host example.com"
# 抓取 HTTP 请求头
sudo tcpdump -A -n -s 0 "tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420"
# 0x47455420 = "GET "
# 抓取 HTTP POST 请求
sudo tcpdump -A -n -s 0 "tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354"
# 0x504f5354 = "POST"
# 抓取 DNS 查询
sudo tcpdump -n -s 0 "port 53"
# 抓取 HTTPS(只能看到加密流量)
sudo tcpdump -n "tcp port 443"
实战:网络故障排查
bash
#!/bin/bash
# 网络故障排查抓包脚本
# 用法: ./net_diag.sh [接口] [包数]
IFACE="${1:-eth0}"
COUNT="${2:-100}"
PCAP="/tmp/diag_$(date +%Y%m%d_%H%M%S).pcap"
echo "接口: $IFACE"
echo "抓包数: $COUNT"
echo "输出: $PCAP"
echo ""
# 1. 检查接口状态
echo "--- 接口状态 ---"
ip addr show "$IFACE" 2>/dev/null || ifconfig "$IFACE" 2>/dev/null
# 2. 抓取所有流量
echo ""
echo "--- 开始抓包 ($COUNT 个包) ---"
sudo tcpdump -i "$IFACE" -c "$COUNT" -n -w "$PCAP"
# 3. 分析结果
echo ""
echo "--- 抓包统计 ---"
sudo tcpdump -r "$PCAP" -n -q 2>/dev/null | \
awk '{print $3}' | sort | uniq -c | sort -rn | head -20
# 4. 检查异常
echo ""
echo "--- TCP SYN 数量 ---"
sudo tcpdump -r "$PCAP" -n "tcp[tcpflags] & (tcp-syn) != 0" 2>/dev/null | wc -l
echo ""
echo "--- 建议使用 Wireshark 打开 $PCAP 做详细分析 ---"
抓包技巧
bash
# 使用环回接口调试本地服务
sudo tcpdump -i lo -n port 8080
# 抓取 VLAN 标签
sudo tcpdump -n -i eth0 -e vlan
# 抓取特定 TCP 标志
sudo tcpdump -n "tcp[tcpflags] == tcp-syn" # 仅 SYN
sudo tcpdump -n "tcp[tcpflags] == tcp-syn-ack" # SYN+ACK
sudo tcpdump -n "tcp[tcpflags] == tcp-fin" # FIN
sudo tcpdump -n "tcp[tcpflags] == tcp-rst" # RST
sudo tcpdump -n "tcp[tcpflags] & (tcp-syn|tcp-fin) != 0" # SYN 或 FIN
# 统计各协议占比
sudo tcpdump -i eth0 -c 1000 -n | \
awk '{print toupper($NF)}' | \
grep -E 'TCP|UDP|ICMP|ARP' | sort | uniq -c | sort -rn
# 后台抓包(长时间)
sudo nohup tcpdump -i eth0 -w /tmp/capture.pcap -c 100000 &
echo $! > /tmp/tcpdump.pid
# 停止
sudo kill $(cat /tmp/tcpdump.pid)
选项速查
| 选项 | 说明 |
|---|---|
-i IFACE |
指定网络接口 |
-n |
不解析主机名 |
-nn |
不解析主机名和端口名 |
-v/-vv/-vvv |
详细输出级别 |
-c COUNT |
抓取指定数量包后退出 |
-w FILE |
写入 pcap 文件 |
-r FILE |
读取 pcap 文件 |
-A |
ASCII 格式输出 |
-X |
十六进制+ASCII 输出 |
-s SNAPLEN |
快照长度(0=全部) |
-e |
显示以太网头 |
-D |
列出可用接口 |
tcpdump是网络工程领域的"瑞士军刀"。其 BPF 过滤表达式语法虽然学习曲线较陡,但一旦掌握就能精确捕获任何你关注的流量。配合 Wireshark 做离线分析,是网络排障的标准工作流程。