在 Ethernet 环境中,所有的数据最终都要以二层 Ethernet Frame 的形式发送,要添加 Src MAC, Dst MAC, 以及其他的 header,比如 CRC 等,Ethernet 就会把数据送达到目的地。
我们在编程的时候经常指定 IP 和 Port,但是几乎从没有指定过 MAC 地址,那么 Frame 是怎么发出去的呢?这是操作系统帮我做了这件事。如果系统不知道一个 IP 对应的 MAC 地址是什么,系统会发送一个广播的 ARP 请求,(由于这个请求也是要通过 Ethernet 发送出去的,所以也要填充 Dst MAC,Dst MAC 就是 ff:ff:ff:ff:ff:ff
。)询问谁有目的 IP,如果有,请回复给 MAC-B。广播域中所有的 Host 都会收到这个请求,只有拥有这个 IP 的 Host 才会回复给 MAC-B 自己的 MAC 地址,这样,B 就知道了这个 IP 对应的 MAC 地址。
这就是普通的 ARP request 和 response 的过程。
其中,里面的几个值得注意的 field 如下:
对于 ARP request 来说:
- Operation:
1
(1表示 request,2
表示 response); - Src MAC: sender 的 MAC;
- Src IP: sender 的 IP;
- Dst MAC:全1,即广播给所有主机;
- Dst IP:是要询问的 IP;
对于 ARP Response 来说:
- Operation:
2
; - Src MAC: sender(sender 在这里是响应者) 的 MAC;
- Src IP: sender 的 IP;
- Dst MAC:receiver (在这里是 ARP 问题的发出者)的 MAC;
- Dst IP:receiver IP;
ARP 是一个很简单的协议,但是人们基于交换机和主机的工作原理,设计了其他的用法。这些用法其实并不复杂,最重要的就是理解这些设备最基本的工作原理,这样就可以理解这些特殊的 ARP 设计意图了。
Gratuitous ARP
在之前的博客中介绍过两次使用 Gratuitous ARP 的例子。Gratuitous ARP 的目的是更新其他设备的 ARP cache,或者交换机 mac-address table。
在 VRRP1 中,目的主要是切换网关,更新的对象是 mac-address table。交换机的 mac-address table 主要是通过收到的包的 Src MAC 来学习 MAC 对应的物理 port 的,所以最重要的是 Src MAC,其他的都不重要。
所以在 VRRP 中的 Gratuitous ARP 是这样的:
- Operation:
1
(request); - Src MAC: sender 的 MAC;
- Src IP: sender 的 IP;
- Dst MAC:全1,即广播给所有主机;
- Dst IP:全1;
在 Linux 的 balance-alb bonding 模式2中,ARP 的目的是为了刷新其他主机的 ARP Cache,并且希望不同的主机拿到不一样的 MAC 地址,所以使用的 ARP 是 response,并且是 unicast。
- Operation: 2 (response);
- Src MAC: sender 的 MAC;
- Src IP: sender 的 IP;
- Dst MAC:bond driver 记录的 MAC;
- Dst IP:bond driver 记录的 IP;
取决于使用场景,Gratuitous ARP 也是 broadcast 的 reply,将 response 信息广播给所有的主机3。
ARP Probe
ARP Probe 的作用是,在分配到一个 IP 之后,但是在 IP 使用之前,可以先用 ARP 协议来检查一下当前的 LAN 内有没有人在使用这个 IP。
检查的方式就是用 ARP 询问这个 IP 的 MAC 地址,如果有主机正在使用,那么就会收到 ARP reply。
但是这里有一个问题。一个主机如果收到了 ARP request,询问谁有 IP X?请发送回复给 IP 地址 Y at MAC 地址 Z。即使这个主机没有 IP X,也不会单纯丢弃这个 ARP request,而是会从这个 ARP request 中学习到,IP Y 对应 MAC Z,会将它放到自己的 ARP cache 中。
这里我们只是想检查一个 IP 是否正在被使用,我们还没有真正地开始使用这个 IP。如果用普通的 ARP 请求来询问,假设这个 IP 已经被使用,那么发出去的 ARP request 就会传达错误的信息,其他主机就会根据这个 ARP request 来更新自己的 ARP cache。
为了解决这个问题,ARP Probe 使用的 request 将 Src IP 设置为 0.0.0.0
,这样,这个 ARP request 就完全无害了。
ARP 请求如下(加粗部分是和普通的 ARP request 不一样的部分)。
- Operation:
1
(request); - Src MAC: sender 的 MAC;
- Src IP:
0.0.0.0
; - Dst MAC:全1,即广播给所有主机;
- 询问的 IP:自己将要使用的 IP;
ARP Announce
ARP Announce 用于在 ARP Probe 确定没有问题之后,决定使用这个 IP,但是再一次确定唯一性。
ARP Announce 发送一个普通的 ARP request, 在 LAN 内询问自己将要使用的 IP,正常情况下不会收到任何回复,因为这个 IP 是自己的。异常情况下收到回复,那么说明 LAN 已经有人在使用这个 IP 了,需要终止继续使用这个 IP。
ARP Announce 是普通的 ARP 请求,和 Gratuitous ARP 很像。询问的目标 IP 是自己的 IP。
ARP Announce 又叫做 Unsolictied ARP。
ARP Announce 和 ARP Probe 的唯一区别就是 Src IP 不同,ARP Announce 使用自己的 IP 来发送,所以也会更新 LAN 内其他设备的 ARP cache。
- Operation:
1
(request); - Src MAC: sender 的 MAC;
- Src IP: sender 的 IP;
- Dst MAC:全1,即广播给所有主机;
- Dst IP:自己即将使用的 IP;
参考资料:
- ARP Probe and ARP Announcement https://www.practicalnetworking.net/series/arp/arp-probe-arp-announcement
- 首跳冗余协议 VRRP ↩︎
- 数据中心网络高可用技术之从服务器到交换机:balance-tlb 和 balance-alb ↩︎
- Gratuitous ARP https://www.practicalnetworking.net/series/arp/gratuitous-arp/ ↩︎
文章中的”询问的 IP”是代指什么呢?比如 ARP Probe “Dst IP:全1;询问的 IP:自己将要使用的 IP;”, 这个场景下 DstIP 应该是自己要使用的 IP 地址?
看了下目前 K8s 场景下用的比较多的 kube-vip 项目,他们是交替发送 ARP request 和 ARP reply,在 Issue 里面提到的原因是:“After digging more it turns out that, both ARPRequest and ARPReply can be used to send gratuitous ARP, and network devices may only support either one of them.” ,
相关代码: https://github.com/kube-vip/kube-vip/blob/main/pkg/vip/arp.go#L107-L113
文字的意思是,arp 问题中请求的 IP 是自己即将使用的 IP,在 ARP 协议的 body 中。ARP over IP, 外层 IP 包的 dest IP 是全 1 的,因为 ARP 请求是广播包,dst MAC 地址是全 1,dst IP 是全1.
你说的方式:Dst IP 是 unicast IP 但是 dst MAC 地址是全 1,好像也没有什么问题?但是不符合广播包的定义吧。我理解错了,文中已经修改。
你提的这个例子确实这样做比较 solid,学习了。网络设备只从某一种来学习是有些道理的,比如 ARP request 发出去的时候,主机可能不使用正确的 ip 和 mac 地址对应。只能说现实世界太复杂了。
“The packets are carried at the data link layer of the underlying network as raw payload.” https://en.wikipedia.org/wiki/Address_Resolution_Protocol
ARP 不是 over IP 的,没有外层的 IP 包啊。
额,你说的对,我完全理解错了,修改一下。
Operation: 1 (request);
Src MAC: sender 的 MAC;
Src IP: sender 的 IP;
Dst MAC:全1,即广播给所有主机;
Dst IP:全1;
Dst IP不是全1啊,应该是要询问的对应mac地址的IP啊
你说的对,已经修改,感谢!