IP 实战与排错 — 网际协议

Wireshark IP 过滤式、ip/ping/traceroute/mtr 命令、MTU 黑洞与路由不对称排查 / 网络层 / RFC 791、RFC 8200

这篇你能学到

  • 看一眼 IP 头就能推断四件事:过了几跳、对端是什么操作系统、路径上有没有发生分片、是不是快撞上 MTU 上限了。
  • 握住三把最有用的工具ip route get(让内核直接告诉你这个包会怎么走)、ping -M do -s(二分法量出真实路径 MTU)、mtr(定位丢包发生在第几跳)。
  • 啃得动八类典型故障:MTU 黑洞(小包通大包断)、ping 通但业务不通、traceroute 满屏星号、地址变成 169.254、大量分片、三种 Unreachable 的区分、路由环路、多网卡回包走错。

1. 抓包观察

1.1 Wireshark 显示过滤式

这张表按用途分了几档:地址类用来框范围,TTL 类用来查环路和推 OS,分片/DF 类用来查 MTU 问题,协议号类用来按上层筛。排错起手式建议永远是 ip.addr == <目标>,它同时抓双向,比 src/dst 省事。

过滤式作用
ip / ipv6所有 IPv4 / IPv6 包
ip.addr == 10.0.0.5与该地址相关的双向流量(排错首选,比 src/dst 更省事)
ip.src == 10.0.0.5 && ip.dst == 8.8.8.8单方向定向过滤
ip.addr == 192.168.1.0/24整个网段
ip.ttl < 5TTL 即将耗尽,怀疑路由环路
ip.ttl == 64 || ip.ttl == 128判断是否为直连(未经路由)流量、推断源端 OS
ip.flags.df == 1设置了 DF 的包(PMTUD 相关)
ip.flags.mf == 1 || ip.frag_offset > 0所有分片包(排查分片问题的标准式)
ip.fragment.count > 1Wireshark 已重组的多片数据报
ip.len > 1500超大包(可能是巨帧或 TSO/LRO 卸载导致的抓包假象)
ip.proto == 6 / == 17 / == 1 / == 47按上层协议筛:TCP / UDP / ICMP / GRE
ip.dsfield.dscp == 46EF(语音)流量,QoS 验证
ip.dsfield.ecn == 3ECN CE 置位,路径出现拥塞
ip.checksum.status == "Bad"头部校验错误(注意:网卡校验卸载会产生大量误报,需在首选项中关闭校验验证)
ip.hdr_len > 20携带 IP Options 的包
icmp.type == 3 && icmp.code == 4Fragmentation Needed,MTU 问题的铁证
ipv6.nxt == 44IPv6 分片扩展头
ipv6.flow != 0带流标签的 IPv6 包

捕获过滤式(BPF)host 10.0.0.5net 192.168.1.0/24ip proto 47ip[6:2] & 0x3fff != 0(抓所有分片)。这些在抓包时就把无关流量丢掉,适合长时间挂机采集。

1.2 典型字段判读

下面这段是 Wireshark 展开一个 IPv4 头部的样子,右边的注释就是排错时该盯的位置——照着这几行看,一个包能告诉你的信息比想象中多得多:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Internet Protocol Version 4, Src: 192.168.1.10, Dst: 172.16.1.100
    0100 .... = Version: 4
    .... 0101 = Header Length: 20 bytes (5) ← IHL=5 表示无 Options
    Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
    Total Length: 1500 ← 达到 MTU 上限,注意分片风险
    Identification: 0x1c46 (7238) ← 同一数据报各分片相同
    Flags: 0x02 (Don't Fragment) ← DF=1,触发 PMTUD
    Fragment Offset: 0
    Time to Live: 62 ← 初值 64 → 已过 2 跳
    Protocol: TCP (6)
    Header Checksum: 0x0000 [validation disabled]

看 IP 头能得到的四条关键信息

  1. TTL 推跳数与 OS:64→Linux/macOS,128→Windows,255→网络设备;初值 − 实测值 = 跳数
  2. DF + Total Length 接近 MTU → 排查 PMTUD/MTU 黑洞的信号。
  3. MF=1 或 Offset>0 → 路径上发生了分片,需评估丢包放大风险。
  4. 同一会话 TTL 忽高忽低 → 存在多路径(ECMP)或路由震荡。

2. 常用命令 / 配置

2.1 地址与接口(Linux,iproute2)

这组命令能干什么:看清"这台机器上有哪些地址、挂在哪块网卡、MTU 多大、有没有收发错误"。排 MTU 问题时改 MTU 那一行是关键操作;最后一条的 errors/dropped 计数则常常是物理层/驱动层问题的第一个线索。

1
2
3
4
5
6
7
8
ip addr show # 查看所有接口地址(简写 ip a)
ip -4 addr show dev eth0 # 只看 IPv4
ip -6 addr show # 只看 IPv6
ip addr add 192.168.1.50/24 dev eth0 # 临时加地址
ip addr del 192.168.1.50/24 dev eth0
ip link set eth0 up # 启用接口
ip link set eth0 mtu 1400 # 修改 MTU(排 MTU 问题的关键操作)
ip -s link show eth0 # 接口收发包与错误统计(errors/dropped 是排错重点)

2.2 路由(排错核心)

这组命令能干什么:回答"这个包到底会往哪走"。重点是 ip route get——show 只是把规则列给你,还得自己脑补最长前缀匹配和策略路由;get 则直接让内核给出实际结论:选了哪个源 IP、下一跳是谁、从哪个口出去。多网卡、多路由表环境下,这一条能顶十条。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
ip route show # 查看路由表(简写 ip r)
ip route show table all # 含所有策略路由表
ip route get 8.8.8.8 # 最有用内核实际会怎么走这个包(源IP、下一跳、出接口一次看全)
ip route get 8.8.8.8 from 10.0.0.5 # 指定源地址做决策模拟

ip route add 10.10.0.0/16 via 192.168.1.254 dev eth0 # 加静态路由
ip route add default via 192.168.1.1 # 加默认路由
ip route del 10.10.0.0/16
ip route replace default via 192.168.1.2 metric 100

ip rule show # 策略路由规则(多网卡/多出口环境必查)
ip route show table 100

# 开启转发(做路由器/NAT 网关时必需)
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1

2.3 连通性与路径探测

这组命令能干什么:分三件事。ping 测通不通;带 -M do -sping用二分法量出这条路最多能过多大的包(负载 + 28 就是 MTU);traceroute / mtr 则回答"路径长什么样、丢包丢在第几跳"。实战中优先用 traceroute -T -p 443,因为它走 TCP,最贴近真实业务路径,不容易被针对 UDP/ICMP 的限速误导。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
ping -c 4 8.8.8.8
ping -c 4 -I eth0 8.8.8.8 # 指定出接口
ping -c 4 -t 5 8.8.8.8 # 指定 TTL

# MTU 探测:-M do 设置 DF,-s 指定负载大小
# 负载 1472 + ICMP头8 + IP头20 = 1500
ping -c 3 -M do -s 1472 8.8.8.8 # 通过 → 路径 MTU ≥1500
ping -c 3 -M do -s 1372 8.8.8.8 # 二分逼近,找到最大可通值 +28 即 PMTU

traceroute 8.8.8.8 # 默认 UDP 探测
traceroute -I 8.8.8.8 # ICMP 探测(部分网络只放行 ICMP)
traceroute -T -p 443 example.com # TCP 探测,最能反映真实业务路径(绕过 UDP/ICMP 限速)
traceroute -n 8.8.8.8 # 不做反解,快很多
tracepath 8.8.8.8 # 自带 PMTU 发现,会打印 pmtu 值

mtr -rwc 100 8.8.8.8 # 持续探测+丢包统计,定位丢包发生在第几跳
mtr -T -P 443 example.com # TCP 模式

traceroute 结果判读要点:中间跳显示 * * * 不一定是故障——很多路由器限速或禁用 ICMP Time Exceeded 回复。只有最后一跳不通才算真故障;中间某跳丢包但后续跳正常,也属正常现象(该跳只是控制平面响应慢,转发平面正常)。

2.4 抓包

这组命令能干什么:按不同维度把包捞出来。前两条按地址/网段捞;第三条 ip[6:2] & 0x3fff != 0抓所有分片包的标准写法(它直接看 Flags+Offset 那两个字节);第四条抓所有不可达报文,MTU 通知就藏在里面;最后一条按 TTL 小于 5 捞,专门用来查环路。

1
2
3
4
5
6
7
sudo tcpdump -i eth0 -nn host 10.0.0.5
sudo tcpdump -i eth0 -nn net 192.168.1.0/24
sudo tcpdump -i eth0 -nn -v 'ip[6:2] & 0x3fff != 0' # 抓所有分片包
sudo tcpdump -i eth0 -nn 'icmp[icmptype] == 3' # 抓所有不可达(含 MTU 通知)
sudo tcpdump -i eth0 -nn -v 'ip proto 47' # GRE
sudo tcpdump -i eth0 -nn 'ip[8] < 5' # TTL < 5,查环路
sudo tcpdump -i eth0 -w ip.pcap -s 0 host 10.0.0.5 # 存盘全量

2.5 Windows

这组命令能干什么:Windows 上做同样的三件事——看地址与路由、探测路径、处理 MTU。其中 pathping 相当于 tracert 加丢包统计(近似 mtr);ping -f -l-f 就是 DF 位,等价于 Linux 的 -M do;最后两条用来查看和永久修改接口 MTU。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
ipconfig /all
route print
Get-NetRoute -AddressFamily IPv4
Get-NetIPAddress
Test-NetConnection 8.8.8.8 -TraceRoute
tracert -d 8.8.8.8
pathping 8.8.8.8 # 结合 tracert 与丢包统计
ping -f -l 1472 8.8.8.8 # -f 即 DF,探测 MTU
netsh interface ipv4 show subinterfaces # 查看各接口 MTU
netsh interface ipv4 set subinterface "以太网" mtu=1400 store=persistent
New-NetRoute -DestinationPrefix 10.10.0.0/16 -InterfaceAlias "以太网" -NextHop 192.168.1.254

3. 常见故障与排错

3.1 现象:小包能通,大包卡死(网页转圈、SSH 登录后一敲 ls 就挂)

先记住结论“小包通、大包断"这八个字直接指向 MTU 黑洞,不要再怀疑"网络不稳定”。 根因是路径上有小 MTU 链路,而"你的包太大了"这条 ICMP 通知被防火墙吃掉了,发送方蒙在鼓里一直发大包。

这是 MTU 黑洞的典型特征,也是最容易被误判为"网络不稳定"的故障。

原因:路径中存在小 MTU 链路(VPN/GRE/PPPoE),而中间防火墙把 ICMP Type 3 Code 4 全部丢弃,发送方无法感知,持续发送超大包被静默丢弃。

排查

三步走:先用二分法量出这条路真实能过多大的包,再抓包确认"包太大"的通知是不是根本没回来,最后从 TCP 重传特征上交叉验证。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 1. 二分法定位真实 PMTU
ping -M do -s 1472 目标 # 失败
ping -M do -s 1400 目标 # 失败
ping -M do -s 1372 目标 # 成功 → PMTU ≈ 1372+28 = 1400

# 2. 抓包确认有没有收到 ICMP 通知
sudo tcpdump -i eth0 -nn 'icmp[icmptype]==3 and icmp[icmpcode]==4'
# 一个都没有 → 确认是黑洞

# 3. Wireshark 侧:过滤 tcp.analysis.retransmission,看是否总是同一大小的包在重传

处置:调小接口 MTU(ip link set eth0 mtu 1400);在网关上做 MSS Clampingiptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu);放行 ICMP Type 3 Code 4(根治手段,切勿一刀切丢弃 ICMP)。

