Linux tcpdump命令

tcpdump 是一个功能强大的命令行网络数据包分析工具,用于捕获、显示和分析网络流量。它是网络管理员、安全专家和开发人员必备的网络调试工具,可以深入分析TCP/IP协议栈的各个层面。

注意:使用tcpdump需要管理员权限(root),因为它需要访问网络接口的原始数据包。在大多数情况下,您需要使用sudo运行tcpdump。

安装tcpdump

在基于Debian/Ubuntu的系统上安装:

sudo apt-get update
sudo apt-get install tcpdump

在基于RHEL/CentOS的系统上安装:

sudo yum install tcpdump
# 或者
sudo dnf install tcpdump

在基于Arch Linux的系统上安装:

sudo pacman -S tcpdump

在macOS上安装(通过Homebrew):

brew install tcpdump

语法格式

tcpdump [选项] [表达式]

常用选项

选项 说明
-i 接口 指定要监听的网络接口(如eth0、wlan0)
-c 数量 捕获指定数量的数据包后退出
-n 不将地址转换为主机名(禁用DNS解析)
-nn 不将地址和端口转换为主机名和服务名
-v, -vv, -vvv 详细输出模式,v越多越详细
-s 长度 设置捕获数据包的长度(默认96字节)
-w 文件 将捕获的数据包写入文件(pcap格式)
-r 文件 从文件读取数据包进行分析
-A 以ASCII格式显示数据包内容
-X 以十六进制和ASCII格式显示数据包内容
-q 快速输出模式,显示较少信息
-l 行缓冲模式,适合管道处理
-D 列出可用的网络接口
-e 显示数据链路层头部信息
--version 显示版本信息

查看网络接口

# 列出所有可用接口
tcpdump -D
# 或
tcpdump --list-interfaces

# 使用ip命令查看接口
ip addr show

# 使用ifconfig查看接口
ifconfig -a

输出示例:

1.eth0
2.eth1
3.wlan0
4.any (Pseudo-device that captures on all interfaces)
5.lo [Loopback]

基本使用示例

示例1:捕获所有网络接口的数据包

sudo tcpdump -i any

示例2:捕获特定接口的数据包

sudo tcpdump -i eth0

示例3:捕获指定数量的数据包

sudo tcpdump -i eth0 -c 10

示例4:禁用DNS解析(提高性能)

sudo tcpdump -i eth0 -n

示例5:详细输出

sudo tcpdump -i eth0 -v
sudo tcpdump -i eth0 -vv
sudo tcpdump -i eth0 -vvv

过滤器表达式

tcpdump支持强大的BPF(Berkeley Packet Filter)过滤器语法:

主机过滤

# 捕获与特定主机的所有通信
sudo tcpdump host 192.168.1.100

# 捕获来源或目标为特定主机的数据包
sudo tcpdump src host 192.168.1.100
sudo tcpdump dst host 192.168.1.100

# 使用主机名
sudo tcpdump host example.com

端口过滤

# 捕获特定端口的数据包
sudo tcpdump port 80
sudo tcpdump port 443

# 捕获来源端口
sudo tcpdump src port 22

# 捕获目标端口
sudo tcpdump dst port 53

# 端口范围
sudo tcpdump portrange 20-23

网络过滤

# 捕获特定网络的流量
sudo tcpdump net 192.168.1.0/24
sudo tcpdump src net 192.168.1.0/24
sudo tcpdump dst net 192.168.1.0/24

协议过滤

# 捕获特定协议的数据包
sudo tcpdump icmp
sudo tcpdump tcp
sudo tcpdump udp
sudo tcpdump arp
sudo tcpdump icmp6

组合过滤

# 使用逻辑运算符
sudo tcpdump host 192.168.1.100 and port 80
sudo tcpdump src host 192.168.1.100 and dst port 443
sudo tcpdump host 192.168.1.100 and not port 22
sudo tcpdump port 80 or port 443
sudo tcpdump "(src host 192.168.1.100 and dst port 80) or (dst host 192.168.1.100 and src port 80)"

高级过滤示例

TCP标志过滤

# 捕获TCP SYN包
sudo tcpdump 'tcp[tcpflags] & tcp-syn != 0'

# 捕获TCP SYN-ACK包
sudo tcpdump 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0'

# 捕获TCP RST包
sudo tcpdump 'tcp[tcpflags] & tcp-rst != 0'

# 捕获TCP FIN包
sudo tcpdump 'tcp[tcpflags] & tcp-fin != 0'

数据包大小过滤

# 捕获大于指定大小的数据包
sudo tcpdump greater 1000

# 捕获小于指定大小的数据包
sudo tcpdump less 100

# 捕获特定大小的数据包
sudo tcpdump length == 64

TCP流过滤

# 捕获包含特定字符串的数据包
sudo tcpdump -A 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

实际应用场景

