这是一个异常包与排障实操博客。
我们会按「先认异常长什么样 → 再自己制造 → 最后用固定套路排障」一步一步来。每关都是:抓包 → 产生问题 → Wireshark 里找 → 得出结论。
排障总口诀(先记住)
打不开 / 很慢 / 不对 → 从上到下查四层:
- DNS 域名有没有解析成 IP?
- TCP 连没连上?有没有 RST、重传?
- TLS HTTPS 握手成没成?(若是 https)
- HTTP 状态码是不是 200?
1. 连接被拒绝
本机或对方 端口上没有程序在监听,TCP 会直接拒绝,常见 RST。
1.1 实操
终端 1:
sudo tcpdump -i any -nn -s 0 -w ~/Desktop/fail-refused.pcap终端 2:
curl -v http://127.0.0.1:9999让本机去连 本机 127.0.0.1 的 9999 端口, 9999 端口一般没人监听,所以系统会 拒绝连接。
终端2 会报错:Connection refused(连接被拒绝)。终端 1:Ctrl+C停抓。
1.2 Wireshark 里看包
过滤器:tcp.flags.reset == 1 或 tcp.port == 9999
No.21 — 第一次 SYN(我们自己想连)
50842 → 9999 [SYN]你的 curl 从临时端口 50842 向 9999 发 SYN:「有人在 9999 吗?我想连。」
这是 三次握手的第一步,和正常访问网站一样。
No.22 — 回环接口重复捕获(Wireshark 启发式标记为重传)
[TCP Retransmission] 50842 → 9999 [SYN]No.22 与 No.21 的序号相同,时间仅相差约 26 微秒;这个间隔远小于重传超时(RTO),因此不符合等待后重发的特征。这里是在回环接口抓包时同一个 SYN 被重复捕获,Wireshark 的“TCP Retransmission”只是启发式标记;判断是否真正重传还应结合时间差、序号和应答关系。
No.23 — RST, ACK(红色行,关键)
9999 → 50842 [RST, ACK]9999 端口一侧(实际是内核协议栈)回复:RST + ACK。
RST(Reset) 表示:这个连接不行,直接重置/拒绝。
对 SYN 收到 RST 的典型含义:
主机在,但这个端口没有服务在监听 → Connection refused
不是「网络不通」,而是 「端口没人接」。
Wireshark 用 红色 标 RST,表示异常终止。
No.24 — 回环接口重复捕获的 RST, ACK
9999 → 50842 [RST, ACK]No.23 与 No.24 是同一个 RST, ACK 在回环接口上的重复捕获;它们并不是分别响应两次 SYN。
1.3 总结
为什么会出现 Connection refused?
| 问题 | 答案 |
|---|---|
网通不通? | 通,127.0.0.1 是本机 |
DNS? | 不涉及,直接用 IP |
原因? | 9999 端口没有进程 listen |
谁回的 RST? | 操作系统 TCP 栈(没有应用接 SYN 时由内核回 RST) |
常见真实场景:
- 服务没启动
- 服务监听了别的端口(如 8080 不是 9999)
- 防火墙较少在本机 loopback 上拦 refused(一般是 RST)
1.3.1 和「超时」的区别
| Connection refused | 超时 / 一直重传 | |
|---|---|---|
响应速度 | 很快(毫秒级) | 很慢(几秒) |
典型包 | RST | 多次 SYN,没有 RST,也没有 SYN+ACK |
含义 | 端口没人监听 | 包到不了或被中间设备丢掉 |
curl | Connection refused | Connection timed out |
图中的这次是 快 + RST → 典型的 refused。
1.3.2 排障结论怎么写
① 停在哪一层:TCP 层(没到 HTTP)
② 证据:SYN 后有 RST,ACK,无 SYN+ACK
③ 原因:目标端口 9999 无服务监听,应检查进程是否启动、端口是否配置正确
2. DNS 解析失败
域名根本 解析不出 IP,后面 TCP、HTTP 都不会正常发生。
2.1 实操
终端 1:
sudo tcpdump -i any -nn -s 0 -w ~/Desktop/fail-dns.pcap port 53终端 2:
nslookup this-domain-does-not-exist-12345.com终端 1: 停抓。
2.2 Wireshark看包
在 Wireshark 打开,.pcap 文件,过滤可输入 udp.port == 53 或 dns.qry.name contains "does-not-exist" ,我这里就不过滤了,现象如下。
这张图,一共 4 个包,前 2 个是我的 Cursor 后台正常 DNS,后 2 个才是刚刚故意造的 DNS 解析失败的包,正好放在一起可以对比一下DNS解析 正确 和 失败 的情况。
No.1 — DNS 查询(Cursor,成功案例)
| 字段 | 内容 |
|---|---|
Source | 10.2.73.219(你的电脑) |
Destination | 10.2.255.2(DNS 服务器) |
Info | Standard query 0x73a6 A api2.cursor.sh |
含义: 你的电脑向 DNS 问:api2.cursor.sh 的 IPv4(A 记录)是多少?
0x73a6 是这次查询的编号,用来和回复配对。
这是 Cursor 编辑器 在后台查域名,不是你 nslookup 的那次,但格式和正常 DNS 查询一样。
No.2 — DNS 响应(Cursor,解析成功)
| 字段 | 内容 |
|---|---|
Source | 10.2.255.2(DNS 服务器) |
Destination | 10.2.73.219(你的电脑) |
Info | Standard query response 0x73a6 … CNAME api2geo.cursor.sh … |
含义: DNS 回答编号 0x73a6 的查询:api2.cursor.sh 是别名(CNAME),指向 api2geo.cursor.sh 等,并带上 IP。
结果:解析成功。 有 query 就有 response,且没有 “No such name”。
No.3 — DNS 查询(你造的失败案例)
| 字段 | 内容 |
|---|---|
Source | 10.2.73.219 |
Destination | 10.2.255.2 |
Info | Standard query 0x6ab5 A this-domain-does-not-exist-12345.com |
含义: 你执行 nslookup 不存在的域名时,电脑问 DNS:这个假域名 IP 是多少?
编号是 0x6ab5(和 No.1 的 0x73a6 不同,是另一次查询)。
方向: 你 → DNS,和 No.1 一样,是 query(提问)。
No.4 — DNS 响应(解析失败,重点)
| 字段 | 内容 |
|---|---|
Source | 10.2.255.2 |
Destination | 10.2.73.219 |
Info | Standard query response 0x6ab5 No such name … |
含义: DNS 回答 0x6ab5:No such name(没有这个名字)。
在 DNS 里这叫 NXDOMAIN(Non-Existent Domain):
域名在 DNS 系统里不存在,解析失败。
注意:
- 不是 DNS 服务器挂了(服务器正常回了包)
- 不是网络不通(有 query 也有 response)
- 是 这个域名本身不存在
终端 nslookup 通常会显示NXDOMAIN或can't find。
2.3 总结:
| 对比 | No.2(成功) | No.4(失败) |
|---|---|---|
查询 ID | 0x73a6 | 0x6ab5 |
域名 | api2.cursor.sh | this-domain-does-not-exist-12345.com |
Info 关键词 | CNAME、A 记录(有 IP) | No such name |
结果 | 解析成功 | NXDOMAIN,解析失败 |
后面 TCP | 可以连该 IP | 不会有 向该域名的正常 TCP |
2.3.1 四个包串成两条线
线 1(Cursor,正常):
- No.1 问 api2.cursor.sh
- No.2 答:有,CNAME + IP → 成功
线 2(你的测试,失败):
- No.3 问 this-domain-does-not-exist-12345.com
- No.4 答:No such name → 失败(NXDOMAIN)
2.3.2 排障时怎么写结论
针对 No.3 + No.4:
① 停在哪一层:DNS 层
② 证据:有 query 和 response,但 response 里是 No such name(NXDOMAIN)
③ 原因:域名不存在或写错,不是 TCP/HTTP 问题
3. 重传
快重传和超时重传都是 TCP 发现数据可能丢了之后,再发一遍 的机制。在 Wireshark 里能直接看到,但要 先有过丢包或迟迟收不到 ACK 的场景,下面分 怎么认 和 怎么抓 两部分说。
3.1 两种重传有什么区别
| 类型 | 什么时候发生 | Wireshark 常见标记 |
|---|---|---|
超时重传 | 等 ACK 超过一定时间(RTO),还没收到 | TCP Retransmission |
快重传 | 连续收到 3 个重复 ACK(Dup ACK) 后立刻重传 | 先 TCP Dup ACK,再 TCP Fast Retransmission |
超时重传: 发数据 → 等很久没 ACK → 再发一次(慢)
快重传: 发数据 → 对方连发 3 个相同 Ack → 马上补发丢失的那段(快)
本次 Connection refused 抓包中,No.22 与 No.21 的序号相同且仅相差约 26 微秒,属于回环接口重复捕获;Wireshark 将其启发式标记为重传,但不应作为超时重传证据。真正的 SYN 超时重传应表现为相同序号的 SYN 按约 1 秒或更长间隔重复发送,且始终没有收到 SYN-ACK 或 RST。
3.2 Wireshark 里用什么过滤器
打开 pcap 后,在顶部试这些(变绿就对了):
所有 TCP 重传(含超时重传、快重传、SYN 重传):
tcp.analysis.retransmission
只要快重传:
tcp.analysis.fast_retransmission
重复 ACK(快重传的前兆):
tcp.analysis.duplicate_ack
三种异常一起看:
tcp.analysis.duplicate_ack || tcp.analysis.fast_retransmission || tcp.analysis.retransmission
Wireshark 推断可能有段丢失(常和重传一起出现):
tcp.analysis.lost_segment3.3 超时重传过程
3.3.1 典型过程
- Connection refused:SYN → RST, ACK(端口未监听,通常很快返回)
Connection timeout(一直没有响应):
[SYN]
[TCP Retransmission] SYN
[TCP Retransmission] SYN
[TCP Retransmission] SYN
... 多次后 curl 才 Timeout
3.3.2 数据阶段的超时重传
[PSH, ACK] Seq=100 发数据
... 等很久,没收到 Ack ...
[TCP Retransmission] Seq=100 同一序号再发一次
认法: 同一个 Seq 出现两次及以上,第二次标 Retransmission,且中间 没有 先出现 3 个 Dup ACK。
3.4 快重传过程
3.4.1 典型顺序(传数据过程中丢了一包)
- 正常传包:Seq=1, 100, 200, 300 ...
- 假设 Seq=200 那段丢了
- 对方收到 300,发现缺 200,会反复发:Ack=200(我要 200 之后的数据)
- Wireshark 标:TCP Dup ACK #1、#2、#3(Ack 号相同)
- 你这边连收 3 个 Dup ACK 后:[TCP Fast Retransmission] Seq=200 立刻补发 200,不等超时
3.4.2 Info 列大概会看到
... [ACK] Ack=200
... [TCP Dup ACK #1]
... [TCP Dup ACK #2]
... [TCP Dup ACK #3]
... [TCP Fast Retransmission] Seq=200
认法: 先有至少 3 个 Dup ACK,紧接着 Fast Retransmission,且重传的 Seq 和丢的那段一致。
3.5 对照表:在图上怎么读
| 你想看 | 过滤器 | 看什么 |
|---|---|---|
所有重传 |
| Info 里 Retransmission |
快重传 |
| 紧跟 Dup ACK 之后 |
重复 ACK |
| 同一 Ack 连出现 3 次 |
SYN 超时重传 |
| 多个 SYN,Seq 相同 |
某次连接 | 先 | 缩小范围 |
4. HTTP 层错误
连接建好了,但 HTTP 状态码不是 2xx。
4.1 实操
练的 HTTP 404 场景,属于 应用层错误:网络和连接都正常,但我们故意要一个不存在的页面。
终端 1:
sudo tcpdump -i any -nn -s 0 -w ~/Desktop/fail-http404.pcap port 80终端 2:
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY all_proxy ALL_PROXY curl -v http://www.example.com/this-page-does-not-exist-404终端 1: 停抓,终端2这里会出现一个ip,过滤的时候用这个ip。
4.2 Wireshark 里看包
过滤部分输入 http 或 http.response.code >= 400,或者是看整个过程就用 ip.addr == 172.66.147.243(前面出现过的),就能看到 404 Not Found。
看整个过程,关注Info字段:
- No.5–7 TCP 三次握手 接通 80 端口
- No.8 HTTP GET 要 /this-page-does-not-exist-404
- No.9 TCP ACK 服务器确认收到请求
- No.10 服务器发数据 带 404 页面内容
- No.11 HTTP 404 Not Found 应用层报错:页面不存在
- No.12 TCP ACK 你确认收到响应
- No.13–15 TCP 四次挥手 断开连接
4.3 总结
4.3.1 和 Connection refused、DNS 失败对比
| 阶段 | 你这次 404 |
|---|---|
DNS | 已成功(否则不会有 172.66.147.243) |
TCP | No.5–7 握手成功 |
HTTP | No.8 请求发出,No.11 返回 404 |
结论 | 应用层 URL 错,不是网络层连不上 |
4.3.2 常见 HTTP 错误码(了解)
| 状态码 | 含义 |
|---|---|
200 | 成功 |
404 | 页面/路径不存在 |
403 | 禁止访问(权限) |
500 | 服务器内部错误 |
502/503 | 网关错误 / 服务不可用 |
过滤器:http.response.code >= 400
可看所有 4xx、5xx 错误响应。
4.3.3 结论模板
① 停在哪一层:HTTP 层
② 证据:TCP 握手完整,有 GET,响应为 404 Not Found
③ 原因:请求路径不存在,检查 URL 是否正确
5. HTTPS / TLS 握手失败
TCP 443 通了,但 TLS 握手没完成,看不到正常 Application Data。
常见情况(了解即可)
- 证书错误(curl 会报错)
- 用 HTTP 去连 HTTPS 端口(协议不对)
- 中间设备劫持
终端 1:
sudo tcpdump -i any -nn -s 0 -w ~/Desktop/fail-tls.pcap port 443终端 2:
# 故意用明文 HTTP 去连 443(很多服务器会断开或乱码) curl -v http://www.example.com:443没有看到handshake环节
怎么认
| 现象 | 含义 |
|---|---|
有 TCP 握手,无正常 TLS | TLS 层失败 |
curl 报 SSL/TLS error | 加密协商或证书问题 |
明文 HTTP 打 443 | 协议用错 |
结论模板
TCP 通了,TLS 没建好:查 https/http 是否混用、证书、代理。