3.2 现象:ping 得通但业务不通 / 单向能通

先记住结论ping 通只证明"去程通、且对方愿意回 ICMP",什么都不能证明。 这类故障的头号原因是回程路由缺失——去得了回不来。所以排查要点是"双向各查一次",而不是盯着去程反复测。

可能原因排查方法
回程路由缺失(最常见)在目标端 ip route get <客户端IP> 看回程走向;traceroute 双向各做一次对比
防火墙只放行了 ICMPiptables -L -n -vnft list ruleset、安全组规则
服务未监听或监听在 127.0.0.1ss -lntpLocal Address 是否为 0.0.0.0/::
rp_filter 反向路径过滤丢包多网卡不对称路由时被内核丢弃。sysctl net.ipv4.conf.all.rp_filter,改为 2(松散模式)或 0
NAT/负载均衡改写地址导致回程走错抓包对比进出包的源目地址是否符合预期

3.3 现象:traceroute 中间某跳开始全是 * * *,但业务正常

先记住结论星号不等于故障,“转发"和"报到"是两回事。 路由器可以正常转发你的包,同时拒绝或限速回复 ICMP Time Exceeded——它只是不吭声,不是不干活。唯一的判断标准是最终目的通不通。

多数情况不是故障。路由器可能限速 ICMP、禁用 Time Exceeded 回复、或不响应 UDP 高端口探测。判断标准:最终目的是否可达。可换 traceroute -I(ICMP)或 traceroute -T -p 443(TCP)复测,TCP 模式最贴近真实业务路径。

3.4 现象:接口地址变成 169.254.x.x

先记住结论看到 169.254 就等于"根本没拿到地址”。 这是 DHCP 失败后系统自己给自己编的一个临时链路本地地址(APIPA),不是网络配错了地址段。排查方向应全部集中在"DHCP 为什么没成功"。

