第十八篇:一文说清楚ICMP的底层原理

作为程序员或者网络工程师,有时候无法访问对方主机;导致这个现象的有很多原因,那要排查具体的网络原因,可能会用到ping的指令。而ping的底层实现是互联⽹控制报⽂协议(ICMP)。

ICMP 全称是 Internet Control Message Protocol ,也就是互联⽹控制报⽂协议。

ICMP 功能都有啥?

ICMP 主要的功能包括:

① 确认IP 包是否成功送达⽬标地址

② 报告发送过程中IP 包被废弃的原因和改善⽹络设置等。

在 IP 通信中如果某个 IP 包因为某种原因未能达到⽬标地址,那么这个具体的原因将由ICMP 负责通知。

注意:

① ICMP是基于IP协议工作的,但是它并不是传输层的功能,因此人们仍把它归结于网络层协议。

② ICMP只能搭配IPv4使用。如果是IPv6的情况下,需要使用ICMPv6。

如上图例⼦,主机 A 向主机 B 发送了数据包,由于某种原因,途中的路由器 2 未能发现主机 B 的存在,这时,路由器 2 就会向主机 A 发送⼀个 ICMP ⽬标不可达数据包,说明发往主机 B 的包未能成功。

ICMP 的这种通知消息会使⽤ IP 进⾏发送。

因此,从路由器 2 返回的 ICMP 包会按照往常的路由控制先经过路由器 1 再转发给主机 A 。收到该 ICMP包的主机 A 则分解 ICMP 的⾸部和数据域以后得知具体发⽣问题的原因。

ICMP报文格式

说明

① 类型:1字节,说明该报文属于什么类型。

② 代码:1字节,说明ICMP报文的代码。

③ 检验和:2字节,检验ICMP报文是否有错误。

ICMP 包头的类型字段,⼤致可以分为两⼤类:

① 「查询报⽂类型」

ICMP协议报文里面的类型是0和8的时候,说明这是一个查询报⽂。

可以向对端主机发送回送请求的消息( ICMP Echo Request Message ,类型 8 ),也可以接收对端主机发回来的回送应答消息( ICMP Echo Reply Message ,类型 0 )。这里的回送就是有来有回的意思。

② 「差错报⽂类型」

ICMP协议报文里面的类型不是0和8的时候,说明这是一个差错报⽂。

目标不可达

IP 路由器⽆法将 IP 数据包发送给⽬标地址时,会给发送端主机返回⼀个⽬标不可达的 ICMP 消息,并在这个消息 中显示不可达的具体原因,原因记录在 ICMP 包头的代码字段。

举例 6 种常⻅的⽬标不可达类型的代码:

a. ⽹络不可达

IP 地址是分为⽹络号和主机号的,所以当路由器中的路由器表匹配不到接收⽅ IP 的⽹络号,就通过 ICMP 协议以网络不可达( Network Unreachable )的原因告知主机。

b. 主机不可达

当路由表中没有该主机的信息,或者该主机没有连接到⽹络,那么会通过 ICMP 协议以主机不可达( Host Unreachable )的原因告知主机。

c. 协议不可达

当主机使⽤ TCP 协议访问对端主机时,能找到对端的主机了,可是对端主机的防⽕墙已经禁⽌ TCP 协议访问,那么会通过 ICMP 协议以协议不可达的原因告知主机。

d. 端⼝不可达

当主机访问对端主机 8080 端⼝时,这次能找到对端主机了,防⽕墙也没有限制,可是发现对端主机没有进程监听8080 端⼝,那么会通过 ICMP 协议以端⼝不可达的原因告知主机。

e. 需要进⾏分⽚但设置了不分⽚

发送端主机发送 IP 数据报时,将 IP ⾸部的分⽚禁⽌标志位设置为 1 。根据这个标志位,途中的路由器遇到超过MTU ⼤⼩的数据包时,不会进⾏分⽚,⽽是直接抛弃。

原点抑制消息(ICMP Source Quench Message):

在使⽤低速⼴域线路的情况下,连接 WAN 的路由器可能会遇到⽹络拥堵的问题。

ICMP 原点抑制消息的⽬的就是为了缓和这种拥堵情况。当路由器向低速线路发送数据时,其发送队列的缓存变为零⽽⽆法发送出去时,可以向 IP 包的源地址发送⼀个 ICMP 原点抑制消息。

收到这个消息的主机借此了解在整个线路的某⼀处发⽣了拥堵的情况,从⽽增⼤ IP 包的传输间隔,减少⽹络拥堵的情况。 然⽽,由于这种 ICMP 可能会引起不公平的⽹络通信,⼀般不被使⽤。

定向消息(ICMP Redirect Message):

如果路由器发现发送端主机使⽤了「不是最优」的路径发送数据,那么它会返回⼀个 ICMP 重定向消息给这个主机。

在这个消息中包含了最合适的路由信息和源数据。这主要发⽣在路由器持有更好的路由信息的情况下。路由器会通过这样的 ICMP 消息告知发送端,让它下次发给另外⼀个路由器。

超时消息(ICMP Time Exceeded Message)

IP 包中有⼀个字段叫做 TTL ( Time To Live ,⽣存周期),它的值随着每经过⼀次路由器就会减1 ,直到减到 0 时该IP 包会被丢弃。

