起步
在一个局域网中存在两台服务器 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 文件。
- 我们已经知道,“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:
可以看到,B 发出的 ICMP 包尽管目标 IP 是 A 的 IP 地址,但目标 MAC 地址却是网关的。对 B 来说,A 跟自己不在一个网段内,只能通过网关转发数据。
包 4:
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 时,不需要网关转发。
A ping B
基于上述分析,我们就很容易知道 A 可以 ping 通 B。
子网的误判
在前面示例中,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 可以正常通信,且不需要网关转发。
抓包可得:
讲的很好,可以进一步讲一下vlan 和vxlan
想请问一下,这个场景是B和网关还在同一网段,所以B仍能通过请求网关ARP来通过网关和A通信,那么加入把网关地址设置为192.168.211.254,那B还能ping到A吗?
这个很简单,你手动试一下就知道了