TCP/IP 学习笔记 | ARP:地址解析协议
切记:少就是多,慢就是快。
ARP (Address Resolution Protocol)
地址解析协议是一个通过解析网络层地址来找寻数据链路层地址的网络传输协议,它在IPv4中极其重要。当一台主机把以太网数据帧发送到位于同一局域网上的另一台主机时,是根据 48 bit 的以太网地址来确定目的接口的。设备驱动程序从不检查 IP
数据报中的目的 IP
地址。ARP
为 IP
地址到对应的硬件地址之间提供动态映射。
执行流程
大致简化流程是这样的,网络层收到 IP
数据报,调用 IP
选路函数,判断目标主机 MAC
地址是否在 ARP
缓存中。若存在,装帧,交给以太网驱动;若不存在,广播 ARP
请求,大声呼喊:“谁是这个 IP
啊,大声告诉我你的 MAC
地址好吗?” 这时路人甲收到广播请求,发现是自己的 IP
,便回应:“是我,我的 MAC
地址是 … ” 然后装帧,交给以太网驱动。
MAC 地址
MAC
地址由 IEEE
定义,有三种:MAC-48
、EUI-48
、EUI-64
,我们常用的是 MAC-48
。MAC-48
,地址空间 48bit
,它的设计目标是一百年内够用。常以16进制数表示 MAC
地址,通用表示方法有三种格式:
01-23-45-67-89-ab
01:23:45:67:89:ab
0123.4567.89ab
MAC
地址其前3个字节为 OUI
(Organizationally
Unique
Identifier
) 组织唯一标识符,由 IEEE
的注册管理机构给不同厂家分配的代码,区分不同的厂家,后3字节由厂家自行分配。
例如 f0:18:98:1c:8:75
根据前3个字节 F01898
即可在 OUI
上查出硬件厂商为 Apple Inc.
ARP 高速缓存
当主机 A 要向本局域网上的某个主机 B 发送 IP
数据报时,先在其 ARP
高速缓存中查看是否有主机 B 的 IP
地址。如果有,就在 ARP
高速缓存中查出其对应的硬件地址,再把这个硬件地址写入 MAC
帧,然后通过局域网把该 MAC
帧发往此硬件地址。也有可能查不到主机 B 的 IP
地址的项目。这可能是主机 B 才入网,也可能是主机 A 刚刚加电,其高速缓存还是空的。在这种情况下,主机 A 就自动运行 ARP
,然后按以下步骤找到主机 B 的硬件地址。
查看系统 arp 缓存
$ arp -a
'''
? (192.168.31.1) at 64:9:80:70:c6:3 on en0 ifscope [ethernet]
? (192.168.31.25) at f0:18:98:1c:8:75 on en0 ifscope permanent [ethernet]
? (192.168.31.163) at 24:f0:94:50:83:41 on en0 ifscope [ethernet]
? (192.168.31.255) at ff:ff:ff:ff:ff:ff on en0 ifscope [ethernet]
? (224.0.0.251) at 1:0:5e:0:0:fb on en0 ifscope permanent [ethernet]
? (239.255.255.250) at 1:0:5e:7f:ff:fa on en0 ifscope permanent [ethernet]
清空 arp 缓存
$ sudo arp -ad
'''
Password:
192.168.31.1 (192.168.31.1) deleted
delete: cannot locate 192.168.31.25
192.168.31.163 (192.168.31.163) deleted
192.168.31.255 (192.168.31.255) deleted
224.0.0.251 (224.0.0.251) deleted
239.255.255.250 (239.255.255.250) deleted
抓包
这里我使用了一个 ARP
扫描工具作为测试,他能查询到同一网段的所有主机地址,安装方式如下:
$ brew install arp-scan
'''
==> Installing dependencies for arp-scan: libpcap
==> Installing arp-scan dependency: libpcap
==> Downloading https://mirrors.aliyun.com/homebrew/homebrew-bottles/bottles/libpcap-1.9.1.mojave.bottle.tar.gz
==> Pouring libpcap-1.9.1.mojave.bottle.tar.gz
==> Caveats
我们发现它依赖了 libpcap
(Packet Capture Library)
,事实上这是一个很有名的用 C
写的包捕获函数库,著名的 tcpdump
、wireshark
等工具都是基于这个库写的。下面通过我的 en0
网卡扫描一下试试:
$ sudo arp-scan -I en0 -l
'''
Interface: en0, type: EN10MB, MAC: f0:18:98:1c:08:75, IPv4: 192.168.31.25
Starting arp-scan 1.9.7 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.31.1 64:09:80:70:c6:03 Xiaomi Communications Co Ltd
192.168.31.182 d4:61:da:51:f8:1a Apple, Inc.
535 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9.7: 256 hosts scanned in 1.863 seconds (137.41 hosts/sec). 2 responded
与此同时,打开 Wireshark
抓包:

从抓包结果不难看出,这个工具广播了包含局域网整个 IP
段的 ARP
请求。
数据结构

以太网帧头
''' 下面这 14B 的数据即为以太网帧头数据
-------------------------------------------------------------------------
0000 ff ff ff ff ff ff f0 18 98 1c 08 75 08 06 ...........u..
Destination
6B
目的地址,抓包结果中为ff:ff:ff:ff:ff:ff
,即广播地址。Source
6B
源地址,抓包结果中为f0:18:98:1c:08:75
为本机MAC
地址。Type
2B
帧类型,表明后面的数据类型,对于ARP
请求或应答来说,该字段的值为0x0806
。还有常用的IPv4
值为0x0800
ARP 请求/应答
''' 下面这 28B 的数据即为 ARP 请求数据
-------------------------------------------------------------------------
0000 00 01 08 00 06 04 00 01 f0 18 98 1c 08 75 c0 a8 .............u..
0010 1f 19 00 00 00 00 00 00 c0 a8 1f 02 ............
Hardware Type
2B
硬件类型,表示硬件地址的类型,值为 1 表示以太网地址。Protocol Type
2B
协议类型,表示要映射的协议地址类型。它的值为0x0800表示IPv4
地址类型,它的值与包含IP数据报的以太网数据帧中的类型字段的值相同。Hardware Size
1B
硬件地址长度,值为 6 表示MAC
地址长度为 6B。Protocol Size
1B
协议地址长度,值为 4 表示IPv4
地址长度为 4B。Eth Source Addr
6B
发送端MAC
地址,抓包结果中,发送端为本机,即本机MAC
为f0:18:98:1c:08:75
。Oper
6B
操作类型,1 表示ARP
请求,2 表示ARP
应答。Proto Source Addr
4B
发送端IP
地址,本机IP
为192.168.31.25
。Eth Target Addr
6B
接收端端MAC
地址,因为不知道,所以为00:00:00:00:00:00
。Proto Target Addr
4B
接受端IP
地址,希望查询MAC
地址的IP
为192.168.31.2
。
以上数据大致意思就是,我是 192.168.31.25
,谁的 IP
是 192.168.31.2
。