目录
ARP 地址解析协议
在 Ethernet 中,每台主机的网卡都有一个唯一的 MAC 地址,而主机之间 Internet 通信需要使用 IP 地址。因此,当一台主机需要向另一台主机发送数据时,它需要将目标主机的 IP 地址解析为对应的 MAC 地址才能发送数据。
在 Ethernet 诞生之初,主机的 MAC 地址和 IP 地址通常是静态配置的,需要手动进行映射。这种方式有很多问题,比如:当网络拓扑发生变化时,需要手动修改主机的配置,而且还需要管理大量的映射关系。因此,ARP 协议应运而生,它提供了一种自动解析 IP 地址到 MAC 地址的机制,简化了网络管理。
ARP(Address Resolution Protocol)协议最早在 1982 年提出(Ethernet I 标志诞生的 6 年后),并在 RFC826 中进行了规范。ARP 协议通过 ARP table 来完成 IPv4 地址和 MAC 地址之间的转换,称之为地址解析(Address Resolution)。而在 IPv6 中,则使用了 NDP(邻居发现协议)代替 ARP。
每台安装了 Ethernet 网卡的主机都会维护一个 ARP table(缓存表)。
-
主机收到 Frame 时,通过解析 Frame dstMAC 地址来确定自己是否为目的主机,如果是则接收,如果不是则丢弃。
-
主机发送 Frame 时,第一时间只知道 dstIP 却不知道 dstMAC,所以需要通过 ARP 广播来询问 Ethernet 局域网中 dstIP 所对应的 dstMAC 地址是多少,然后才能将 dstMAC 填充到 Frame Header 中并发出。
可见,ARP 协议主要应用于 Ethernet 局域网的主机发包场景。在一些非 Ethernet 局域网场景,比如点对点链路中是不需要 ARP 的,因为点对点网络也不存在 MAC 地址。
ARP 协议栈
ARP 协议栈由 Ethernet Frame 协议和 ARP 协议组成,所以需要分成 2 个不同的部分来进行展开。
Frame Header
- srcMAC(8Byte):发出 Frame 的主机网络的 MAC 地址。
- dstMAC(8Byte):在 ARP Request 中,dstMAC 为 FF:FF:FF:FF:FF:FF,是一个局域网广播地址,表示发给局域网中的所有主机。
- Type(2Byte):表示 Frame 的类型。
- ARP Type:0x0806;
- IP Type:0x0800。
Frame Data
ARP Header
- Hardware type:表示 ARP 工作在什么类型的网络中,需要什么样的物理地址。通常是 1(Ethernet 类型、MAC 物理地址)。
- Protocol type:表示上层协议的类型。通常是 0x0800(IPv4)。
- Hardware size 字段:Hardware type 为 MAC 类型时,Size 为 6Byte。
- Protocol size 字段:Protocol type 为 IP 类型时,Size 为 4Byte。
- Opcode(操作码)字段:表示 ARP 报文的操作类型。
- 1:ARP Request
- 2:ARP Reply
- 3:RARP Request
- 4:RARP Reply
ARP Data
- Sender MAC address:ARP 报文发送者的 MAC 地址。
- Target MAC address:ARP 报文目标的 MAC 地址。当发送的是 ARP Request 时,Target MAC address 为全 0,因为 ARP Request 就是要获得这个地址。当 Target 设备收到 Request 后,就会把自己的 MAC 地址写到这个字段,并把操作码改成 2,再 Reply 回去。
- Sender IP address:ARP 报文发送者的 IP 地址。
- Target IP address:ARP 报文目标的 IP 地址。
注意,因为 ARP Header + Data 的长度为 28Byte,还不够 Ethernet 协议要求的 Frame Data 至少为 46Byte,所以需要填充至少 18Byte。
ARP 的工作原理
下面以主机 A(192.168.38.10)向主机 B(192.168.38.11)发送数据为例。
-
当 A 发送数据时,首先会在自己的 ARP table 中寻找是否有 B 的 IP 地址。如果找到,就得到了 B 的 MAC 地址 00-BB-00-62-C2-02。将其作为 dstMAC 地址封装入 Frame Header,然后通过数据链路层发送就可。
-
如果没有找到,那么 A 就会在局域网广播一个 ARP Request。Frame Header 的 dstMAC 为 FF.FF.FF.FF.FF.FF,表示广播。意思是向同一 LAN 内的所有主机发出询问:“192.168.38.11 的 MAC 地址是什么?”
ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 53.53.53.53 tell 192.168.200.10, length 28
- 由于 Frame 的 dstMAC 是广播地址,所以所有主机都需要接收,同时就只有 B 的 IP 地址与 ARP Data 中的 Target IP address 一致,所以 B 将自己的 MAC 填充到 ARP Data 中的 Target MAC address,并回应。意思是回答:“192.168.38.11 的 MAC 地址是 00-BB-00-62-C2-02”。ARP Reply 是单播的,因为 B 知道 A 的 MAC 地址。
- A 更新自己的 ARP table。
- ARP table 具有老化机制,在一段时间内(一般为 20 分钟)如果 Table 中的某条记录一直没有被使用,就会过期删除。
- srcMAC 为主机自己的 MAC 地址,用于接收 ARP reply。
- dstMAC 为全 1(ff:ff:ff:ff:ff:ff),表示该 ARP 报文是广播报文,所有主机都要接收。
- Sender IP address 为全 0(0.0.0.0),表示该 ARP 报文是无效报文,主机的 ARP table 不需要缓存。
- Target IP address 为需要探测的 IP 地址,如果数据链路中已经有同 IP 的设备,收到探测包之后会给源主机发送 ARP reply。
- 对于网关:将所有的客户端的 MAC 以及对应 IP 进行静态绑定,防止攻击者假冒客户端。
- 对于客户端:绑定网关 MAC 地址,防止攻击者假冒网关;
- Sender MAC address 为自己的 MAC 地址。
- Target MAC address 为全 1(ff:ff:ff:ff:ff:ff),表示该 ARP 报文是广播报文,所有主机都要接收。
- Sender IP address 和 Target IP address 相同,都是自己的 IP 地址。
- Announcing a Node’s Existence(宣布节点存在):ARP Probe 后使用。
- Updating ARP Mapping(更新 ARP 映射):主机更新 IP 地址后使用。
- Link Redundancy(链路冗余):在 HA 场景中进行 VIP 切换或物理链路切换时使用。
- 仅 IP 冗余:两个 MAC 使用同一个 IP。
- IP 和 MAC 都冗余:两个 MAC 各自有一个 IP。
ARP Proxy(代理/代答)
在跨 LAN(局域网)通信场景中,ARP request 是没法被广播的,因为跨 LAN 通信的 Router(路由器)会隔离广播域。所以此时,会由 Router 来充当 ARP Proxy 的角色,对跨 LAN 的 ARP request 进行代答(具体参考 RFC925 和 RFC1027)。
表示将 Frame 发给我,然后交由我来完成 L3 路由转发。于是,此后源主机发往目的主机的所有 Frames,都将先发往该 Router,再通过它向外发送。
ARP proxy 是 Router 实现的一种功能,配置即可开启。
ARP proxy 还会被用于 NAT 设备,因为 NAT 设备本质也是一个划分不同 LANs 的 Gateway。
ARP Probe(探测)
ARP probe 在 RFC5227 中定义,用于预防 IP 地址冲突。ARP probe 的工作就是判断当前局域网中是否已经存在了指定的 IP 地址。
ARP probe 报文是一个 APR request 操作类型,有以下特点:
这样,源主机就知道数据链路中存在相同 IP 地址了。如果 ARP 探测发现 IP 没有被占用,那么主机紧接着就会发送一个 gARP 来告知数据链路中的其他主机,自己的 IP 地址和 MAC 地址。
MAC 地址冲突问题
当同一个 LAN 中存在两个 MAC 地址一致的网卡设备时(通常是虚拟)的,就会出现 MAC 地址冲突。这种情况通常出现在虚拟机场景中,因为虚拟网卡的 MAC 地址是可以手动指定的。
MAC 地址冲突会导致次优路径问题,ICMP 会出现如下返回。
ARP Spoofing(欺骗)
ARP 机制是一种 “无状态”、“无验证” 的协议,即:A 在收到 ARP Reply 后,更新 ARP table 前,是不会进行任何甄别的。这就是 ARP 协议很容易受到 ARP spoofing 攻击的原因。
ARP Spoofing 的运作原理是由攻击者发送假的 ARP 数据包到网络上,尤其是送到网关上。假设你的网关的 IP 地址是 192.168.0.2,MAC 地址为 00-11-22-33-44-55,那么你发送的数据都会从这个 MAC 地址经过,这时候我发送大量的 ARP 数据包,然而我的包是构造出来的,IP 依旧是你的 IP,但 MAC 地址却被我替换成了我的 MAC 地址。此时当你更新你的 ARP 缓存时,就会把我机器的 MAC 地址当成 192.168.0.2 的 MAC 地址,于是你的流量都到我这来了。
所以 ARP 欺骗的目的是要让送至特定的 IP 地址的流量被错误送到攻击者所取代的地方。因此攻击者可将这些流量另行转送到真正的网关(Passive Sniffing,被动式数据包嗅探)或是篡改后再转送(Man-in-the-middle Attack,中间人攻击)。攻击者亦可将 ARP 数据包导到不存在的 MAC 地址以达到阻断服务攻击的效果。
预防方式之一就是使用 static ARP mapping 记录,这在虚拟化云平台中被采用。
但是 static ARP mapping 的方式在物理网络中缺乏可行性,因为 ARP table 经常需要更新。所以采用 DHCP snooping 的方式,即:网络设备可借由 DHCP 保留网络上各主机的 MAC 地址,在伪造的 ARP 数据包发出时即可侦测到。此方式被广泛应用。
gARP
gARP(Gratuitous ARP),是一种特殊的 ARP request,具有以下特点:
gARP 报文通常用于更新其他主机的 ARP table 记录,表示主动告知对方自己对 IP-MAC mapping 关系的占用。基于这种灵活的形式,gARP 有着广泛的用途:
Link Redundancy(链路冗余)
Redundancy(冗余)的目的是为了设计 HA(High-Availability,高可靠性)系统的 Failover(故障转移)。
通常有两种情况:
VIP 切换
典型应用就是 Keepalived 和 Pacemaker。
下图很好的说明了通过 GARP 支撑 VIP 偏移的实现原理:在 VIP 漂移(IP 从一个 MAC Failover 到另外一个 MAC)后马上发送 GARP 刷新所有其他主机的 ARP 缓存。
需要注意的是,有一些防火墙是不支持 GARP 流量的(防止使用 GARP 进行 ARP 欺诈),此时要考虑采用 VMAC(MAC 地址是在两个节点之间共享)来代替 GARP 方案。
Keepalived 1.2.20 及更高版本支持下列 GARP 的配置设置:
# delay for second set of gratuitous ARPs after transition to MASTER
vrrp_garp_master_delay 10 # seconds, default 5, 0 for no second set
# number of gratuitous ARP messages to send at a time after transition to MASTER
vrrp_garp_master_repeat 1 # default 5
# delay for second set of gratuitous ARPs after lower priority advert received when MASTER
vrrp_garp_lower_prio_delay 10
# number of gratuitous ARP messages to send at a time after lower priority advert received when MASTER
vrrp_garp_lower_prio_repeat 1
# minimum time interval for refreshing gratuitous ARPs while MASTER
vrrp_garp_master_refresh 60 # secs, default 0 (no refreshing)
# number of gratuitous ARP messages to send at a time while MASTER
vrrp_garp_master_refresh_repeat 2 # default 1
# Delay in ms between gratuitous ARP messages sent on an interface
vrrp_garp_interval 0.001 # decimal, seconds (resolution usecs). Default 0.
# Delay in ms between unsolicited NA messages sent on an interface
vrrp_gna_interval 0.000001 # decimal, seconds (resolution usecs). Default 0.
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
交换链路切换
该场景中,有两张不同的网卡都具有同一个 MAC 地址和 IP 地址,并连接到交换机的两个端口。
此时,尽管我们不需要考虑刷新主机的 ARP 缓存,但需要使用一个 GARP 来通知交换机进行重新选路(刷新交换机的 MAC table),继而才能通过新的 MAC 找到正确的通路。
ARP 的客户端
Linux 操作系统都会安装 ARP 客户端,操作如下:
arp --help
-a 查看缓存中的所有项目
-s, --set 设置一个新的 ARP 项目、不带任何参数表示查看静态 MAC 地址
-d, --delete 人工删除一个静态项目
-v, --verbose be verbose
-n, --numeric don't resolve names
-i, --device specify network interface (e.g. eth0)
-D, --use-device read <hwaddr> from given device
-A, -p, --protocol specify protocol family
-f, --file read new entries from file or from /etc/ethers
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 查看 ARP 缓存表
$ arp -a
? (172.18.22.205) at 08:9e:01:fc:48:7d [ether] on br0
? (172.18.22.10) at 52:54:00:bd:23:9e [ether] on br0
gateway (172.18.22.1) at ac:7e:8a:6c:41:c4 [ether] on br0
- 2
- 3
- 4
- 查看 ARP 缓存表的详细信息
$ arp -nv
Address HWtype HWaddress Flags Mask Iface
172.18.22.205 ether 08:9e:01:fc:48:7d C br0
172.18.22.10 ether 52:54:00:bd:23:9e C br0
172.18.22.1 ether ac:7e:8a:6c:41:c4 C br0
Entries: 3 Skipped: 0 Found: 3
- 2
- 3
- 4
- 5
- 6
- 增加一个静态的 ARP 表项
$ arp –s 157.55.85.212 00-aa-aa-562-c6-09
# 增加超时条目
$ arp -s 211.161.17.21 00:00:00:00:00:00 temp
- 2
- 3
- 4
- 禁用主机 ARP,要求配置静态 ARP 缓存才能通信:
$ ip link set dev eth0 arp off
- 发送 Gratuitous ARP,让网络中所有主机更新当前机器的 ARP 记录:
$ arping -A -I eth0 172.16.42.161
这个命令就是把机器上 eth0 绑定的 MAC 地址和 172.16.42.161 作为 ARP 记录发送出去。