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 连接都有发送缓冲区和接收缓冲区。如果缓冲区满了,数据就发不出去。这是排查“应用层发了数据,但对端没收到”的关键。
  • 路由表:决定数据包从哪个网卡出去,下一跳是谁。路由错了,一切白搭。

下面这张图,是我每次培训都会画的。它把调试工具和协议栈的对应关系标了出来,你一看就明白该在哪个环节用什么工具。

TCP/IP 协议栈与调试工具对应关系 TCP/IP 协议栈与调试工具对应关系 应用层 (Application) HTTP, MQTT, CoAP, Modbus TCP 工具: netstat, ss, curl 传输层 (Transport) TCP, UDP, SCTP 工具: netstat, ss, tcpdump 网络层 (Network) IP, ICMP, ARP 工具: tcpdump, iptables, route 链路层 (Link) 以太网, WiFi, PPP 工具: tcpdump, ethtool, ifconfig 调试思路: 1. 先确认应用层是否正常(netstat/ss 看端口监听) 2. 再抓传输层包确认 TCP 握手/挥手(tcpdump) 3. 最后检查网络层路由和防火墙(iptables/route)

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% 的网络问题了。

记住我的一句话:调试网络问题,不要猜,要看数据。 用好这些工具,让数据说话。