**IPv4地址是一个32位长的二进制数。**而这个32位二进制数又通常会表示为4个用点隔开的十进制数。那么,这个32位二进制数要如何通过4个十进制数表示出来呢?
我们在配置IPv4地址时,同时配置的“掩码”又有何用途?
IPv4地址的一个重要概念在于分层。在定义一个可以实现全局网络互联的逻辑地址时,这个地址是否可以分层对于实现全局寻址至关重要。
IPv4地址将地址分为网络部分(网络位)和主机部分(主机位),网络部分从第32位(也就是最左侧的那一位)开始向右,直至某一位为止,主机部分则从那一位右侧的一位开始,直至第1位(也就是最右侧的那一位)。
网络部分标识的是这个IPv4地址所在的网络,而主机部分标识的则是这个IPv4地址在该网络中的特定接口或适配器。
IPv4地址规定,当网络位确定时,主机位取全0的地址表示这个网络的网络地址;而主机位取全1表示这个网络中所有主机的地址,也即这个网络的广播地址。
在IP地址问世之初,它被设计为左侧的8位二进制数表示网络地址,右侧的24位二进制数表示主机地址,如图示。
由于路由器所做的转发决策是跨网络的,因此这样设计可以让路由器在转发数据包时,能够通过固定查看数据包IP地址的左侧8位来做出转发决策,而不需要通过计算来判断IP地址中有多少位是网络地址。这样可以节省路由器所消耗的计算资源。
这种分类方式的负面效应随着网络的增加而显现了出来。缺点如下:
于是,这种固定网络地址位的做法被调整为一种兼顾路由器性能,同时在地址分配方面也更加灵活的手段——即根据IP地址最左侧的4位二进制数将IPv4地址分为A、B、C、D、E类的有类编址方式。
A类地址是左侧第1位数为0的地址。按照点分十进制表示法,即第一个十进制数为0~127的地址。
因此,A类地址的范围是0.0.0.0~127.255.255.255。这种地址的左侧8位数为地址的网络位,右侧24位则为主机位,和采用IPv4地址分类法之前,IP地址的网络位和主机位分配方式相同。因此,一个A类网络可以容纳的主机数量就是16777214个。
B类地址是左侧前2位数为10的地址。按照点分十进制表示法,即第一个十进制数为128~191的地址。
因此,B类地址的范围是128.0.0.0~191.255.255.255。这种地址的左侧16位数为地址的网络位,右侧16位则为主机位。由此可以计算出,一个B类网络可以容纳的主机数量为216-2=65534个。
C类地址是左侧前3位数为110的地址。按照点分十进制表示法,即第一个十进制数为192~223的地址。
因此,C类地址的范围是192.0.0.0~223.255.255.255。这种地址的左侧24位数为地址的网络位,右侧8位为主机位。由此同样可以计算出,一个C类网络可以容纳的主机数量为28-2=254个。
D类地址是左侧前4位数为1110的地址。按照点分十进制表示法,即第一个十进制数为224~239的地址。
因此,D类地址的范围是224.0.0.0~239.255.255.255。D类地址用于组播(Multicast),不区分主机位和网络位。所谓组播,是指多台设备通过加入一个相同的感兴趣组,实现组成员一对多通信的数据传输方式。组播在通信模型上类似于即时通信软件的群聊。
E类地址是左侧前4位数为1111的地址。按照点分十进制表示法,即第一个十进制数为240~255的地址。
因此,E类地址的范围是240.0.0.0~255.255.255.255。E类地址为保留地址,旨在留给未来使用或用作研究用途,E类地址也同样不区分主机位和网络位。
上面这种分类方式希望兼顾路由器转发数据包时用来计算目的IP地址网络位长度所消耗的性能,以及将网络位与主机位的分配方式一刀切所造成的IP地址浪费。但是,随着路由器性能的不断增强和IPv4地址的愈发紧缺,进一步细化网络位与主机位分配方式的技术也就应运而生。
最初,为了让网络设备能够根据数据包头部目的IP地址的网络位迅速对数据包进行转发,网络地址采取了固定网络位长度的方式。
但随着网络的普及和网络设备数量的增加,因这种方式使IPv4地址遭到大量浪费的情况让固定网络位长度的做法显得越来越不合时宜。
由此,网络位的长度也就由过去的固定长度,变成了当今的可变长度。
这也就意味着,对于网络设备来说,它们需要将IPv4地址与某种用来标识IPv4地址网络位的代码进行运算,来获得IPv4地址的网络位,以便路由器对数据包执行转发。
IPv4地址是一个长度为32位的逻辑地址,其中左侧N位表示其网络位,其余32-N位则表示主机位。
用来标识IPv4地址网络位的代码的特点是:网络设备能够通过将它与IPv4地址进行运算,将从某一位(也就是从左侧数起第1个主机位)起,后面的IPv4地址的主机位隐藏起来,留下的前半部分地址就是IPv4地址的网络位。
这个称为**掩码(Mask)**的代码需要与IPv4地址同样为32位。并且这种计算需要实现以下效果:若掩码对应位的IPv4地址为网络位,则掩码的这一位取1;若其对应位的IPv4地址为主机位,则该代码这一位取0。
接下来,网络设备只需要将这个代码与对应的IPv4地址进行与(AND)运算,即可得到这个IPv4地址的网络位。这就是用掩码来标识IPv4地址网络位和主机位的方式。
掩码通常也和IPv4地址一样采用点分十进制法表示,例如,掩码可以表示为255.0.0.0。除此之外,掩码也常常会在点分十进制的IPv4地址之后,用“/网络位位数”的方法表示掩码中取值为1的位数。因此类似45.168.42.212/255.0.0.0的IPv4地址/掩码二元组也可以表示为45.168.42.212/8。
无论是最初固定左侧8位作为网络位,还是后来让设备能够根据IP地址的左侧4位就迅速判断出这个IP地址类别的有类编址方式,这样设计都是为了让性能有限的网络设备能够尽快地判断出一个IP地址的网络位并作出转发决策。
在那个IP地址资源看似取之不尽耗之不竭的时代,照顾网络设备的性能才是人们首要考虑的因素。然而,随着网络设备性能的迅速提升和IP地址资源的大量流失,网络设备转发效率和IP地址资源保护这对矛盾体的主次关系在不到十年的时间里就以惊人的速度发生了逆转,有类编址方式所硬性定义的“类”再次成为了导致IP地址利用率不高的瓶颈。在这样的大背景下,逐步废除IP地址类的限制成为了必然趋势。
例如,某高等院校原本只是一所学院,后来经过投资和扩招,这所学院升级为了一个拥有3所学院的大学。这所学院早年间曾经申请到了一个B类地址,可以分配给6万多人使用。如何给他分配网络呢?
分析1:
哪怕在它升级为大学后,这个数量还是远远超过了这所学院对于IPv4地址的需求。
但是,如果要给这3所学院分别建立网络地址各不相同的独立网络,即使这家地址空间明明已经富富有余,还需要再向地址分配机构申请两个新的B类地址空间,而这样做只会带来更加严重的IPv4地址资源浪费。
分析2:
这个问题最理想的解决方法是,把这个完整的有类IPv4网络分为几个子网,用这些子网的掩码分别标识每个子网的网络位和主机位。
比如,这家拥有3所学院、6万多IPv4地址的高校,就最好能够根据每个学院的人数,将6万多IPv4地址划分成3个小于B类地址的地址块,然后分别将它们分配给3所学院。
这样一来,这所高校不仅不再需要申请更多地址空间,还将原先申请到的B类地址进行了充分的利用。
可变长子网掩码(VLSM)允许人们根据自己的需求,将固定的主机位进一步划分为子网位和主机位。
如图,将173.168.0.0这个B类网络,划分为了255个子网,每个子网的地址空间大小均相当于一个C类网络。
在有类编址方式中,由于IPv4地址的左侧4位(或第1个十进制数)已经明明白白地指出了这个地址的网络位,因此掩码多少显得有些可有可无。
那么在使用VLSM时,子网掩码就是网络设备判断一个地址主机位的唯一方式。在图中,划分后的256个子网(即173.168.x.0),它们的子网掩码均为24位,即子网掩码皆为255.255.255.0。
注意:子网掩码的位数是网络位与子网位的位数之和,并不单单是子网位数。
假设这个高校当时申请到的B类IPv4地址就是173.168.0.0/16这个地址空间,而它的3所学院分别需要15000个IPv4地址、7000个IPv4地址和3000个IPv4地址。那么改如何划分子网呢?
经过计算,如果不考虑未来的扩展性,那么可以以如下划分方式:
从需要14个主机位的子网开始划分,这个子网的子网掩码长度应该为32-14=18位,由于B类地址一共提供了16位主机位,因此我们需要将从左侧数起第17位和第18位划分为子网位,在此管理员可以选择如何设置这两个子网位的取值。
因为无论这两位如何取值,只要服务提供商之前分配的前16位二进制数不变,这个子网就都是这个B类网络173.168.0.0/16中的子网。
为求方便,我们将第17和第18位全部取0,得到子网173.168.0.0/18,这个子网可以分配给需要15000个IPv4地址的学院。
同样,对于需要13个主机位的子网,这个子网的子网掩码长度应该为32-13=19位,由于B类地址一共提供了16位主机位,因此我们需要将从左侧数起第17位、第18位和第19位划分为子网位,在此管理员可以选择如何设置这3个子网位的取值,不过第17位和18位此时不能取全0,因为若取全0,则无论第19位如何取值,这个子网都属于已经分给另一所学院的子网173.168.0.0/18。
为求方便,我们将第17和第19位取0,第18位取1,得到子网173.168.64.0/19,这个子网可以分配给需要7000个IPv4地址的学院。
最后,对于需要12个主机位的子网,这个子网的子网掩码长度应该为32-12=20位,由于B类地址一共提供了16位主机位,我们需要将从左侧数起第17、第18位、第19和第20位划分为子网位,管理员可以选择如何设设置这4个子网位的取值,但第17位、18位不能取00,第17、18、19位也不能取010,否则这个子网就会属于某一个已经分配给其他学院的子网。
为求方便,我们将第17和第20位取0,第18位和第19位取1,得到子网173.168.96.0/20,这个子网可以分配给那个需要3000个IPv4地址的学院。
结果划分为:
学院1(需要拥有15000个IPv4地址的学院):
学院2(需要拥有7000个IPv4地址的学院):
易错点:
子网划分不是计算好主机位容量之后,简单的把子网掩码分别划分为173.168.0.0/18、173.168.0.0/19、173.168.0.0/20三类,这样会导致IP冲突。
在划分子网时,只要管理员所进行的地址规划确能让各个子网满足IPv4地址的需求,同时又保证子网与子网之间不出现地址冲突,那么这个子网规划就不能算错误。这也就是说,在实际分配子网时,网络工程师固然可以将子网分配得更加零散,但按照图所示的方法更加紧凑地规划地址分配方案仍然是实际网络工作中最值得推荐的地址规划方法。
我们不妨对规划子网的流程进行一个简单的概括。在获得一段IPv4地址空间,并且需要对其进行规划时,我们可以按照下面的流程计算出各个子网的地址与掩码:
有一些特殊的IP地址并不需要由ICANN进行分配,也不能连接到互联网中。定义这些特殊IP地址的目的是为了将它们在全球局域网中复用,以达到节省IP地址空间的目的。
例如,当一家企业需要获得1000个IPv4来组建自己的网络时,地址分配机构应该如何分配呢?
分析:
可以计算出,这家机构需要的是一个主机位为10位的网络地址(210-2=1022),因此分配给它一个22位掩码的网段最能够满足需求。
按照可变长子网掩码技术,在这种情况下,从一个B类地址的主机位中借6位作为子网位获得的网络地址可以满足这样的需求。但这样做会导致这个B类地址被划分得过于零散。
要想满足这类申请,地址分配机构很快就只能从A类地址中借14位作为子网位进行分配,或者将4个C类地址作为一个完整的22位网络地址进行分配。
当然,更理想的方法是采用这样一种不区分地址类别的无类编址方式,即IPv4地址最左侧4位的取值与这个地址的网络位数和主机位数没有任何关系,一个IPv4地址的网络位与主机位完全靠掩码进行定义。
这样一来,一个22位网络就是一个22位网络,它既不是某个A类主网或B类主网的子网,亦非几个C类主网的集合。
这种无类编址方式还可以解决当时网络中面临的另一个问题,那就是随着网络蓬勃发展导致的核心网络路由器路由表条目数量剧增的问题。
路由器在转发数据包时,会用数据包的目的IP地址一一匹配路由表中的条目,随着网络数量的增加,路由表中的条目也在相应增加,这会延长每一台路由器查询路由表的时间,导致网络性能下降。
如果彻底打破类的概念,路由器就可以根据任意长度的网络位来路由数据包,这就让路由器能够根据实际情况通过合并同类项的方式对路由表进行汇总,充分发挥逻辑地址层级化的优势,减小路由表的数量,达到优化网络性能的效果。
1993年,一项基于VLSM的技术在这样的背景下诞生,这项称为无类域间路由(CIDR)的技术彻底打破了IPv4地址中类的概念,支持使用任意长度的网络位来分配地址和描述路由信息。
在无类域间路由技术的背景下,地址分配机构可以给一个需要1000个IPv4地址的企业分配诸如192.48.8.0/22这样的一个超网地址。如果按照有类编址方式的老眼光去看待这个地址,它其实是由198.48.8.0/24、198.48.9.0/24、198.48.10.0/24和198.48.11.0/24这4个C类主网地址组成的(即将192.48.8.0/22的左起第23位和第24位分别取00、01、10、11后得到的4个网络地址)。而在这家企业之外的路由设备上,这个网络最多是通过一条目的网络为192.48.8.0/22的路由,而不是4条C类主网路由来标识的,路由表的规模得以显著减小。
尽管目前MAC地址也可以通过逻辑的方式进行修改,但它最初被设计为一种天然的、不可人为更改的硬件地址。
虽然MAC地址也可以满足唯一性的需求,但由于这种地址不可由技术人员根据需求通过逻辑方式进行管理,因此它只能用来进行局部寻址,而无法用于实现全局范围内的寻址。
而IP地址则不是硬件本身自带的天然地址,而是一种由网络技术人员按需为设备分配的逻辑地址。
类比:
虽然邮政地址和人的相貌都满足唯一性条件,但两者相较,凭借相貌寻人的方法只适合用于那些范围十分有限的场合,比如任职于同一个单位的同事在工作场合可以只通过相貌来识别对方的身份,这种寻人方式基本不会超过对方居住的公寓或者对方单位办公楼的范围。邮政地址则恰好相反,这种分级的地址特别适合用来实现全局寻址。
以太网中的终端设备最后会根据接收到的数据帧是否以自己适配器的MAC地址作为目的MAC地址封装数据帧,来判断是否解封装这个数据帧。因此,数据帧至少要在被转发给终端设备之前,以目的设备的MAC地址作为数据帧头部的目的MAC地址。
而一台终端设备在向目的设备发送数据包时,有时只知道对方的IP地址,而并不知道对方的MAC地址,此时就需要有一种专门的协议能够通过目的设备的IP地址,来查询它的MAC地址。
用来根据目的设备的IP地址来查询MAC地址的协议,就是地址解析协议,简称为ARP协议。
当一台终端设备希望向处于同一个以太网中的另一台终端设备发送数据帧,却苦于不知道对方的MAC地址时,它就会以那台设备的IP地址作为目的IP地址,以广播MAC地址(全1位MAC地址,即FF-FF-FF-FF-FF-FF)作为目的MAC地址,向整个以太网发送广播消息,这个消息叫作ARP请求消息。
二层交换机并不会查看数据包三层的IP地址,它们只会根据数据帧头部封装的目的MAC地址将其从除了接收到数据帧的那个接口之外的所有接口转发出去。
接下来,所有接收到ARP请求的终端设备都会对数据帧进行解封装,但只有终端3发现数据包三层的IP地址是自己的IP地址,因此终端3发现这个ARP请求包所请求的MAC地址是自己的MAC地址。
于是,被请求方(终端3)会以自己的MAC地址和IP地址作为源MAC地址和源IP地址,同时以请求方(终端1)的MAC地址和IP地址作为目的MAC地址和目的IP地址,封装一个ARP响应数据包,发送给ARP请求方(终端1)。
至于终端2和终端4,尽管它们都会接收到终端1发送的广播ARP请求消息,但在它们解封装数据帧后,会发现这个请求消息所请求的MAC地址并不是自己的MAC地址,因为这个数据包的目的IP地址与自己的IP地址并不一致,于是终端2和终端4都不会对这个ARP请求消息做出响应。
由于此前交换机已经接收到了终端1发送的ARP请求消息,因此交换机的CAM表中已经建立了终端1的MAC地址与自己接口之间的对应关系。所以,在交换机接收到终端3发送的单播ARP响应消息时,它可以通过查看CAM表找出终端1连接在自己的哪个接口上,并将数据帧从那个接口发送出去。而当终端1接收到终端3发送的ARP响应消息后,它也就通过数据的源MAC地址获取到了终端3的MAC地址。
在通过ARP查询到目的设备的硬件地址之后,发送ARP请求的设备(如图6-12中的终端1)会把目的设备(如图6-12中的终端3)的IP地址与MAC地址对应关系保存到一张高速缓存表中。这样一来,当设备需要再次向同一台目的设备发送数据时,只需要查询自己的本地缓存就可以封装目的MAC地址,而无需再次在网络中广播ARP请求。所以,ARP高速缓存既能够减少网络中传输的ARP通信流量,提高网络传输数据的效率,又可以节省全体设备处理ARP请求的资源。
总之,ARP的工作方式是,当一台设备由于不知道目的设备的MAC地址,而无法封装以目的设备MAC地址为目的MAC地址的以太网数据帧时,它会先以广播MAC地址作为目的MAC地址封装广播数据帧,向整个网络请求目的IP地址对应的MAC地址。
当目的设备通过目的IP地址识别出这是请求自己MAC地址的ARP请求包时,就会以自己的MAC地址作为源MAC地址,向ARP请求包的始发设备发送单播的ARP响应数据包。在接收到这个响应数据包之后,请求设备也就看到了目的设备的MAC地址。
IP协议提供的是一种尽力而为的服务。作为网络层的协议,这项协议的初衷在于定义如何将数据从源传输到目的,但它基本不负责对网络层数据传输的差错提供检测和报告。
鉴于源设备与目的设备在网络层的通信是否正常是网络信息交互的一项重要因素,因此人们一定会定义一个能够承担网络层通信差错监测和报告机制的协议,而由此诞生的协议就是互联网控制消息协议(Internet Control Message Protocol,ICMP)。
ICMP的使用相当频繁,比如当一个数据包到达某台路由器时,路由器发现这个数据包IP头部的TTL字段已经过期,它就会丢弃这个数据包,这一点我们在本章介绍IP协议头部封装格式的TTL字段时已经进行了介绍。除了丢弃数据包之外,这台路由器此时还会封装一个ICMP TTL过期消息(ICMP消息类型11)发送给数据包的始发设备,以此通知数据包的始发设备,该数据包TTL已经过期。
在封装方面,ICMP协议虽然属于网络层协议,但ICMP消息的外层仍会封装IP头部。也就是说,ICMP消息是IP数据包的负载。从这个角度上看,ICMP协议虽然和IP协议都工作在OSI模型的网络层,但它可以视为是IP的上层协议,因为设备在封装ICMP消息时,会在网络层执行先ICMP头部、后IP头部的两次封装。而上一自然段中提到的“以对方的IP地址作为目的地址封装”,指的是设备封装ICMP消息的IP头部时需要添加目的IP地址。而ICMP头部封装格式中,并没有涉及IP地址的字段。
常见ICMP消息对应的类型和编码值:
当一台设备通过ping工具来测试另一台设备的网络层地址是否可达时,这台设备会以对方的IP地址作为目的地址,封装一个ICMP Echo-Request消息(ICMP消息类型8),并将这个消息发送出去。
如果对方能够接收到这个消息,则会封装一个ICMP Echo-Reply消息(ICMP消息类型0),并将这个消息发回给始发设备。
因此,如果发送Echo-Request消息的设备能够接收到对方设备发来的ICMP Echo-Reply消息,代表双方在网络层可以实现双向通信。
除了ping工具之外,我们所提到的另一个0级网络诊断命令tracert也是通过ICMP协议来实现的。
这项工具的作用是帮助管理员了解和查看从当前设备向目的设备发送数据所经历的整条路径。
Tracert工具所采取的做法很有创意:它会依次让设备封装一系列去往目的设备的数据包,并且将它们发送出去,这些数据包IP头部的TTL值依次设置为1、2、3,以此类推。
这样一来,当去往该目的地址的第1跳设备接收到第1个数据包时,这个设备会发现这个数据包的TTL已经过时,因此第1跳设备会封装一个ICMP TTL过期消息发送给源设备,这样源设备也就了解去往目的设备的路径中,第1跳设备的消息。
当第1跳设备接收到第2个数据包,也就是TTL值为2的那个数据包时,它会将这个数据包的TTL值减去1,然后转发给去往目的路径中的第2跳设备。
因此,当第2跳设备接收到这个数据包时,它会发现这个数据包的TTL也已经过时,因此第2跳设备会同样封装一个ICMP TTL过期消息发送给源设备,这样源设备也就了解了去往目的设备的路径中,第2跳设备的消息。
这个过程会不断持续下去,直至最终的目的设备接收到源设备发送的数据包。