搞了运维开发这么多年,原来 Ping 还能这么玩儿!

2022-03-03 10:40:41 浏览数 (1)

刘勇

腾讯后台研发工程师,就读于北京大学。目前主要从事腾讯云-云拨测项目后台开发相关工作。

网络:良辰有一百种方法让你 Ping 不通,你却无可奈何

为什么 Ping 不通了?为什么又通了?这些居然都能Ping 通?这似乎是每个开发或运维会经常面对的灵魂拷问。而关于 Ping 你又了解多少?知道 Ping 还能这么玩吗?

Ping 的含义-两端的连通性

在开发和运维中我们时常要关心一类问题,客户端和服务器是否可以通信,业务服务能否连接到数据库等两端连通性问题。最常用到的手段就是对目标网络执行 Ping 命令,通过向目标机器发送请求数据并接收回应数据来确认是否存在丢包等网络不畅通的情况。在网络架构日益复杂的情况下,Ping 的身影无处不在,举几个例子:如图所示,在 WLAN 下为了确认主机是否与路由器联通,主机会定时向路由地址发送数据并接收路由器的响应(如图中每2秒进行一次探测);比如在使用 Redis 时,可以通过输入 "ping" 检查是否与该 Redis 连接成功,如果连接正常就会回复一个"pong";同样在使用数据库时也有类似的 Ping 操作来确认连接;再比如网游中的 Ping时延也是通过定时 Ping 游戏服务器得到的延迟数据。谈到网络协议就不得不提到计算机网络中的分层模型,一般的网络分层模型中,Ping 操作处于 IP 层/网络层,但是基于 Ping 操作的理念(即确认两端的连通性并不局限在网络层),在传输层甚至应用层都有其不同的实现和应用。接下来,我们就依照从网络层到传输层再到应用层的顺序,来详细讲解一下 Ping 的实现原理以及拓展的 Ping 的形式。

[点击查看大图]

在讲解具体的 Ping 协议内容之前,我们先来看一下百科中 Ping 的标准定义:Ping 的全称是 Packet Internet Groper,即分组间包探测,是一种因特网包探索器,用于测试网络连通性的检查。我们仔细看一下 Ping 的英文全称——Packet Internet Groper,大家有没有觉得很奇怪,为什么 Ping 的英文不是像DNS(Domain Name Serve)这样的首字母缩写,而是并不与英文完全对应,还用到了 groper 这样并不标准化的词语?实际上 Ping 的英文全称是后来人们”生搬硬套“上去的。回顾 Ping 的历史,第一个开发出 Unix 中 Ping 程序的美国程序员 Mike Muuss,在他的 "The Story of the PING Program(Ping 程序的故事)" 这篇文章中提到,他是根据声呐探测和回声定位中的 Ping 协议为这个 Ping 程序命名的,因为在这个程序的过程与声呐探测有着异曲同工之妙。主动声呐中发出的声波称为 Ping,而对应的回声称为 pong。而网络探测中主动探测方发出的请求称为 Ping,接受者的回应称为 pong。

[点击查看大图]

Ping 的实质就是用类似打招呼的方式来确认双发的通信状况,只不过在互联网世界中由于网络状况复杂,很容易出现打招呼对方接收不到的情况,即丢包的情况出现。这个时候,我们光知道通信不了这个现实没有什么用,重要的是要知道丢包的具体原因,是网络拥堵导致丢包,还是对端机器出现故障,又或是其他原因。这就涉及到 Ping 的又一大功能——通过协议内容的错误信息来确认丢包的具体原因。我们就先从最基本的网络层层面的 ICMP 协议 Ping 讲起。

ICMP 协议- Ping 

ICMP (Internet Control Message Protocol 因特网报文控制协议)主要的功能包括:确认IP包是否成功送达目标地址、报告发送过程中IP包被废弃的原因和改善网络设置等。在 IP 通信中如果某个 IP 包因为某种原因未能达到目标地址,那么这个具体的原因将由 ICMP 负责通知。所以 ICMP 在网络分层中与 IP 层处于同一层,用于传递 IP 报文的控制信息。在协议名字中有一个很关键的词——控制。网络包在复杂的网络传输环境里,常常会遇到各种问题。咱们并不怕遇到问题,怕的是不知道问题产生的原因,就像线上发现 bug 查询监控日志一样,我们需要一种控制手段来确定网络不通问题出错的点,是本地网络不通还是对端网络问题,或是对方网络根本不存在。在网络层要确定错误原因我们就需要传出消息,从回显的报告中获知遇到了什么问题,这样才可以调整传输策略,以此来控制整个局面。下面以 ICMP -Ping 目标不可达为例子来说明一下 ICMP-Ping 的过程:

[点击查看大图]

