3. 网络协议栈调试(一):TCP/IP协议栈核心概念回顾、netstat与ss命令深度使用、tcpdump抓包分析基础、iptables规则调试与日志
各位工程师朋友,欢迎来到第三章。这一章我们正式进入网络协议栈调试的世界。说实话,TCP/IP 协议栈是嵌入式 Linux 网关的灵魂,也是出问题最多的地方。我见过太多同事在协议栈问题上抓耳挠腮,其实很多时候,只是工具没用对,或者对底层概念理解不够深。
今天,我们先打好基础。把核心概念过一遍,再把几个最常用的调试工具——netstat、ss、tcpdump、iptables——用透。嗯,别小看这些“老家伙”,用好了,能解决 80% 的网络问题。
3.1 TCP/IP 协议栈核心概念回顾
在动手调试之前,脑子里得有一张清晰的协议栈地图。我习惯把 TCP/IP 协议栈想象成一个“数据包加工流水线”。
核心要点:数据从应用层一路向下,每层加一个头(封装),到达对端后,每层剥一个头(解封装)。调试的本质,就是检查这个“封装/解封装”过程在哪一步出了问题。
我们重点回顾几个调试中经常打交道的概念:
- MTU(最大传输单元):链路层限制。以太网通常是 1500 字节。如果 IP 包超过 MTU,就会分片。分片是很多诡异问题的根源,我曾经在一个 4G 网关上被分片重组问题折腾了两天。
- TCP 状态机:
LISTEN、SYN_SENT、ESTABLISHED、FIN_WAIT1、TIME_WAIT…… 每个状态都对应一个特定的阶段。用netstat看状态,基本能猜出连接卡在哪。 - Socket 缓冲区:每个 TCP 连接都有发送缓冲区和接收缓冲区。如果缓冲区满了,数据就发不出去。这是排查“应用层发了数据,但对端没收到”的关键。
- 路由表:决定数据包从哪个网卡出去,下一跳是谁。路由错了,一切白搭。
下面这张图,是我每次培训都会画的。它把调试工具和协议栈的对应关系标了出来,你一看就明白该在哪个环节用什么工具。
3.2 netstat 与 ss 命令深度使用
这两个命令是查看网络连接状态的“眼睛”。netstat 是经典工具,ss 是它的现代替代品,性能更好,信息更全。我个人现在基本只用 ss,但在一些老系统上,netstat 还是得会。
3.2.1 netstat 常用场景
先看几个我工作中最常用的 netstat 用法:
# 查看所有监听中的 TCP 端口
netstat -tlnp
# 查看所有已建立的 TCP 连接
netstat -tunp | grep ESTABLISHED
# 查看路由表信息
netstat -rn
# 查看网络接口统计(丢包、错误)
netstat -i
小技巧:-t 表示 TCP,-u 表示 UDP,-l 表示监听,-n 表示数字显示(不解析域名),-p 显示进程 PID。这几个选项组合起来,基本能覆盖 90% 的排查场景。
我记得有一次,客户反馈网关的某个服务连不上。我 SSH 上去,第一件事就是跑 netstat -tlnp。结果发现,服务进程根本没在监听端口。原来是启动脚本里有个环境变量没传对,服务启动失败但没报错。你看,一个命令就定位了问题。
3.2.2 ss 命令:更现代、更快速
ss 直接从内核的 socket 信息中读取数据,比 netstat 快得多。尤其是在连接数上万的时候,netstat 会卡死,ss 依然秒出。
# 查看所有 TCP socket(包括监听和已建立)
ss -tlnp
# 查看所有 UDP socket
ss -ulnp
# 查看 socket 的详细信息(包括缓冲区大小)
ss -tlnpi
# 按状态过滤(比如只看 TIME_WAIT)
ss -tlnp state time-wait
这里有个参数 -i,能显示 TCP 连接的内部信息,比如拥塞窗口、慢启动阈值、RTT 等。这在排查 TCP 性能问题时非常有用。
对比总结:
| 特性 | netstat | ss |
|---|---|---|
| 数据来源 | /proc/net/tcp 等 | 内核 netlink 接口 |
| 性能 | 连接数多时慢 | 快,适合高并发 |
| 信息详细度 | 基础信息 | 支持 TCP 内部状态 |
| 推荐场景 | 老系统、简单查看 | 日常调试、性能分析 |
3.3 tcpdump 抓包分析基础
如果说 netstat/ss 是“看门牌号”,那 tcpdump 就是“看快递内容”。它能抓到网卡上流过的每一个数据包,是协议栈调试的终极武器。
很多新手觉得 tcpdump 输出太乱,看不懂。其实只要掌握几个核心过滤表达式,就能精准定位问题。
3.3.1 基本抓包语法
# 抓取 eth0 网卡上的所有包
tcpdump -i eth0
# 抓取指定主机的包(host 过滤)
tcpdump -i eth0 host 192.168.1.100
# 抓取指定端口的包(port 过滤)
tcpdump -i eth0 port 80
# 抓取指定协议的包(proto 过滤)
tcpdump -i eth0 tcp
# 组合过滤:抓取从 192.168.1.100 发往 80 端口的 TCP 包
tcpdump -i eth0 tcp and src host 192.168.1.100 and dst port 80
注意:在嵌入式设备上抓包,要小心 CPU 和存储。我曾经在一个只有 64MB 内存的网关上抓包,没加 -c 限制,结果抓了几分钟,系统直接 OOM 了。建议加上 -c 100(抓 100 个包后停止)或者 -W 轮转文件。
3.3.2 常用选项
| 选项 | 作用 | 示例 |
|---|---|---|
-i |
指定网卡 | -i eth0 |
-n |
不解析域名(加快速度) | -n |
-v |
显示更详细信息 | -v |
-X |
以十六进制和 ASCII 显示包内容 | -X |
-w |
保存到文件(供 Wireshark 分析) | -w dump.pcap |
-r |
读取文件 | -r dump.pcap |
3.3.3 实战案例:排查 TCP 重传
TCP 重传是网络不稳定的典型信号。用 tcpdump 可以一目了然:
# 抓包并显示 TCP 标志位
tcpdump -i eth0 -n tcp and host 192.168.1.100
# 输出中看到类似下面的内容,就是重传
# 17:23:45.123456 IP 192.168.1.100.12345 > 10.0.0.1.80: Flags [S], seq 100, ...
# 17:23:46.234567 IP 192.168.1.100.12345 > 10.0.0.1.80: Flags [S], seq 100, ... (重传!)
看到同一个 seq 号出现两次,基本就是重传了。这时候就要检查链路质量、MTU 设置、或者对端是否存活。
3.4 iptables 规则调试与日志
iptables 是 Linux 内核的防火墙工具,也是网络层调试的“总开关”。很多网络不通的问题,最后都查到是 iptables 规则把包丢了。
我调试 iptables 的核心思路是:先放行,再收紧。先把所有规则清空,确认网络能通,然后一条一条加规则,加一条测一条。
3.4.1 查看当前规则
# 查看所有规则(默认 filter 表)
iptables -L -n -v
# 查看 NAT 表规则
iptables -t nat -L -n -v
# 查看规则序号(方便插入/删除)
iptables -L --line-numbers
-v 选项会显示每个规则匹配了多少个包。如果某个规则的 pkts 列一直是 0,说明规则没生效,或者流量没走到这条链上。
3.4.2 添加日志规则
这是调试 iptables 最强大的技巧。在关键位置加一条 LOG 规则,把匹配到的包信息打印到内核日志(dmesg 或 /var/log/kern.log)。
# 在 INPUT 链添加日志规则,记录所有发往 80 端口的包
iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix "IPTABLES-DEBUG: "
# 查看日志
dmesg | tail -20
# 输出类似:
# [12345.678901] IPTABLES-DEBUG: IN=eth0 OUT= MAC=... SRC=192.168.1.100 DST=10.0.0.1 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=0 PROTO=TCP SPT=54321 DPT=80 WINDOW=65535 RES=0x00 SYN URGP=0
避坑指南:我曾经在调试时,忘了在 LOG 规则后面加 ACCEPT 或 DROP。结果 LOG 规则匹配后,包就继续往下走,被后面的规则处理了。LOG 规则本身不会终止包的匹配,它只是“看一眼,记下来”。所以,LOG 规则通常放在 ACCEPT 或 DROP 规则之前。
3.4.3 常用调试场景
这里列几个我经常用的调试命令组合:
# 场景1:检查某个端口是否被防火墙拦截
# 先清空规则(谨慎!)
iptables -F
# 然后测试端口连通性
# 如果通了,说明是防火墙问题
# 场景2:跟踪某个 IP 的流量
iptables -I INPUT -s 192.168.1.100 -j LOG --log-prefix "FROM-192.168.1.100: "
iptables -I OUTPUT -d 192.168.1.100 -j LOG --log-prefix "TO-192.168.1.100: "
# 场景3:查看 NAT 转换是否生效
iptables -t nat -L -n -v
3.5 本章小结
这一章我们回顾了 TCP/IP 协议栈的核心概念,重点掌握了四个调试工具:
- netstat/ss:看连接状态,查端口监听,找进程对应关系。
- tcpdump:抓包看细节,确认数据包是否发出、是否收到、有没有重传。
- iptables:控制流量走向,加日志定位丢包点。
这些工具是协议栈调试的“基本功”。下一章,我们会深入更复杂的场景,比如 TCP 连接异常、DNS 解析问题、以及如何用 Wireshark 做离线分析。但今天的内容,足够你解决日常工作中 80% 的网络问题了。
记住我的一句话:调试网络问题,不要猜,要看数据。 用好这些工具,让数据说话。