写在前面
上一篇把 NAT、DHCP 这些“地址怎么来、怎么转换”的机制讲完了,五层模型从下到上的协议也就齐了。但会背协议和“真的会排障”是两回事——线上一个“网站打不开”,到底是 DNS 挂了、网关不通、端口被占,还是应用自己炸了?
本篇是系列收官,目标是把前十二篇的原理落到工具上:先给一张网络诊断工具速查表,再重点拆 tcpdump 和 Wireshark,最后给一套按层排查的连通性方法论。结尾会把整个 TCP/IP 系列串一遍,并指向本站相关的实战文章。
一、工具速查表
先一张总表,每层对应的常用工具:
| 层 | 工具 | 解决什么问题 |
|---|---|---|
| 网络层 | ping | 连通性 + RTT(基于 ICMP Echo) |
| 网络层 | traceroute / mtr | 观察探测路径与逐跳响应,辅助定位异常区间(基于 TTL) |
| 传输层 | ss / netstat | 连接状态、监听端口、TIME_WAIT 堆积 |
| 应用层 | dig / nslookup / host | DNS 解析是否正常 |
| 全层 | tcpdump | 抓包,看链路上真实在跑什么 |
| 全层 | Wireshark | 读 pcap、按协议分层解析、交互式过滤 |
下面挑最常用的逐个说清楚。
ping:连通性与 RTT
ping 发 ICMP Echo Request,对端回 ICMP Echo Reply,用来判断可达性和往返延迟(RTT) 。
| |
读懂输出:ttl 是应答到达你时剩余的跳数;只有先假设对端使用了某个常见初始 TTL,才能粗略估计回程跳数,而且回程路由可能与去程不同。time 是 RTT,丢包率是重要指标。注意 ping 不通不等于网络断了——很多服务器 / 防火墙会禁掉 ICMP,HTTP 服务照样能访问。
traceroute / mtr:逐跳路径
ping 只能观察目标是否回应特定 ICMP 探测;traceroute 则通过各跳返回的 ICMP 响应观察一条可能的探测路径,帮助缩小异常范围,但不能单凭某一跳不回应就断定业务包在那里丢失。原理是利用 IP 头里的 TTL:
- 先发一个 TTL=1 的包,第一跳路由器收到后 TTL 减到 0,丢弃并回 ICMP Time Exceeded;
- 再发 TTL=2 的包,第二跳路由器回 Time Exceeded;
- 如此递增,直到到达目的或超时。
| |
平台差异要注意:Linux 的 traceroute 默认发 UDP 包到高端口(33434 起),Windows 的 tracert 默认发 ICMP Echo。有的路由器只对 ICMP 放行、对 UDP 高端口丢包,所以同一目标两边结果可能不同。
mtr(my traceroute)结合了持续探测与逐跳统计,实时显示各跳响应率和延迟,是常用的路径诊断工具。中间节点可能限制 ICMP 回包;若某一跳显示丢包而后续节点和最终目标正常,通常不能认定业务流量在该跳丢失:
| |
一个常见误读:中间某跳显示丢包,但后面几跳正常——这往往是该路由器对 ICMP 限速(control-plane policing),不是真丢包。看最终目的的丢包率才靠谱。
ss / netstat:连接状态与监听端口
netstat 是老牌工具,现代 Linux 发行版通常推荐使用 ss(socket statistics)。两者有一部分相似的短参数,但语法、过滤能力和输出并不完全兼容。排查“端口被谁占了”“连接建立没建立”“TIME_WAIT 是不是爆了”都可以用到它们。
| |
经典场景:服务起不来报 Address already in use,用 ss -tlnp | grep :8080 看端口被哪个进程占着;短连接打多了,ss -s 里 TIME-WAIT 几万条,就是连接复用要做优化了(详见 TCP 那篇的状态机)。
dig / nslookup / host:DNS
“能访问 IP、按域名访问失败”时,DNS 是优先检查项之一,但 Host / SNI、代理、虚拟主机和应用配置也可能造成相同表象。三个工具各有侧重:
| |
排 DNS 时常用 dig @指定DNS 域名 对比。不同解析器结果不一致,说明问题与解析路径有关,可能是本地缓存或配置,也可能是 split-horizon、区域调度、DNS 劫持或不同解析器命中了不同 CDN 节点,需要结合权威记录和业务预期继续判断。
二、tcpdump:抓包与过滤语法
上面这些工具都是"问别人",tcpdump 是直接看链路上跑的原始字节。它是网络排障的终极武器,也是 Wireshark 抓包数据的命令行来源。
基本用法
| |
习惯上排障时用 tcpdump -i any -nn 监听所有网卡、不解析名字,先看清流量再说。
过滤表达式(BPF 语法)
tcpdump 用的是 BPF(Berkeley Packet Filter)表达式,逻辑是"按条件筛选包"。这套语法也适用于 Wireshark 的抓包过滤器(capture filter,注意和显示过滤器 display filter 不是一回事)。核心原语:
| 原语 | 含义 | 示例 |
|---|---|---|
host | 源或目的是某 IP | host 8.8.8.8 |
src host / dst host | 只匹配源 / 目的 | src host 192.168.1.10 |
net | 匹配网段 | net 192.168.1.0/24 |
port | 源或目的是某端口 | port 80 |
src port / dst port | 只匹配源 / 目的端口 | dst port 443 |
tcp / udp / icmp | 按协议 | tcp and port 80 |
and / or / not | 逻辑组合 | host A and port 80 |
实战组合:
| |
TCP 标志位的写法要特别说明:tcp[tcpflags] 是 TCP 头里标志字段,后面跟位掩码 &。可用的标志常量是 tcp-fin、tcp-syn、tcp-rst、tcp-push、tcp-ack、tcp-urg。想抓"某组合位都被置上",用 == (tcp-syn|tcp-ack);想抓"只要含某位",用 & tcp-syn != 0。
语法细节参考官方 pcap-filter(7) man page。记住一点:tcpdump 的过滤表达式和 Wireshark 的显示过滤器是两套语法 。tcpdump 过滤(BPF)在抓包时就生效,决定哪些包写入 pcap;Wireshark 显示过滤是抓完之后再筛,语法完全不同(如
ip.addr == 8.8.8.8)。
三、Wireshark:分层解析利器
tcpdump 适合在服务器上快速看一眼,真正要"逐字段拆解协议",还得靠 Wireshark。典型工作流是:服务器上 tcpdump -w 存成 pcap → 下载到本地用 Wireshark 打开。
Wireshark 的核心能力是按协议分层展开一个包:点开一个帧,能看到以太网头、IP 头、TCP 头、HTTP 报文逐层嵌套,每一层的每个字段(TTL、序号、标志位、窗口大小……)都标好了含义——正好对应第一篇讲的封装。
显示过滤器(Display Filter)
Wireshark 的显示过滤器是一套独立语法,比 BPF 强大得多:
| 过滤表达式 | 含义 |
|---|---|
ip.addr == 8.8.8.8 | 源或目的是 8.8.8.8 |
tcp.port == 443 | TCP 端口 443 |
tcp.flags.syn == 1 | SYN 标志位置 1 |
tcp.flags.reset == 1 | RST 包 |
dns | 所有 DNS 报文 |
http.request.method == "GET" | HTTP GET 请求 |
tls.handshake.type == 1 | TLS ClientHello |
还能按协议右键某个字段 → “作为过滤器应用”,组合条件非常方便。
常用排障视角
- TCP 流跟踪:右键一个 TCP 包 → Follow → TCP Stream,把一个连接的请求 / 响应整理成可读的对话,看 HTTP 在裸 TCP 上是怎么一来一回的。
- 统计 → 会话(Conversations):列出所有连接的端点、包数、字节数,快速发现"谁在异常大量通信"。
- 统计 → IO 图表:按时间画吞吐量曲线,定位性能毛刺。
Wireshark 配合前十二篇的协议知识,基本是"协议的活体解剖"——你能在里面亲眼看到三次握手、TLS 握手、HTTP 请求头、DNS 查询响应。
四、分层连通性排障方法论
工具会用了,关键是怎么有章法地用 。网络问题的典型困境是:现象一样(“连不上”),原因五花八门。乱试一通效率极低,正确做法是沿协议栈自底向上逐层排除,在哪一层断了就停在那查。
| |
每一层的判断准则:这一层通了,才往上查;这一层不通,先修这一层 。原因很简单——下面断了,上面必然全断;下面不通时去调应用,纯属浪费时间。
每层的关键检查项
物理层:看网卡灯、ethtool eth0 看链路是否 up、有没有大量物理层错误。云服务器里这层基本是虚拟的,可跳过。
链路层:ip neigh(旧 arp -n)看 ARP 表,目标 IP 的 MAC 学到了吗?ip -s link 看网卡有没有 RX/TX 丢包、错误帧。VLAN、二层隔离的问题也在这层。
网络层:
ping 网关通吗?不通说明本机到网关就有问题(链路层或本机配置)。ping 8.8.8.8有回应吗?有回应只说明这条 ICMP 路径此刻可达,不代表所有出口协议和目标都正常;无回应时可换目标并结合traceroute/mtr观察异常从哪一段开始持续出现。ip route看默认路由在不在、对不对。
传输层:
ss -tlnp确认服务真的在监听那个端口、那个地址(监听127.0.0.1:8080是连不上外部访问的)。nc -zv host port或telnet host port测端口可达性。ss -s看连接状态,TIME_WAIT / CLOSE_WAIT 堆积是常见病。
应用层:
dig验证 DNS。curl -v看完整的 HTTP / TLS 交互,分清是 DNS、连接、TLS 还是应用层返回错误。- 看应用自身日志——很多"网络问题"最后是应用抛的异常。
五、实战:网站打不开怎么按层排查
把方法论套到一个真实场景。假设用户反馈 https://api.example.com 打不开,按层走一遍:
1. 物理层 / 链路层(先确认本机网络没断)
| |
本机到网关正常,底层没问题。
2. 网络层(确认出网正常)
| |
能 ping 通某个公网 IP,说明到该目标的 ICMP 往返路径可达,但不能据此断言整个网络层或所有出口策略都正常。如果这步异常,可更换探测目标,并用 mtr -n 8.8.8.8 观察异常是否从某一跳开始延续到最终目标。
3. 应用层 - DNS(域名能解析吗)
| |
定位到 DNS 路径差异后,再检查本机、递归解析器和权威记录。使用 systemd-resolved 的新系统可执行 resolvectl flush-caches;DNS 配置通常由 NetworkManager、systemd-resolved 或 DHCP 管理,不要在未确认管理方式前直接修改可能被自动覆盖的 /etc/resolv.conf。
4. 传输层(端口可达吗,假设 DNS 修好了拿到 IP)
| |
端口通说明 TCP 层没问题。如果这里超时,多半是对端没监听、被防火墙拦或本机出口被限。
5. 应用层 - HTTP/TLS(服务正常响应吗)
| |
curl -v 会展示连接、TLS 握手和 HTTP 请求响应等阶段。失败阶段能帮助确定优先排查方向,但跨层依赖和中间设备会让同一根因表现为不同阶段失败,不能把它当成严格的一一映射。这里若是 TLS 失败,应继续检查证书、时间、SNI 和协议协商;若收到 HTTP 500,说明请求已经到达某个 HTTP 服务,重点转向应用及其后端依赖。
整个过程对应的方法论就是:从下到上逐层排除,用工具验证每一层的假设,定位到具体层后再深入 。比起一上来就重启服务、瞎改配置,这套方法省时得多。
小结
- 网络诊断要按层排查:物理 → 链路(ARP/MAC)→ 网络(ping/路由/traceroute)→ 传输(端口/TIME_WAIT)→ 应用(DNS/HTTP/TLS),一层通了才往上查。
- ping 观察 ICMP 可达性与 RTT,traceroute / mtr 观察探测路径和异常区间,ss / netstat 看连接与端口,dig 查 DNS。
- tcpdump 是抓包终极武器,过滤用 BPF 语法(
host/port/tcp[tcpflags] & tcp-syn),存成 pcap 交给 Wireshark。 - Wireshark 按协议分层展开,配合系列前十二篇的知识能看懂每个字段;显示过滤器是独立语法,别和 BPF 混。
系列总结
十三篇,从"为什么要分层"到"怎么抓包排障",TCP/IP 的主干终于串完了。回顾整个系列,可以浓缩成一条主线:数据在发送端被逐层封装,在接收端被逐层解封装,每一层只解决自己的问题 。
| 篇 | 主题 | 一句话要点 |
|---|---|---|
| 1 | 分层模型 | OSI 七层是参考、TCP/IP 四层贴实际、五层是教学折中 |
| 2–3 | 链路层 | 以太网帧 + MAC 地址,ARP 把 IP 翻译成 MAC,交换机按 MAC 转发 |
| 4–6 | 网络层 | IP 编址与子网划分,路由怎么选路,ICMP 反馈通断 |
| 7–9 | 传输层 | TCP 三次握手 / 四次挥手 / 状态机,可靠性与流控拥塞控制,UDP 轻量无连接 |
| 10–11 | 应用层 | DNS 分层解析与缓存,HTTP 语义、连接复用与 TLS |
| 12 | 地址机制 | NAT/NAPT 改写地址省公网 IP,DHCP 自动分配 IP,CGNAT 让家网失去公网 IP |
| 13 | 诊断方法论 | 工具速查 + 按层排障 |
把这些拼起来,一个 HTTP 请求的全貌就是:
| |
每一步都对应系列里某一篇的原理。理解了这条链,再回头看平时写的后端代码,很多"玄学问题"就有了着落。
网络是后端、云原生、分布式共同的地基,本站还有几篇从应用侧把网络用起来的实战文章,正好衔接:
- HttpClient 的前世今生:从 Socket 耗尽到 .NET 8 韧性管线 ——传输层连接池、Socket 耗尽、DNS 刷新在工程里怎么踩坑怎么治。
- epoll 的前世今生:从 select/poll 到 io_uring ——高并发下传输层的 I/O 复用是怎么演进的。
- 跟着一个 API 请求走完全程:后端全链路解剖 ——把本系列的网络层和业务代码、中间件串起来看。
- .NET 高并发编程全景:从异步到高性能实战 ——传输层之上,应用怎么榨干单机的并发能力。
TCP/IP 系列到此完结。原理是死的,排障是活的——希望你下次遇到网络问题时,能从容地掏出这套分层方法论,而不是只会重启服务。
参考: