彻底理解Cisco/Linux/Windows的IP路由
-1.只要理解实质,名称并不重要!
很多使用Linux的网络高手在面对Cisco管理员的诸如管理距离,路由度量等词汇时,还没有PK就自觉败下阵来了。我觉得这实在太可惜了,大家本是一家,为何这么为难对方呢?如果理解了实质,如何描述就不是那么重要了。如果一个Cisco设备管理员对你说一些你不懂的名词,或者对你描述一些Cisco上有但是基于Linux的网关设备上没有的特性,而且那个人因为拥有了CCIE证书而目中无人,你要怎么面对?如果你是一个熟悉且精通Linux的人(比如我),你首先就要明白,Linux是无所不能的,只要你愿意,你下班回家就能写一个基于Netfilter的模块,实现所有的Cisco IOS的特性,如果你认为自己做不到,那么就看完本文,给自己一些信心。(注:我并不贬低以Cisco为业的哥们儿,某种意义上,我也是其中一员,当年只是因为没钱才没有考CCIE,因为太TM贵了,因为没钱,我转到了一个草根平台,不高贵,但却自由。背叛的意义在我这里成了类似“出埃及记”的东西...)
0.要读一些历史
一位IT人员,在这里谈历史,有点不妥,但是我请各位关注一下理查德.费曼,一位全才,在关注一下更猛的沃纳·卡尔·海森堡,一位历史系科班出身的顽童。读一点历史能让你知道一些常识,更能让你明白事情为什么会成现在这个样子。任何事情都是一点一滴积累的,我们现在的即便再发达的科学技术,都是从原始人发明弓箭(并不是常规认为的发明火开始的,如有疑问,私信)开始的。你可能看不起原始人,因为他们没有iPad,没有手机,动不动就咬人...但是我们确实不比他们强多少,我们有iPad,因为苹果做了它,我们有手机,因为有人卖,我们不咬人,不随意打人杀人,因为我们害怕法律的制裁...
任何事情一开始都不是复杂的,其基础理念都是极其简单的。这是我的信条!然后逐步堆积,就成了现在这个样子,然后学子们开始背诵,虽然他们不知道为何如此,但是还是在背诵,然后考试成绩非常好,被认为是高才生,然后,突然有个机会,聚餐,或者年会,抑或相亲,突然听到了重金属摇滚乐,...他们不知所措了,...生活不能自理,...唉,总之,我们是复活的魔鬼,而撒旦就是历史!
1.有类IP和无类IP
IP之初,并无此分类,当时的概念全部是“有类”的。只是到了后来,为了解决逐步发现的问题,才引入“无类”的概念,于是就有了这个分类。不用再强调的是,任何事情一开始是都是无法发现问题和不足的,导致到了后来发现时才能弥补,因此技术上的进化都是逐步堆砌而成的,也造成了一项技术会发展进化得越来越复杂。
当人们在实验环境下使用IP可以联网的时候,下一步的计划就是制定一套如何将这些IP地址分发给需要联网的机构的方案,这其实也是当时唯一的问题,因为实验环境中发现的问题都在实验环境中解决了,真实世界的问题只有将IP地址分配出去并且大家都使用了之后才能发现!鉴于此,美国短视且一厢情愿地将IP地址空间分成了5个类,每一个IP地址的“网络号”标示了该IP地址的归属方的规模,其中A类地址的规模最大,C类地址的规模最小,仅仅能承载254台主机。
1.1.子网划分
然而使用A类地址的机构并不是很多,A类地址的数量却是如此之多,以至于出现了地址浪费问题,于是分级就成了唯一的解决方案,毕竟地址空间已经划分好,不能推倒重来,那么只能靠分级划分子网了,于是在一个机构的所有IP地址的主机部分,还可以拉出去一部分用来作为子网网络号,这就叫基于分类IP地址的子网划分。于是一个机构中可以承载多个规模相同的子机构,注意是规模相同的!然而这仅仅是裂变的第一步...
1.1.1.问题:为何子网规模必须相同?
子网划分规模必须相同的言外之意就是子网掩码必须一致,这成了有类IP子网划分的硬性规定,但是为何会这样呢?这就不得不从IP路由的另一个维度,即IP管理平面的路由通告上作一番解释。
在有类年代,给出一个IP地址,你就能得到所有的信息,你能得到其主类网段,即x.0.0.0/8的A类网段,y.z.0.0/16的B类网段等,进而你就知道该IP属于什么机构...但是子网划分就是机构内部的事情了,外界并不知道你的机构内部的子网是怎么划分的,对于全局的路由通告而言,当然也不能带有任何子网的信息,也就是说,路由通告只能通告主类网段的路由,并不携带子网掩码!比如RIPv1协议就不能通告1.2.3.0/24这样的路由!那咋办捏?毕竟一个子网就是一个小的网段,在IP路由层次上来讲就是一个真正的三层网段,172.16.1.0/24和172.16.2.0/24虽然都是属于172.16.0.0/16这个主类,但是由于有了子网划分这个操作,它们毕竟不是一个网段!怎么识别并区分它们呢?好办(此时我这么说并不是意味着我就是上帝,我站在一个后来人的角度,采用一种历史的眼光来评述这件事)!就配置在接口上的IP地址的掩码来识别。由于IP地址的配置是独立的,即使现在,IP地址的自动配置也不是常见的事,自动配置大多在端系统!为了不丢失被掩码掩掉的网段,必须要求所有同网段的接口配置相同的掩码,实话说,这是上帝的要求,你可以不遵循,但是你要付出某些主机不可达的代价,,比如,某个接口A配置了172.16.1.0/24的地址,和它通过二层交换机直连的某个接口B配置了172.16.1.128/25的IP地址,那么请问,它们能达到共识吗?对于接口B而言,172.16.1.0/25的就不是同一个网段的,但是对于A而言,所有172.16.1.0/24都是一个网段的,虽然在如今的无类环境中,这完全没有问题,完全可以通过路由的方式解决可达性问题,在有类IP环境中,完全按照主类和“通过配置在接口上IP上的掩码”来识别子网,任何路由协议通告的路由都不会携带掩码,这就成了问题,因此这有类环境中,必须要求子网掩码一致!
这让我想起了小说《猴爪》和基于史蒂芬.金的小说拍成的电影《宠物公墓》(又名《夜半鬼敲门》,有两部)。你希望得到一些逝去的补偿,但是你的代价就是更多的逝去!
为何这么复杂?因为有类IP年代,“IP类”隐含了很多的隐性信息,信息高度的不凝聚!你可以从类中得到很多东西...这并不是上帝的方式。
1.2.无类以及VLSM
子网在每个机构被不同程度地划分着,然而仅仅如此划分子网是不够的,第一,一个机构中的子机构不一定规模相同;第二,规模比较大的机构的子机构可能还有子机构,现有的IP地址分配方案无法真实反映实际机构的组织架构关系。
一个分类IP段(即分类IP地址的网络号标示的部分)已经被分配给了一个机构,那么如何来分配该段内的地址是机构内部的事情,为何还要遵循硬性的子网划分规定(划分为规模相同的子王,即子网掩码相同)呢?由于当时做出来的网络设备都是按照当时的“有类”标准执行的,所以其结果阻碍了人们灵活地使用IP地址!
终于,有人大胆地要求取消地址分类,VLSM被提出。如此标准提出后,在无类环境中,子网掩码成了VL(变长)的了,不再是固定的“IP地址的类别指定的掩码+同分类地址段内相同的子网掩码”的了,于是你可以写成IP/mask的形式,IP不再按照基于第一个字节的头几位二进制值而分类,mask也不再遵循8,16,24等基于分类地址的固定划分,事实上,IP可以是任意的符合规定的IP地址,mask如果写成prefix前缀形式(指示多少连续的1)的话,可以是0到32的任意值!实际上,到此为止,裂变已经发生了!
1.3.合并成超网和CIDR
取消分类带来了超猛的效果!其中最猛烈的效果就是改变了路由查找的算法,另外改变了人们解读IP地址的方式。对于路由查找算法的改变就是将路由查找进化到了“最长掩码匹配年代”,这个后面要说,对于人们解读IP地址方式的改变,则是在无类环境中,一个块IP地址段不再和唯一的机构关联了,它包含的所有IP地址原则上可以属于任何人,任何机构,可以处在任何物理位置。当然,这也带来了不少的问题,实际上是将IP地址的分配任务交给了实施人员,一旦出现地址空间碎片,将会导致无法汇聚,从而最终导致路由表的条目增加。
有点跑题!正说着无类的好呢,又扯到它的缺点了...言归正传。无类编址的提出实际上最开始是为了解决机构内部分配地址的问题的,然而它事实上却带来了一种副作用,那就是将一块本属于一个机构的地址段可以延伸到该机构之外,也即,机构和地址块不再关联!既然在机构内,一系列的连续子网可以合并成一个主类网络段,那么现在已经是不再在意机构界限的无类环境了,是否可以将连续的VLSM子网合并成一个大一级的网络呢?这是肯定可以的,是为超网。取消了分类是解除了一种束缚,随之解放的就是人们分配IP地址的权力,分配过程变得自由了,因此虽然连续的VLSM子网可以合并成超网,但是你却并不能假设一定可以这么做。完全有可能1.2.40.0/24在美国,而1.2.41.0/24却在阿富汗,你当然不能将其合并成1.2.40.0/23,因为它们真的不属于任何交集内!结果是什么呢?结果就是路由查找算法的改变,可以说是简化。这个进化的诱因就是:可以合并成超网的若干子网由于允许不属于同一个分支机构内而无法合并,因此也就不能假设分类环境中的属于子网的IP地址一定属于它们合并成的超网中。
摆脱了分类的限制,去除了诸多的假设,路由查找算法就变成了“最长掩码匹配”算法了,路由查找和IP地址的分配完全没有关系,一直找到一个所有路由表项中和目标网络最接近的,将目标锁定在一个最小的范围内。这遍可以用一种更加统一的方式来实现查找算法了。而分类IP路由查找的实现则不能做到统一。
1.4.有类IP路由查找算法
有类IP路由查找算法是两个步骤,可以简称为,目标地址分类和子网查找。首先将目标地址分类得到主类网段,然后看系统路由表中有没有此主类网段的路由,如果没有则直接丢弃,如果有则看是否有划分子网,如果没有划分子网,则取出下一跳发包,如果有子网划分则查找该目标地址是否处于其中一个子网内部,如果没有发现这样的子网,则丢弃,如果找到了,说明该目标IP属于该子网,取出下一跳发包。
这个算法在现代网络人看来,有点奇怪,为何这么查找呢?实际上,在IP分类的年代,如果从一个IP地址中取出了其主类网段,那么它必然处在该主类网段所直接连接的网络内或者其直连的路由器所承载的子网内,这也是最初IP地址分配的首要原则,IP地址空间只能按机构进行划分,不能打散!如果没有找到主类路由或者找到了带有子网的主类路由但是没有找到对应的子网,难道你能指望目标在另一个地方吗?分类IP的分配就是机构和IP地址主类的对应关系,一个萝卜一个坑,在这种情况下,设置默认路由的唯一意义就是在“找不到主类路由的情况下”进行默认转发。只要找到了主类路由,转发还是丢弃就已经确定了!算法如下:
Network=确定主类地址(DST)
Route Entry=Search该主类
if (Route Entry)
if (包含完整的下一跳信息)
转发
else //仅仅是一个Level 2子网路由的Entry
Route Entry=Search该主类的Level 2路由
if (Route Entry)
转发
else
丢弃
else if(存在默认路由)
转发
else
丢弃
典型但不绝对的一种实现方法就是:保存N张路由表(N为IP地址类别数量),添加路由表项的时候,根据目标地址将其置于特定的类别的路由表中,转发时,根据目标IP地址计算出IP地址类,然后就在该类路由表中进行查询。
1.5.无类IP路由查找算法
无类IP路由查找算法其实就是“全局最长掩码匹配”算法,这个在如今已经成了大家认为的那样唯一一种查找算法,虽然很多网管都知道,分类环境中,并不使用这个算法。最长掩码匹配的具体内容就不多说了。
算法比较简单,典型的Linux实现有HASH和TRIE两种,不管哪一种都是从32位掩码到0位掩码的单掩码查找,找到最先匹配到的。
1.6.现状
现在主流的操作系统Linux,Windows的路由查找都是无类的,但是Windows的IP地址却保留了一个有类特性,那就是保留了新添加IP地址主类的广播地址。对于一种网络设备OS,比如Cisco 以及H3C VRP,分类IP以及分类路由还是可以启用的。说实话,随着IP管理平面的发展,无类IP将逐步取代有类IP,然而不可否认,现如今,某种特定的人工干预情况下,使用分类IP会提高效率,特别是管理员对IP地址分布了然于胸并且路由表项数目很大的时候。
2.动态路由以及路由的管理距离
在网络的原始社会,静态路由是唯一的选择,实际上有它就够了,因为那时的互联网也不过超不出两纵两横的规模,节点最大出度入读不会超过4,甚至只有2。管理员一般都可以把这张网络完全记在心里或者本子上。但是随着网络规模的扩展,静态路由便成了牵一发而动全身的瓶颈,在一个大型网络中,如果更改一个IP地址或者断掉一条链路,需要多么高强度的人工干预啊,事实上,即便出动一个团,也无法监控网络拓扑的更改。动态路由就是这么被呼唤出来的。
动态路由是来帮管理员忙的,减轻他们配置静态路由的负担!动态路由有多种,它们使用了不同的路由协议,目的只有一个,可以动态算出到达连通网络中任意节点的最短距离。不同的算法基本可以分为距离矢量算法和链路状态算法。
2.1.距离矢量算法
这种算法就是在这个网络的所有路由器节点之间进行运算的,是一种分布式算法。可以设想每一个路由器是一个点,连接路由器的链路是连接点的边,所有节点一起开始计算,直到一个稳定的状态。计算的方法就是信息不断在节点间通过边来传递,所使用的是分布式Dijkstra算法,因为每一个节点都不是根据自己所掌握的信息自己算出最短路径的,而是通过别人给自己的信息计算最短路径的。
由于每一个节点都参与了计算-仅仅是与相邻节点交互,在相邻节点的计算结果基础上,且互相依赖,因此一旦有拓扑变更,信息依赖链断裂,就不得不重来开始一次运算,因此距离矢量算法的收敛速度是比较慢的。
2.2.链路状态算法
这种算法是在每一台路由器节点上独立计算的,是一种集中式算法。但是要想进行集中运算,必须要事先有必要的且完整的信息,因此在计算开始之前,必须进行信息同步,当所有节点掌握的信息达到一致后,计算在各个节点分别独立地进行。发生拓扑变更时,只需要检测到且同步一下发生改变的部分即可,重新计算仅仅在必要时进行,且无需全体参与。
由于每一个节点独立运算,和信息(链路状态)的同步分离,相关节点的计算可以在链路状态信息同步后一起同时进行,而不像距离向量那种分布式算法那样必须依赖邻居的计算结果,那种情况算法本身就要同步,在前一个节点计算完成前,后一个节点无法计算。因此链路状态协议收敛比较快。
2.3.可信度与可依赖性
存在多种多样的动态路由协议。如果多种协议同时发现了到达同一目标的多条路径怎么办?根据对算法的评估结果,引出一个管理距离的概念。对算法进行评估要比直接设置路由优先级要好,如果说到达网络A使用RIP生成的路由,到达网路B使用OSPF生成的路由,那一定是极其的混乱,所以就分离出了管理距离。某种动态路由协议生成的路由就是比别的协议生成的要好,这是对算法进行评估的结果,评估点包括但不限于收敛速度。
管理距离是一种硬性的优先级,也就是说,管理距离偏高的路由只是一种备选路由,只要低管理距离的路由存在,高管理距离的路由将永远不会被使用。同样的,路由优先级也是这样一种硬性优先级。
使用设计良好的用户态程序,可以将管理距离和路由优先级统一成路由项的一个字段。
3.路由的度量和优先级
刚说过管理距离,现在看路由优先级。如果查到了同一目标的多个路由,首先应用管理距离低的,如果管理距离低的有多条,那么就用优先级高(数值低的)的。路由优先级只是和管理距离不同的优先级层次而已。管理距离标示生成该路由的程序的可信度,而此处的路由优先级标示路由的度量,即该条路由的代价或者路由的好坏,也称做Metric值。
Linux在添加路由时,如果目标相同,就会基于你设置的Metric值来排序,这样,Metric比较小的路由就会排在前面,而的路由查找是在最长掩码匹配的基础上进行第一次匹配,即只要有符合的就会跳出来输出结果。
3.1.关于“跃点”
如果man一下Linux的route命令,就会出现:
Metric The 'distance' to the target (usually counted in hops). It is not used by recent kernels, but may be needed by
routing daemons.
是的,如今的Linux内核上已经没有“跃点”了,但是Windows上有,就在你配置网卡IP地址的时候,在“高级”里面有一个“自动跃点计数”的选框,自动跃点计数一般就是20,你也可以手工写入一个值。这个值的含义其实就是你配置的IP地址生效的时候,内核生成的直连路由的Metric值,Linux内核将这个配置去掉了,也就是说,直连路由的Metric为默认值0。“跃点”这个翻译实在是不太好,叫做接口代价或许更加好一点吧。
4.Linux路由的metrics
最后有一个Linux路由配置的问题。内核结构体fib_info中的字段名字真的在误导人啊!其中的fib_priority其实对应的是iproute2中的metric,而其中的fib_metrics(注意复数)实际上和常规意义上理解的路由metric没有关系,它仅仅指示的是该条路由的某些特征计数值,比如该条路由的MTU。一条路由指的是到达目的地的路径,因此fib_info里面的fib_metrics数组都是该条路径的计数值,比如fib_metrics[RTAX_MTU-1]代表的就是该条路径的MTU,使用它就省去了MTU发现的过程了,也可以直接在端系统指导分片。这些计数值目的在于告诉行路者,即数据包这条路上的一些特征,以使端系统或者中间系统可以直接根据这些计数值初始化一些协议字段,如果没有这些计数值,可能需要协议来执行某种动作来“发现”这些值。
5.关于翻译
route,这个词无论如何都不宜翻译成“路由”,这么翻译太神秘了,实际上,google翻译的结果更好一些:路线,路径,航线。“路由”这个结果有点民国的意味,类似“记忆体”,“网路”一样。如果翻译为“路线”,“路径”的话,我想很多人就会明白“下一跳”的概念了。现在单说“下一跳”,即nexthop,注意hop这个词尾用的很妙,它直接“隐藏了下面的链路层”,就像飞过去了一样,如果写做next station,那么你就会想到“经过一段路”,一段好长好坎坷的路,到了下一站,公交车或者火车都可能钻山洞...实际上对于IP路由而言,这是事实!所以,我觉得,既然确定了nexthop这个词,那么route就应该翻译成“航线”才更加信,达,雅。
(文章内容如有侵权,敬请来信告知,我们将及时撤销)