主机 A 向主机 B 发送了数据包,途中的路由器 2 时,根据ARP协议映射表中未能发现主机 B 的IP与MAC地址的映射(因为此时B已经关机),这种情况下路由器 2 就会向主机 A 发送一个 ICMP 目标不可达数据包,说明发往主机 B 的包未能成功。ICMP 的这种通知消息会使用 IP 进行发送 。因此,从路由器 2 返回的 ICMP 包会按照往常的路由控制先经过路由器 1 再转发给主机 A 。收到该 ICMP 包的主机 A 则分解 ICMP 的首部和数据域以后得知具体发生问题的原因。

除了不可达信息,其实ICMP报文中了多种错误方式:1. Request timed out请求超时,这是大家经常碰到的提示信息,导致ICMP超时的情况至少有下几种:

  • 网络上不存在目标地址。
  • 对方与自己不在同一网段内,通过路由也无法找到对方。
  • 对方确实存在,但设置了 ICMP 数据包过滤(比如防火墙设置)。
  • 错误设置 IP 地址:正常情况下,一台主机应该有一个网卡,一个 IP 地址,或多个网卡,多个 IP 地址(这些地址一定要处于不同的IP子网)。但如果一台电脑的“拨号网络适配器”(相当于一块软网卡)的 TCP/IP 设置中,设置了一个与网卡 IP 地址处于同一子网的 IP 地址,这样,在 IP 层协议看来,这台主机就有两个不同的接口处于同一网段内。 当从这台主机 Ping 其他的机器时,会存在这样的问题:1. 主机不知道将数据包发到哪个网络接口,因为有两个网络接口都连接在同一网段。2. 主机不知道用哪个地址作为数据包的源地址。 因此,从这台主机去Ping其他机器,IP 层协议会无法处理,超时后,Ping 就会给出一个“超时无应答”的错误信息提示。但从其他主机 Ping 这台主机时,请求包从特定的网卡来,ICMP 只须简单地将目的、源地址互换,并更改一些标志即可,ICMP 应答包能顺利发出,其他主机也就能成功 Ping 通这台机器了。

2. Destination host Unreachable

  • 对方与自己不在同一网段内,而自己又未设置默认的路由,比如上例中 A 机中不设定默认的路由,运行 Ping 192.168.0.1.4 就会出现“Destination host Unreachable”。
  • 链路层出现故障

这里要说明一下“destination host unreachable”和 “time out”的区别,如果所经过的路由器的路由表中具有到达目标的路由,而目标因为其他原因不可到达,这时候会出现“time out”,如果路由表中连到达目标的路由都没有,那就会出现“destination host unreachable”。3.Bad IP address这个信息表示您可能没有连接到DNS服务器,所以无法解析这个IP地址,也可能是IP地址不存在。4.Source quench received这个信息比较特殊,它出现的机率很少。它表示对方或中途的服务器繁忙无法回应。5.Unknown host——不知名主机这种出错信息的意思是,该远程主机的名字不能被域名服务器(DNS)转换成IP地址。故障原因可能是域名服务器有故障,或者其名字不正确,或者网络管理员的系统与远程主机之间的通信线路有故障。6.No answer——无响应这种故障说明本地系统有一条通向中心主机的路由,但却接收不到它发给该中心主机的任何信息。故障原因可能是下列之一:中心主机没有工作;本地或中心主机网络配置不正确;本地或中心的路由器没有工作;通信线路有故障;中心主机存在路由选择问题。7.Ping 127.0.0.1127.0.0.1是本地循环地址,如果本地址无法 Ping 通,则表明本地机 TCP/IP 协议不能正常工作。8.no rout to host网卡工作不正常。9.unknown host nameDNS 配置不正确。

拓展的 Ping 操作

ICMP-Ping只是 Ping 的一种最常用的形式,实际上检测两端的连通性并不一定要用到 ICMP 协议。在网络分层模型中,我们知道 ICMP 协议工作在网络层,而建立两端的主机通信就是在网络层,所以采用网络层的 ICMP 进行连通性检测理所应当。

不过在分层模型中我们也知道传输层和应用层协议依赖着网络层,TCP、UDP 协议要依靠 IP 协议进行传输,HTTP 协议依赖 TCP 协议通过握手建立连接后通信。所以网络层可达是其上层协议成功的必要非充分条件。所以我们也可以通过 TCP,UDP 协议进行 Ping 操作。下面我们就详细说一下使用 TCP、UDP 协议进行 Ping 的原理和流程。

1. TCPPing

