起步

在一个局域网中存在两台服务器 A, B:

  • A:IP=192.168.211.110, NETMASK=255.255.255.0
  • B:IP=192.168.211.3, NETMASK=255.255.255.224

此时,A B 能相互通信吗?

环境说明

A, B 服务器均为 centos7 —— 通过 vmware 启动的虚拟机。

A:IP=192.168.211.110, NETMASK=255.255.255.0, MAC=00:0c:29:69:73:ae
B:IP=192.168.211.3, NETMASK=255.255.255.224, MAC=00:0c:29:3a:1b:85
网关:IP=192.168.211.2, NETMASK=255.255.255.0, MAC=00:50:56:e3:77:90

实现过程中需要用的工具:

$ yum install tcpdump
$ yum install net-tools

为方便分析数据包,在宿主机上安装 wireshark。

B ping A

在 B 上执行 ping 192.168.211.110 之前,应该确保 B 环境上没有 arp 缓存。可通过以下命令查看:

$ arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
192.168.211.2            ether   00:50:56:e3:77:90   C                     ens33

# 或者
$ ip neigh show
192.168.211.2 dev ens33 lladdr 00:50:56:e3:77:90 DELAY

执行 ip neigh flush dev ens33 清除 arp 缓存。


这里先说结论:B 可以 ping 通 A。问题来了,为什么 B 还可以 ping 通 A 呢?子网掩码还有意义吗?ping 通之前发生了什么?我们用“抓包”揭晓谜底。

第一步,在 B 上执行:

$ tcpdump -i ens33 -vvvvAls0 -w b_ping_a.pcap

第二步,新开一个窗口,在 B 上执行:

$ ping 192.168.211.110

一段时间后结束抓包,在宿主机上用 wireshark 打开 pcap 文件
Alt text

  • 我们已经知道,“85” 是 B ens33 网卡的 MAC 地址,“90” 是网关的 MAC 地址,“ae” 是 A 的网卡地址。

1    0.000000    VMware_3a:1b:85    Broadcast    ARP    42    Who has 192.168.211.2? Tell 192.168.211.3

当开始 B ping A 时,B 通过子网掩码计算,发现目标 IP(192.168.211.110) 跟自己不在一个网段,所以 B 需要找到网关,希望网关把自己数据包转发出去。

但 B 只知道网关的 IP 是 192.168.211.2,可在局域网中,通信要靠 MAC 地址。于是 B 发起了 arp 协议的广播包,询问网关的 MAC 地址:Who has 192.168.211.2? Tell 192.168.211.3。(wireshark 中 info 的解释十分明了,不多做解释)


2    0.000068    VMware_e3:77:90    VMware_3a:1b:85    ARP    60    192.168.211.2 is at 00:50:56:e3:77:90

此时网关听说有人找他,立马回复 B,告诉 B 自己的 MAC 地址是 xxxx:192.168.211.2 is at 00:50:56:e3:77:90


3    0.000071    192.168.211.3    192.168.211.110    ICMP    98    Echo (ping) request  id=0x0b32, seq=1/256, ttl=64 (no response found!)
4    0.000113    192.168.211.3    192.168.211.110    ICMP    98    Echo (ping) request  id=0x0b32, seq=1/256, ttl=128 (reply in 7)

第 3、4 个包耐人寻味,B 为啥一连发两个 ICMP 包呢?而且第 3 个包还说“no response found!”。此时需要查看包的详情。

包 3:
Alt text

可以看到,B 发出的 ICMP 包尽管目标 IP 是 A 的 IP 地址,但目标 MAC 地址却是网关的。对 B 来说,A 跟自己不在一个网段内,只能通过网关转发数据

包 4:
Alt text

IP 层的 源IP 和 目标IP 没有变动,但 MAC 层的 源MAC地址 和 目标MAC地址 有了不同。源MAC地址 变成了网关的 MAC 地址,也就是说,这个包确实从网关转发到 A。


5    0.000185    VMware_69:73:ae    Broadcast    ARP    60    Who has 192.168.211.3? Tell 192.168.211.110
6    0.000188    VMware_3a:1b:85    VMware_69:73:ae    ARP    42    192.168.211.3 is at 00:0c:29:3a:1b:85

A 收到 ICMP 请求包之后,需要回复 B。A 用自己的网络掩码计算 B 的网段,嘿,居然是自己人!于是直接 arp 广播:Who has 192.168.211.3? Tell 192.168.211.110

B 也直接 arp 回复:192.168.211.3 is at 00:0c:29:3a:1b:85


7    0.000250    192.168.211.110    192.168.211.3    ICMP    98    Echo (ping) reply    id=0x0b32, seq=1/256, ttl=64 (request in 4)

A 得知 B 的 MAC地址 之后,直接向 B 回复之前 B 发出的 ICMP request。

从抓到的包来看,之后 B ICMP request A 时,一直都需要网关转发;A ICMP reply B 时,不需要网关转发。
Alt text

A ping B

基于上述分析,我们就很容易知道 A 可以 ping 通 B。

在 A 上抓包
Alt text

子网的误判

在前面示例中,B 认为 A 跟自己不在一个网段,A 却认为 B 跟自己在一个网段。这是因为做网段判断时,AB 是用自己的子网掩码来计算的,这就可能引发误判。

现在将 B 的 IP 改为:192.168.211.111,掩码依旧保持 255.255.255.224。

此时 B 认为自己属于 255.255.255.0110 0000 网段;计算 A 的网段时,认为 A 的网段也是 255.255.255.0110 0000。 对于 A 来说,子网掩码是 255.255.255.0,于是得出 B 在 255.255.255.0000 0000 网段,跟自己同属一个子网。

尽管 A, B 不在一个子网,但在它们自己看来,它们“属于”一个子网。恰好 arp 不考虑跨网问题,于是 A, B 可以正常通信,且不需要网关转发。

抓包可得
Alt text

感谢



本文由 Guan 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

3 条评论

  1. chauncey
    chauncey

    讲的很好,可以进一步讲一下vlan 和vxlan

  2. nigosim
    nigosim

    想请问一下,这个场景是B和网关还在同一网段,所以B仍能通过请求网关ARP来通过网关和A通信,那么加入把网关地址设置为192.168.211.254,那B还能ping到A吗?

    1. Guan
      Guan

      这个很简单,你手动试一下就知道了

添加新评论