在局域网当中,当主机或其它网络设备有数据要发送给另一个主机或设备时,它必须要知道对方的IP地址,但仅仅有IP地址是不够的,因为IP数据报文必须封装成帧才能通过物理网络发送,因此发送站还必须有接收站的物理地址,所以需要一个从IP地址到物理地址的映射。ARP就是实现这个功能的协议。
我们通过一个简单的例子来解释一下ARP在局域网中的运作。
1.假设现在有一个主机A和一个主机B,二者处在同一个局域网当中。当主机A需要和主机B进行数据通信的时候,主机A会在自己的ARP缓存中查找是否有与主机B对应的ARP表项。
2.如果A在自己的ARP缓存当中找到了与主机B对应的ARP表,主机A直接利用ARP表中的MAC地址将IP数据包进行帧封装,将数据包发送给主机B。
3.如果A在自己的ARP缓存中没有找到与主机B对应的ARP表,则主机A将以广播的方式发送一个ARP请求,该请求中包含了主机A本身的IP地址(源IP地址)和MAC地址(源MAC地址),同时包含了主机B的IP地址(目标IP地址)。由于请求是以广播的形式发送的,所以处于该局域网的所有主机都能够检测到该ARP请求,但是只有和ARP请求中目标IP地址相同的主机才能够收到ARP请求,其余的主机都会讲该ARP请求抛弃。主机B收到由A发送的ARP请求后,会向主机A以单播的形式发送一个ARP回复,该回复中包含了主机B的IP地址(源IP地址),主机B的MAC地址(源MAC地址),主机A的IP地址(目标IP地址),主机A的MAC地址(目标MAC地址)。同时会将主机A的IP地址和MAC地址写入自己的ARP缓存当中。4.主机A收到来自主机B的ARP的回复后,将ARP回复中的主机B的IP地址和MAC地址添加到自己的ARP缓存当中。这样主机A便能和主机B进行通信了。
在对ARP的工作过程进行剖析后,我们就能够对ARP欺骗进行讲解了。
ARP欺骗分为两种,一种是针对路由器进行欺骗,使路由器的ARP缓存中建立错误的IP与MAC地址映射表,结果就是从路由器发送的数据都发给了一个错误的MAC地址,造成主机无法正常接收信息。另一种是对主机中的ARP缓存进行欺骗,伪造主机路由器IP和MAC地址映射表,使主机发送的数据都发送到伪造后的MAC地址对应的主机上,这种情况不仅会使主机不能正常上网,而且还能用来窃取信息。
我们用程序实现第一种ARP欺骗,并对第一种欺骗方式进行举例。
假设现在主机A和主机B通过路由器C连接在同一个局域网内,主机A是欺骗方,主机B是被欺骗方。主机A在自己的ARP缓存中查到路由器C的IP地址IP_C,MAC地址MAC_C,查到主机B的IP地址IP_B。接下来,主机A自己生成一个ARP回复,该回复的源IP并不是主机A的IP地址,而是冒充主机B的IP地址IP_B,同时编造一个不存在的MAC地址作为回复的源MAC地址,目标IP是IP_C,目标MAC地址是MAC_C。这个ARP回复以单播的形式发送给路由器C之后,路由器并不会验证回复的真实性,而是会把IP_B和一个不存在的MAC地址写入自己的ARP缓存,此时,所有通过路由器发送给主机B的数据,都会因为找不到目标而发送失败。
总结一下:主机A冒充主机B不断向路由器发送一个包含错误的IP和MAC映射表的ARP回复,使经由路由器发给B的数据无法到达目的地,从而致使主机B无法正常上网。
接下来,我们用Java程序来实现这个欺骗过程。注意:JAVA自身是没有办法对数据链路层进行相关操作的,而ARP包的发送处于数据链路层。我们必须借助WinPcap来实现对数据链路层的相关操作,同时需要jpcap来作为沟通JAVA和WinPcap的媒介。所以应该提前安装WinPcap和jpcap。
需要补充解释一点:我们会在程序当中伪造一个ARP回复,这里必须了解ARP报文的结构。报文结构如下:
上图详细的说明了报文的构成,我们在生成ARP回复时,是通过jpcap提供的类ARPPacket来生成的,必须要把ARP中的每一个数据填充清楚,否则就会发送不成功。
代码如下: