闲聊计算机IP网络
记得刚上第一节《计算机网络》课的时候,下课时就记得网络分为通信子网和资源子网,当时觉得这是多么的教条,时隔多年以后,再来回味这个通信子网和资源子网的划分,还真是能牵扯出来不少东西呢...
通信子网和资源子网的划分是横向的划分,而纵向的划分就是诸协议栈。
什么是通信子网呢?通信子网就是负责网络交通的子网,它的任务就是路由寻址。什么是资源子网呢?资源子网中存储资源数据。一般而言,处在末梢端的网络都是资源子网,主干部分的则是通信子网。这么解释还是太教条了,如果理解了IP地址的话,冲着这个资源子网和通信子网分类,可以洋洋洒洒上千字了...
IP地址和IP寻址IP地址IP地址可以分为网络位和主机位,其中网络位标识网络,用来执行IP路由寻址,主机位用来标识主机。那么很显然,IP地址的网络位就可以表示通信子网,而主机为则可以表示资源子网。
IP寻址IP寻址的机制就是IP路由,IP理由的实质就是“局部逐跳地沿着链路向前推进”。根据目的地和当前位置的关系,IP路由的路由项可以分为四类,分别是:
1.Global路由:本机距离目的地之间需要跨越其它的路由器,其中包含路径的下一个路由器的IP地址,需要下一跳解析协议解析其链路层地址。
2.Link路由:本机距离目的地之间不需要跨越其它路由器,目的地就在连接本机的链路的另一端,其中不包含下一个路由器的地址,因为已经可以直接用下一跳解析协议直接解析目的地了。Link路由即直连路由。
3.Host路由:本机就是目的地,即数据包已经到达。本机配置的所有IP地址都会是Host路由。
4.Blackhole路由:黑洞路由,即数据包永远都到达不了目的地。
现在我们来看一下一个数据包从源头到目的地的经历。不考虑遇到黑洞的情形,基本可以分为以下的过程:
1.数据包始发,通过查找路由表发现目的地路由是一条Global路由,于是将包传递到下一跳;
2.路径上可能会持续命中Global路由多次,逐跳传递包;
3.数据包在某台路由器上匹配到了一条Link路由,直接解析目的地的链路层地址,数据包继续前进;
4.数据包匹配到一条Host路由,终于到达了目的地,该设备的第四层接收例程开始处理数据包。
为了保证上述的过程,路由器需要确保:对于Global路由,下一跳一定是Link可达的。也就是说在添加Global路由的时候,要执行一次针对下一跳的路由查找,确保查找结果是一条Link路由。当然,在支持路由递归查询的路由器上,可以不必要求下一跳一定是Link的,然而在内部,最终递归查找的结果还是Link上的下一跳。
主机标识-最后一跳数据包在到达目的地的过程中,对于目标是逐步接近的,如果将Global路由,Link路由,Host路由来做一个排序的话,数据包在经过更后面的路由类型后,是绝对不可能在经历一次前面的路由类型的,比如数据包的路径上的路由类型匹配序列不可能是:Global,Global,Link,Global。
可以肯定的是,数据包的最后一跳的依据是一条Link路由,接下来数据包就到达了目的地。但是并不能保证它能被上层接收,因为还需要匹配一条Host路由,也就是说,目标IP地址必须是本机的一个IP地址才可以。虽然有些实现中,在上一跳的“下一跳解析协议”执行的时候,这一点就能保证了,但是标准的IP路由还是需要去匹配路由表的Host路由项。在Linux中,arp_process中,对于REQUEST,目标IP地址一定要是Local表中的Host路由项才会回复REPLY。
关于直连路由直连路由是内核自动生成的。基本上业内没有人不知道这句话,然而关于直连路由的认识,很多人附加了一些内容,即直连路由不能手工配置。不能手工配置和不需要手工配置是完全不同的两回事。其实直连路由也是可以手工配置的。这也就是说,我们可以配置32位掩码的IP地址,这样就不会生成直连路由,然后我们手工配置一条直连路由即可。实质上,所谓的直连路由,就是指出到达某IP网段的数据包可以在路由指出的网卡上解析目标IP地址。
直连路由即Link路由,上文提到过,在添加Global路由的时候,要确保下一跳是Link可达的,这一点就是通过针对下一跳地址做路由查找来实现的,如果返回的路由不是Link路由,则添加不成功。现在我们来看一下Link路由的生成。有三种生成方式:
第一种:自动生成当你添加了一个IP地址在网卡上,协议栈就会根据你的IP地址掩码解析出其网络ID,根据IP地址以及其路由原则,属于同一网络的所有主机必须处在同一链路内,系统会生成一条链路层路由,即直连路由。
第二种:手工添加如果信息所拥有的信息不足以让它生成一条直连路由,但是管理员站在人的角度可以确定该直连路由的话,就可以手工添加一条,比如管理员知道线缆另一端的网卡的IP地址是1.1.1.1/24,那么他就可以在本端配置一条直连路由,虽然他并不定将本端网卡的IP地址也配置成1.1.1.0/24网段的。
第三种:强制添加导致的隐Link路由如果你能确保Global路由的下一跳IP地址真的不会跨越路由器,即它真的就在本链路,然而本地又没有和它同一网段的IP,这就说明本端不会有到达下一跳IP地址的Link路由,那么如何来将该Global添加入系统路由表呢?可以强制添加,一旦强制添加,系统会认为该下一跳在Link上,到达下一跳的路由是一条Link路由,但是该路由不会显示出来。
配置32位掩码的IP地址IP地址使用其网络位标识其通信子网ID,使用主机位标识其资源子网ID,二者统一于子网掩码,即前缀(不考虑有类编址),因此这个通信子网和资源子网的分类界限就可以平滑移动了,因此我们可以将32位掩码的IP地址看作是一个“退化的通信子网ID”,即一个资源子网ID。有了子网掩码,分类便不需要了。
每一个非32位掩码的IP地址都指示了一个网络-一个通信子网ID,该网络有一个全0的主机位表示的IP地址和一个全1的主机位表示的IP地址,前者是该网络的标识,后者是该网络上所有主机的标识,因此在一个网络中,这两个IP地址是不能使用的,不过有个例外,那就是31位掩码的IP地址表示的网络,RFC3021详述了这种情况。只要掩码非32位(RFC3021说的31位掩码也这样),IP地址在配置的时候,就会生成一条网络路由和一条广播路由以及一条直连路由。但是如果掩码是32位的,将只生成一条Host路由(置于Local表),此时不会有任何广播路由和直连路由生成,也就是说任何IP地址都不会被解释成广播或者网络,节省了IP地址。
但是,既然没有了直连路由,那么如何来执行IP路由呢?要知道,IP路由的最后一跳必然是直连路由,而且由于IP报文是逐跳前行的,要求下一跳也必须在直连链路上。这些问题其实都不是问题,如果你明确知道下一跳或者目的地在线缆的另一端,你还发愁数据包无法到达它吗?以Linux为例,有两种解决方法,第一就是使用force-onlink路由,强制直接解析下一跳;第二就是手工添加一条直连路由。注意,手工添加的直连路由仅仅就是一条直连路由,它不会把和该直连路由相关的广播路由也添加进去。
关于标准化-TCP/IP是如何赢的TCP/IP成为事实标准之前,一切都是杂乱无章的。标准化的过程总是一个争吵和竞争的过程。OSI模型是第一次的标准化尝试,然而其内容却包含大量的厂商标准,实际上就是厂商们的混战和妥协的过程,这种标准化过程不可能产生一个自洽又简单的第三层协议,因为就算是取交集也是众厂商复杂标准的交集,事实上还真的就是一个取交集的过程而不是一个设计的过程。
最终,OSI模型的网络层协议也就变成了一个毫无操作性可言的抽象层,毕竟,即使是ISO也无法撼动诸如X.25,FR,PSTN等协议背后的那个强者。因此,只要对这些协议进行一些“符合OSI模型网络层定义的”增强,它们就俨然成了一个网络层协议。事实上,它们成功的这种根基是不牢的,复杂,缺乏互操作性成了其硬伤。后来,OSI的网络层协议有CLNP,(虽然Cisco等大佬级的公司主动支持了OSI的标准网络层协议),但是由于大多数人此时或者趋势中已经倒向了TCP/IP,再多的努力也于事无补。目前,在OSI模型上唯一(如果其它的关于超大运营商的故事不计在内的话)起重要作用的协议就是IS-IS了。我想这期间的PK,并不总是公平的。
CLNP提出时,如此的抽象,此时,X.25等网络已经运行多时,置它们于何地?新标准虽被提出,确实是想统一混乱的OSI网络层,人们的选择也是两个,即CLNP和IP,会选择一个新秀还是一个老牌?更何况,牌子虽老,但是行动迟缓,X.25,FR,ATM等网络层次不清,互操作导致的开销过大就已经让人们对这些厂商驱动的标准化组织没有耐性和信心了,人们更多的可能是想试一下IP的本领...更何况,IP此时已经被提出了。我们看看对阵的双方:
OSI:ISO/IEC 8208, X.25 (Packet-LaISO/IEC 8878, X.223, ISO/IEC 8473-1, CLNP X.233
TCP/IP:IP, IPsec, ICMP, IGMP, OSPF, RIP
很明显,这场战争和公元前凯撒和庞培之间的战争很类似,庞培方,数倍于凯撒的兵力,然而士兵却是拼凑的,有来自行省的,有附属国的,毫无忠诚度可言,反观凯撒方,全部都是跟了他多年的高卢老兵,个个精悍且忠诚。我们看下OSI方的阵容,标准不一,和庞培方很类似,再看看TCP/IP的阵容,其实它们都是围绕IP的,没有一个是IP之外的。胜负,还没有对决就已经确定了!关于古罗马的那场著名的法萨卢战役,即使凯撒不出奇兵,也能制胜,关键在于双方阵容有没有核心,以及是否围绕核心。时隔2000年,同样的法萨卢战役在TCP/IP和OSI/RM之间重新进行,千百年以来,一切又重头。
关于TCP/IP,人们很长一段时间都认为它只是一个在OSI标准全部推出前的过渡,正如古罗马的内战当事当时,元老院很看好庞培一样(也许是为了给自己道德的背叛找个台阶下,毕竟是元老院先求庞培的),人们一直以为定乾坤的是庞培,为他的一次次失利找各种理由,如果不是因为他命殒埃及,法萨卢战役的失败也会仅仅是一次失利...凯撒赢了,但是却没有对庞培派的人赶尽杀绝,甚至重用之。TCP/IP赢了,同样也没有推出新的标准,正如它的司职就是网络层(传输层仅仅是提供一个有连接机制,严格说,TCP/IP分层不是基于服务提供点的),它并不过问其它的OSI的layer,因此像X.25之类的协议就填补了这个空白,变成了纯粹的承载传输协议。甚至,在网络层,IS-IS也是一样重要的指路协议,我认为这并不是因为ITU,ISP们太强大,ISO在他们那上头有人,而是TCP/IP太开放,太包容。
TCP/IP最终的命运如何,那要看TCP/IP是否能像凯撒一样,一如既往地开放,包容。
要完全按照标准做事吗 完全按照标准做事是好的,规范化操作是为了互操作的方便,也是为了方便和外界接口。但是规范化操作却不利于创新,任何标准,在最开始的时候都是非规范的尝试。另外,一样东西标准化的过程总是有着取交集的过程,即使像TCP/IP这样的几乎完全设计出来的标准,也是吸取了很多已经有的东西,那么交集之外的,曾经被使用的但是却没有成为标准的一部分的那些内容,反成了不标准的东西了,你不按标准做事,就会有人说你术业不精,而实际上,并不总是那样!
如果你理解事情的本质,那就不必完全按照标准来,当然前提是要么你不和别人接口,要么你能说服别人。举一个例子,我做了一个模块,实现了IP地址冲突的情形下也能照样通信。这个对于TCP/IP来讲绝不是标准的,然而却符合SDN。任何事情都不能因为它不是标准的东西就不敢去尝试,要勇于尝试,前提是你要知道违反标准操作的后果并且能承担后果,我并不提倡盲目尝试。