ARP是干什么的:
Address Resolution Protocol,地址解析协议,就是当某个主机要编包,但是只知道目的主机的IP,不知道目的主机的MAC,那么这时候就用ARP协议来由目的主机的IP查找目的主机的MAC
ARP在TCP/IP协议栈中的位置:
为了说明ARP所处的位置以及与其他协议的关系,还是祭出王道咸鱼的图:
其实这图画的有一点欠妥,那就是:
ARP与IP是同级互不依赖的协议,
咸鱼这样用虚线箭头从IP指向ARP,让人有点不明就里
ICMP和IGMP报文,都是封装进IP数据报的数据部分,而ARP是有自己的报文,不用封装进IP数据报。
ARP报文格式:
ARP报文格式,在一般大学本科的教学中不要求掌握,但本文为了清晰全面的讲解ARP还是放在这里:
从吉大演练平台的协议编辑器的截图里也可以看出来,ARP分组是被直接封装进以太网帧的
当ARP分组被封装进以太网帧时,以太网帧的“收发协数验”的协议字段的值就是0x0806
ARP缓存表
首先我们任何一个主机发送一个帧的时候,要填写目的IP也要填写目的MAC,那么怎么保存这些信息呢,首先我们每个主机和每个路由器都各自有一个ARP缓存表,注意是一个主机一个ARP缓存表,一个路由器一个ARP缓存表,不是每个路由器的每个端口都有,ARP缓存表长这样:
windows操作系统可以用arp -a查看本主机的arp缓存表
ARP Request
首先一个主机发数据帧之前会检查自己的ARP表,如果有目的IP和目的MAC的对应那就直接填入,没有那么会发一个广播帧ARP Request,
ARP Request是个广播帧,而ARP Response是个单播帧,可以通俗理解为: 在一堆人里面,有个人要找北子,然后就大喊了一声:“计院25班北子你在哪?!” 他这声大喊是让每个人都听到的,因为只有让每个人都听到,才能确保被他想找的那个人听到。然后北子就听到了,然后这时北子没必要也大喊一声“我北子在这!”了,因为北子完全可以走到喊自己的那个人面前,然后单独对他说:“我就是你想找的北子”。
Request帧:
对于同一网段而言,即同一网段里的两台主机想要通信:
MAC层:
源MAC:自己的MAC
目的MAC:全1(广播MAC地址)
ARP层:
源IP:自己的IP
源MAC:自己的MAC
目的IP:就是你想通信的那个目的主机的IP
目的MAC:全0
这里就比较值得注意了,ARP报文里的目的MAC是全0表示不知道,而MAC层的目的MAC是全1表示广播
这个ARP分组放进一个广播帧里面,然后广播,这就是Request这个动作,相当于站人堆里大喊一声。
那么对于不同网段而言,比如说下图中A想向E发送数据帧,
那么此时Request帧的别的信息不用变,就是目的IP该填谁的这是个问题,填谁的呢?填E的吗?错,填的是172.16.1.21(默认网关)
也就是说当主机A想和另外一个网段上的某台主机通信时,会调用ARP协议去查默认网关的MAC,注意不是去查目的主机的MAC。
ARP Response
那么各主机如何来处理这个广播的ARP Request呢?
各主机会拿Request帧中的ARP分组中的目的IP,和自己的IP比对,如果:
- 不匹配,那就什么都不做
- 匹配,那就:
- 把源主机的IP和MAC存入自己的ARP缓存表
- 发送一个ARP Response单播帧给源主机
然后当ARP Response传播到源主机后,源主机会在自己的ARP缓存表中添加目的主机的IP和MAC,这样就查到目的主机的MAC了,然后就可以编包发送给目的主机进行通信了。
关于这里我一开始学的时候有个疑问:
为什么主机接收到ARP Request后如果目的IP和自己IP不匹配就什么都不做?
我觉得应该无论匹配不匹配,都更新自己的ARP缓存表,这样不就能尽可能地扩大每个主机的“知识”了嘛?
这是设计思想的事了,可能表项冗余,ARP欺骗这些问题也比较头疼,总之最后采用的是不匹配就什么都不做的这种设计。
所以综合来讲,当一个主机A想发送数据帧时,会先有一个检查步骤,检查目的主机和自己是不是一个网段,如果是一个网段,那么调用ARP去查它的MAC然后发送数据帧,如果不是一个网段,那么调用ARP去查默认网关的MAC,然后发送数据帧中,目的IP填的是 目的主机的IP但目的MAC填的是默认网关的MAC,然后这个帧发到默认网关之后,路由器还会再调用一次ARP协议,来查目的主机的MAC。
这样来看,ARP协议其实是不同跨网段通信的,也就是说一个ARP分组不可能被路由器转发,只能在一个网段内传播。
ARP表项的动态与静态
对于这样一个过程,我们管这种通过ARP Request/Response更新ARP缓存表,所得到的那些表项,我们说它们是“动态的”,那么对应的“静态”表项就是手动设置的,通过arp -s命令。这里说的动态静态其实和路由器的动态路由和静态路由意思是一样的。
动态ARP缓存表表项,因为本身不安全容易收到ARP欺骗,所以有老化机制,即如果这个表项过了一个设置好的时间(比如两分钟)后一直没有被用到,那么就删除掉它。
ARP欺骗
学到ARP就不得不学一种黑客技术,ARP欺骗
ARP欺骗能实现的效果,就是能实现:你兄弟写给他女朋友的情书,他以为寄给了他女朋友,实际上全寄到了你这里。
那么ARP欺骗是怎么实现的,核心原理就是建立错误的IP与MAC对应关系,比如给A的ARP缓存表添加一个错误表项,让C的IP对应上了D的MAC,那么A发给C的数据帧就会实际发给D
那怎么在某主机的ARP缓存表中增加错误表项呢?
关键依赖的一个机制就是上面提到的,一个主机一旦接收到一个ARP请求或回复后,只要目的IP是自己,就会更新自己的ARP缓存表。就利用这个机制,我D发送一个ARP Request,目的IP就填A的,我发这个Request可不是为了查A的MAC和A通信,而是单纯就为了让A把我给他的这个IP和MAC对应关系存进去,我给A的源IP是C的IP,而源MAC是我D的MAC。
是的没错,一个主机在发送ARP Request的时候,源IP可以不填自己的IP,如果真的是目的单纯,为了通信,那肯定要填自己的IP,但咱现在目的不是为了通信是为了骗。
那么这样,在A的ARP缓存表里就建立了错误的对应关系,A以后想给C发送数据帧,都会实际发到D那里。
这种骗术显然成立的前提是你知道A要和谁通信,你知道A的通信目的方的IP,那么你就能成功行骗。
还想举个通俗例子,假如你兄弟叫北子,北子的女朋友叫翠花,北子经常给翠花写信,翠花家住朝阳区2699号,北子就寄信到朝阳区2699号。然后有一天你使坏心眼,大喊一声:“北子,翠花现在住南关区1270号了!”,然后此时咱们假设北子是个sb,他对他听到的一切信息不会质疑真伪,只会无脑相信,于是他以后就真的寄信到南关区1270号了,然后他以为寄到女朋友手中的信件就都被你收到了。反观这个骗局,这里的人物名字其实就类比IP地址,人物住址就类比MAC地址,那么其实只要你知道北子的女朋友的名字,那你就能骗到北子,当然前提是他够蠢,对什么话都无脑相信,而事实上ARP协议也没有对Request的鉴定真伪机制,所以ARP欺骗看似简单,但危害极大。