网络安全 | tcpdump使用详解

关注CodingTechWork

tcpdump 简介

什么是 tcpdump

tcpdump 是 Linux/Unix 系统下最强大的网络抓包工具,它能够捕获和分析网络中传输的数据包。作为命令行版的 Wireshark,tcpdump 轻量、灵活、功能强大,是网络工程师、运维人员和开发人员排查网络问题的必备工具。

核心功能

功能 说明
数据包捕获 实时捕获经过网络接口的数据包
过滤规则 支持丰富的过滤表达式,精准定位目标包
协议解析 自动解析 TCP、UDP、ICMP、ARP 等协议
保存与读取 支持将捕获结果保存为 pcap 文件,离线分析
格式输出 支持多种输出格式,可与其他工具配合使用

工作原理

tcpdump 使用 libpcap 库,通过 BPF(Berkeley Packet Filter) 在内核态进行数据包过滤,只将匹配规则的数据包传递给用户态,极大地提高了效率。

安装与基础命令

安装方法

bash 复制代码
# CentOS / RHEL
yum install -y tcpdump

# Ubuntu / Debian
apt-get install -y tcpdump

# Alpine Linux
apk add tcpdump

# macOS(已预装)
# 或使用 brew 升级
brew install tcpdump

权限要求

tcpdump 需要 root 权限才能抓包:

bash 复制代码
# 使用 sudo
sudo tcpdump

# 或者切换到 root
su - root
tcpdump

基础命令格式

bash 复制代码
tcpdump [选项] [过滤表达式]

命令行参数详解

核心参数一览

参数 说明 示例
-i 指定网络接口 -i eth0
-c 捕获指定数量的包后退出 -c 100
-n 不解析主机名(显示 IP) -n
-nn 不解析主机名和端口名 -nn
-s 设置抓包长度(snaplen) -s 1500
-v/-vv/-vvv 详细输出级别 -vv
-w 写入文件 -w capture.pcap
-r 从文件读取 -r capture.pcap
-e 显示链路层头部 -e
-X 以十六进制和 ASCII 显示 -X
-A 以 ASCII 显示 -A
-t 不显示时间戳 -t
-tt 显示 Unix 时间戳 -tt
-D 列出可用网络接口 -D
-q 安静模式(简洁输出) -q
-G 按时间滚动文件 -G 3600
-C 按大小滚动文件 -C 100
-W 限制滚动文件数量 -W 10

参数详细说明

接口选择 -i

bash 复制代码
# 查看所有可用接口
tcpdump -D

# 输出示例:
# 1.eth0
# 2.lo
# 3.docker0

# 指定接口抓包
tcpdump -i eth0

# 抓取所有接口(需要特定支持)
tcpdump -i any

数量控制 -c

bash 复制代码
# 只抓 100 个包
tcpdump -c 100 -i eth0

# 抓取 1000 个包后自动退出
tcpdump -c 1000 -w capture.pcap

名称解析 -n / -nn

bash 复制代码
# 不解析主机名(显示 IP)
tcpdump -n

# 输出对比:
# 不加 -n: 192.168.1.100 -> server.example.com
# 加 -n:   192.168.1.100 -> 10.0.0.1

# 不解析主机名和端口名
tcpdump -nn

# 输出对比:
# 不加 -nn: 192.168.1.100.443 -> 10.0.0.1.8080
# 加 -nn:  192.168.1.100.80 -> 10.0.0.1.3306

抓包长度 -s

bash 复制代码
# 默认抓取 262144 字节
# 设置抓取前 100 字节
tcpdump -s 100

# 抓取完整数据包
tcpdump -s 0

# 通常设置为 MTU 大小
tcpdump -s 1500

输出格式 -X / -A / -xx

bash 复制代码
# 十六进制 + ASCII 输出
tcpdump -X -c 10

# 只输出 ASCII
tcpdump -A -c 10

# 十六进制输出(包含链路层)
tcpdump -xx -c 10

高级参数

bash 复制代码
# 限制抓包时间
timeout 30 tcpdump -i eth0

