ARP(Address Resolution Protocol,地址解析协议),是一个通过解析网络层 IP 地址来找寻数据链路层 MAC 地址的网络传输协议,它在 IPv4 中极其重要。ARP 最初在 1982 年的 RFC 826 中提出并纳入互联网标准 STD 37。在 IPv6 中,使用的是 NDP(邻居发现协议)用于代替 ARP。
MAC 地址(Media Access Control Address),直译为媒体存取控制位址,也称为局域网地址(LAN Address),MAC 位址,以太网地址(Ethernet Address)或物理地址(Physical Address),它是一个用来确认网络设备位置的地址。
以太网是一种计算机局域网技术。IEEE 组织的 IEEE 802.3 标准制定了以太网的技术标准,它规定了包括物理层的连线、电子信号和介质访问层协议的内容。以太网是目前应用最普遍的局域网技术,取代了其他局域网技术如令牌环、FDDI 和 ARCNET。
在以太网协议中规定,同一局域网中的一台主机要和另一台主机进行直接通信,必须要知道目标主机的 MAC 地址。而在 TCP/IP 协议中,网络层和传输层只关心目标主机的 IP 地址以及端口号。这就导致在以太网中使用 IP 协议时,数据链路层的以太网协议接到上层 IP 协议提供的数据中,只包含目的主机的 IP 地址。而没有 MAC 地址就无法最终定位目的主机,于是需要一种方法,根据目的主机的 IP 地址,获得其 MAC 地址。这就是 ARP 协议要做的事情。所谓地址解析(Address Resolution)就是主机在发送数据帧前将目标 IP 地址转换成目标 MAC 地址的过程。
而在点对点链路中不会使用 ARP,实际上在点对点网络中也不会使用 MAC 地址,因为在此类网络中分别已经获取了对端的 IP 地址。
注意:ARP 已经在很多网路层和数据链接层之间得以实现,包括 IPv4、Chaosnet、DECnet 和 Xerox PARC Universal Packet(PUP),使用 IEEE 802 标准。可见,ARP 不仅限于使用在 IPv4 网络,这一点从 ARP 的数据包结构设计中有体现出来。
以太网目的地址和以太网源地址:表示目标设备和发送端设备的以太网地址。其中,目的以太网地址全为 1,即 FF:FF:FF:FF:FF:FF,为广播地址,在本地局域网内,所有的以太网接口都要接收这个数据帧。
帧类型:表示以太网数据帧的数据类型。对于 ARP 来说这里是 0x0806,对于 IP 数据报文是 0x0800,还有 RARP(逆地址解析协议)是 0x8035。
NOTE:如果以太网数据帧的帧类型是 ARP,那么数据部分就会拥有 ARP 首部。
ARP 首部:
硬件类型和协议类型:这两个字段用来描述 ARP 分组。前者表示 ARP 工作在什么类型的网络中,需要什么样的物理地址;后者则表示需要映射的协议地址类型。例如:用来描述 IPv4 时,则协议类型为 IP,硬件类型为以太网的物理地址。所以协议类型为 0x0800,硬件类型为 1,表示以太网地址。
硬件地址长度和协议地址长度:用来描述 IPv4 时,分别表示 MAC 地址和 IP 地址的长度,分别为 6 字节和 4 字节。
操作码:表示 ARP 数据包的操作类型。
源硬件地址和目标硬件地址:与以太网首部中的目的以太网地址和源以太网地址重叠。
源协议地址和目标协议地址:用来描述 IPv4 时,分别表示源设备 IP 地址和目的设备 IP 地址。
NOTE 1:在发送 ARP 请求时,目标硬件地址是空着的(全为 0),因为 ARP 请求要请求的就是它的值,当目标设备请求收到后,就会把自己的硬件地址写到这个字段,并把操作码改成 2,再应答回去。
NOTE 2:在 ARP 中,有效数据的长度为 28 个字节,不足以太网的最小长度 46 字节长度。所以需要填充字节,填充字节最小长度为 18 个字节。
在每台安装有 TCP/IP 协议的电脑或路由器里都有一个 ARP 缓存表,表里的 IP 地址与 MAC 地址是一对应的,如下表所示。
工作流程:
下面以主机 A(192.168.38.10)向主机 B(192.168.38.11)发送数据为例:
当主机 A 发送数据时,会在自己的 ARP 缓存表中寻找是否有目的 IP 地址。如果找到就知道目标 MAC 地址为 00-BB-00-62-C2-02,直接把目的 MAC 地址封装入数据帧,然后通过数据链路层发送就可。
如果在 ARP 缓存表中没有找到目的 IP 地址,那么主机 A 就会在网络上发送一个广播(ARP Request),目标 MAC 地址是 FF.FF.FF.FF.FF.FF,这表示向同一网段内的所有主机发出这样的询问:“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
NOTE:请求解析方收到 ARP 回应包之后,不会进行任何判断,就直接将对应的 MAC 地址存入自己的 ARP 缓存中,这也是 ARP 投毒攻击的产生原因。
当协议栈中需要再次进行 IP 解析的时候,系统会自动到 ARP 缓存表中查找是否已经存在相应的 IP 表项,如果已存在则使用之,如果不存在,则执行解析流程,对指定的 IP 进行 ARP 解析。
同时,ARP 缓存表采用老化机制,在一段时间内(一般为 20 分钟)如果表中的某一行没有使用,就会被过期删除,这样可减少缓存表的长度,加快查询速度。
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
[root@ctl-host ~]# 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
[root@ctl-host ~]# 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
$ 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
ip link set dev eth0 arp off
另外,当源主机和目的主机不在同一个局域网中时,即便知道对方的 MAC 地址,两者也不能直接通信,必须经过三层路由转发才可以。所以此时,源主机通过 ARP 协议获得的将不是目的主机的真实 MAC 地址,而是一台可以通往局域网外的路由器的 MAC 地址。于是此后源主机发往目的主机的所有帧,都将发往该路由器,通过它向外发送。这种情况称为委托 ARP 或 ARP 代理(Proxy)。这是设计好的网络特性,具体参考 RFC925 和 RFC1027。
ARP proxy 可以在路由器上配置,从而代替默认网关,为子网实现三层转发,而子网内的设备仍然会认为自己在一个二层网络中。这种用途现在比较少。
ARP proxy 还有个用途就是用于 NAT 设备的 ARP 应答。设备 X 访问设备 Y,当网络包走到路由器 C,路由器 C 首先也会发送 ARP 广播请求,来查询目的设备的 MAC 地址。但是由于 Y 设备与路由器 C 不在一个数据链路中,Y 设备收不到路由器 C 发出的 ARP 广播请求,因此需要 NAT 设备代答 ARP。这里也可以理解成,22 为一个虚拟的端口(72.3.4.55)提供 ARP 响应功能。这样数据包能接着发送到 NAT 设备,进而转发到设备 Y。
ARP 探测由 RFC5227 定义。当一个设备以任何方式获取了 IP 地址,想在一个数据链路中上线时,如果该数据链路中已经存在了一个相同 IP 地址的设备,那该设备上线将导致两个设备网络都不可用。为了防止该情况的发生,可以使用 ARP probe 判断当前网络是否已经有指定 IP 地址。
ARP 探测包本身也是一个普通的 ARP 请求(操作码 1),但是其 SPA 需要设置成 0.0.0.0。ARP cache 的更新内容来自于 SPA 和 SHA,由于 SPA 为空,ARP 探测包中的 ARP 数据是无效的,因此 ARP probe 数据包不会更新任何设备的 ARP cache。这是合理的,因为 ARP 探测本身就是一个不确定的行为,如果数据链路中已经有了相应的 IP 地址设备,自然也不希望在 ARP 探测时修改已有的 ARP entry。
同样的,ARP 探测报文是一个广播报文,也就是说它的以太网报头中的目的 MAC 地址是 ff:ff:ff:ff:ff:ff。ARP 探测报的 TPA 设置成希望探测的 IP 地址,这样如果数据链路中已经有同 IP 的设备,收到探测包之后会给源设备发送 ARP 响应,而源设备也就知道了数据链路中存在相同 IP 地址的设备。
ARP 探测如果没有发现 IP 被占用,通常会接着发送一个 GARP 来告知数据链路中的其他设备有关自己的 IP 地址和 MAC 地址。根据 RFC5227,这个时候的 GARP 应该是一个 ARP 请求(操作码 1)。
ARP 机制是一种 “无状态”、“无验证” 的协议,所以它很容易受到 ARP spoofing 攻击。ARP spoofing,即 ARP 欺骗,又称 ARP 投毒,是一种针对 ARP 的攻击方式。
ARP 欺骗的运作原理是由攻击者发送假的 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 地址以达到阻断服务攻击的效果。
最理想的预防方式就是使用静态的 ARP 条目,对于网关:将所有的客户端的 MAC 以及对应 IP 进行静态绑定,防止攻击者假冒客户端。而对于普通客户端:绑定网关 MAC 地址,防止攻击者假冒网关;不过在大型网络不可行,因为 ARP 经常需要更新,另外一种方法,例如:DHCP snooping,网络设备可借由 DHCP 保留网络上各电脑的 MAC 地址,在伪造的 ARP 数据包发出时即可侦测到。此方式已在一些厂牌的网络设备产品所支持。
GARP(Gratuitous ARP),是一种特殊的 ARP 请求,ARP 数据包的 dstIP 和 srcIP 地址相同,并且 dstMAC 为全 0/f。显然 GARP 是一种自己发送给自己的数据报文,其目的是:旨在更新其它收到这个通告的主机的 ARP 缓存。这种不请自来的 ARP 通常用于在主机启动或更换网卡时通知其它主机,所以称之为 “免费 ARP”。
因为 ARP 本身是无状态的。因此,就算设备没有发出 ARP 请求,如果该设备收到了其他设备发来的 ARP 数据包(包括 ARP 请求和响应),那么该设备还是会更新自身的 ARP cache。这就是 GARP 的实现背景。
作用:
Linux 系统中可以使用 arping 命令行来发送 Gratuitous ARP,让网络中所有主机更新当前机器的 ARP 记录:
arping -A -I eth0 172.16.42.161
这个命令就是把机器上 eth0 绑定的 MAC 地址和 172.16.42.161 作为 ARP 记录发送出去。
GARP 的前两种应用场景详细大家都非常熟悉且易于理解,下面主要关注通过 GARP 实现的冗余网络。
Redundancy(冗余)的目的是为了设计 HA(High-Availability,高可靠性)系统的 Failover(故障转移)。对于冗余,通常有两种情况:
即:有两个不同 MAC 的机器拥有同一个 IP(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.
该场景中,有两张不同的网卡都具有同一个 MAC 地址和 IP 地址,并连接到交换机的两个端口。此时,尽管我们不需要考虑刷新主机的 ARP 缓存,但需要使用一个 GARP 来通知交换机进行重新选路(刷新交换机的 MAC table),继而才能通过新的 MAC 找到正确的通路。
https://www.jianshu.com/p/65710069d934
https://www.cnblogs.com/littlehann/p/3735816.html
https://juejin.im/post/59f1e319f265da430405db4a
https://www.ibm.com/developerworks/cn/linux/l-arp/index.html