我用 LinuxLinuxTCP/IP详解 卷1:协议

TCP/IP协议笔记5-ICMP协议及其应用

2019-03-31  本文已影响10人  __七把刀__

1 ICMP协议概述

ICMP(Internet Control Message Protocol)协议是因特网控制报文协议,ICMP常被认为是网络层协议,它的报文存在于IP数据报的数据部分,如图。

ICMP协议栈

因为ICMP是基于IP数据报的,所以跟TCP不同的是,它是不需要指定端口的,更没有建立连接一说。而且,通常来说ICMP协议都是内核帮你实现的,系统自身就支持了,并不像TCP/HTTP等还要自己开个服务监听对应端口啥的。 可能有人会有疑问了,既然没有端口来标识了,那我有时候开多个ping进程,这些响应消息是怎么对应到不同的ping进程的? 这个就是ICMP报文里面的标识符的作用了。标识符会在响应中带回来,这样发送方就能根据标识符将请求和应答匹配了。在ping中,这个标识符就是进程ID。

ICMP报文有多种类型,如地址掩码请求和应答、时间戳请求和应答、请求回显和回显应答等。ICMP报文通用格式如下,不同类型的报文内容有所不同。ICMP协议在 ping,traceroute等工具中有典型应用,下面都分析一下。

ICMP报文格式

2 Ping 原理分析

ping使用的是 ICMP 的请求回显/回显应答类型的报文,格式如下。它的内容包括标识符、序列号以及回显数据3部分,报文大小默认为 64 字节(header的8字节+body的56字节)。

ICMP回显报文格式

实例分析

在测试机ping我的虚拟机 ping -c2 192.168.33.10,192.168.33.10是我测试用的虚拟机IP,wireshark抓包如下:

Ping请求 Ping响应

可以验证前面的分析。第2对请求和应答跟第一对类似,只是序列号,校验和等不同罢了。

关于校验和

ICMP报文头部中的校验和生成/校验方式也比较简单。

ICMP校验和算法

如何自己写一个ping?可以参考下这位朋友的ping工具的 python实现。 Lingerhk: icmp_ping_tool.py

3 Traceroute 原理分析

traceroute 用于查看IP数据报从一台主机传到另一台主机所经过的路由。其实,在IP数据报的头部的选项字段有一个 IP记录路由选项(RR),它也可以记录路由。为什么不直接用它而是另外弄出个traceroute工具,这是因为:

traceroute 用到ICMP协议和TTL字段。TTL字段是数据报的生存周期,初始值通常默认是64,每个处理数据报的路由器都需要把TTL值减去1或者数据报在路由器停留的秒数(因为绝大多数路由器转发数据报时延都小于1秒,因此通常都是减去1,而且很多路由器的实现即便超过1秒也是减去1,因此可以把TTL看做一个跳站计数器)。路由器接收到一份IP数据报时,如果TTL为0或者1,则路由器不转发该数据报,而是丢弃并给源机器发送一份ICMP超时报文,而ICMP信息中的IP报文中源地址正是路由器的IP地址。

traceroute的原理就是:

实例分析

运行 traceroute 119.75.217.109,可以看到wireshark抓包的前几跳信息,TTL最开始是1,然后是2...,端口是33435到33437,每个TTL发3次报文,在没有达到目的主机前,返回的是ICMP超时报文。到达主机后,则会返回ICMP端口不可达报文。

traceroute 请求的UDP报文 traceroute 响应的ICMP超时报文 traceroute 目的主机响应的ICMP端口不可达报文

由于IP路由通常都是动态的,每个路由器都要判断数据报接下来要转发到哪个路由器,应用程序对路由策略并不控制。而traceroute程序的IP源站选路选项(-g gateway)可以实现发送者指定路由,比如指定必须经过哪些路由IP,这里就不展开了。有兴趣的可以参见 《TCP/IP详解 卷1:协议》的第8章。

参考资料

上一篇 下一篇

猜你喜欢

热点阅读