原因:DHCP 获取失败,系统启用 APIPA(RFC 3927)链路本地地址。

排查journalctl -u NetworkManager / dhclient -v eth0 看 DHCP 交互;抓包 tcpdump -i eth0 port 67 or port 68 确认 Discover 是否发出、有无 Offer;检查交换机端口 VLAN、DHCP 中继(ip helper-address)、地址池是否耗尽;若为 802.1X 环境,先确认端口已授权。

3.5 现象:出现大量 IP 分片,业务时快时慢

先记住结论分片会把丢包影响放大好几倍——任何一片丢了,整个原始数据报都得重来。所以"时快时慢"的背后往往不是链路质量差,而是分片把本来能忍受的低丢包率放大成了严重问题。方向是消灭分片,而不是优化重传。

排查tcpdump -v 'ip[6:2] & 0x3fff != 0' 统计分片量;Wireshark 过滤 ip.flags.mf==1

危害:任一分片丢失整包作废,丢包率被放大数倍;重组占用内存;防火墙无法读取后续分片的端口信息。

处置:查明为何超 MTU(常见于 UDP 大包应用、DNS over UDP 大响应、VXLAN/GRE 隧道叠加开销、NFS 大 rsize/wsize);调小应用层报文或接口 MTU;TCP 场景做 MSS Clamping;DNS 场景启用 EDNS0 尺寸限制或回退 TCP。

3.6 现象:Destination Host Unreachable vs Destination Net Unreachable vs Request timed out

先记住结论这几句报错各自指向完全不同的层次,看懂了就等于直接定位了故障范围——Host Unreachable 是本机二层没解析出来,Net Unreachable 是路由器没路可走,Port Unreachable 说明 IP 层其实已经通了,Time Exceeded 则是在绕圈。

报错含义定位方向
Destination Host Unreachable(本机发出)本机 ARP 解析不到下一跳同网段 → 目标不在线/不同 VLAN;查 ip neigh
Destination Net Unreachable(路由器回)路由器无到达该网段的路由补路由或查路由协议邻居状态
Destination Port Unreachable(ICMP 3/3)IP 层通了,但对端该 UDP 端口无监听检查服务是否启动、端口是否正确
Request timed out / 无响应包发出去了但无回应防火墙静默丢弃、回程路由缺失、目标禁 ICMP
Time to live exceededTTL 归零路由环路或跳数确实超过 TTL 初值

3.7 现象:TTL 异常小 / traceroute 出现地址来回跳动

先记住结论两个地址交替出现 = 路由环路,几乎没有别的解释。 包在两台设备之间来回推诿,直到 TTL 耗尽。根因在配置,不在链路。

原因:路由环路(静态路由配错、动态路由收敛异常、双向重分发未做防环)。

排查mtr 看是否有两跳交替出现;各跳 ip route get <目的IP> 逐台确认下一跳指向;检查路由重分发与路由过滤策略。

3.8 现象:多网卡服务器回包走错网卡

先记住结论根因是"回包只看目的地址查同一张全局路由表",它压根不知道请求是从哪块网卡进来的。 想让"从哪进就从哪出",必须用策略路由给每张网卡配一张独立路由表。

原因:Linux 弱主机模型 + 单一路由表,回包按目的地址查全局路由表,可能选到另一张网卡。

处置:用策略路由为每张网卡建独立路由表:

1
2
3
4
echo "100 wan1" >> /etc/iproute2/rt_tables
ip route add default via 10.0.1.1 dev eth1 table wan1
ip rule add from 10.0.1.50 table wan1
ip route get 8.8.8.8 from 10.0.1.50 # 验证

4. 与其他协议对比

维度IPARPICMPTCPUDP
所属层网络层数据链路层网络层(依附 IP)传输层传输层
职责寻址 + 路由转发IP→MAC 解析差错与控制报告可靠有序字节流无连接数据报
是否有端口否(用 Protocol 号)否(用 Type/Code)(16 位)(16 位)
可靠性不可靠、尽力而为不可靠不可靠可靠(确认+重传)不可靠
连接状态无连接无状态无连接无连接面向连接(三次握手)无连接
头部大小IPv4 20–60 / IPv6 4028(报文体)8 + 数据20–608
关键字段TTL / Protocol / 分片OPER / SHA / SPAType / Code序号 / 确认号 / 窗口长度 / 校验和
对应 RFC791 / 8200826792 / 44439293768

IPv4 与 IPv6 关键差异(排错视角):IPv6 无广播(ping ff02::1%eth0 代替广播 ping)、无中间分片、地址解析看 ip -6 neigh、必须放行 ICMPv6(禁 ICMPv6 会直接导致 IPv6 网络瘫痪,因为 NDP、PMTUD、MLD 全靠它)。