此时,路由器将会发送⼀个 ICMP 超时消息给发送端主机,并通知该包已被丢弃。

设置 IP 包⽣存周期的主要⽬的,是为了在路由控制遇到问题发⽣循环状况时,避免 IP 包⽆休⽌地在⽹络上被转发。

此外,有时可以⽤ TTL 控制包的到达范围,例如设置⼀个较⼩的TTL 值。

  • ping命令

ping的报文格式

相⽐原⽣的 ICMP,这⾥多了两个字段:

① 标识符:⽤以区分是哪个应⽤程序发 ICMP 包,⽐如⽤进程 PID 作为标识符;

② 序号:序列号从 0 开始,每发送⼀次新的回送请求就会加 1 , 可以⽤来确认⽹络包是否有丢失。

使用方法

ping + 域名或IP

ping命令执行细节

① ping命令会发送一个ICMP Echo Request给对端;

每发出⼀个请求数据包,序号会⾃动加 1 。为了能够计算往返时间 RTT ,它会在报⽂的数据部分插⼊发送时间。

ICMP报文被ICMP协议的实现程序组织好后,交给网络层的程序处理,加上源地址IP与目的IP,再传给数据链路层,加上源MAC地址与目的MAC地址;然后发送出去

说明:源和目的IP为上图的IP

② 对端接收后,返回一个ICMP Echo Reply;

③ 注意是在主机A网络层发出ICMP Echo Request,在主机B接收到网络层,再发出ICMP Echo Reply;

在规定的时候间内,源主机如果没有接到 ICMP 的应答包,则说明⽬标主机不可达;如果接收到了 ICMP 回送响应消息,则说明⽬标主机可达。

此时,源主机会检查,⽤当前时刻减去该数据包最初从源主机上发出的时刻,就是 ICMP 数据包的时间延迟。

针对上⾯发送的事情,总结成了如下图:

当然这只是最简单的,同⼀个局域⽹⾥⾯的情况。如果跨⽹段的话,还会涉及⽹关的转发、路由器的转发等等。

但是对于 ICMP 的头来讲,是没什么影响的。会影响的是根据⽬标 IP 地址,选择路由的下⼀跳,还有每经过⼀个路由器到达⼀个新的局域⽹,需要换 MAC 头⾥⾯的 MAC 地址。

说了这么多,可以看出 ping 这个程序是使⽤了ICMP ⾥⾯的ECHO REQUEST (类型为8 ) 和ECHO REPLY (类型为0 )。

  • traceroute命令

traceroute充分利⽤ ICMP 差错报⽂类型;(在UNIX、MacOS中是这个命令,⽽在Windows中对等的命令叫做 tracert )。

  1. 使用

Windows:tracert + 域名或IP地址

Linux/macOS:traceroute + 域名或IP地址

定位从源主机到目标主机之间经过了哪些路由器,以及到达各个路由器的耗时

原理: traceroute使用UDP,主机之间通信,网络层IP数据报的首部中,有个TTL字段(Time To Live)。TTL的作用是,设置IP数据报被丢弃前,最多能够经过的节点数。

每经过一个中间节点,再向下一个节点转发数据前,都会将TTL减1。如果TTL不为0,则将数据报转发到下一个节点;否则,丢弃数据报,并返回错误,错误类型是时间超时。

问题 如何判断 报文是否到达目标主机?

traceroute发送UDP报文时,将目标端口设置为较大的值( 33434 - 33464),避免目标主机B上该端口有在实际使用。

当报文到达目标主机B,目标主机B发现目标端口不存在,则向源主机A发送ICMP报文(Type=3,Code=3),表示目标端口不可达。

源主机A收到差错报文,发现Type=3,Code=3,知道已经到达目标主机B。记录下IP、耗费,检测结束。

② 故意设置不分⽚,从⽽确定路径的 MTU

有的时候我们并不知道路由器的 MTU ⼤⼩,以太⽹的数据链路上的 MTU 通常是 1500 字节,但是⾮以外⽹的 MTU 值就不⼀样了,所以我们要知道 MTU 的⼤⼩,从⽽控制发送的包⼤⼩。

它的⼯作原理如下:

⾸先在发送端主机发送 IP 数据报时,将 IP 包⾸部的分⽚禁⽌标志位设置为1 。根据这个标志位,途中的路由器不会对⼤数据包进⾏分⽚,⽽是将包丢弃。

随后,通过⼀个 ICMP 的不可达消息将数据链路上MTU 的值⼀起给发送主机,不可达消息的类型为「需要进⾏分⽚但设置了不分⽚位」。发送主机端每次收到 ICMP 差错报⽂时就减少包的⼤⼩,以此来定位⼀个合适的 MTU 值,以便能到达⽬标主机。

相关推荐
七夜zippoe7 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
盟接之桥7 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
会员源码网8 小时前
理财源码开发:单语言深耕还是多语言融合?看完这篇不踩坑
网络·个人开发
米羊1219 小时前
已有安全措施确认(上)
大数据·网络
Fcy6489 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满9 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠9 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
主机哥哥9 小时前
阿里云OpenClaw部署全攻略,五种方案助你快速部署!
服务器·阿里云·负载均衡
Harvey9039 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
ManThink Technology10 小时前
如何使用EBHelper 简化EdgeBus的代码编写?
java·前端·网络