zoukankan      html  css  js  c++  java
  • TCP/IP的排头兵――地址解析协议(ARP) (转载)

    转自:http://blog.csdn.net/wangxg_7520/article/details/2488442

     

    一、引言

     

    古人行军打仗,都要有一个可以引领队伍前进方向的排头兵,在TCP/IP网络大军中,也存在这种排头兵,为TCP/IP传输指明方向,它就是地址解析协议――ARP

     

    二、ARP协议及应用

     

    地址解析协议(ARP),是TCP/IP协议簇中较底层的一个,它是TCP/IP应用的基础,但又不完全隶属于TCP/IP,所以在名著《TCP/IP详解》中,它被单独的划分出来,与IP一起并列于以太网驱动程序以上。之所以要把它分离出来,是因为, 其一,它不像IP数据报那样,使用IP地址和端口号收发数据;其二, 它与IP一样,使用了单独的以太网帧类型字段(0x0806)。下面我们就来看看它是怎么工作的。

     

    我们知道,连接在同一网络上的两台主机,要通过TCP/IP进行通信,必须要知道彼此的IP地址(我们这里不打算讨论端口和IP广播)。但是仅仅知道IP 地址还是不够的,因为所有的IP数据报最终都要封装为以太网帧,才能发送出去。而以太网卡用的是另一种地址――MAC地址来标识每一台主机(这里假设每台主机只有一张网卡)。所以在IP数据报传输之前,必须要首先知道目的IP所对应的MAC地址。

     

    那么怎么才能得到IP地址所对应的MAC地址呢?地址解析协议,它就是用来在传输IP数据报之前,建立起从IP地址到MAC地址之间的动态映射,为TCP/IP数据传输指引方向,就如行军中的排头兵。

     

    下面我们就通过一个简单的例子来看ARP是怎么工作的。

     

    假设主机AB连接在同一以太网上,他们的IP地址分别是192.168.1.2192.168.1.3MAC地址分别是02:10:18:01:00:0202:10:18:01:00:03

     

    现在我们先使用工具 arp -d 清除系统内所有ARP缓存,然后在主机A输入命令:

    ping 192.168.1.3

     

    接下来将会发生以下事情:

    1ping程序产生ICMP包,将要通过TCP/IP传输给主机B 192.168.1.3

    2TCP/IP查找ARP缓存,看有没有主机B 192.168.1.3所对应的MAC地址;

    3、如果没有(此时肯定没有),就会将ping发送过来的ICMP包放到一个待发送队列里等待,然后就向整个网段广播ARP请求,询问谁拥有IP地址192.168.1.3

    4、接到改以太网上的所有主机都将收到此ARP请求,但只有拥有IP地址192.168.1.3的主机B会给出应答,告诉主机A自己的MAC地址,并同时把主机AIP地址和MAC地址的映射保存到自己的ARP缓存中,因为主机B可能很快就要同主机A进行TCP/IP通信了,这样可以避免网络内有过多的ARP 请求;

    5、主机A收到来自主机BARP应答后,更新ARP缓存,然后从待发送队列中取出等待的ICMP包,使用主机BMAC地址封装成以太网帧后发送给驱动程序;

    6、方向已经确定,接下来主机AB就可以使用TCP/IP正常的通信了。

     

    三、ARP缓存

     

    从以上分析可以看到,ARP缓存在TCP/IP中扮演着重要的角色,所以对ARP缓存的处理将会对TCP/IP的性能产生重要的影响。一方面ARP缓存加快了TCP/IP的传输,但另一方面,如果ARP缓存过时了(缓存中的MAC地址所对应的主机已经断开,IP地址现在可能已经为另一个主机所用),就会使 TCP/IP数据包永远得不到应答,直到ARP缓存超时,就像先锋部队修了一座桥,但这桥不够坚固,部队没过完桥就塌了,所以后面的同志们都得落水,直到有人通知后面的长官停止前进;或者有人再重新把桥修好,但桥的方向就不能保证了。所以对ARP缓存的超时限制是必不可少的。这个超时限制应该是多少呢?一般是20分钟,但如果ARP缓存都在20 分钟后超时的话,势必会引起整个网络的阻塞,所以需要对ARP缓冲做一下优化(refinement)。

     

    我们知道,ARP请求都是广播出去的,所以同一网络上的所有主机都将收到任何其他主机发出的ARP请求。利用这一特性,我们就可以对ARP缓存做一些优化。如前面例子所说,主机A广播ARP请求给整个网络,而只有主机B会给出应答,其他主机都保持沉默。但保持沉默并不意味着其他主机只能不闻不问,他们会接收 ARP请求,然后拿出发送请求者的IP地址和MAC地址,并与自己的ARP缓存相比较,如果发现自己缓存中存在该主机的匹配,就会更新ARP缓存,并重置 ARP缓存超时时间。这样既保证不会ARP广播而引起网络阻塞,也能使ARP缓存得到及时的更新。但是依然会有搭错桥的问题,如主机B掉线或当机了,这时主机C刚好上线,并抢了主机BIP地址,这样主机C发出的ARP请求将会使网络上所有主机的ARP缓存更新为主机CMAC地址,结果要发送给B的数据就会发往C了。就像部队本来要攻打南京,过桥之后发现竟然是芜湖…… 这就是传说中的ARP欺骗(ARP Snoofing),虽然你不是故意的:)

     

     

    四、ARP数据包格式

     

    ARP数据包没有固定长度,它的长度是由两个字段控制的,一个是硬件地址长度字段(Hardware Len),另一个是协议地址长度字段(Protocol Len)。如下图所示:

    arp packet format

    图一 ARP数据包格式

    Hardware Type指硬件接口的类型,对以太网,其值为1

    Ptotocol Type指高层协议,0x0800指IP地址;

    Hardware Len指硬件地址长度,对以太网为6

    Protocol Len指协议地址长度,对TCP/IP为4(这里之对IPv4);

    Operation指操作类型,1ARP请求,2ARP应答,3RARP请求,4RARP应答;

    Sender/Target Hardware/IP Addr指发送/应答者的MAC/IP地址

     

    下面我们给出上面所说ARP过程的具体数据包内容,从中可以清楚的看到ARP传请求/应答的过程。在ARP数据包前面我们还给出了以太网帧头,意在表明ARP包所用的以太网帧类型,同时还忽略了对我们没用的以太网帧最后的填充位(对少于64字节的帧)和CRC校验和。

     

    ARP请求: host A 192.168.1.2 (02:10:18:01:00:02) -> host B 192.168.1.3 (00:00:00:00:00:00)

    由于此时我们还不知道主机B的MAC地址,所以用0填充。

    arp request frame

    图二 ARP请求帧

     

    ARP应答: hostB 192.168.1.3 (02:10:18:01:00:03) -> hostA 192.168.1.2 (02:10:18:01:00:02)

    图三 ARP应答帧

     

    从上图中不难看出,在主机B发出的ARP应答中,已经由对网络的多播改为只对主机A的单播。另外把ARP包中的操作(Operation)由请求(1)改为应答(2),硬件地址已经填入主机BMAC地址,并且发送/接收者的硬件地址和协议地址发生了互换。

     

     

     

    五、ARP代理

     

     

     

    以 上我们讨论的都是在同一网络内的情况,那么如果ARP请求的IP地址不在本网络内,将会发生什么情况呢?例如上例中,如果主机A ping另一个网络内的 主机b(192.168.2.3),结果会怎样呢?很可能ping程序会给出形如host unreachable的失败信息。这是因为,主机b在另一个 网段,而ARP请求的广播只对本网段有效,送往其他网段的会被路由器丢弃,所以没有主机会对它作出回应。要想让ARP能够穿过路由器到达另一网段,就需要 使用ARP代理。如下图所示,ARP代理会接收来自一个网段主机A发往另一网段主机b的ARP请求,然后将ARP请求转发给另一网段的主机b,最后把从主 机b收到的应答再回传给发送ARP请求的主机A。这样对主机A来说,就像直接从主机b收到ARP应答一样,完全感觉不到ARP代理的存在。

    arp agent

    图四 ARP代理

     

    六、逆向地址解析协议――RARP

     

    与 ARP相对应的还有一个RARP,称为逆向地址解析协议,它的包格式与ARP相同,但是它使用以太网帧类型0x8035。RARP的主要应用是为无盘系统 启动时提供从MAC地址到IP地址的映射,但它的使用需要RARP服务器的支持。在硬盘价格如大白菜的今天,(当然,嵌入式系统除外),我想应该不会有几 个人会使用无盘系统了吧!所以这里不对RARP做过多的讨论。

    七、ARP命令

    Windows和Linux系统都提供了ARP命令,用这些命令可以很方便的管理系统的ARP缓存。ARP命令比较简单,有兴趣的朋友可以直接查看在线帮助,我们这里只给出几个简单的命令以供参考。

    Windows:

    显示所有ARP缓存:arp -a

    清除所有ARP缓存:arp -d

    添加一条静态ARP映射:arp -s 192.168.1.20 00-40-4C-34-01-20

    清除刚才添加的ARP:arp -d 192.168.1.2


     

    Linux:

    显示所有ARP缓存: arp -a

    添加一条静态缓存: arp -s 192.168.1.20 00-40-4C-34-01-20

    清除刚才添加的缓存: arp -d 192.168.1.20

     

    Linux不会真正清除ARP缓存,它只是对要清除的条目设一个标志,详见下节。另外Linux中上面的IP地址也可以用有效的主机名替代。

    八、关于/proc/net/arp

    Linux内核会把当前ARP缓存以可读的形式存于文件/proc/net/arp中。现在我们就来研究一下/proc/net/arp及其与arp命令之间的关系。

    首先查看一下系统ARP缓存:

    # arp -a
    ? (192.168.1.254) at 00:30:0A:BD:6B:25 [ether] on eth0
    ads (10.1.8.11) at 00:03:FF:64:51:A6 [ether] on eth1
    atm (10.1.10.26) at 00:90:CC:D1:46:0F [ether] PERM on eth1
    ? (10.1.8.254) at 00:B0:64:6F:B9:A0 [ether] on eth1

    从中可以看到,我的系统两张网卡上共有四条ARP缓存,对没有主机名的条目,主机名一栏用?表示。下面再来看一下/proc/net/arp:

    # cat /proc/net/arp
    IP address       HW type     Flags       HW address            Mask     Device
    192.168.1.254    0x1         0x2         00:30:0A:BD:6B:25     *        eth0
    10.1.8.11        0x1         0x2         00:03:FF:64:51:A6     *        eth1
    10.1.10.26       0x1         0x6         00:90:CC:D1:46:0F     *        eth1
    10.1.8.254       0x1         0x2         00:B0:64:6F:B9:A0     *        eth1

    在 该文件中保存有IP地址,网络类型,ARP标志,MAC地址,网络掩码,和网络接口名等ARP缓存信息。其中IP地址,MAC地址和网络接口意思很明显; 网络掩码用于指定ARP代理,2.2之后的内核已经不再支持;网络类型参见RFC826,0x1指以太网;我们需要重点说明的是Flags。首先我们删除 10.1.8.11的ARP缓存:

    # arp -d 10.1.8.11

    # arp -a
    ? (192.168.1.254) at 00:30:0A:BD:6B:25 [ether] on eth0
    ads (10.1.8.11) at <incomplete> on eth1
    atm (10.1.10.26) at 00:90:CC:D1:46:0F [ether] PERM on eth1
    ? (10.1.8.254) at 00:B0:64:6F:B9:A0 [ether] on eth1

    #cat /proc/net/arp
    IP address       HW type     Flags       HW address            Mask     Device
    192.168.1.254    0x1         0x2         00:30:0A:BD:6B:25     *        eth0
    10.1.8.11        0x1         0x0         00:03:FF:64:51:A6     *        eth1
    10.1.10.26       0x1         0x6         00:90:CC:D1:46:0F     *        eth1
    10.1.8.254       0x1         0x2         00:B0:64:6F:B9:A0     *        eth1

    删 除10.1.8.11之后,arp -a会显示<incomplete>,/proc/net/arp中将它的Flags设为0x0,以表明该ARP cache暂时无效,等待更新,但该条目并没有从ARP cache中彻底删除。收到ARP应答后,该条目会自动更新,我们并不一定要发出ARP请求,详见第三节。

    我们还可以用ARP命令给网络接口指定一个ARP代理:

    # arp -i eth0 -s 202.22.30.10 00:40:78:90:66:02 pub

    # arp -a
    ? (192.168.1.254) at 00:30:0A:BD:6B:25 [ether] on eth0
    ads (10.1.8.11) at 00:03:FF:64:51:A6 [ether] on eth1
    atm (10.1.10.26) at 00:90:CC:D1:46:0F [ether] PERM on eth1
    ? (10.1.8.254) at 00:B0:64:6F:B9:A0 [ether] on eth1
    pubarpproxy.somedomain.com (202.22.30.10) at * PERM PUP on eth0

    #cat /proc/net/arp
    IP address       HW type     Flags       HW address            Mask     Device
    192.168.1.254    0x1         0x2         00:30:0A:BD:6B:25     *        eth0
    10.1.8.11        0x1         0x2         00:03:FF:64:51:A6     *        eth1
    10.1.10.26       0x1         0x6         00:90:CC:D1:46:0F     *        eth1
    10.1.8.254       0x1         0x2         00:B0:64:6F:B9:A0     *        eth1
    202.22.30.10    0x1         0xc         00:00:00:00:00:00     *        eth0

    但是Linux2.2之后,kernel会根据路由表自动选择ARP代理,所以我们现在已经不必再指定任何ARP代理了,此例仅用于说明问题。在文件/usr/include/linux/if_arp.h中,ARP标志定义如下:

    /* ARP Flag values. */
    #define ATF_COM        0x02        /* completed entry (ha valid)    */
    #define ATF_PERM       0x04        /* permanent entry        */
    #define ATF_PUBL       0x08        /* publish entry        */
    #define ATF_USETRAILERS    0x10        /* has requested trailers    */
    #define ATF_NETMASK     0x20            /* want to use a netmask (only for proxy entries) */
    #define ATF_DONTPUB    0x40        /* don't answer this addresses    */

    也许你会发现,从上面的定义里,我们找不到/proc/net/arp中诸如0x6,0xc之类的Flag。这是因为在/proc/net/arp中使用的是几种Flag按位或的结果,所以0x6 = ATF_COM | ATF_PERM,0xc = ATF_PERM | ATF_PUBL。

     

     

    九、小节

     

    说了这么多,你应该对ARP的工作原理比较了解了吧?呵呵,其实很简单, 由于TCP/IP所使用的地址机制与以太网所使用的硬件地址机制不一样,所以 ARP/RARP提供了一种地址映射机制,目的就是使以太网地址能与IP地址对应起来,让TCP/IP数据能够通过以太网正常传输。只要它工作正常,你可能根本感觉不到它的存在,但一旦它罢工了,你可能就死无葬身之地了……

     

    参考文献:

     

    [1] W. Rechard Stevens 《TCP/IP详解·卷1:协议》机械工业出版社

    [2] Douglas E. Comer 《TCP/IP网络互联·卷1:原理、协议和体系结构》英文版 第5版 人民邮电出版社

    [3] RFC826 - Ethernet Address Resolution Protocol

    [4] RFC903 - Reverse Address Resolution Protocol

     

     

     

    声明:

    本文仅供学习和交流,转载请注明作者和出处,谢谢!

     

     

  • 相关阅读:
    第36课 经典问题解析三
    第35课 函数对象分析
    67. Add Binary
    66. Plus One
    58. Length of Last Word
    53. Maximum Subarray
    38. Count and Say
    35. Search Insert Position
    28. Implement strStr()
    27. Remove Element
  • 原文地址:https://www.cnblogs.com/lance-ehf/p/3877443.html
Copyright © 2011-2022 走看看