# 环形缓冲区:每 100MB 滚动,保留 5 个文件
tcpdump -G 3600 -C 100 -W 5 -w capture_%Y%m%d_%H%M%S.pcap

# 缓冲区大小(减少丢包)
tcpdump -B 4096

# 不进入混杂模式
tcpdump -p

# 监听模式下不输出任何信息
tcpdump -l

过滤表达式详解

类型过滤

类型 关键字 示例 说明
主机 host host 192.168.1.100 指定 IP 地址
网络 net net 192.168.1.0/24 指定网段
端口 port port 80 指定端口
端口范围 portrange portrange 8000-9000 端口范围

方向过滤

方向 关键字 示例 说明
源地址 src src host 192.168.1.100 源 IP
目标地址 dst dst host 192.168.1.100 目标 IP
源端口 src port src port 8080 源端口
目标端口 dst port dst port 443 目标端口

协议过滤

协议 关键字 示例
TCP tcp tcp
UDP udp udp
ICMP icmp icmp
ARP arp arp
HTTP tcp port 80 tcp port 80
HTTPS tcp port 443 tcp port 443
DNS udp port 53 udp port 53

逻辑运算符

运算符 符号 英文 示例
&& and host 192.168.1.100 and port 80
` `
! not not port 22

TCP 标志位过滤

