侧边栏壁纸
  • 累计撰写 16 篇文章
  • 累计创建 1 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

tcpdump 网络抓包实战指南(持续更新)

tcpdump 网络抓包实战指南(持续更新)

前言

tcpdump 是什么?

想象一下:你要调查一封信是怎么从发送方到接收方的。中途经过哪些邮局、每站停留多久、有没有丢失。

tcpdump 就是网络的"快递追踪器",它能截获并显示经过网卡的每一个数据包,让你看清网络通信的每一个细节。

tcpdump 是 Linux/Unix 系统下最强大的网络抓包工具,是网络故障排查和安全分析的必备技能。作为运维工程师,我们用它来诊断网络问题、分析攻击、调试协议。

本文档会告诉你:

  • tcpdump 核心概念
  • 基础抓包命令
  • 过滤表达式详解
  • 高级过滤技巧
  • 常用抓包场景
  • 分析工具使用

目录

  1. 核心概念详解
  2. 基础命令
  3. 过滤表达式
  4. 高级技巧
  5. 常用场景
  6. 输出分析
  7. Wireshark 配合

核心概念详解

1. TCP/IP 协议基础

数据包是什么?

想象一下:你寄一封信,信封上有收件人/发件人地址,内容在信纸里。

网络数据包也是这样:

  • IP 头 = 信封上的地址
  • TCP/UDP 头 = 邮戳(端口信息)
  • 数据 = 信的内容

协议层次:

层次 协议 通俗解释
应用层 HTTP, DNS, SSH 信的内容
传输层 TCP, UDP 邮戳(端口)
网络层 IP 收件人地址
链路层 Ethernet 街道地址

2. TCP 三次握手

三次握手是什么?

想象一下:打电话时,双方要确认:

  • 你好,我能听到你吗?(SYN)
  • 能听到,你也能听到我吗?(SYN-ACK)
  • 能,开始通话!(ACK)

TCP 连接建立就是这样,需要三次确认。

👀 TCP 三次握手:

客户端                          服务端
   │                              │
   │ ────── SYN (seq=100) ──────▶│  第一次:客户端发送 SYN
   │                              │
   │ ◀──── SYN-ACK (seq=300,ack=101) ───│  第二次:服务端返回 SYN-ACK
   │                              │
   │ ────── ACK (ack=301) ──────▶│  第三次:客户端发送 ACK
   │                              │
   │         建立连接!            │

3. TCP 标志位

标志位 全称 通俗解释
SYN Synchronize “你好,我想连接”
ACK Acknowledge “我收到了”
FIN Finish “我要关闭连接了”
RST Reset “出问题了,重置”
PSH Push “数据很急,马上处理”
URG Urgent “这是紧急数据”

4. 端口作用

端口 服务 通俗解释
22 SSH 远程服务器的"大门"
80 HTTP 普通网页的"入口"
443 HTTPS 安全网页的"入口"
3306 MySQL 数据库的"专用通道"
6379 Redis 缓存的"专用通道"
53 DNS 域名查询的"问讯处"

基础命令

安装与基本使用

# 👀 检查是否安装
which tcpdump

# 👀 安装(Ubuntu/Debian)
sudo apt install tcpdump

# 👀 安装(CentOS/RHEL)
sudo yum install tcpdump

# 👀 查看版本
tcpdump --version

基础抓包命令

# 👀 抓取所有数据包(按 Ctrl+C 停止)
sudo tcpdump

# 👀 抓取指定数量包后停止
sudo tcpdump -c 10

# 👀 抓取并保存到文件
sudo tcpdump -w capture.pcap

# 👀 读取保存的抓包文件
tcpdump -r capture.pcap

# 👀 抓取时显示详细信息
sudo tcpdump -v

# 👀 抓取时显示更详细信息
sudo tcpdump -vv

# 👀 不解析域名(加快抓包速度)
sudo tcpdump -n

# 👀 不解析域名和端口
sudo tcpdump -nn

指定网卡

# 👀 查看所有网卡
tcpdump -D

# 输出示例:
# 0.eth0 [Up, Running, Connected]
# 1.lo [Up, Running, Connected]
# 2.any [Pseudo-device that captures on all interfaces]
# 3.docker0 [Up, Running, Connected]

# 👀 抓取指定网卡
sudo tcpdump -i eth0

# 👀 抓取任意网卡(用于多网卡服务器)
sudo tcpdump -i any

# 👀 抓取 Docker 容器网卡
sudo tcpdump -i docker0

过滤表达式

主机过滤

# 👀 抓取来自特定主机的数据包
sudo tcpdump -i eth0 src host 192.168.1.10

# 👀 抓取发往特定主机的数据包
sudo tcpdump -i eth0 dst host 192.168.1.10

