ARP请求详解.docx
- 文档编号:30006864
- 上传时间:2023-08-04
- 格式:DOCX
- 页数:67
- 大小:44.70KB
ARP请求详解.docx
《ARP请求详解.docx》由会员分享,可在线阅读,更多相关《ARP请求详解.docx(67页珍藏版)》请在冰豆网上搜索。
ARP请求详解
ARP请求详解
IP地址是不能直接用来进行通信的。
这是因为IP地址只是主机在抽象的网络层中的地址。
若要将网络层中传送的数据报交给目的主机,还要传到链路层转变成MAC帧后才能发送到实际的网络上。
因此,不管网络层使用的是什么协议,在实际网络的链路上传送数据帧时,最终还是必须使用硬件地址。
由于IP地址有32bit,而局域网的硬件地址是48bit,因此它们之间不存在简单的映射关系。
此外,在一个网络上可能经常会有新的主机加入进来,或撤走一些主机。
更换网卡也会使主机的硬件地址改变。
可见在主机中应存放一个从IP地址到硬件地址的映射表,并且这个映射表还必须能够经常动态更新。
地址解析协议ARP很好地解决了这些问题。
每一个主机都设有一个ARP高速缓存(ARPcache),里面有所在的局域网上的各主机和路由器的IP地址到硬件地址的映射表,这些都是该主机目前知道的一些地址。
如果不使用ARP高速缓存,那么任何一个主机只要进行一次通信,就必须在网络上用广播方式发送ARP请求分组,这就使网络上的通信量大大增加。
ARP将已经得到的地址映射保存在高速缓存中,这样就使得该主机下次再和具有同样目的地址的主机通信时,可以直接从高速缓存中找到所需的硬件地址而不必再用广播方式发送ARP请求分组。
(详解过程请参考第2页)
ARP将保存在高速缓存中的每一个映射地址项目都设置生存时间(例如,10~20分钟)。
凡超过生存时间的项目就从高速缓存中删除掉。
设置这种地址映射项目的生存时间是很重要的。
设想有一种情况。
主机A和B通信。
A的ARP高速缓存里保存有B的物理地址。
但B的网卡突然坏了,B立即更换了一块,因此B的硬件地址就改变了。
A还要和B继续通信。
A在其ARP高速缓存中查找到B原先的硬件地址,并使用该地址向B发送数据帧。
但B原先的硬件地址已经失效了,因此A无法找到主机B。
但是过了一段时间,A的ARP高速缓存中已经删除了B原先的硬件地址(因为它的存在时间到了),于是A重新广播发送ARP请求分组,又找到了B。
这里需要指出,ARP是解决同一个局域网上的主机或路由器的IP地址和硬件地址的映射问题。
如果所要找的主机和源主机不在同一个局域网上,例如,在TCP/IP详解卷1中,第29页的例子,那么这时就要借助于网络层的协议,配合链路层协议才能将数据报成功的发送到目的主机上。
(详解过程请参考第3页)
这里要指出的是,这种从IP地址到硬件地址的解析是自动进行的,主机的用户对这种地址解析过程是不知道的。
只要主机或路由器要和本网络上的另一个已知IP地址的主机或路由器进行通信,ARP协议就会自动地将该IP地址解析为链路层所需要的硬件地址。
那么就可能会产生这样的问题:
既然在网络链路上传送的帧最终是按照硬件地址找到目的主机的,那么为什么我们不直接使用硬件地址进行通信,而是要使用抽象的IP地址并调用ARP来寻找出相应的硬件地址呢?
这个问题必须弄清楚。
由于全世界存在着各式各样的网络,它们使用不同的硬件地址。
要使这些异构网络能够互相通信就必须进行非常复杂的硬件地址转换工作,因此几乎是不可能的事。
但统一的IP地址把这个复杂问题解决了。
连接到因特网的主机都拥有统一的IP地址,它们之间的通信就像连接在同一个网络上那样简单方便,因为调用ARP来寻找某个路由器或主机的硬件地址都是由计算机软件自动进行的,对用户来说是看不见这种调用过程的。
设想有两个主机可以直接使用硬件地址进行通信(具体实现方法暂不必管)。
再假定其两个主机的网卡都同时坏了,然后又都更换了一块,因此它们的硬件地址也都改变了。
这时,这两个主机怎样能够知道对方的硬件地址呢?
显然很难。
但IP地址是独立于主机或路由器的硬件地址的。
硬件地址的改变不会影响使用IP协议的主机的通信。
因此,在虚拟的IP网络上用IP地址进行通信给广大的计算机用户带来很大的方便。
*以太网解释协议(ARP).文件名:
/sys/netinet/if_ether.c
*注释ie_minix
*一,函数入口:
*ARP有两个入口:
1
*由ether_input发出一软中断(见我的ethernet网络代码详解一文),arpintr中断例程被调用,检查完数据后
*该中断例程调用in_arpinput函数.
*入口2:
*由ether_output函数在查询输出的硬件地址时,调用arpresolve函数进行地址解析.
*所以,ARP基本上是和ether网输出密切相关的.
*二,相关的结构:
*关于他使用的结构方面,llinfo_arp是和路由相关的一个结构,ether_arp结构是个遵循RFC826的一个ARP包的结构.
*三,学习顺序:
*在看本文的时候,一般从函数arpintr(中断例程)开始看,紧接着看in_arpinput函数.再看看支撑函数arplookup后停止,这是第一入口.
*arpresolve是第二入口的开始,他是解析地址的函数,如果解析不了,调用arprequest函数发送一ARP请求包,第二入口结束.
*关于arp_rtrequest函数和路由函数相关,作用是添加或删除一ARP节点.如果看不懂,可到以后的路由函数讲解时再了解.
*四,ARP欺骗的核心内实现:
*在整个程式中,有hack------是我加入的代码,一直到end------结束,大概有十来段这样的代码,是用来实现ARP欺骗,下面我简要的讲一
*讲他的实现原理:
*在我们开机后,系统初始化阶段,确切的说是在arp_ifinit初始函数被调用时,将发送一免费ARP,所谓免费,是指要寻找的IP地址是我自
*己的IP地址,那么网络上如果有和我相同的IP地址的机器(IP地址冲突),他就会根据我的这个ARP包中的发送源硬件地址应答一个ARP
*包给我,我的接收函数就能判断是否有人和我的IP设置的是相同的.初始化函数不仅在开机后初始化时实行,而且在你执行ifconfig改动
*IP地址时也会调用,如果要进行ARP欺骗,那么你就不能发送一免费ARP包,要不然对方的机器会记录下你的欺骗.这一点是其他的关于
*ARP欺骗方式在用户区域所不能达到的.在你的机器冒充另外一台机器期间,会遇见两种情况,第一种是:
被冒充的机器发送一个ARP
*请求,因为是广播发送,所以你也接到了该请求,被请求的机器会应答一ARP,这时我们也要应答一ARP,不过要比真正的那台机器晚一点
*(在程式中我用的是DELAY延迟500毫秒,该数据能进行调整,以适合你本地网络中较慢的机器),他就在被冒充的机器上进行覆盖前
*一个回应,使得被冒充的机器认为你就是他要找的机器,当然被冒充的机器紧接着将发送IP包给你的机器,由于你的IP层会判断包的目的
*IP地址(肯定目的IP不对,因为被欺骗了),所以IP层会将他抛弃.第二种情况是:
有其他的机器想和被欺骗的机器相联系,其他机器也将广播
*一ARP请求,目的IP是被欺骗机器的IP,首先被欺骗主机会回应一ARP,我们也和被欺骗主机相同回应一ARP,覆盖被欺骗主机的回应.
*五,漏洞的分析:
*目前,我所见到的BSD类操作系统都可能被欺骗,其原因是没有判断ARP请求方的目的硬件地址是否是来之于广播地址,而我们进行的
*所有欺骗都是进行单播方式的请求.
*六,解决方案:
*在程式中的patch到patchend部分是我的解决方案.主要是对ARP请求部分的目的硬件地址是否是广播地址进行判断,如果要使用,请
*把注释去掉就行了.
*七,编译:
*对于FreeBSD4.4版本,可直接拷贝覆盖/sys/net/if_ether.c文件,对于当前版本,只要把hack-----到end-----之间的段粘贴到相应的地方.
*本程式在4.4下已编译通过,由于实验条件不行,实验没有在两台以上机器进行过,在这里希望网友能帮忙测试,测试的方法是:
*1.覆盖原文件后,进行核心编译.
*2.重启动后,执行:
*arp-d-a
*sysctlnet.link.ether.inet.ctrlhack=1
*ifconfigvr0192.168.0.4255.255.255.0
*^^^
*你的卡你要冒充的IP掩码
*最佳是把上面几个命令放到批执行文件中执行.
*3.用被冒充的机器去PING其他机器,这时候有可能ICMP包能发出几个,但应该即时没有反应.
*4.如果有什么问题,大家能把他记录,并发布到BBS上,更希望能多测试几种系统.
*
*/
#include"opt_inet.h"/*2个头文件由编译器在编译操作系统核心时产生的一些常量*/
#include"opt_bdg.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdefBRIDGE/*如果定义了桥转发*/
#include
#include
#endif
#include
#include
#include
#include
/*hack:
------------------------*/
#include
staticintarphacklock=0;/*全局变量用的锁*/
structin_addrgatewayip;/*网关IP*/
structin_addroldip;/*我机器老的IP地址*/
staticinttrueip=0;/*是否使用冒充IP发送ARP请求*/
staticu_charithardaddr[6];/*要冒充机器的硬件地址,在转移到临时缓冲之前由锁来控制其写*/
staticintfromsubr=100;/*实验用,看看本机发出ARP请求是那个函数*/
/*end-------------------------*/
#defineSIN(s)((structsockaddr_in*)s)/*强制转化成sockaddr_in结构,即Internet地址结构,其中s一般是sockaddr结构*/
#defineSDL(s)((structsockaddr_dl*)s)/*强制转化成sockaddr_dl结构,即ethernet地址结构,其中s一般是sockaddr结构*/
SYSCTL_DECL(_net_link_ether);/*用于sysctl用法如下:
sysctlnet.link.ether....=XXX,
SYSCTL_DECL是申明下面的SYSCTL_NODE将继承的节点*/
SYSCTL_NODE(_net_link_ether,PF_INET,inet,CTLFLAG_RW,0,"");/**/
/*
hack:
staticinthackarp=0;
SYSCTL_INT(_net_link_ether_inet,OID_AUTO,ctrlhack,CTLFLAG_RW,&hackarp,0,"");
/*这方便你在用户区可控制核心变量,用法如下:
sysctlnet.link.ether.inet.ctlhackarp=1那么变量hackarp就为1了.
下面的程式会根据hack的真假判断来进行欺骗
*/
/*一些记时器的值*/
staticintarpt_prune=(5*60*1);/*每5分钟过一遍列表,这个变量是由计时器使用,看看有没有超时ARP结点,有就删除他*/
staticintarpt_keep=(20*60);/*一旦解析了,保持20分钟*/
staticintarpt_down=20;/*一旦公开了down,20秒不发送*/
/*对以上3个变量的控制*/
/*使用方法:
sysctlnet.link.ether.inet.prune_intvl=180也就是把ARP定时期改为了每3分钟查一次ARP结点*/
SYSCTL_INT(_net_link_ether_inet,OID_AUTO,prune_intvl,CTLFLAG_RW,
&arpt_prune,0,"");
SYSCTL_INT(_net_link_ether_inet,OID_AUTO,max_age,CTLFLAG_RW,
&arpt_keep,0,"");
SYSCTL_INT(_net_link_ether_inet,OID_AUTO,host_down_time,CTLFLAG_RW,
&arpt_down,0,"");
#definert_expirert_rmx.rmx_expire/*这里是放当前时间的,如果rtinit路由初始程式加入一IP路由,那么把当前时间+20*60秒放进去,*/
/*arptimer函数会和当前时间(当前时间由时钟每秒加1)比较,如果相等或比当前时间小,即到了或*/
/*该ARP结点时间过了20分钟.即超时*/
/*这里其实是真正的ARP列表*/
structllinfo_arp{
LIST_ENTRY(llinfo_arp)la_le;/*单向列表宏,说明该结构是一单向的列表,尾巴为0*/
structrtentry*la_rt;/*和该结点相关的路由*/
structmbuf*la_hold;/*由于该地址正等待解释,所以要发送的数据(mbuf链头)指针暂时存放*/
longla_asked;/*为该地址发送了一共几个ARP请求,如果到了5个,那么暂时停止20秒*/
#definela_timerla_rt->rt_rmx.rmx_expire
};
staticLIST_HEAD(,llinfo_arp)llinfo_arp;/*全局ARP链表及表头,从这开始就能遍历整个ARP结点*/
structifqueuearpintrq={0,0,0,50};/*ARP请求队列,在我的"ethernet网络代码详解"中有说明,因为我们要hack,所以要改大一些,100*/
staticintarp_inuse,arp_allocated;/*这都是统计用的*/
staticintarp_maxtries=5;/*在解释地址时重复发送ARP请求的包的次数*/
staticintuseloopback=1;/*在本地使用环回接口*/
staticintarp_proxyall=0;/*ARP代理是否使用*/
/*对以上3个变量的控制*/
SYSCTL_INT(_net_link_ether_inet,OID_AUTO,maxtries,CTLFLAG_RW,
&arp_maxtries,0,"");
SYSCTL_INT(_net_link_ether_inet,OID_AUTO,useloopback,CTLFLAG_RW,
&useloopback,0,"");
SYSCTL_INT(_net_link_ether_inet,OID_AUTO,proxyall,CTLFLAG_RW,
&arp_proxyall,0,"");
staticvoidarp_rtrequest__P((int,structrtentry*,structsockaddr*));/*添加或删除一ARP节点,和路由有关*/
staticvoidarprequest__P((structarpcom*,/*发送一ARP请求,目的硬件地址是广播地址*/
structin_addr*,structin_addr*,u_char*));
staticvoidarpintr__P((void));/*ARP软中断,由ether_input函数(if_ethersubr.c)调用*/
staticvoidarptfree__P((structllinfo_arp*));/*释放一ARP节点*/
staticvoidarptimer__P((void*));/*定时查询ARP节点是否超时*/
staticstructllinfo_arp
*arplookup__P((u_long,int,int));/*在路由表中查询IP的路由,并返回该IP路由的相关的ARP节点信息*/
#ifdefINET
staticvoidin_arpinput__P((structmbuf*));/*由ARP软中断调用,对进入的ARP包进行分析*/
#endif
/*
*定时程式.该函数用来查看是否有ARP超时(20分钟).有就清除他
*/
staticvoid
arptimer(ignored_arg)
void*ignored_arg;
{
ints=splnet();/*链路层中所有对链表要操作的都要屏蔽网络中断*/
registerstructllinfo_arp*la=llinfo_arp.lh_first;/*第一个ARP结点表,是个单向链表,通过la->la_le.le_next链接到下一个*/
structllinfo_arp*ola;/*临时存放ARP界点用的*/
timeout(arptimer,(caddr_t)0,arpt_prune*hz);/*每格5分钟查看一次(调用自己)*/
while((ola=la)!
=0){/*没有到链表尾巴就继续循环*/
registerstructrtentry*rt=la->la_rt;/*该ARP结点相关的路有表*/
la=la->la_le.le_next;/*while的循环可遍历整个ARP结点表*/
if(rt->rt_expire&&rt->rt_expire<=time_second)/*如果是非永久性ARP并且时间超时,在启用了一个ARP结点时,*/
/*rt->rt_expire会设置成当前的time_second(系统内的秒)+20分钟*/
/*然后time_second就滴答滴答的在走,当系统的time_second走了20*/
/*分钟时候,就使rt->rt_expire和time_second相等了,等式成立.就...*/
arptfree(ola);/*定时器期满,清晰该ARP记录,函数在后面*/
}
splx(s);/*开网络中断*/
}
/*
*当你在设置你的某块网卡的IP时(如:
ifconfig...),
*/
staticvoid
arp_rtrequest(req,rt,sa)
intreq;/*是删除,添加还是克隆一个路由(克隆路由是因为到外网的IP都必须经过网关,也就是说,你的数据包发给网关就没事了),*/
/*所以外网的IP的路由都是克隆网关的就OK了.*/
registerstructrtentry*rt;
structsockaddr*sa;
{
registerstructsockaddr*gate=rt->rt_gateway;
registerstructllinfo_arp*la=(structllinfo_arp*)rt->rt_llinfo;
staticstructsockaddr_dlnull_sdl={sizeof(null_sdl),AF_LINK};
staticintarpinit_done;
if(!
arpinit_done){/*判断是否建立了ARP节点队列*/
arpinit_done=1;
LIST_INIT(&llinfo_arp);/*建立ARP节点队列*/
timeout(arptimer,(caddr_t)0,hz);/*启动计时器*/
register_netisr(NETISR_ARP,arpintr);
/*我们来看看register_netisr函数,即设置中断向量,NETISR_ARP是中断号,arpintr中
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ARP 请求 详解