我觉得我要以一个真实的故事来开始这一部分。在我上大二的时候,突然从某一天开始,我们那层连着的6个寝室全都不能上网了,但是有时候又能短暂的上一会儿网,没有规律。不过有一个同学例外,虽然他也处在这6个寝室之中,但无论何时他都能上网。我们很苦闷,于是他那段时间挨个寝室炫耀自己可以上网。就这样过了大约一个星期,后来他们寝室另外三个人突然发现一个规律,只要这个同学没有插网线我们就能上网,只要他一插网线我们就全完了。在用他的电脑做了几次开关机时间之后,我们确认了这个事实。这是个不得了的发现呐,考虑到之前他太高调了,我们6个寝室的人勒令他不允许开电脑,哈哈。但是我们还是有良心的,开始在网上搜索资料,后来架不住人(mei)多(wang)力(shang)量(bu)大(xing),我们在茫茫互联网资料中,搜索到了两个词“arp欺骗”和“arp病毒”。特别是想到那位同学前几天炫耀的表情,在兴(fen)趣(nu)的指引下,我们认真学习了其原理,确认了确实是那位同学的锅。然后下载了个杀毒软件,给那位同学的电脑彻底的杀毒,从此上面的现象再也没有出现过了。而且在后面长达一周的时间内,我们每天必做的一件事就是去问候一下那位同学,哈哈。
ARP是什么?
ARP学名Address Resolution Protocol,从英文上看意思已经跃然纸上了。地址解析协议,解析啥呢,解析IP地址到MAC地址。为什么要这么做呢,因为两个计算机通信本质上是通过MAC地址来识别对方的。我觉得在避免陷入一个协议复杂的细节之前,可以先从一个宏观上面弄明白协议的整个流程是什么样的,是时候再一次献上我的手绘版了。
ARP协议主要在两个场景下有所使用,第一个犹如图中绘制的,某一段想向另一端发送数据包之前,需要通过ARP协议来知晓对方的的地址,具体用文字描述就是如下:
首先,发送端会发出一个ARP请求以太网报文,由于现在发送端还不知道对端的MAC地址,所以ARP的请求报文利用了链路层广播,使得局域网内所有的主机都能接受到这个信息,这就像我们小时候站在别的班教室门口找人一样,大喊,谁谁谁,有人找你,所有人都能听到,但是只有正确的谁谁谁才会发出响应。
按照这个逻辑,回忆一下,其实就是点击一下“MAC地址与数据链路层”里介绍的数据链路层以太网帧格式,其中以太网头部填上目标链路层广播MAC地址,也就是在前一节里已经介绍过的全FF,接下来的填入自己的MAC地址,剩下的帧类型是0x0806,标识ARP协议。
接下来就是数据部分了,在ARP协议的数据部分, 要填入的数据类型的很多, 我想以一个表格的形式来表示会比较清晰(表中黑体部分标识以太网帧头部分,普通字体表示数据部分):
长度 | 数据类型 |
---|---|
48 | 目标以太网地址(FF:FF:FF:FF:FF:FF) |
48 | 发送端以太网地址 |
16 | 帧类型(0x0806) |
16 | 硬件类型(0x0001表示以太网) |
16 | 协议类型(0x8000表示IPv4,0x86DD标识IPv6) |
8 | 硬件地址长度(6) |
8 | 协议地址长度(4对应IPv4,6对应IPv6) |
16 | 操作码(1) |
48 | 发送端MAC地址 |
32 | 发送端IP地址 |
48 | 目标MAC地址(全0标识空) |
32 | 目标IP地址 |
当这个请求数据帧构造后之后,发送端将其发送给整个网络,接下来的局域网中所有接口卡都会读入这个帧,但是在驱动程序读到数据部分的目标IP地址之后发现与自己的IP地址并不匹配,所以就什么也不做,简单的丢弃这个帧就好。直到正确的对端出现,他发现这个帧里面的IP地址就是自己,于是下面他就需要构造一个ARP应答帧。
这个应答帧的组成绝大部分和上表列出的一样,不同的只有这几点:
- 目标以太网地址不再是全FF的广播地址,而是刚才发送端A的MAC地址,因为该应答端B已经从A的ARP请求帧的数据部分可以知道A的MAC地址,没必要再广播了。
- 操作码改为2,2表示ARP应答。
- 其余将所有"发送端”相关的都填自己(B)的信息,目标端都填要回复的那一端的信息(A),这一点是显而易见的。
当应答帧构造完毕发送出去以后,A的网卡驱动程序就能筛选出发给自己应答帧,里面含有他需要的对端的B的MAC地址信息。这时候以备以后使用,A会把这个信息写入自己的一个cache里面存起来,这个缓存会有个老化机制,会定期淘汰很久没用的,这样可以保持这个表不至于太庞大,加快查询速度。这样下次再想和B通信的时候就不用再一次的广播消息重走长征路了,占用带宽而且也没有必要。而这个缓存信息,在每个机器上都能看到,在windows上用arp -a命令,在linux上使用arp命令就可以看到。
这里有个有趣的现象,我的局域网的广播地址对应的物理地址是全ff,这一点我在上一节也说过了,链路层广播地址和IP层次的广播地址没有完全直接的关系,可能好几类的IP层次的广播地址映射的都是全ff的链路层广播地址。
按照惯例,我会截图截个wireshark的数据包来看一下实际中的包表示标准没有欺骗我们,那么当然这一次也不例外:看看wireshark这个相当用户友好化的界面说明,我的电脑要找到局域网的路由器的地址,先霸气的在网络里大叫,“谁TM的拥有192.168.8.1,告诉我192.168.8.124”,而且注意第一个消息的地址是Broadcast,是一个广播消息,接下来,路由器做出了应答,“我是192.168.8.1,我的MAC地址是。。。”,这里的发送地址已经准确的是我的电脑了。
为了更一步的看看包里面到底有啥,就选取ARP请求包展开看一下其中内容,对比一下前面表中的内容,又一次发现,标准说明没有骗我们:
免费ARP和免费一点也没有关系
前面我说了,ARP协议主要用在两个场景,在上一节中已经介绍了第一个,第二个就是这个翻译的令人感到很困惑的免费ARP了。免费ARP,其实学名是gratuitous ARP, gratuitous这个词主要有三个意思,无端的,没有理由的和免费的。我觉得翻译成另外两个都比免费的这个翻译好。
废话不多说了,那么这个gratuitous ARP到底是干啥的呢?不知道大家有没有遇到过这样一个现象,在公司里用电脑用的好好的,突然会右下角会出现一个气泡提示,说你的IP地址冲突了。这个提示就来源于gratuitous ARP,每个机器在DHCP(后面会详细介绍这个重要协议的)拿到这个IP之后,会向局域网中广播一个ARP请求,但是这个请求中的目标IP地址是自己已经分配了的IP地址,按照前面的逻辑,如果局域网上还有一个主机具有同样的IP地址的主机,那么他就会发送一个回复,而这个回复中会包含自己MAC地址。发送端如果接收到这么一个回复,那么意味着在网络中有一个和自己一模一样的IP地址的主机,他自己就知道自己的IP地址重复了,于是就会给出这个么一个提示给用户。
ARP欺骗
有了前面这个免费ARP的例子,那么ARP欺骗就很好理解了。只要做一个如下的想象:
如果有一个程序,他可以篡改ARP应答包里的MAC地址,也就是把MAC地址改成自己规定好的主机,那么按照我们上面说的,,发送包在收到这个ARP应答后会把cache起来以防下次再做不必要的努力。那么你以后本来想发送到B的包就会被发到一个指定的主机上,因为数据层的MAC地址已经被邪恶的入侵者所改掉,不会填入B的MAC地址。
这也就是为什么最开始的故事中我们都上不了网,唯独我那一个同学能上网的原因,因为他机器上的ARP病毒将所有包的地址都改为他自己的主机,我们其余的电脑都根本无法完成通信,或者也可能是说根本收不到消息。