# 👀 抓取特定主机(双向)
sudo tcpdump -i eth0 host 192.168.1.10

# 👀 抓取来自或发往 IP 段
sudo tcpdump -i eth0 net 192.168.1.0/24

端口过滤

# 👀 抓取特定端口(双向)
sudo tcpdump -i eth0 port 80

# 👀 抓取源端口
sudo tcpdump -i eth0 src port 80

# 👀 抓取目标端口
sudo tcpdump -i eth0 dst port 80

# 👀 抓取多个端口
sudo tcpdump -i eth0 port 80 or port 443

# 👀 抓取非标准端口(排除 22)
sudo tcpdump -i eth0 port not 22

协议过滤

# 👀 抓取 TCP 包
sudo tcpdump -i eth0 tcp

# 👀 抓取 UDP 包
sudo tcpdump -i eth0 udp

# 👀 抓取 ICMP 包(ping)
sudo tcpdump -i eth0 icmp

# 👀 抓取 ARP 包
sudo tcpdump -i eth0 arp

# 👀 抓取 DNS 包(DNS 用 UDP/TCP 53)
sudo tcpdump -i eth0 "port 53"

组合过滤

# 👀 AND 组合
sudo tcpdump -i eth0 tcp and port 80

# 👀 OR 组合
sudo tcpdump -i eth0 host 192.168.1.10 or host 192.168.1.20

# 👀 NOT 排除
sudo tcpdump -i eth0 tcp and not port 22

# 👀 复杂组合
sudo tcpdump -i eth0 "tcp and (port 80 or port 443) and src host 192.168.1.10"

高级技巧

抓取 HTTP 请求

# 👀 抓取 HTTP 请求内容
sudo tcpdump -i eth0 -A "tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)"

# 👀 简化版
sudo tcpdump -i eth0 -A port 80 | grep -i "GET\|POST\|HTTP"

# 👀 抓取完整 HTTP 请求和响应
sudo tcpdump -i eth0 -A -s 0 "tcp port 80 and tcp[((tcp[12:1] & 0xf0) >> 2)] = 0x"

抓取特定内容

# 👀 抓取包含特定字符串的包
sudo tcpdump -i eth0 -A "tcp[20:]" | grep -a "password\|token\|secret"

# 👀 抓取 POST 请求中的数据
sudo tcpdump -i eth0 -A -s 0 "tcp[((tcp[12:1] & 0xf0) >> 2)] = 0x50"

# 👀 抓取 JSON 数据
sudo tcpdump -i eth0 -A -s 0 | grep -i "{"

抓取连接建立和断开

# 👀 抓取 TCP 连接建立(SYN)
sudo tcpdump -i eth0 "tcp[tcpflags] == tcp-syn"

# 👀 抓取 TCP 连接断开(FIN)
sudo tcpdump -i eth0 "tcp[tcpflags] == tcp-fin"

# 👀 抓取 TCP 重置(RST)
sudo tcpdump -i eth0 "tcp[tcpflags] == tcp-rst"

# 👀 抓取 SYN 和 FIN 都算
sudo tcpdump -i eth0 "tcp[tcpflags] & (tcp-syn|tcp-fin) != 0"

抓取特定包大小

# 👀 抓取大于指定大小的包
sudo tcpdump -i eth0 "ip[2:2] > 1000"

# 👀 抓取 TCP 头部长度
sudo tcpdump -i eth0 "tcp[((tcp[12:1] & 0xf0) >> 2)]"

常用场景

场景 1:诊断无法连接 Web 服务

# 👀 抓取与 Web 服务器的通信
sudo tcpdump -i eth0 -nn host 192.168.1.100 and port 80 -w web-debug.pcap

# 👀 分析
# 1. 看有没有 SYN 包发出
# 2. 看有没有 SYN-ACK 包返回
# 3. 如果没有 SYN-ACK,可能是防火墙或网络不通

排查思路:

👀 连接问题排查流程:

1. 发 SYN 包
   │
   ▼
2. 收到 SYN-ACK? ──否──▶ 检查服务端防火墙
   │                         检查服务端服务是否启动
   是
   ▼
3. 发 ACK 包
   │
   ▼
4. 连接建立成功?
   │
   是 → 继续排查应用层问题
   否 → 检查防火墙(RST)

场景 2:分析 DNS 解析

# 👀 抓取 DNS 查询和响应
sudo tcpdump -i eth0 -nn port 53

# 👀 输出示例
# 12:34:56.789 IP 192.168.1.10.12345 > 8.8.8.8.53: 12345+ A? www.example.com.
# 12:34:56.801 IP 8.8.8.8.53 > 192.168.1.10.12345: 12345 1/0/0 A 93.184.216.34