场景1:监控HTTP流量

# 捕获HTTP流量
sudo tcpdump -i eth0 -A 'tcp port 80'

# 捕获特定网站的HTTP流量
sudo tcpdump -i eth0 -A 'host example.com and tcp port 80'

# 捕获HTTP GET请求
sudo tcpdump -i eth0 -s 0 -A 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'

场景2:监控DNS查询

# 捕获DNS查询和响应
sudo tcpdump -i eth0 -n 'udp port 53'

# 捕获特定域名的DNS查询
sudo tcpdump -i eth0 -n 'udp port 53 and dst host 8.8.8.8'

场景3:监控SSH连接

# 捕获SSH连接尝试
sudo tcpdump -i eth0 'tcp port 22'

# 捕获到特定主机的SSH连接
sudo tcpdump -i eth0 'tcp port 22 and host 192.168.1.100'

场景4:分析ICMP流量(Ping)

# 捕获ICMP Echo请求和回复
sudo tcpdump -i eth0 icmp

# 捕获特定主机的Ping流量
sudo tcpdump -i eth0 'icmp and host 8.8.8.8'

数据包分析

查看完整数据包内容

# 以十六进制和ASCII格式显示
sudo tcpdump -i eth0 -X 'tcp port 80'

# 以ASCII格式显示
sudo tcpdump -i eth0 -A 'tcp port 80'

# 显示数据链路层头部
sudo tcpdump -i eth0 -e 'tcp port 80'

保存和读取数据包文件

# 将数据包保存到文件
sudo tcpdump -i eth0 -w capture.pcap

# 保存特定流量
sudo tcpdump -i eth0 -w http.pcap 'tcp port 80'

# 从文件读取数据包
tcpdump -r capture.pcap

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

tcpdump输出解读

TCP数据包示例

15:30:45.123456 IP 192.168.1.100.51234 > 93.184.216.34.80: Flags [S], seq 1234567890, win 64240, options [mss 1460,sackOK,TS val 1000 ecr 0,nop,wscale 7], length 0
字段 说明 示例值
时间戳 数据包捕获时间 15:30:45.123456
协议 网络层协议 IP
来源 源IP地址和端口 192.168.1.100.51234
目标 目标IP地址和端口 93.184.216.34.80
Flags TCP标志位 [S] (SYN)
seq 序列号 1234567890
win 窗口大小 64240
options TCP选项 [mss 1460,...]
length 数据长度 0

TCP标志位说明

标志 说明 含义
S SYN 连接建立请求
. ACK 确认
P PSH 推送数据
F FIN 连接终止
R RST 连接重置
U URG 紧急数据
E ECE ECN-Echo
C CWR 拥塞窗口减少

性能优化

减少捕获数据包大小

# 只捕获头部,不捕获数据
sudo tcpdump -i eth0 -s 0

# 捕获前96字节(默认)
sudo tcpdump -i eth0 -s 96

# 捕获完整数据包
sudo tcpdump -i eth0 -s 65535

提高性能的技巧

# 使用-nn禁用DNS解析
sudo tcpdump -i eth0 -nn

# 使用-q快速输出模式
sudo tcpdump -i eth0 -q

# 将输出重定向到文件而不是屏幕
sudo tcpdump -i eth0 -w /tmp/capture.pcap

# 使用BPF过滤器减少处理的数据量
sudo tcpdump -i eth0 'tcp port 80'

相关工具

工具 说明 特点
wireshark 图形化网络协议分析器 功能强大,支持深度分析,GUI界面
tshark Wireshark的命令行版本 命令行操作,适合脚本处理
ngrep 网络grep工具 基于正则表达式过滤网络数据
tcpflow TCP流重组工具 重建TCP会话内容
tcpreplay 网络流量重放工具 重放捕获的网络流量
nmap 网络探测和安全审计工具 端口扫描、服务识别
netstat 网络连接统计工具 显示网络连接、路由表等
ss socket统计工具 netstat的现代替代品

故障排除

问题1:权限不足

tcpdump: eth0: You don't have permission to capture on that device
(socket: Operation not permitted)

解决方案:

# 使用sudo
sudo tcpdump -i eth0

# 或添加用户到特定组
sudo usermod -aG wireshark $USER
# 注销重新登录后生效

问题2:接口不存在

tcpdump: eth0: No such device exists
(BIOCSETIF: No such device)

解决方案:

# 查看可用接口
tcpdump -D
ip addr show

# 使用正确的接口名
sudo tcpdump -i wlp3s0  # 无线接口示例
sudo tcpdump -i enp0s3  # 有线接口示例

问题3:没有捕获到数据包

# tcpdump运行但没有显示任何数据包

解决方案:

# 1. 检查接口是否正确
sudo tcpdump -i any  # 捕获所有接口

# 2. 检查网络连接
ping 8.8.8.8