5. 速查表 / 常见面试题

5.1 速查

记忆点
IPv4 头部长度20–60 字节(IHL×4)
IPv6 头部长度固定 40 字节
Total Length 上限65535
以太网 MTU / MSS1500 / 1460
IPv6 最小 MTU1280
Protocol 号1 ICMP,2 IGMP,6 TCP,17 UDP,47 GRE,50 ESP,51 AH,58 ICMPv6,89 OSPF
TTL 初值Linux/macOS 64,Windows 128,网络设备 255
分片偏移单位8 字节
私有地址10/8、172.16/12、192.168/16
APIPA169.254.0.0/16
最有用的一条命令ip route get <目的IP>
MTU 探测ping -M do -s <负载>(负载 + 28 = MTU)

5.2 常见面试题

Q1:数据包从 A 到 B 的过程中,源/目的 IP 和 MAC 分别怎么变化? IP 端到端不变(NAT 除外),MAC 逐跳改写。每一跳路由器解封装、查路由、用 ARP 解析新的下一跳 MAC 后重新封装。

Q2:路由器如何选路?多条路由都匹配时怎么办?最长前缀匹配:掩码最长者优先。前缀相同时再比管理距离(直连 0 < 静态 1 < OSPF 110 < RIP 120),再比 metric,仍相同则 ECMP 负载分担。

Q3:TTL 的作用?为什么 traceroute 能画出路径? TTL 防环,每跳减 1,归零丢弃并回 ICMP Time Exceeded。traceroute 依次发 TTL=1,2,3… 的包,让沿途每台路由器依次"报到",从而逐跳还原路径。

Q4:DF 位是什么?置 1 时包过大会发生什么? Don’t Fragment。置 1 时路由器不得分片,遇到 MTU 不足直接丢弃并回 ICMP Type 3 Code 4(携带下一跳 MTU),发送方据此执行 PMTUD 调小报文。若该 ICMP 被防火墙拦截,就形成 MTU 黑洞

Q5:为什么分片偏移以 8 字节为单位? Fragment Offset 只有 13 位,而 Total Length 有 16 位。13 位无法直接表达 65535 的偏移范围,故以 8 字节(2³)为粒度:13+3=16 位,恰好覆盖。代价是除最后一片外各片长度必须是 8 的倍数

Q6:分片重组在哪里做?为什么不在中间路由器做? 只在目的主机做。中间路由器若重组需维护大量状态、缓存分片、等待超时,严重影响转发性能与可扩展性;且各分片可能走不同路径,中间节点未必能收齐。

Q7:IPv6 为什么取消头部校验和? 链路层 FCS 已做错检、传输层校验和覆盖端到端数据(含伪首部),头部校验和属于冗余,且每跳都要因 Hop Limit 变化而重算,是纯粹的性能负担。副作用是 IPv6 下 UDP 校验和变为强制

Q8:/24 网段有多少可用主机?/30 呢?为什么减 2? /24:2⁸−2 = 254/30:2²−2 = 2(点对点链路)。减去的是网络地址(主机位全 0)与广播地址(主机位全 1)。特例:/31(RFC 3021)用于点对点链路时可用 2 个地址,/32 用于主机路由。

Q9:看到 169.254.x.x 说明什么? DHCP 获取地址失败,系统回落到 APIPA 链路本地地址。排查方向:DHCP 服务/地址池、VLAN 配置、DHCP 中继、802.1X 是否已授权。

Q10:IP 是不可靠的,为什么互联网还能可靠传输文件? 端到端原则:IP 保持简单(无状态、尽力而为)以获得极致的可扩展性与异构兼容性,把可靠性(确认、重传、排序、去重)与拥塞控制交给端系统的 TCP。网络核心简单、智能在边缘,这正是互联网成功的架构基石。

Q11:为什么不能把 ICMP 全部禁掉? 会破坏 PMTUD(Type 3 Code 4)造成 MTU 黑洞,破坏路径诊断能力;在 IPv6 下更严重——ICMPv6 承载 NDP、MLD、PMTUD,全禁会直接导致 IPv6 网络不可用。正确做法是按 Type/Code 精细放行,并对速率做限制。

Q12:ip route get 8.8.8.8ip route show 好在哪? show 只是列出规则,需要人脑做最长前缀匹配和策略路由推演;get 直接让内核给出实际决策结果——选中的源 IP、下一跳、出接口,在多网卡、多路由表、策略路由环境下能一步锁定问题。