概念:
1. ARP协议(地址解析协议):由IP地址转换为MAC地址的协议。IP地址:网络号+主机号。MAC地址:数据链路层的物理地址(硬件地址)。IP协议使用了ARP协议,因此被划归为网络层,但其用途是从网络层使用的IP地址解析出数据链路层的硬件地址,因此有些也将其划归为数据链路层。与ARP协议成对的协议为RARP,它是从MAC地址到IP地址的转换。
2. 网络层使用的是IP地址,但在实际网络的链路上传送数据帧时,最终还是使用网络的硬件地址。但IP地址和网络的硬件地址本身存在格式上的不同,也没有什么直接的映射关系。同时,网络上也有不同的主机加入进来,或撤走一些主机,更换网络适配器也会使硬件地址改变,因此引入了ARP协议,ARP协议主要解决此类问题的方法是在主机ARP高速缓存中存放一个从IP地址到硬件地址的映射表,并且这个映射表经常动态更新。
3. 每个主机都有一个ARP高速缓存,里面有局域网的主机和路由器的IP到硬件地址的映射表,这些都是该主机目前知道的一些地址。举个栗子哦,当主机A要给主机B发送报文时,主机A会在高速缓存中找是否有B的IP地址,如果有,则在ARP高速缓存中找到对应的硬件地址,再把这个地址写入MAC帧,然后通过局域网把该MAC帧发送到此硬件地址。也有可能查不到其IP地址,可能是由于主机B才入网,也可能是主机A刚加电,高速缓存还是空的。这种情况的话,主机A会自动运行ARP,来找出硬件地址。
(1) ARP在局域网中广播请求分组,找主机B的IP地址
(2) 在局域网上运行的主机都可以接收到ARP广播的消息,但只有主机B会有响应,其他主机则忽略该广播。
(3)主机B响应分组后,会在ARP响应分组中写入自己的硬件地址,此时的响应分组是单播的。刚刚广播是因为不知道主机是哪一个,现在知道了具体是哪一个主机后,主机B直接给主机A响应,因此是普通的单播。
(4) 主机A收到主机B的响应分组后,在ARP高速缓存中写入主机B的从IP地址到硬件地址的映射。为什么要将其写入ARP高速缓存呢,你发送数据报可能不止一次,当你发送完之后,主机B也给主机A响应后,可能也会发送数据报,这时如果没有ARP高速缓存,可能主机B也得以广播的方式先找到主机A的IP,再找硬件地址,这样就大大降低了网络的通信量,因此使用ARP来增加网络的通信量,也提供了方便。
4. ARP把保存在高速缓存中的每一个映射地址项目都设置生存时间,超过生存时间的项目就从高速缓存中删除掉。比如说主机A给主机B发数据,某一天,主机B的网络适配器坏了,B更换了一块,这时其硬件地址也被修改,这样的话高速缓存中存的还是原来的那个地址,这下你肯定找不到确定的硬件地址,有了生存时间后,你可以在限定的时间内找,如果找不到的话,就将原先的硬件地址删除,再重新广播发送ARP请求分组,重新找到B。继续上述的步骤,在高速缓存中写入正确的硬件地址即可。
5. ARP协议是解决局域网的情况,如果是不同的网络中的主机间的传送数据报呢?这里我们涉及到路由器的概念。主机A无法直接解析主机B的硬件地址,我们这时通过连接到主机A的路由器来进行转发,找到另一网络(通过将路由器A的IP转化为硬件地址,以便将IP数据报写入路由器A,A从转发表中找到下一跳路由B,同时解析出路由器B的硬件地址,于是再将数据报转发到路由B上),再通过路由器广播的方式(解析目的主机的硬件地址),找到正确的主机,传送数据报。
关于ARP,主要有四种典型情况:
1. 发送方是主机,把IP数据报发送到同一网络的另一个主机,此时主机A发送ARP请求分组,广播,找到目的主机的硬件地址
2. 发送方是主机,把IP数据报发送到不同网络的另一个主机,这时主机A发送ARP请求分组,找到主机A的路由器的硬件地址,剩下的工作由路由器完成。
3. 发送方是路由器,把IP数据报转发到同一网络的另一个主机,此时路由器发送ARP请求分组,广播,找到目的主机的硬件地址
4. 发送方是路由器,把IP数据报转发到不同网络的另一个主机,这时路由器R1发送ARP请求分组,找到下一跳路由器R2的硬件地址,剩下的工作由路由器R2完成。
下面我们来写个脚本来实现抓取主机MAC地址:
#!/bin/bash
net='192.168.127.' //是我自己的主机IP
i=1
count=0
while [ $i -le 254 ]
doif [ $count -eq 20 ];thencount=0sleep 1fiping -c1 $net$i & //检查网络是否连通let i++let count++donewait
我们可以使用arp -a来查看缓存中的MAC地址。如下:
其中显示incomplete的就是没有存入缓存中的。我们可以过滤一下。
#!/bin/bash
net='192.168.127.'
i=1
count=0
while [ $i -le 254 ]
doif [ $count -eq 20 ];thencount=0sleep 1fiping -c1 $net$i &let i++let count++donewait
arp -a | grep -v 'incomplete'