# 3. 检查防火墙设置
sudo iptables -L

# 4. 尝试更宽泛的过滤器
sudo tcpdump -i eth0 icmp
sudo tcpdump -i eth0 arp

实用示例脚本

脚本1:监控HTTP POST请求

#!/bin/bash
# monitor_http_post.sh - 监控HTTP POST请求

INTERFACE="eth0"
LOG_FILE="/var/log/http_post.log"

echo "开始监控HTTP POST请求..."
echo "接口: $INTERFACE"
echo "日志文件: $LOG_FILE"
echo "按Ctrl+C停止监控"
echo ""

# 清理旧日志
> "$LOG_FILE"

# 开始监控
sudo tcpdump -i "$INTERFACE" -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' | \
while read line; do
    if echo "$line" | grep -q "POST"; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 检测到POST请求:" >> "$LOG_FILE"
        echo "$line" >> "$LOG_FILE"
        echo "---" >> "$LOG_FILE"
    fi
done

脚本2:网络流量统计

#!/bin/bash
# traffic_stats.sh - 网络流量统计

INTERFACE="eth0"
DURATION=60
OUTPUT_FILE="/tmp/traffic_stats.txt"

echo "开始捕获网络流量,持续时间: ${DURATION}秒"
echo "接口: $INTERFACE"
echo ""

# 捕获流量并统计
sudo timeout $DURATION tcpdump -i "$INTERFACE" -n -q 2>/dev/null | \
awk '{
    if ($1 == "listening") next

    # 提取协议
    split($1, a, ".")
    protocol = a[1]

    # 提取源IP和目标IP
    if (protocol == "IP") {
        src_ip = $3
        dst_ip = $5

        # 清理端口号
        sub(/\.[0-9]+$/, "", src_ip)
        sub(/:[0-9]+$/, "", dst_ip)

        # 统计
        src_count[src_ip]++
        dst_count[dst_ip]++
        total_packets++
    }
} END {
    print "=== 流量统计报告 ==="
    print "总数据包数: " total_packets
    print "持续时间: '"$DURATION"' 秒"
    print ""
    print "=== 来源IP统计 (前10) ==="
    for (ip in src_count) {
        print ip ": " src_count[ip] " 个数据包"
    }
    print ""
    print "=== 目标IP统计 (前10) ==="
    for (ip in dst_count) {
        print ip ": " dst_count[ip] " 个数据包"
    }
}' > "$OUTPUT_FILE"

echo "统计完成,结果保存在: $OUTPUT_FILE"
cat "$OUTPUT_FILE"

安全注意事项

  1. tcpdump可以捕获网络上的所有数据,包括敏感信息(如密码、私人通信)
  2. 只应在自己拥有或有权监控的网络上使用
  3. 遵守当地法律和公司政策
  4. 在公共场所使用时需格外小心
  5. 使用过滤器减少不必要的数据捕获
  6. 定期删除捕获的文件,特别是包含敏感信息的文件

专业技巧

高级tcpdump技巧:
  1. 组合过滤器:使用括号组合复杂条件,如(host 192.168.1.100 and port 80) or (host 192.168.1.200 and port 443)
  2. 保存到多个文件:使用-C-W选项轮转捕获文件
  3. 实时分析:将tcpdump输出通过管道传递给grep、awk等工具
  4. 性能监控:使用-c限制捕获数量,避免系统过载
  5. 离线分析:使用-r读取保存的pcap文件进行离线分析
  6. 与其他工具集成:结合Wireshark进行深度协议分析

tcpdump与Wireshark配合使用

# 1. 使用tcpdump捕获数据包
sudo tcpdump -i eth0 -w capture.pcap 'tcp port 80'

# 2. 使用Wireshark分析
wireshark capture.pcap

# 3. 或使用tshark(Wireshark命令行版本)分析
tshark -r capture.pcap
tshark -r capture.pcap -Y "http.request.method == GET"

# 4. 实时捕获并分析
sudo tcpdump -i eth0 -U -w - 'tcp port 80' | wireshark -k -i -

tcpdump常用命令速查表

用途 命令
基本捕获 sudo tcpdump -i eth0
捕获HTTP流量 sudo tcpdump -i eth0 -A 'tcp port 80'
捕获DNS查询 sudo tcpdump -i eth0 -n 'udp port 53'
捕获到特定主机的流量 sudo tcpdump -i eth0 'host 192.168.1.100'
捕获TCP SYN包 sudo tcpdump 'tcp[tcpflags] & tcp-syn != 0'
保存到文件 sudo tcpdump -i eth0 -w capture.pcap
从文件读取 tcpdump -r capture.pcap
显示详细输出 sudo tcpdump -i eth0 -vvv
禁用DNS解析 sudo tcpdump -i eth0 -n
捕获指定数量 sudo tcpdump -i eth0 -c 100