ICMP Ping

2018-04-02 Monday     network

Internet Control Message Protocol, ICMP(RFC-792) 基于 IP 协议,工作在七层协议的第三层,主要用来解析网络路由情况,通过返回错误信息进行分析定位。

其它

抓包

可以通过如下命令获取包。

----- ICMP echo request
$ tcpdump -nni eth0 -e icmp[icmptype] == 8

----- ICMP echo reply
$ tcpdump -nni eth0 -e icmp[icmptype] == 0

----- 保存到文件中
$ tcpdump -nni eth0 -w /tmp/icmp.pcap -e icmp[icmptype] == 0

----- 读取文件
$ tcpdump -nn -r icmp.pcap

TTL

Time To Live, TTL 存活时间,表示这个 PING 数据包能在网络上存活多少时间,实际上就是用来表示可以被路由转发多少次,在 IP 头中通过 8bits 表示。

执行 Ping 操作时,会在本机发送一个数据包,正常来说,数据包会经过一定的路由到达目的主机。不过,由于很多原因可能会导致一些数据包不能正常传送到目的主句,为了防止由于数据包一直传输导致网络负载增加,增加的 TTL 作为包的存活时间。

当数据包传送到一个路由器之后,TTL 就自动减 1,如果减到 0 了还是没有传送到目的主机,那么就自动丢弃,此时一般是 Request timed out 了。

64 bytes from 192.168.9.1: icmp_seq=1 ttl=60 time=0.909 ms

目前测试来看,当 ICMP 报文发送之后,其返回的报文实际上会重新设置(依赖目标机器的设置),也即是说 TTL 的值是单程的。

在 Linux 命令行中,可以通过 -t 参数进行设置。例如,返回的 TTL 为 60,那么你可以初步猜测对端设置的初始 TTL 为 64,那么通过 -t 2 设置时候,就会出现 Time to live exceeded 的报错。

系统设置

Windows 一般在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters 注册表中设置。

在 Linux 中,可以通过如下方式修改默认的 TTL 。

----- 临时修改
# sysctl net.ipv4.ip_default_ttl=129
# echo 129 > /proc/sys/net/ipv4/ip_default_ttl
----- 保存到配置文件中
$ cat /etc/sysctl.conf
net.ipv4.ip_default_ttl=129

各个系统的默认值如下。

Linux              64/255
Windows NT/2000/XP 128
Windows 98         32
UNIX               255

QoS

Quality of Service, QoS 服务质量,提供的质量越好,表示有越低的延迟、丢包、抖动等,同时其吞吐量和可靠性要更高。简单来说,就是利用包的特定标志位,告诉路由器如何处理包,是先还是后。

在第二层(Link Layer)和第三层(IP)都有标示位,其中 IP 层采用的是 8Bits,包括 IPv4 和 IPv6 都有,只是其位置不同。

套接字

ICMP 套接字的目的是允许在不设置 SUID 或者 CAP_NET_RAW 权限的时候允许 ping 程序的使用,详细的实现可以查看内核的邮件列表 add IPPROTO_ICMP socket kind

是否支持是通过内核的 net.ipv4.ping_group_range 指定,这是一对整数,指定了允许使用 ICMP 套接字的组 ID 的范围,默认为 1 0 也就意味着没有人能够使用这个特性。

可以通过如下命令修改。

# sysctl -w net.ipv4.ping_group_range='0 10'

然后可以通过如下方式创建 ICMP 的套接字。

import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_ICMP)

如果系统不支持这个特性,在创建套接字的时候会得到 Protocol not supported 的错误,而如果没有权限,则会得到 Permission denied 的错误。

它的类型和 UDP 套接字一样,是 SOCK_DGRAM 而非 SOCK_RAW,这也就意味着你不会收到 20 字节的 IP 头,而且内核会计算校验和,并且填充 ICMP ID,在接收到响应后,内核会只把相应 ID 的 ICMP 响应返回给程序,不需要自己或者要求内核过滤了。

参考

可以参考 Github liboping

关于各个操作系统的默认 TTL 可以参考 Default TTL (Time To Live) Values of Different OS



如果喜欢这里的文章,而且又不差钱的话,欢迎打赏个早餐 ^_^


About This Blog

Recent Posts

Categories

Related Links

  • RTEMS
    RTEMS
  • GNU
  • Linux Kernel
  • Arduino

Search


This Site was built by Jin Yang, generated with Jekyll, and hosted on GitHub Pages
©2013-2019 – Jin Yang