Open hankviv opened 4 years ago
ICMP 包头的类型字段,大致可以分为两大类: 一类是用于诊断的查询消息,也就是「查询报文类型」 另一类是通知出错原因的错误消息,也就是「差错报文类型」
一、查询报文类型: 类型 0 和 8
回送消息用于进行通信的主机或路由器之间,判断所发送的数据包是否已经成功到达对端的一种消息, ping 命令就是利用这个消息实现的。 序号:序列号从 0 开始,每发送一次新的回送请求就会加 1 , 可以用来确认网络包是否有丢失。 在选项数据中, ping 还会存放发送请求的时间值,来计算往返时间,说明路程的长短。
可以向对端主机发送回送请求的消息( ICMP Echo Request Message ,类型 8 ),也可以接收对端主机发回来的回送应答消息( ICMP Echo Reply Message ,类型 0 )。
二、差错报文类型 1.目标不可达消息 —— 类型 为 3 IP 路由器无法将 IP 数据包发送给目标地址时,会给发送端主机返回一个目标不可达的 ICMP 消息,并在这个消息中显示不可达的具体原因,原因记录在 ICMP 包头的代码字段。
代码字段:
2.原点抑制消息 —— 类型 4 在使用低速广域线路的情况下,连接 WAN 的路由器可能会遇到网络拥堵的问题。ICMP 原点抑制消息的目的就是为了缓和这种拥堵情况。 3.重定向消息 —— 类型 5 如果路由器发现发送端主机使用了「不是最优」的路径发送数据,那么它会返回一个 ICMP 重定向消息给这个主机。在这个消息中包含了最合适的路由信息和源数据。 4.超时消息 —— 类型 11 IP 包中有一个字段叫做 TTL ( Time To Live ,生存周期),它的值随着每经过一次路由器就会减1,直到减到 0 时该 IP 包会被丢弃。此时,路由器将会发送一个 ICMP 超时消息给发送端主机,并通知该包已被丢弃。设置 IP 包生存周期的主要目的,是为了在路由控制遇到问题发生循环状况时,避免 IP 包无休止地在网络上被转发。
traceroute —— 差错报文类型的使用: 有一款充分利用 ICMP 差错报文类型的应用叫做 traceroute (在UNIX、MacOS中是这个命令,而在Windows中对等的命令叫做 tracert ) traceroute 的第一个作用就是故意设置特殊的 TTL,来追踪去往目的地时沿途经过的路由器。
它的原理就是利用 IP 包的生存期限 从 1 开始按照顺序递增的同时发送 UDP 包,强制接收 ICMP 超时消息的一种方法。 比如,将 TTL 设置 为 1 ,则遇到第一个路由器,就牺牲了,接着返回 ICMP 差错报文网络包,类型是时间超时。 接下来将 TTL 设置为 2 ,第一个路由器过了,遇到第二个路由器也牺牲了,也同时返回了 ICMP 差错报文数据包,如此往复,直到到达目的主机。这样的过程,traceroute 就可以拿到了所有的路由器 IP。当然有的路由器根本就不会返回这个 ICMP,所以对于有的公网地址,是看不到中间经过的路由的。 traceroute 在发送 UDP 包时,会填写一个不存在的端口号(大于3000),当目的主机,收到 UDP 包后,会返回 ICMP 差错报文消息,但这个差错报文消息的类型是「端口不可达」。所以,当差错报文类型是端口不可达时,说明发送方发出的 UDP 包到达了目的主机。 traceroute 还有一个作用是故意设置不分片,从而确定路径的 MTU。 目的是为了发现路径上一个合理的MTU值。因为路由器等设备由于操作系统等不一致,MTU也不不一致。所以我们要知道 MTU 的大小,从而控制发送的包大小。 首先在发送端主机发送 IP 数据报时,将 IP 包首部的分片禁止标志位设置为 1。根据这个标志位,途中的路由器不会对大数据包进行分片,而是将包丢弃。随后,通过一个 ICMP 的不可达消息将数据链路上 MTU 的值一起给发送主机,不可达消息的类型为「需要进行分片但设置了不分片位」。 发送主机端每次收到 ICMP 差错报文时就减少包的大小,以此来定位一个合适的 MTU 值,以便能到达目标主机。
ICMP 全称是 Internet Control Message Protocol,也就是互联网控制报文协议。 常见场景: 网络包在复杂的网络传输环境里,常常会遇到各种问题。当遇到各种问题的时候,所以需要传出消息,报告遇到了什么问题,这样才可以调整传输策略,以此来控制整个局面。 ICMP 主要的功能包括:确认 IP 包是否成功送达目标地址、报告发送过程中 IP 包被废弃的原因和改善网络设置等。 在 IP 通信中如果某个 IP 包因为某种原因未能达到目标地址,那么出问题的节点就会使用 ICMP协议返回具体的原因。
实验: 当我在浏览器随便输入了一个不存在的IP地址后,收到了一个ICMP响应: 当我使用Ping命令的时候: