由一个子网掩码配置错误所想到的

今天线上发现了一个机器的子网掩码配置错了,其实问题比较简单,一开始没有想到会是这个问题,想了好久才想到这里。

我觉得网络有意思的地方就是在于这些网络协议要考虑的不仅仅是正常的情况,处理正常的情况很简单,而主要的设计其实都是针对不正常的情况如何处理的,比如处理网络中的错误、环路,错误的路由等等。但现实就是,各种各样奇怪的事情会发生,协议必须能处理好各种异常。

不妨拿这个问题来复习一下网络协议:如果子网掩码配置错了,那么两台机器能 ping 通吗?

这个问题看似比较简单,但是答案并不是一个简单的“是”或者“不是”,因为这分成好几种情况。

首先,我们明确这个子网掩码的作用,简单来说,就是判断目标地址和自己是否在同一个网络内

  • 如果是,就直接走二层网络便可达;
  • 如果不是,那么就应该将数据发给网关,让路由器去路由到目的地址,需要三层网络。

即,这个判断是发生在本地的,是一台机器判断应该将数据包的目标地址设置成网关的 MAC(不在同一个子网),还是目的 IP 的 MAC(在同一个子网下)。

对于其他的计算机来说,他们不知道你设置的子网是什么,对于他们发送给你的数据包来说,无论你的子网设置成什么,只要 IP 设置对了,都可以收到。子网的设置只对 egress 流量有影响,对 ingress 流量没有影响(不考虑 ingress 依赖 ARP 这些的话)。下文中会用 “我” 来表示本地的机器。

子网配置的比较大的情况

首先看子网配置的范围比正确范围大的情况,比如我的 IP 本来应该是 1.1.3.2/24, 但是错误的配置成了 1.1.3.2/16.

可以从不同的目标地址来分析影响:

  • 1.1.3.0/24 本来,这个范围和我是在同一个地址下面,现在由于我的子网配置的过大,那么现在,这个段还是跟我在同一个子网下面,所以我和它们之间的通讯丝毫不会收到影响;
  • 1.1.0.0/16 下面,不包含 1.1.3.0/24 的部分:本来,这部分不是跟我在同一个子网下面,现在由于我的子网配置过大,导致我认为它们跟我在一个子网下。那么,本来数据应该发往 router,现在由于我错误地认为这些目标和我在同一个子网,所以我现在会直接查询 ARP 表,通过 ARP 查到目的地址然后发出去。这显然是查询不到的,发出去的 ARP 也不会有响应的,故,这些 IP 是一定不可达

子网配置较小的情况

比如我的 IP 本来应该是 1.1.3.2/16, 但是错误的配置成了 1.1.3.2/24

如上,首先,1.1.3.0/24 这个网段,在错误之前和之后都是和我在同一个网段,所以不会收到影响,能够正确路由。

然后下面就是有意思的部分了。

假设现在要发送到的一个目的地址是 1.1.4.3, 正确的话,这应该是和我在同一个子网,但是现在我的子网变小了,我会认为它不和我在同一个网络内,需要经过路由器转发,所以我会将要发给 1.1.4.3 的数据包的目标 MAC 地址设置成路由器,并且发给路由器。

现在又出现了两种情况,第一种比较简单,是路由器的 IP 地址和我也因为错误变成了不同的网段,比如 1.1.2.1, 那么我会直接认为是 Unreachable,ping 失败。

第二种情况比较有意思:如果我因为阴差阳错,即使子网掩码配置小了,但是依然幸运地和路由器处在同一个网络内呢?

上面已经分析过,这个时候我是可以 ping 通路由器的:

那么我能 ping 通 1.1.4.3 这个地址吗?

让我们一步一步分析一下。

按照上面的逻辑,我会把去往 1.1.4.3 的包丢给路由器,对于路由器来说,它遇到了一个奇怪的事情:这个家伙来自 1.1.3.2/16(路由器视角,路由器的子网配置是正确的),然后要把这个包发送给 1.1.4.3/16, 这不是都在同一个网络 1.1.0.0/16 内吗?发给我干嘛,直接发给它呀!

这时候路由器会怎么做呢?

对于 ICMP 包来说,路由器还是会帮我把这个包转发到目的地址,即路由器通过这个 interface 收到我的包,一看,发现是目的同一个 network,它再从同一个 interface 发出去。

RFC 792 (Internet Protocol)

The gateway sends a redirect message to a host in the following situation.
A gateway, G1, receives an internet datagram from a host on a network
to which the gateway is attached. The gateway, G1, checks its routing
table and obtains the address of the next gateway, G2, on the route to
the datagram’s internet destination network, X. If G2 and the host
identified by the internet source address of the datagram are on the same
network, a redirect message is sent to the host. The redirect message
advises the host to send its traffic for network X directly to gateway
G2 as this is a shorter path to the destination. The gateway forwards
the original datagram’s data to its internet destination.

在路由器上抓包,也可以看到它产生的 Redirect message,里面有说,你应该直接去找 1.1.4.3 , 不要再来找我啦!

所以说,ping request 的包是可以发给目的地址的,只不过会多回复给发送这一个错误消息而已。

现在请求到了 ping reply 这边,reply 能成功发回去吗?

按理说前面提到过,对于其他人来说,正常发给我消息是没有问题的。但是这个回复有一个依赖,就是它要知道我的 MAC 地址,要知道我的 MAC 地址,就需要我来告诉它。

那么第二个有意思的问题就来了:如果我收到了一个 ARP 请求,和我不在同一个网段,但是询问的确实是我的 MAC 地址,我会回复吗?

这个是 Linux 配置参数,位置在 /proc/sys/net/ipv4/conf/eth0/arp_ignore 含义如下:

arp_ignore – INTEGER
Define different modes for sending replies in response to
received ARP requests that resolve local target IP addresses:
0 – (default): reply for any local target IP address, configured
on any interface
1 – reply only if the target IP address is local address
configured on the incoming interface
2 – reply only if the target IP address is local address
configured on the incoming interface and both with the
sender’s IP address are part from same subnet on this interface
3 – do not reply for local addresses configured with scope host,
only resolutions for global and link addresses are replied
4-7 – reserved
8 – do not reply for all local addresses

The max value from conf/{all,interface}/arp_ignore is used
when ARP request is received on the {interface}

因为默认值是 0, 所以是会回复的。通过 tcpdump 在 linux1 上抓包可以确认:

这时候 1.1.4.3 拿到了我的 MAC,就直接在二层把 ping 的 reply 发给我了。

如果在 Linux2 这台机器上,即 1.1.4.3 上,抓包,会发现一个有意思的现象:它从路由器 MAC 收到的 ping 包,回复给了另一个 MAC 地址。

这个奇怪的 ping 链路整体的数据流向如下:

所以说,这种情况下是可以 ping 通的。



由一个子网掩码配置错误所想到的”已经有4条评论

  1. 《Wireshark网络分析就这么简单》,这本书的第一章就提到了这个问题,和你本篇讨论的一模一样;
    我根据书本实践了下,确实收到了 ping redirect 。但这个和路由器也有关系,如果是 小米路由器 就看不到ping redirect ,应该是被小米路由器丢包了。换成 tp-link 路由器就可以正常ping通。
    同时也要注意电脑的防火墙,我ping windows主机,windows主机确实收到了ping 请求,但是windows没有给响应,原来是windows防火墙 认为 这个ping 请求比较特殊(ip不在一个网段,但是是直接发给windows主机的)。直接全部关闭windows防火墙,或者具体调整下防火墙ping策略就通了。

    • 感谢,我之前就知道这本书,但是一直没去读,原来它也讲了这个问题,感觉是时候好好读一下了。

      家用的网络环境跟 DC 的网络有很多不同之处,家用路由器也比较复杂,一般是一个二层+三层的基于 Linux 的设备,以易用性为主,可能很多设计也没有遵循规范,能用就行。

      这种测试我一般用网络网络模拟器去做,比如 GNS3,这样在研究某一个问题的时候可以排除掉很多其他因素的影响。

Leave a comment

您的电子邮箱地址不会被公开。 必填项已用 * 标注