ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ICMP协议深度解析:从报文结构到故障排查与安全防护

ICMP协议深度解析:从报文结构到故障排查与安全防护 如果你在网络环境里排查过一通故障大概率逃不开“先ping一下”这个动作。敲下ping之后屏幕上刷出几个“时间xx ms”这背后就是 ICMP 协议在默默往返。很多人把 ICMP 和 ping 画等号其实 ping 只是 ICMP 众多能力中最常见的使用场景之一。作为一个在网络底层摸爬滚打了十来年的老运维我觉得有必要把这个协议从里到外拆一遍——它帮你定位过无数次链路问题也有不少场景下它自己成了故障的源头。这篇文章我会从报文结构讲起结合 Wireshark 抓包、ping 和 traceroute 的实际用法把 ICMP 常见的类型、行为模式和排查技巧全部过一遍。无论你是刚入行的网工、做后端的程序员、还是考网工认证的学生这篇文章都能帮你少踩几个坑。1. 先搞清楚ICMP 到底是个什么角色1.1 它不是传输数据的协议而是 IP 的“体检报告”网络通信里大家最熟的是 TCP 和 UDP一个是可靠传输的“快递签收”一个是尽力而为的“平邮寄件”。ICMP 既不传业务数据也不给应用层做端口服务它更像是 IP 层内置的一套诊断和差错反馈系统。RFC 792 里给 ICMP 的定位很明确当网络出现异常比如包丢了、路径不通、设备太忙ICMP 负责把出错信息反馈给源节点。我经常用一个类比解释给新人听你寄了一箱货快递车在路上撞了护栏货物没法送达。TCP 的做法是让收件人签不了字系统就自动重发但 IP 层本身没有这种机制它连“货到底到没到”都不知道。ICMP 相当于随车的一个安全员路段封了它会返回来告诉你“前方不通”超时了它能告诉你“车卡在哪个中转站”让你知道问题出在链路哪一段。ICMP 不抢占端口号。TCP/UDP 用 16 位端口去区分进程ICMP 靠“类型代码”去区分信息含义。这一点是理解 ICMP 一切行为的钥匙。1.2 它属于哪一层别再纠结这种没营养的问题面试特别喜欢问“ICMP 属于网络层还是传输层”。从分层模型看ICMP 报文被 IP 首部封装不依赖 TCP/UDP 端口标准答案是网络层。但从功能上看它又承担了类似传输层的状态反馈工作。说实话纠结这个意义不大——实际排障时你要关心的是“这个 ICMP 报文是哪一种类型”“它对应当前网络的什么状态”而不是它该塞进 OSI 的哪一格。值得记住的是 ICMP 的状态是基于动态路由和实时网络状况反馈的它不维护连接状态也不做重传。它更像一套“只报告、不处理”的报警系统告诉你链路断了、包超时了、有重定向需求了但真正决定怎么做的是 TCP 或应用层的策略。1.3 ICMP 的能力边界ICMP 能做的几件事大概率超出很多人对它的认知连通性探测echo request / echo reply也就是 ping 的基础。路径探测借助 TTL 超时报文实现 traceroute。差错反馈目标不可达、端口不可达、网络不可达、需要分片但 DF 置位等。路由控制ICMP Redirect 通知主机更优的下一跳路径。时间同步ICMP Timestamp 请求/应答常用于内网安全基线的检测。网络拥塞信号Source Quench 曾经用于反馈“别发了设备扛不住”后来因为效果太差被废弃。除了这些常规操作ICMP 还会被用于隐蔽隧道、DDoS 放大攻击等灰色场景后文我会单独开一节讲安全。2. 报文结构拆解看懂一个 ICMP 包2.1 通用头部格式无论什么类型的 ICMP 报文前四个字节是固定的字段长度含义Type1 字节报文类型决定 ICMP 的功能Code1 字节类型下的细分代码Checksum2 字节校验和覆盖整个 ICMP 报文Type 和 Code 组合起来才是一条完整的语义。比如 Type 3 是“目标不可达”但它下面还有 0网络不可达、1主机不可达、2协议不可达、3端口不可达、4需要分片但 DF 置位等十几个代码。排障时必须 Type 和 Code 一起看只看 Type 容易误判方向。2.2 常见 ICMP 类型速查我整理了一张高频类型表建议收藏TypeCode含义典型场景00Echo Reply 回显应答ping 通时返回的报文30Network Unreachable 网络不可达路由表里没有目标网络31Host Unreachable 主机不可达最后一跳找不到目标主机 MAC33Port Unreachable 端口不可达UDP 端口没人监听traceroute 靠它识别终点34Fragmentation Needed 需要分片MTU 不合理时的关键报错50 / 1Redirect 重定向路由策略有更优路径80Echo Request 回显请求ping 发出的报文110TTL Expired 超时traceroute 逐跳探测的基础13 / 140Timestamp Request / Reply 时间戳请求/应答安全基线检查会重点扫描这里有一个特别容易懵的点Type 3 Code 3 端口不可达。TCP 连不上时通常听到的是“Connection refused”这是 TCP RST 的行为而 UDP 协议往一个没人监听的端口发包时如果中间路由器或目标主机回 ICMP 端口不可达上层应用才能知道“对面没开这个口”。traceroute 就是利用这一点用 UDP 报文发向一个不可能有人监听的端口靠收到 Type 3 判断已经走到了终点。2.3 校验和的计算方式ICMP 的校验和算法和 IP、TCP、UDP 的校验和算法一样都是 16 位二进制反码求和。计算方法把校验和字段置 0对整个 ICMP 报文按 16 位切分求和如果最高位有进位需要回卷累加最后取反码填入。抓包时 Wireshark 会自动算校验和。如果你看到某个 ICMP 报文标记为“incorrect checksum”通常说明链路中有人篡改了报文、或者抓包工具本身没开启校验和校验功能也可能是加载了 checksum offload 的网卡在抓包时还没填充这个字段。这个点新人容易误判为“协议错误”。3. 实操环节一ping 命令和 traceroute 背后的 ICMP 逻辑3.1 ping 的完整请求应答流程ping 命令发的是 Type 8 回显请求目标主机收到后回 Type 0 回显应答。一个正常的 ICMP Echo Request 报文里除了通用头部还包含 Identifier 和 Sequence Number 两个字段。Identifier 一般取发起进程的 PIDSequence Number 则是每个请求包的递增序号。这两个字段合起来让发起方能够把应答和请求精确对应起来——多进程同时 ping、或者同一进程连续发很多包都不会配错对。Linux 下 ping 默认每秒发一个包Windows 下 ping 默认发 4 个包后停止。这个区别每次跨平台排障时都会坑到人在 Linux 上敲了一步ping 10.0.0.1后一直刷屏而在 Windows 上同样的命令敲完就停了。所以 Windows 上想持续探测要加-tLinux 上想限定次数要加-c 5。3.2 ping 的常用参数和排障技巧我这里列几个实用场景# 指定发包数量适合脚本化探测 ping -c 4 192.168.1.1 # 指定间隔和包大小适合测试大包是否触发分片或丢包 ping -i 0.2 -s 1472 192.168.1.1 # Linux 下禁止分片并设置 DF 标志测试路径 MTU ping -M do -s 1472 192.168.1.1 # Windows 下持续 ping 加时间戳方便记录故障时间点 ping -t 8.8.8.8-s 1472这个数字不是随便取的。以太网默认 MTU 是 1500 字节减去 IP 首部 20 字节和 ICMP 头部 8 字节负载最大就是 1472。如果你设的包大于 1472 且不禁止分片数据会被分片传输设了-M do之后如果中间链路 MTU 不够就会收到 Type 3 Code 4 的错误。MTU 问题的典型场景是ping 通但访问网页打不开。通常就是因为某些链路 MTU 配置偏小比如 PPPoE 拨号是 1492而服务器发出的 TCP 报文又带 DF 标志。此时路径上路由器会回 ICMP 分片需要报文但如果防火墙把这类 ICMP 过滤掉了发送方就永远不知道需要降低包大小形成“黑洞”——这就是 MTU 黑洞问题。排查方式从大到小调整-s参数找到不触发分片的最大值。3.3 traceroute 的两种实现方式traceroute 的原理非常聪明利用 IP 首部 TTL 字段一步步探测路径。数据包每经过一个路由器 TTL 减 1减到 0 时路由器会返回一个 Type 11 超时报文。于是 traceroute 先发 TTL1 的包第一跳路由器会回超时再发 TTL2 的包第二跳会回超时以此类推直到到达目标。Linux 的 traceroute 默认用 UDP发向一个高位端口通常是 33434 起路径每跳会收到 Type 11终点会收到 Type 3 Code 3 端口不可达。Windows 的 tracert 则直接用 ICMP Echo Request靠 Type 11 和 Type 0 来标记每跳和终点。这两种方式的差异在实际场景里会造成偶发的“tracert 通了但 traceroute 不通”的现象——某些防火墙只放行 ICMP 而丢弃 UDP 探测。反之亦然。所以做路径排查时我习惯两种都试一遍能确认是协议策略过滤还是链路真的断了。有一个实战小技巧如果 ping 目标通但 traceroute 中间某跳全是星号* * *不要立刻断定是故障。很多运营商路由器限速或策略配置会让 ICMP 超时报文被丢弃但数据转发是正常的。判断的标准是看后续跳有没有正常显示、最终目标是否可达。中间几跳“隐身”是常态不必慌。4. 实操环节二Wireshark 抓包分析 ICMP 报文4.1 抓包的完整步骤用 Wireshark 分析 ICMP 是理解这个协议最直观的路径。具体步骤打开 Wireshark选择接入目标网络的网卡双击开始捕获。在过滤器栏输入icmp避免其他报文刷屏。另开一个终端执行ping 目标地址发送几组请求。停止捕获点开任意一条 Echo Request / Echo Reply 报文逐字段观察。4.2 一次典型 ping 包的关键字段以一次ping 192.168.1.1为例抓到 Echo Request 后重点看这几处Internet Control Message Protocol 层Type 8、Code 0这是请求报文。Identifier本次 ping 进程的标识不同进程的值不同。Sequence Number这个请求的序号从 0 开始递增。Data默认负载是一些填充字符内容本身没有业务含义。再看对应的 Echo ReplyType 变为 0Identifier 和 Sequence Number 与请求完全一致。这两个字段的匹配就是 ping 能“识别自己人”的关键。用 Wireshark 的“统计 → 流量图”功能把这两个报文关联起来能看到请求和应答在时间线上的对应关系非常直观。4.3 只分析“通不通”太浪费学学延时和重传分析Wireshark 的分析价值远不止确认通不通。我经常用两个字段排查质量Time 列的时间差同一组请求和应答之间的时间差就是 RTT。如果连续看到的 RTT 波动很大比如从 1ms 跳到 300ms 又回落通常说明链路存在拥塞或负载均衡策略在切换出口。重复请求如果看到连续多个 Echo Request 都没有对应的 Echo Reply之后再补发可能就是 TCP 层的重传在影响——不过 ICMP 本身不重传这些重复往往是你手动刷新 ping 或者后台监控程序在频繁采集需要结合实际命令判断。我习惯抓 5 分钟连续 ping 的包然后看 Wireshark 的专家信息Expert Info里有没有校验和错误、有没有分片不完整的标记。有经验的排障人员通过波形图基本就能判断故障是周期性拥塞还是持续性劣化。4.4 Wireshark 过滤表达式的几个实用例子# 只看 ICMP 回显请求 icmp.type 8 # 只看 ICMP 回显应答 icmp.type 0 # 只看目标不可达 icmp.type 3 # 按源 IP 过滤 ICMP 流量 icmp ip.src 192.168.1.10 # 只看分片需要的不可达报文MTU 黑洞排查核心 icmp.type 3 icmp.code 4这些过滤表达式配合抓包分析排查效率会比纯看 ping 命令输出高很多。原因很简单ping 只告诉你通或不通、延时多少抓包能告诉你这个“不通”到底是哪个设备、什么原因导致的。5. 时间戳报文安全基线整改中的重要角色5.1 为什么 Windows Server 会专门去检测 ICMP 时间戳在热词里出现了“icmp时间戳检测 windows server 2012 服务器整改”这其实对应的是等保测评和服务器安全加固中一个高频检查项。ICMP Timestamp 请求Type 13和应答Type 14可以让主机获取另一台机器的系统时间但这个功能在大多数业务场景中根本用不到反而会被攻击者用来探测内网主机时钟、辅助侦察甚至构造基于时间同步偏差的攻击。因此安全整改时通常要求禁用或过滤掉这些报文。Windows Server 默认是允许回复 ICMP 时间戳的需要通过防火墙规则或注册表策略关闭。Linux 下同样存在风险默认也建议通过 sysctl 或 iptables 丢弃。5.2 检测方法和整改配置检测时可以在本机向目标 Windows Server 发送时间戳请求ping -T tsandreq 目标IP如果收到回复说明目标还开着时间戳功能。抓包时过滤icmp.type 13 || icmp.type 14也能快速识别。整改步骤参考Windows Server 2012 及以上版本在“高级安全 Windows 防火墙”中设置入站规则阻止所有ICMPv4-In中的“时间戳请求”或者使用 netsh 命令netsh advfirewall firewall add rule nameBlock ICMP Timestamp protocolicmpv4:13,any dirin actionblockLinux 主机推荐追加 iptables 规则iptables -A INPUT -p icmp --icmp-type timestamp-request -j DROP iptables -A OUTPUT -p icmp --icmp-type timestamp-reply -j DROP需要说明的是光会敲命令不够。我曾经在一个内网整改项目里发现Windows 防火墙的“文件和打印机共享(回显请求 - ICMPv4-In)”规则被启用了导致时间戳报文也被一并放行。所以最稳妥的做法是在防火墙的高级设置里单独检查“ICMPv4-In”具体允许了哪些类型把时间戳请求明确排除掉。6. 常见问题排查与经验速查6.1 ping 通但业务访问不了这是后台开发找我最多的一类问题。现象是ping 目标IP完全正常、延迟很低但 TCP 端口就是连不上。典型原因有目标主机防火墙丢弃了 TCP 入站但允许 ICMP。中间设备对特定 TCP 端口做了策略只拦截业务端口流量。目标服务没监听TCP 会表现成 Connection refusedRST 返回而 ping 本身不受影响。排查时先确认服务端口监听状态然后抓包看 TCP 三次握手有没有回包。如果回包只有 SYN、没有 SYN-ACK八成是防火墙问题而不是网络链路问题。6.2 ping 丢包严重怎么定位丢包最麻烦的是不知道丢在哪一跳。优先用带-c参数的连续 ping 排除偶发观察丢包是否与发包频率有关再用 traceroute 确认每一跳的转发是否稳定最后抓包看 ICMP Echo Request 和 Reply 的编号连续性。如果丢包只发生在跨网段的路径上而本网段内 ping 一切正常优先怀疑路径上的路由器转发能力或运营商链路质量。6.3 ICMP 被防火墙过滤怎么验证链路质量很多生产环境对 ICMP 的默认策略是“全丢”。这时候ping不通不代表链路有问题。要验证链路质量可以用tcping或nc直接探测 TCP 端口也可以在防火墙放行特定源 IP 的 ICMP 做白名单测试。内网维护时我习惯给运维跳板机单独开 ICMP 白名单既保证核心链路可探测又不暴露给所有来源。6.4 ICMP 常见问题速查表现象可能的 ICMP 报文结论方向ping 返回 “Destination Host Unreachable”Type 3 Code 1目标主机不在同一二层网络ARP 解析失败ping 返回 “Destination Net Unreachable”Type 3 Code 0路由器没有到目标网段的路由ping 大包失败小包正常Type 3 Code 4路径 MTU 不足需要调整 MTU 或关闭 DFtraceroute 到某一跳全部超时无或过滤 Type 11路由器策略限制探测或链路中断ping 通了但 telnet 连不上无 ICMP 报错多半是防火墙或服务未监听6.5 一个真实的经验教训去年排查过一个跨省专线故障现象是丢包率 50% 左右间隔性出现。常规 ping 和 traceroute 都没发现异常最后抓包才发现回程路径上有一个路由器在向源地址发送 ICMP Redirect 报文把原本应该走专线的流量重定向到了另一条低质量链路上。问题根源不是物理链路而是路由策略配置错误导致的 ICMP 重定向污染。后来靠sysctl -w net.ipv4.conf.all.accept_redirects0禁用主机的重定向接收才稳定下来。这提醒我ICMP 的每一个类型都不只是教科书上的定义在真实网络环境里都有可能导致实际问题排障时必须结合报文的上下文和行为特征综合判断。7. 安全视角ICMP 的风险面与防护7.1 基于 ICMP 的经典攻击方式ICMP 在设计时根本没有考虑安全“无连接、不鉴权”的特性让它成为攻击者的好帮手。Ping of Death构造超大的 ICMP 报文超过 IP 包上限 65535 字节利用分片重组时的漏洞让目标系统内存溢出或崩溃。现在的操作系统基本都修复了但历史影响很大。Smurf 攻击把 ICMP 请求的源地址伪造成受害主机地址发送到广播地址。网络内所有主机会同时向受害主机回复 Echo Reply形成流量放大。如今大多数路由器默认丢弃广播 ping这类攻击已经式微。ICMP 隧道将数据隐藏在 ICMP Echo Request 的 Data 字段里利用允许 ICMP 通过防火墙的规则把隧道流量伪装成 ping。极难被发现是红队和恶意软件常用的隐蔽通道。著名的工具 PingTunnel 就是干这个的。ICMP 重定向攻击发送伪造的重定向报文让主机修改路由表把流量导向攻击者控制的设备是实现中间人攻击的前置手段。7.2 合理的 ICMP 安全策略一刀切地屏蔽所有 ICMP 能规避风险但会显著增加排障难度。生产环境的建议是分层处理对外网口过滤 ICMP Redirect、Timestamp、不可达报文的对外暴露保留 Echo 探测能力或直接丢弃。对内网运维区开放 Echo 和 TTL 超时类型便于日常排障但限制来源 IP 白名单。核心设备关闭 ICMP 重定向接收防止路由表被污染。DDoS 防护在边界对 ICMP 流量设置速率限制避免 Smurf 和 flood 放大到内网。一个实用的 iptables 规则组合# 只允许 Echo 请求和应答丢弃时间戳、重定向、不可达 iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT iptables -A INPUT -p icmp -j DROP7.3 排查时的安全注意事项作为一个负责过很多生产网络的老兵我必须提一句抓包分析 ICMP 时不要只盯着协议细节还要留个心眼观察流量模式。如果你在抓包文件里看到大量来自不同 IP、且 Data 区域内容非标准的 Echo Request很可能是有人在内网跑 ICMP 隧道。进一步验证的办法是统计请求的频率和负载长度正常 ping 的负载长度固定且频率稳定异常隧道的负载通常忽大忽小、内容像是加密数据。这种场景下要第一时间隔离端口而不是急着分析协议。8. 结尾的闲谈ICMP 是复杂网络故障定位的显微镜做网络排障这些年我的体感是 ICMP 总是被两种态度对待要么只当它是 ping 的工具要么把它的所有报文都当成安全隐患一刀切禁用。这两种都太极端了。ICMP 其实是一把很锋利的刀——你越理解它的报文类型和行为逻辑越能在混沌的故障现场找到那一丝线索。最近一次线上告警核心交换机间歇性丢包前几批同事换了三次光模块都没解决问题。我拿着抓包文件翻了几分钟发现链路里出现了连续的重定向报文最终定位到是新加的一条静态路由抢占了默认路由的优先级。那一刻我就想如果当时的排障者对 ICMP Redirect 毫无概念这个故障不知道还要排查多久。后面我会计划写一篇基于抓包文件分析具体网络故障的实战复盘把 ICMP、TCP、VLAN 等各种报文的组合分析逻辑完整展开。如果你的工作里也经常被网络问题纠缠先用好这篇文章里的知识点至少下次故障发生时你手里的底牌会多上几张。
返回列表