标志位 过滤表达式 说明
SYN tcp[tcpflags] & tcp-syn != 0 同步包
ACK tcp[tcpflags] & tcp-ack != 0 确认包
FIN tcp[tcpflags] & tcp-fin != 0 结束包
RST tcp[tcpflags] & tcp-rst != 0 重置包
PSH tcp[tcpflags] & tcp-push != 0 推送包
SYN-ACK `tcp[tcpflags] & (tcp-syn tcp-ack) == (tcp-syn

数据包内容过滤

bash 复制代码
# 过滤包含特定字符串的包
tcpdump -A -s 0 | grep "GET /"

# 使用 BPF 过滤 HTTP GET 请求
tcpdump 'tcp[20:4] = 0x47455420'

# 过滤指定长度的包
tcpdump 'greater 1000'

# 过滤指定范围的数据包
tcpdump 'less 64'

输出格式详解

标准输出格式

复制代码
12:34:56.789012 IP 192.168.1.100.54321 > 10.0.0.1.80: Flags [S], seq 123456789, win 65535, length 0

字段说明

字段 说明
12:34:56.789012 时间戳(时:分:秒.微秒)
IP 网络层协议(IP / IPv6 / ARP)
192.168.1.100.54321 源地址.源端口
> 方向标识
10.0.0.1.80 目标地址.目标端口
Flags [S] TCP 标志位(S=SYN, .=ACK, F=FIN, R=RST, P=PSH)
seq 123456789 序列号
ack 987654321 确认号(有 ACK 标志时)
win 65535 窗口大小
length 0 数据长度

TCP 标志位表示

标志 显示 含义
SYN [S] 建立连接
SYN-ACK [S.] 响应 SYN
ACK [.] 确认
FIN [F] 关闭连接
FIN-ACK [F.] 关闭确认
RST [R] 连接重置
PSH [P] 推送数据

不同协议的输出格式

TCP 包

复制代码
12:34:56.789012 IP 192.168.1.100.54321 > 10.0.0.1.80: Flags [S], seq 123456789, win 65535, options [mss 1460], length 0

UDP 包

复制代码
12:34:56.789012 IP 192.168.1.100.54321 > 10.0.0.1.53: UDP, length 48

ICMP 包(ping)

复制代码
12:34:56.789012 IP 192.168.1.100 > 10.0.0.1: ICMP echo request, id 12345, seq 1, length 64
12:34:56.789123 IP 10.0.0.1 > 192.168.1.100: ICMP echo reply, id 12345, seq 1, length 64

ARP 包

复制代码
12:34:56.789012 ARP, Request who-has 10.0.0.1 tell 192.168.1.100, length 28

文件大小控制详解

使用 -c-s 精确控制文件大小

通过 -s 设置抓包长度,结合 -c 设置包数量,可以精确控制最终文件大小。

核心原理

复制代码
文件大小 ≈ 抓包长度(snaplen) × 包数量(c)

计算公式

bash 复制代码
# 目标文件大小 = snaplen × packet_count
# 实际文件会有少量额外开销(pcap文件头24字节、每个包头部16字节)

# 100MB = 100 × 1024 × 1024 = 104,857,600 字节
# 如果设置 snaplen = 1500 字节
# 需要的包数量 = 104857600 / 1500 ≈ 69905

# 如果设置 snaplen = 1000 字节  
# 需要的包数量 = 104857600 / 1000 = 104857

基本命令

bash 复制代码
# 设置 snaplen=1500,抓取 70000 个包,文件约 100MB
tcpdump -i eth0 -s 1500 -c 70000 -w capture.pcap

# 设置 snaplen=1000,抓取 105000 个包,文件约 100MB  
tcpdump -i eth0 -s 1000 -c 105000 -w capture.pcap

# 设置 snaplen=500,抓取 210000 个包,文件约 100MB
tcpdump -i eth0 -s 500 -c 210000 -w capture.pcap

不同 snaplen 的包数量参考表

目标大小 snaplen 包数量 实际大小(约) 适用场景
100MB 1500 69,900 100.6MB 完整以太网帧
100MB 1000 104,800 100.3MB 一般应用数据
100MB 800 131,000 100.2MB 节省空间
100MB 500 209,700 100.1MB 只抓头部
100MB 200 524,200 100.0MB 最小抓包
100MB 96 1,092,200 100.0MB 只抓 IP/TCP 头

精确计算脚本

bash 复制代码
#!/bin/bash
# tcpdump_sized.sh - 通过 -s 和 -c 精确控制文件大小

INTERFACE="eth0"
TARGET_SIZE_MB=100
SNAPLEN=1500

# 计算需要的包数量(留出头部开销空间)
TARGET_BYTES=$((TARGET_SIZE_MB * 1024 * 1024))
OVERHEAD=24
PACKET_OVERHEAD=16

AVAILABLE_BYTES=$((TARGET_BYTES - OVERHEAD))
PACKET_SIZE=$((SNAPLEN + PACKET_OVERHEAD))
NEEDED_PACKETS=$((AVAILABLE_BYTES / PACKET_SIZE))

echo "目标大小: ${TARGET_SIZE_MB}MB"
echo "抓包长度(snaplen): ${SNAPLEN} 字节"
echo "每包实际占用: ${PACKET_SIZE} 字节"
echo "预估包数量: ${NEEDED_PACKETS}"

OUTPUT_FILE="capture_$(date +%Y%m%d_%H%M%S).pcap"
tcpdump -i $INTERFACE -s $SNAPLEN -c $NEEDED_PACKETS -w $OUTPUT_FILE

ACTUAL_SIZE=$(stat -c%s "$OUTPUT_FILE")
ACTUAL_SIZE_MB=$((ACTUAL_SIZE / 1024 / 1024))
echo "实际文件大小: ${ACTUAL_SIZE_MB}MB"

动态检测实际包大小方案

bash 复制代码
#!/bin/bash
# tcpdump_dynamic_sized.sh - 动态检测实际包大小

INTERFACE="eth0"
TARGET_MB=100
SAMPLE_COUNT=5000

# 先抓样本来计算平均包大小
SAMPLE_FILE="/tmp/sample.pcap"
tcpdump -i $INTERFACE -c $SAMPLE_COUNT -s 65535 -w $SAMPLE_FILE 2>/dev/null

if [ ! -f "$SAMPLE_FILE" ]; then
    echo "无流量,使用默认值"
    AVG_PACKET_SIZE=500
else
    SAMPLE_SIZE=$(stat -c%s "$SAMPLE_FILE")
    OVERHEAD=24
    PACKET_OVERHEAD=16
    
    DATA_SIZE=$((SAMPLE_SIZE - OVERHEAD - SAMPLE_COUNT * PACKET_OVERHEAD))
    if [ $DATA_SIZE -lt 0 ]; then
        DATA_SIZE=500
    fi
    AVG_PACKET_SIZE=$((DATA_SIZE / SAMPLE_COUNT))
    
    echo "平均包数据大小: ${AVG_PACKET_SIZE} 字节"
fi

# 设置 snaplen 为平均包大小
SNAPLEN=$((AVG_PACKET_SIZE + 100))
[ $SNAPLEN -gt 1500 ] && SNAPLEN=1500

TARGET_BYTES=$((TARGET_MB * 1024 * 1024))
PACKET_OVERHEAD=16
FILE_HEADER=24
PACKET_TOTAL=$((SNAPLEN + PACKET_OVERHEAD))
NEEDED_PACKETS=$(((TARGET_BYTES - FILE_HEADER) / PACKET_TOTAL))

echo "目标大小: ${TARGET_MB}MB"
echo "使用 snaplen: ${SNAPLEN} 字节"
echo "需要包数量: ${NEEDED_PACKETS}"

OUTPUT_FILE="capture_$(date +%Y%m%d_%H%M%S).pcap"
tcpdump -i $INTERFACE -s $SNAPLEN -c $NEEDED_PACKETS -w $OUTPUT_FILE

关于 -C-W 1 的说明

bash 复制代码
# 这个命令会循环覆盖,不会退出
tcpdump -i eth0 -C 100 -W 1 -w capture.pcap

# 工作流程:
# 1. 文件达到 100MB 时,创建 capture.pcap 的新文件
# 2. 由于 -W 1,会覆盖原来的文件
# 3. 继续抓包,无限循环,不会退出

如果需要使用 -C 并自动退出,可以配合脚本:

bash 复制代码
# 使用脚本监控并停止
tcpdump -i eth0 -C 100 -W 10 -w capture.pcap &
PID=$!
sleep 5
while true; do
    if [ -f capture.pcap ]; then
        SIZE=$(stat -c%s capture.pcap 2>/dev/null || echo 0)
        if [ $SIZE -ge $((100 * 1024 * 1024)) ]; then
            kill $PID
            break
        fi
    fi
    sleep 1
done

一行命令快速实现

bash 复制代码
# 快速计算并抓包(snaplen=1500,目标100MB)
SNAPLEN=1500; TARGET_MB=100; PACKETS=$((TARGET_MB * 1024 * 1024 / (SNAPLEN + 16))); tcpdump -i eth0 -s $SNAPLEN -c $PACKETS -w capture.pcap

# 完整包抓取(snaplen=0,目标100MB,需要估算)
tcpdump -i eth0 -s 0 -c 60000 -w capture.pcap

# 只抓头部(snaplen=96,目标100MB)
tcpdump -i eth0 -s 96 -c 1092200 -w capture.pcap

文件大小控制方案对比

方案 精确度 是否退出 复杂度
-s + -c 自动退出
-C + -W 1 精确 循环覆盖
-C + 监控脚本 精确 可退出

命令示例

基础抓包示例

bash 复制代码
# 抓取所有包
tcpdump -i eth0

# 只抓 10 个包
tcpdump -i eth0 -c 10

# 抓取指定主机的包
tcpdump -i eth0 host 192.168.1.100

# 抓取指定端口
tcpdump -i eth0 port 80

# 抓取 HTTP 流量(不解析名称)
tcpdump -i eth0 -nn port 80

# 抓取 HTTPS 流量
tcpdump -i eth0 -nn port 443

# 抓取指定网段
tcpdump -i eth0 net 192.168.1.0/24

组合过滤示例

bash 复制代码
# 抓取 192.168.1.100 的 HTTP 流量
tcpdump -i eth0 host 192.168.1.100 and port 80

# 抓取除 SSH 外的所有流量
tcpdump -i eth0 not port 22

# 抓取源或目标端口是 80 或 443
tcpdump -i eth0 port 80 or port 443

# 抓取源 IP 是 192.168.1.100 的包
tcpdump -i eth0 src host 192.168.1.100

# 抓取目标 IP 是 10.0.0.1 的包
tcpdump -i eth0 dst host 10.0.0.1

TCP 标志位过滤示例

bash 复制代码
# 抓取 SYN 包(TCP 握手开始)
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'

# 抓取 SYN-ACK 包
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0'

# 抓取 RST 包(连接重置)
tcpdump -i eth0 'tcp[tcpflags] & tcp-rst != 0'

# 抓取 FIN 包(连接关闭)
tcpdump -i eth0 'tcp[tcpflags] & tcp-fin != 0'

保存和读取文件

bash 复制代码
# 保存到文件
tcpdump -i eth0 -w capture.pcap

# 保存到文件(不显示输出)
tcpdump -i eth0 -w capture.pcap -q

# 读取文件
tcpdump -r capture.pcap

# 读取文件并过滤
tcpdump -r capture.pcap port 80

# 保存为可读格式
tcpdump -i eth0 -A > capture.txt

# 文件滚动保存(每 100MB 一个新文件)
tcpdump -i eth0 -C 100 -W 10 -w capture.pcap

高级抓包示例

bash 复制代码
# 抓取 HTTP GET 请求
tcpdump -i eth0 -s 0 -A 'tcp[20:4] = 0x47455420'

# 抓取 HTTP POST 请求
tcpdump -i eth0 -s 0 -A 'tcp[20:4] = 0x504f5354'

# 抓取 DNS 查询
tcpdump -i eth0 -nn port 53

# 抓取 ping 包
tcpdump -i eth0 icmp

# 抓取大于 1000 字节的包
tcpdump -i eth0 greater 1000

# 抓取 IPv6 流量
tcpdump -i eth0 ip6

时间控制示例

bash 复制代码
# 按时间滚动文件(每小时)
tcpdump -G 3600 -w capture_%Y%m%d_%H%M%S.pcap

# 按大小滚动并限制文件数
tcpdump -C 100 -W 5 -G 3600 -w capture_%Y%m%d_%H%M%S.pcap

# 抓取 30 秒后自动停止
timeout 30 tcpdump -i eth0 -w capture.pcap

使用场景实战

场景一:排查网络连接问题

bash 复制代码
# 抓取 SYN 包,查看 TCP 握手情况
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0'

# 抓取特定端口的完整握手过程
tcpdump -i eth0 port 8080 -nn

# 输出分析:
# 正常三次握手:
# 12:34:56.1 IP 10.0.0.1.12345 > 10.0.0.2.8080: Flags [S]
# 12:34:56.2 IP 10.0.0.2.8080 > 10.0.0.1.12345: Flags [S.]
# 12:34:56.2 IP 10.0.0.1.12345 > 10.0.0.2.8080: Flags [.]
# 
# 异常情况:
# 12:34:56.1 IP 10.0.0.1.12345 > 10.0.0.2.8080: Flags [S]
# 12:34:56.1 IP 10.0.0.2.8080 > 10.0.0.1.12345: Flags [R]  # 端口未监听

场景二:分析 HTTP 请求响应

bash 复制代码
# 抓取 HTTP 请求并查看内容
tcpdump -i eth0 -A -s 0 port 80

# 输出示例:
# GET /api/users HTTP/1.1
# Host: example.com
# User-Agent: curl/7.68.0

# HTTP/1.1 200 OK
# Content-Type: application/json
# {"status":"ok"}

场景三:排查 DNS 解析问题

bash 复制代码
# 抓取所有 DNS 查询
tcpdump -i eth0 -nn port 53

# 详细查看 DNS 响应
tcpdump -i eth0 -vv -s 0 port 53

# 抓取特定域名的 DNS 查询
tcpdump -i eth0 -nn 'udp port 53 and host 8.8.8.8'

场景四:排查 TCP 重传和丢包

bash 复制代码
# 抓取 TCP 重传包
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0'

# 抓取重传和重复 ACK
tcpdump -i eth0 'tcp[13] & 4 != 0'

# 分析窗口大小变化
tcpdump -i eth0 -vv 'tcp and host 10.0.0.1'

场景五:生产环境长时间抓包

bash 复制代码
#!/bin/bash
# 生产环境安全抓包脚本

INTERFACE="eth0"
OUTPUT_DIR="/var/log/tcpdump"
MAX_SIZE_MB=100
MAX_FILES=10
SNAPLEN=1500

mkdir -p $OUTPUT_DIR

# 使用 -s 和 -c 精确控制文件大小
# 先计算需要的包数量
TARGET_BYTES=$((MAX_SIZE_MB * 1024 * 1024))
PACKET_OVERHEAD=16
FILE_HEADER=24
PACKET_SIZE=$((SNAPLEN + PACKET_OVERHEAD))
NEEDED_PACKETS=$(((TARGET_BYTES - FILE_HEADER) / PACKET_SIZE))

# 后台抓包,降低优先级
nice -n 10 tcpdump -i $INTERFACE \
    -s $SNAPLEN \
    -c $NEEDED_PACKETS \
    -n \
    -w $OUTPUT_DIR/capture_$(date +%Y%m%d_%H%M%S).pcap \
    not port 22

常见问题与解决

抓不到包

bash 复制代码
# 问题1:网卡不在混杂模式
tcpdump -i eth0 -p

# 问题2:BPF 过滤太严格
tcpdump -i eth0 -nn

# 问题3:权限不足
sudo tcpdump -i eth0

丢包严重

bash 复制代码
# 增加内核缓冲区
tcpdump -B 4096

# 减少抓包长度
tcpdump -s 100

# 使用更精确的 BPF 过滤
tcpdump 'host 192.168.1.100 and port 80'

# 降低输出频率
tcpdump -q

# 调整系统参数
echo 4194304 > /proc/sys/net/core/rmem_max

文件太大

bash 复制代码
# 限制抓包长度
tcpdump -s 100

# 使用 -c 限制包数量
tcpdump -c 10000 -w capture.pcap

# 使用 -s 和 -c 组合精确控制
tcpdump -s 1500 -c 70000 -w capture.pcap

# 压缩保存
tcpdump -i eth0 -w - | gzip > capture.pcap.gz

常用命令

bash 复制代码
# 最常用命令
tcpdump -i eth0 -nn -s 0 -c 1000 -w capture.pcap

# 精确控制文件大小(100MB,snaplen=1500)
tcpdump -i eth0 -s 1500 -c 70000 -w capture.pcap

# 排查 HTTP 问题
tcpdump -i eth0 -A -s 0 port 80

# 排查网络连接
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0'

# 排查 DNS
tcpdump -i eth0 -nn port 53

# 实时查看抓包
tcpdump -i eth0 -nn -c 100

# 分析 pcap 文件
tcpdump -r capture.pcap -nn | head -100
相关推荐
skilllite作者5 小时前
Spec + Task 作为「开发协议层」:Rust 大模型辅助的标准化、harness 化与可回滚
开发语言·人工智能·后端·安全·架构·rust·rust沙箱
Figo_Cheung5 小时前
Figo OntoGuard-CRE:基于IIQ本体的下一代AI伦理安全约束推理引擎——已在gitee上线发布
人工智能·安全·gitee
qq_260241237 小时前
将盾CDN:零信任安全架构的演进与落地实践
安全·php·安全架构
qq_260241237 小时前
将盾CDN:移动网络环境下的安全接入技术
网络·安全
无忧智库8 小时前
深度解码:烟草行业数字化转型顶层设计与全场景落地实践(PPT)
安全·架构
瘾大侠9 小时前
OSCP+ 100分 7小时考试心得分享
安全·web安全·网络安全
lingggggaaaa9 小时前
PHP模型开发篇&MVC层&动态调试未授权&脆弱鉴权&未引用&错误逻辑
开发语言·安全·web安全·网络安全·php·mvc·代码审计
航Hang*10 小时前
Windows Server 配置与管理——第7章:配置DNS服务器
运维·服务器·网络·windows·安全·虚拟化
云和数据.ChenGuang10 小时前
鸿蒙6的**星盾安全(StarShield)技术
安全·华为·harmonyos