Files
2026-05-24 11:42:38 +08:00

250 lines
8.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [计算机网络, tcpdump, tshark, curl, dig, iptables, Wireshark]
create time: 2026-05-18 04:50
---
# 抓包、HTTP 调试与 DNS 诊断工具
## 概述
在前一章完成了"通不通"的判断之后,本章深入"报文到了没"和"内容对不对"。涵盖 tcpdump 抓包分析、curl HTTP 调试、dig DNS 诊断以及 iptables 规则排查。
## tcpdump —— 命令行抓包神器
### 基础语法与 BPF 过滤器精选
```bash
sudo tcpdump -i eth0 # 抓取 eth0 所有流量
sudo tcpdump -nn # -n: 不解析域名, -n: 不解析端口名
sudo tcpdump -c 100 # 抓 100 个包后停止
sudo tcpdump -w capture.pcap # 写入 pcap 文件(Wireshark 打开)
sudo tcpdump -A 'port 80' # ASCII 模式打印 HTTP 内容
sudo tcpdump -X 'port 80' # HEX + ASCII 双列输出
```
### BPF (Berkeley Packet Filter) 表达式
```bash
# 按 IP 过滤
sudo tcpdump 'host 93.184.216.34' # 只看这个 IP
# 按端口过滤
sudo tcpdump 'port 80' # HTTP
sudo tcpdump 'port 443' # HTTPS
sudo tcpdump 'port range 8000-9000' # 端口范围
# 组合过滤
sudo tcpdump 'src host 10.0.0.1 and dst port 443' # 源 → 目标端口
sudo tcpdump '(src net 192.168.1.0/24) or (dst net 10.0.0.0/8)' # 多网段
# 匹配 TCP 标志位(非常强大!)
sudo tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' # SYN+ACK
sudo tcpdump 'tcp[tcpflags] & tcp-syn != 0' # SYN 包(新连接)
sudo tcpdump 'tcp[13] & 0x04 != 0' # 同样匹配 SYN
sudo tcpdump 'tcp[13] & 0x10 != 0' # ACK 标志位
sudo tcpdump 'tcp[tcpflags] & tcp-rst != 0' # RST 包(异常断开)
sudo tcpdump 'tcp[tcpflags] & tcp-fin != 0' # FIN 包(正常关闭)
# 排除法
sudo tcpdump 'not host 192.168.1.1 and not port 22' # 排除网关和 SSH
```
### SYN 包实时观察
```bash
# 实时监控新连接建立
sudo tcpdump -nn 'tcp[tcpflags] & tcp-syn != 0'
08:23:45.123456 IP 192.168.1.100:54321 > 10.0.0.1:8080: S 12345678:12345678(...)
08:23:45.123789 IP 10.0.0.1:8080 > 192.168.1.100:54321: S 87654321:87654321(...)
# ↑ 这就是三次握手的前两个包(SYN 和 SYN-ACK)
# 监控 RST(异常断开)
sudo tcpdump -nn 'tcp[tcpflags] & (tcp-rst) != 0'
```
> [!tip] tcpdump → Wireshark 工作流
> ```bash
> # 1. tcpdump 后台抓包
> sudo tcpdump -w /tmp/app.pcap 'host 10.0.0.1 and port 8080' &
> # 2. 复现问题
> # 3. Ctrl+C 停止抓包
> # 4. Wireshark 打开分析
> wireshark /tmp/app.pcap
> # 5. Wireshark 支持深度解码 HTTP/gRPC/TLS 等协议
> ```
## tshark —— CLI 版 Wireshark
```bash
# 实时过滤 HTTP 请求
$ tshark -i eth0 -Y 'http.request'
No. Time Source Destination Protocol Length Info
12 0.123456 10.0.0.1 93.184.xxx HTTP 450 GET /api/users HTTP/1.1
# 导出字段(CSV 风格)
tshark -r capture.pcap -Y 'http' \
-T fields -e ip.src -e http.host -e http.request.uri
# 只追踪 TLS 握手的 ClientHello
tshark -Y 'tls.handshake.type == 1'
# 1 = ClientHello, 11 = ServerHello, 12 = Certificate, etc.
```
## curl —— HTTP 调试利器
### 详细输出与计时分解
```bash
# -v: verbose 模式,看到完整的握手过程和头部交换
curl -v https://example.com
* Trying 93.184.216.34:443...
* Connected to example.com (93.184.216.34) port 443
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.3, TLS handshake, Client hello (1):
* TLSv1.3, TLS handshake, Server hello (2):
* TLSv1.3, Encrypted Extensions (8):
* TLSv1.3, Certificate (11):
* TLSv1.3, TLS handshake, Finished (5):
* TLSv1.3, Encrypted Change Cipher (1):
* ... SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
# -w: custom output 精确测量各阶段耗时 💡
curl -w '\nDNS Resolve: %{time_namelookup}s\nTCP Connect: %{time_connect}s\nTLS Handshake: %{time_appconnect}s\nFirst Byte: %{time_starttransfer}s\nTotal: %{time_total}s\n' \
-o /dev/null -s https://example.com
# 输出示例:
# DNS Resolve: 0.01234s
# TCP Connect: 0.01567s
# TLS Handshake: 0.04567s
# First Byte: 0.15678s
# Total: 0.23456s
```
```
耗时瓶颈分析:
├─ time_namelookup > 0.1s → DNS 慢 → 考虑 DNS 缓存
├─ time_connect - time_namelookup > 0.1s → TCP 连接慢 → 距离远/NAT 问题
├─ time_appconnect - time_connect > 0.2s → TLS 握手慢 → 证书链长/无 session resumption
└─ time_starttransfer - time_appconnect > 0.5s → 服务端处理慢 → 查应用日志
```
### curl 实战用法
```bash
# 自定义 Header 和认证
curl -H 'Authorization: Bearer token' \
-H 'Content-Type: application/json' \
-X POST -d '{"name":"alice"}' \
https://api.example.com/users
# 跟踪重定向(最多 5 层)
curl -L --max-redirs 5 https://short.link
# 查看响应头(快速判断 CDN/缓存状态)
curl -I https://cdn.example.com/style.css
HTTP/2 200
cache-control: public, max-age=86400
age: 1234
x-cache: HIT # ← CDN 命中
cf-cache-status: HIT # ← Cloudflare 标记
content-encoding: br # ← Brotli 压缩
# SSL 证书检查
openssl s_client -connect example.com:443 -servername example.com
# 关注:
# Verify return code: 0 (ok) ✅
# Verify return code: 20 (unable to get local issuer certificate) ❌
# JSON 美化输出
curl https://jsonplaceholder.typicode.com/users/1 | python3 -m json.tool
```
## dig —— DNS 诊断最强工具
### 常用查询模式
```bash
# A 记录简洁输出
$ dig example.com +short
93.184.216.34
# AAAA 记录(IPv6)
$ dig example.com AAAA +short
2606:2800:220:1:248:1893:25c8:1946
# 权威追踪(从根域名开始逐级查询)
$ dig example.com +trace
;; ->>HEADER<<- opcode: QUERY, status: NOERROR
;; QUESTION SECTION: ;example.com. IN A
;; ANSWER SECTION: example.com. 300 IN A 93.184.216.34
# 指定 DNS 服务器对比
$ dig @8.8.8.8 example.com # Google DNS
$ dig @1.1.1.1 example.com # Cloudflare DNS
$ dig @local_dns_server example.com # 本地 DNS(可能被污染)
# TXT 记录(SPF / DKIM 验证邮件配置)
$ dig example.com TXT +short
"v=spf1 include:_spf.google.com ~all"
# MX 记录(邮件服务器)
$ dig example.com MX +short
10 mail.example.com.
20 mail2.example.com.
# SRV 记录(服务发现,gRPC/Kafka 常用)
$ dig _grpc._tcp.service.consul SRV +short
0 100 8080 api.service.consul.
# 查看 CNAME 链全貌
$ dig www.example.com +multiline
```
### dig 高级用法
```bash
# 区域传输(AXFR,通常被禁止)
$ dig @ns1.example.com example.com axfr
# EDNS Client Subnet(CDN 优化用户体验的关键)
$ dig +ecs=203.0.113.0/24 example.com @1.1.1.1
# DNS resolver 把自己的子网发给 authoritative server
# → authoritative server 返回离用户最近的 CDN 节点 IP
# DoH(DNS over HTTPS)检测
$ curl https://dns.google/resolve?name=example.com&type=A
{"Status":0,"Answer":[{"name":"example.com","type":5,"data":"93.184.216.34",...}]}
```
## iptables / nftables 规则排查
```bash
# iptables 规则排查步骤
sudo iptables -L -n -v # 列出 FILTER 表所有规则及计数器
sudo iptables -t nat -L -n -v # 查看 NAT 表(SNAT/DNAT/MASQUERADE)
sudo iptables -t mangle -L -n -v # 查看 MANGLE 表(TOS/TTL 修改)
# 关键排查命令
sudo iptables-save | grep -A 5 INPUT # 只看 INPUT chain 的上下文
sudo iptables -L FORWARD -n -v --line-numbers # 转发规则(容器/代理场景必查)
# 常见规则导致的"假故障"
# ❌ 忘记放行容器的桥接流量
iptables -I FORWARD -i docker0 -j ACCEPT
# ❌ 没有启用 IP forwarding
sysctl net.ipv4.ip_forward=1
# nftables(iptables 的现代替代品)
sudo nft list ruleset # 列出所有 nft 规则
sudo nft add rule inet filter input tcp dport 22 accept
```
## 关联笔记
- [[hhs/NETWORK/连通性与状态探测工具]] — 先看 ping/ss/telnet 再决定要不要抓包
- [[hhs/NETWORK/ICMP与Ping-Traceroute]] — ping/traceroute 协议原理
- [[hhs/NETWORK/DNS与DHCP与WebSocket]] — DNS 递归查询流程补充 dig 实操
- [[hhs/NETWORK/TCP三次握手与四次挥手]] — tcpdump 中观察 SYN/ACK 交互细节