Table of Contents
概述
Address Resolution Protocol,RFC 826.
ARP协议能够实现任意网络层地址到任意物理地址的转换,但是我们只关注从IP地址到以太网地址(MAC地址)的转换。
报文格式
0 1
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Hardware Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Protocol Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Hard Addr len |Proto Addr len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Operation |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| Sender Hardware Address |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ Sender Protocol Address +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| Target Hardware Address |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ Target Protocol Address +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
报文字段
字段名 | 长度 | 含义 |
硬件类型 | 2字节 | 定义物理地址的类型,值为1时表示MAC地址; |
协议类型 | 2字节 | 定义要映射的网络层地址类型,值为0x800时表示IP地址; |
硬件地址长度 | 1字节 | 表示物理地址的长度,对MAC地址来说长度为6; |
协议地址长度 | 1字节 | 表示网络协议地址的长度,对IP地址来说,其长度为4; |
操作字段 | 2字节 | 对于以太网有4种操作类型,ARP请求(值为1),ARP应答(值为2),RARP请求(值为3),RARP请求(值为4); |
最后这4个字段指定通信时双方的以太网地址和IP地址。发送ARP请求的会空着Target Hardware Address不填(貌似填的是-1?),只填其余3个地址,因为发送方不知道Target Protocol Address对应的机器是哪个,他就这样把这个消息在局域网内广播。Target Protocol Address 对应的机器在收到这条消息后,他就给发送方回一条ARP应答,由于发送方在ARP请求里有填写发送方的网络地址和物理地址,应答的机器当然也知道自己的网络地址和物理地址,所以应答机器发出的ARP应答消息里就会把四个地址都给填上。发送ARP请求的机器在收到ARP应答后,就根据ARP应答消息里的源物理地址和源网络地址建立了映射,也就知道了他当初问的网络地址对应机器的物理地址。
由于以太网帧的Payload至少46字节,所以ARP请求/应答消息会增加一些填充字节,这样一个携带ARP请求/应答的以太网帧就是64字节。
ARP请求不能穿过路由器,只能在同一个网段内广播。在路由器启用代理ARP功能,且主机没有设置默认gateway的情况下,ARP请求可以在路由器连接的不同网段中”穿透”。
arp命令的使用
查看arp缓存
arp
其中标志一列的含义:
C代表Cached entry;
M代表Permanent entry;
P代表Published entry;在设置arp proxy时会需要Published entry,并且会和netmask(即上图中的Mask)结合使用,将整个子网的arp请求转发到对应的物理地址。新内核已经不支持通过设置netmask来 proxy整个子网的arp请求,而是通过路由实现了这个功能。
arp缓存表能够保存的条目是有限的,因此有一个垃圾回收的算法不断地回收缓存表中老旧的和不常使用的条目,而被标记为permanent的条目则永远不会被回收。一般一个arp条目20分钟不用就算超时。
如果一个Cached arp条目超过一段时间没有收到正反馈,那么这个arp条目就会被认为失效。获取正反馈的方式来自于上层协议的signal,比如成功收到TCP ACK,或者是sendmsg设置了MSG_CONFIRM标志。
当一个Cached arp条目失效后,会先从local arp daemon更新整个arp缓存,如果没能成功更新,会再向local arp daemon发请求单独更新这个地址的mac地址,如果再失败才发广播请求这个地址的mac地址。只有有数据需要发送时才需要更新对应的arp条目。
arp -a
代理ARP
上面讲到了代理ARP(proxy ARP):当一个路由器连接了2个子网A和B时,子网A里的host1没有设置网关,且host1想要发包给子网B里的host2,于是host1需要知道子网B里的host2的MAC地址,host1发的广播ARP请求到了路由器,路由器就会回复自己的MAC地址。
但是代理ARP功能只有在没有设置网关的时候才需要,在有网关时,电脑host1只需要按照路由表将数据包扔给网关,由网关再将数据包转发给host2,这种情况下host1就不再需要发ARP请求询问host2的MAC地址了,而是发ARP请求询问网关的地址即可。
这篇知乎文章讲的很清楚。
在Linux上可以通过下面的命令来开启auto-proxy ARP特性。
echo 1 > /proc/sys/net/ipv4/conf/<device-name>/proxy_arp
删除arp缓存
arp -d <ip/hostname>
增加arp缓存
arp -s <ip/hostname> <hw_addr>
硬件地址格式为冒号分隔的16进制mac地址。
设置网卡的mac地址
arp -Ds <ip/hostname> <ifname>
使用这个命令时,硬件地址会自动设置为网卡ifname的mac地址。
arp命令选项
选项 | 含义 |
-i <IF> | 指定网卡 |
-n, –numeric | 显示数字格式的地址 |
arp命令示例
arp -i eth0 -Ds 10.0.0.2 eth1 pub
对来自eth0的arp请求,用eth1的mac地址响应
arp -i eth1 -d 10.0.0.1
删除eth1网卡上的10.0.0.1这个地址对应的arp Proxy或者Permanent条目。
概念辨析
网关
在网络层交换两个网络数据的设备。
近期评论