在 TCP 协议中,SYN 包用来表示建立连接请求。如果对方端口处在 listening状态,就会回送 ACK 包,并附上自己的 ISN。但是如果对方端口是关闭的,它会发回一个 RST 包,表示应该马上断开连接(少数情况下会发回一个同时置 SYN 和 ACK 位的包)。如果我们向一个端口发送 ACK 包,而事先没有与此端口建立连接,那么,无论端口是否打开,它都会回送一个 RST 包。所以可以看出,无论这个端口是否打开,总会有某一种数据包返回,以此可以判定目标主机可达。而目标主机如果不可达,路由器就会向扫描主机发送目的地不可达的ICMP 报文。这样,通过向目标主机发送 TCPSYN 包或 TCPACK 包就可以准确判断目标主机是否可达,而且根据 RFC793(TCP),目标主机(或路由器)都无法屏蔽 TCPSYN 包和 TCPACK 包,因此,TCP-Ping 的准确性比 ICMP-Ping 的准确性要高。但要注意的是:与 ICMP 协议不同。使用 TCPing 的时候必须要指定目标主机的端口,如果该端口开启了 TCP 服务,则连接建立成功,表示两端可以正常连通。如果没有开启该端口的 TCP 服务,则会收到该主机发送的 RST 标志位置1的 TCP 包,此时也表示两端可以连通。但是当两端不连通的时候,TCP请求会一直重传(TCP Retransmission),超过超时时间就可认为两端不连通。如图所示,本机的 6901 端口没有开启 TCP 服务,对 6901 端口建立连接时收到 RST 报文。

[点击查看大图]

2. UDP-Ping:

UDP-Ping 与 TCP-Ping的原理类似,在发包时指定一个数量值很大的目的端口号,很少应用程序用到数量值入的端口号,也就是说该端口很有可能是处于关闭状态。首先构建好 UDP 报文,然后递交给网络层发送。如果目标主机不可达(网络不通或主机未打开),则路由器将发送一个目的不可达 ICMP 报文。而如果目标主机可达,在其接收数据时,其 UDP 实体首先判断接收到的目的端口号是否与当前使用的某端口号匹配,如果匹配,则将数据报放入到对应的接收队列,否则如果目的端口号对应的端口关闭则丢弃该数据报,并回送一个“端口不可达”的 ICMP 报文。因此,只要目标主机可达,UDPPing 程序将收到一个 UDP 回应包(也可能没有)或者“端口不可达”的ICMP报 文而目标主机不可达,将收到“目的不可达”的 ICMP报文 。如图所示对本机的 8892 端口发送 UDP 报文,但是8892号端口没有开启 UDP 服务,收到端口不可达的 ICMP 报文。

事实上在 UDP 协议设计之初就考虑到了端口不可达的情况,如果收到一份 UDP 数据报而目的端口与某个正在使用的进程不相符,那么 UDP 返回一个 ICMP 不可达报文。虽然是发送的 UDP 协议的报文,但回包却是 ICMP 协议的报文,这似乎违背了网络分层的初衷。在网络通信中讲究”身份对等“的原则,即每一个分层做的事情在发送端和接收端是对等的。比如发送端用UDP协议发送数据,首先数据要先经过传输层加上 UDP 报文头部,传输到网卡出口时加上网络层的 IP 协议报文头部,随后进入链路层由 ARP 地址解析协议选择路由下一跳,而发送端添加的协议头部内容只会由接收端的对应网络层和传输层进行解析。回到我们 UDP-Ping 的例子,在这里我们发送 UDP 报文,但是却由ICMP这个网络层的协议返回结果,是不是违反了这个”身份对等“的原则?仔细思考一下其实因为目标端口没有开启 UDP 服务,该数据就还没有进入传输层,而是停留在了网络层,所以用 ICMP 协议进行不可达信息的传递也是合理的。在 UDP-Ping 中除了使用上述的利用 ICMP 不可达来进行 Ping ,还有一种方式就是完全通过 UDP 协议进行发包和回包进行 Ping。这种 Ping 需要在接收方的对应端口开启一个 UDP 服务,并在应用层指定相应的收发包的规则,而发送方需要按照这样的发送规则向接收端发送请求。这种 UDP-Ping 的方式在很多业务场景都有使用。比如检测端口服务是否是否正常,返回数据是否符合预期。这里我们着重提到需要应用层指定相应的回包策略才能完成这种 UDP-Ping ,这和 TCP 在自己的传输层层面就能完成 Ping 操作截然不同。究其原因就是 UDP 本身不依赖于建立连接,而是只通过简单的发包传达数据,这就需要上层应用来控制发包与收包的过程。

总结

前面说了这么多 Ping 的方法,不仅有大家通常理解的 ICMP-Ping,也有大家比较陌生的 UDP-Ping,TCP-Ping,可能有朋友觉得有些做法已经超出了 Ping 的工作范围,甚至需要应用层做控制才能完成 Ping 操作,这可能已经包含了整个网络传输的过程。但是不要忘了我们开头所说的 Ping 的含义:两端之间的连通性。只是我们一般用的 Ping 仅限于 ICMP-Ping。但实际上 TCP-Ping 能解决 ICMP 包在网络层被过滤的问题,UDP-Ping 能检测对端端口的服务情况,这些操作都能在一定程度上解决更广义的两端连通性问题,而不仅仅局限于两个主机间的通信。不管是日常使用软件,还是开发具体的业务场景,我们都需要对服务可用性进行探测,不管用什么样的协议,追根到底都是类似 Ping 的操作。

联系我们

如有任何疑问,欢迎加入腾讯云监控技术交流群

精选文章推荐:


关注我们,了解腾讯云监控的最新动态

0 人点赞