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

     

     

     

    声明:

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

     

     

  • 相关阅读:
    【读书笔记】iOS-UDID
    【读书笔记】iOS-优化内存
    【读书笔记】iOS-处理内存警告
    【读书笔记】iOS-方法声明
    【读书笔记】iOS-属性
    【读书笔记】iOS-强类型与弱类型
    【读书笔记】iOS-Objective-C编程
    【读书笔记】iOS-Interface Builder
    【读书笔记】iOS-开发者证书
    【读书笔记】iOS-成为一名开发者
  • 原文地址:https://www.cnblogs.com/lance-ehf/p/3877443.html
Copyright © 2011-2022 走看看