# 👀 解释:
# 192.168.1.10.12345 > 8.8.8.8.53  客户端向 DNS 服务器发送查询
# 12345+ A? www.example.com         查询 ID=12345, 查询类型=A(IPv4)
# 93.184.216.34                      DNS 返回的 IP 地址

场景 3:抓取 MySQL 慢查询

# 👀 抓取 MySQL 端口通信
sudo tcpdump -i eth0 -nn -A port 3306 | grep -i "SELECT\|INSERT\|UPDATE"

# 👀 保存完整 MySQL 流量
sudo tcpdump -i eth0 -nn port 3306 -w mysql.pcap

# 👀 后续分析
tcpdump -r mysql.pcap -A | less

场景 4:分析 HTTP 攻击

# 👀 抓取 HTTP GET 请求
sudo tcpdump -i eth0 -nn -A "tcp port 80 and tcp[((tcp[12:1] & 0xf0) >> 2)] = 0x47455420"

# 👀 47455420 是什么? = "GET " 的十六进制

# 👀 常见 HTTP 方法十六进制
# GET  = 47455420 (space after GET)
# POST = 504F5354 (POST)
# PUT  = 50555420

场景 5:监控 Redis 连接

# 👀 抓取 Redis 命令
sudo tcpdump -i eth0 -nn -A port 6379 | grep -i "SET\|GET\|AUTH"

# 👀 完整 Redis 流量
sudo tcpdump -i eth0 -nn port 6379 -w redis.pcap

输出分析

tcpdump 输出格式

👀 tcpdump 输出格式:

12:34:56.789123  IP  192.168.1.10.12345  >  93.184.216.34.80:  Flags [S], seq 100:200, win 65535, options [mss 1460], length 100

解释:
┌────────────┬──────────┬───────┬──────────┬──────┬───────┬─────────┬─────────┬────────┐
│ 时间       │ 协议    │ 源地址 │   >      │目标  │ Flags │ 序列号  │ 窗口   │ 长度  │
│ 12:34:56  │ IP      │192.168│          │.80   │ [S]   │         │        │       │
│            │         │ .1.10 │          │      │ SYN包 │         │        │       │
│            │         │ .12345│          │      │       │         │        │       │
└────────────┴──────────┴───────┴──────────┴──────┴───────┴─────────┴─────────┴────────┘

Flags 说明

Flags 含义 常见场景
[.] ACK 确认包
[S] SYN 连接建立
[F] FIN 连接关闭
[R] RST 重置连接
[P] PSH 推送数据
[S.] SYN-ACK 握手第二步
[P.] PSH-ACK 数据包
[F.] FIN-ACK 关闭第二步

分析 TCP 会话

# 👀 抓取完整 TCP 会话
sudo tcpdump -i eth0 -nn -c 100 'port 80' -w session.pcap

# 👀 分析会话
tcpdump -nn -r session.pcap | head -20

# 👀 查看会话统计
tcpdump -nn -r session.pcap | awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c

Wireshark 配合

转换为 pcap 格式

# 👀 tcpdump 抓的包直接可以用 Wireshark 打开
sudo tcpdump -i eth0 port 80 -w capture.pcap

# 👀 合并多个 pcap 文件
mergecap -w combined.pcap capture1.pcap capture2.pcap

# 👀 按时间排序
tcpdump -r capture.pcap -nn | sort > sorted.txt

常用过滤语法对比

场景 tcpdump Wireshark
HTTP 流量 port 80 http
TCP SYN tcp[tcpflags] == tcp-syn tcp.flags.syn == 1
GET 请求 tcp[20:] contains "GET" http.request.method == "GET"
IP 过滤 host 192.168.1.10 ip.addr == 192.168.1.10
端口过滤 port 80 tcp.port == 80

总结

黄金法则

  1. 先筛选再抓 - 用过滤减少数据量
  2. 保存到文件 - 抓包后用 Wireshark 分析
  3. 指定网卡 - 不要用 any(太慢)
  4. 减少解析 - 用 -nn 加速
  5. 及时停止 - 抓完按 Ctrl+C
  6. 保留完整 - 抓包时用 -s 0 保存完整数据

常用命令速查

# 👀 基础抓包
sudo tcpdump -i eth0 -nn port 80

# 👀 保存到文件
sudo tcpdump -i eth0 -w file.pcap

# 👀 读取文件
tcpdump -r file.pcap

# 👀 HTTP 请求
sudo tcpdump -i eth0 -A port 80 | grep "GET\|HTTP"

# 👀 SYN 包
sudo tcpdump -i eth0 "tcp[tcpflags] == tcp-syn"

# 👀 ICMP (ping)
sudo tcpdump -i eth0 icmp

持续更新中… 如有问题或建议,欢迎交流讨论!

0

评论区