上一讲我们讲了一个相对简单的情况,网络包出了网关只有一条路。但真实的网络世界是很复杂的,网络包除了网关会有很多条路可以走,那么到底选择走哪一条路呢?
如何配置路由器?
根据上一讲的内容,我们知道路由器就是一个网络设备,有多张网卡。当一个网络包从一个入口进来的时候,路由器会根据一个本地的路由表来决定如何正确地转发数据包。
一张路由表包含多条路由规则,每一条规则至少包含三项信息:
- 目的网络:这个包想去哪儿?
- 出口设备:将包从哪个口扔出去?
- 下一跳网关:下一个路由器的地址。
通过 route 命令和 ip route 命令可以进行查询或配置。
例如:
ip route add 10.10.10.0/24 via 10.10.11.1 dev eth0
这条命令说明要去10.10.10.0/24这个目标网络要从端口eth0出去,经过10.10.11.1。
这种配置方式的特点是根据目的IP地址来配置路由。
如何配置策略路由?
除了可以根据目的IP配置路由外,还可以根据多个参数配置路由,这就是策略路由。
可以配置多个路由表,可以根据源IP地址、入口设备、TOS等选择路由表,然后在路由表中查找路由。
例如:
ip rule add from 192.168.1.0/24 table 10
ip rule add from 192.168.2.0/24 table 20
表示从192.168.1.0/24这个网段来的网络包,使用table10路由表;从192.168.2.0/24这个网段来的,使用table20的路由表。
在一条路由规则中,可以走多条路径。例如:
ip route add default scope global nexthop via 10.10.10.1 weight 1 nexthop via 20.20.20.1 weight 2
下一跳有两个地方,分别是10.10.10.1和20.20.20.1,权重比为1:2。
我们举一个用到上述情况的例子。
房东从运营商拉了两根网线。这两根线分别属于两个运营商,一个带宽大,一个带宽小。
家里的网络就是普通的192.168.1.x/24。家里有两个租户,分别把线连到路由器上。两个租户的IP地址分别为192.168.1.101/24和192.168.1.102/24,网关是192.168.1.1/24。
运营商1给路由器分配的地址是183.134.189.34/32,而运营商里的网关是183.134.188.1/32。/32是一对一的意思。
运营商2给路由器分配的地址是60.190.27.190/30,运营商里的网关是60.190.27.189/30。
根据网络拓扑图,将路由器配置成这样:
$ ip route list table main
60.190.27.189/30 dev eth3 proto kernel scope link src 60.190.27.190
183.134.188.1 dev eth2 proto kernel scope link src 183.134.189.34
192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.1
127.0.0.0/8 dev lo scope link
default via 183.134.188.1 dev eth2
这些规则的含义如下:
- 如果去运营商二,走eth3;
- 如果去运营商一,走eth2;
- 如果访问内网,走eth1;
- 如果所有规则都匹配不上,走运营商1
问题来了,如果租户A不想多付钱,他说我对网速没什么要求,这种情况可以解决。
我们先添加一个路由表,名字叫usera。
# echo 200 usera >> /etc/iproute2/rt_tables
然后田添加一条规则:
# ip rule add from 192.168.1.101 table usera
从192.168.1.101来的包都查看usera这个路由表。
在usera这个路由表中添加规则:
# ip route add default via 60.190.27.189 dev eth3 table usera
# ip route flush cache
默认让租户A的数据包走慢的网络。
以上都是静态的路由,在网络环境简单的时候,还可以自己配置。但有时候网络环境复杂多变,如果使用静态路由一旦网络结构发生变化,让网络管理员手工修改路由实在是太复杂了,因为需要冬天路由算法。
动态路由算法
使用动态路由的路由器,可以根据路由协议生成动态路由表,随网络运行状态的变化而变化。
唐僧西天取经途中,要解决两大问题:一个是在每个国家如何找到正确的路径;一个是在国家之间如何找到正确的路径。
无论是国家内部还是外部,我们都可以将复杂的路径,抽象为一种叫做图的数据结构。唐僧肯定希望走的路越短越好,因此问题成了如何在图中找到最短路径的问题。
我们知道求最短路径常用的有两种方法,一种是Bellman-Ford算法,一种是Dijkstra算法。
1. 距离矢量路由算法
第一大类算法称为距离矢量路由(distance vector routing)。它是基于Bellman-Ford算法的。
这种算法的基本思路是,每个路由器保存一个路由表,路由表包含多行,每行对应网络中的一个路由器。每一行包含两部分信息,一个是要到目标路由器,从哪条线出去,另一个是到目标路由器的距离。
每个路由器是知道全局信息的。这个信息如何更新呢?每个路由器都知道自己和邻居之间的距离,每过几秒,每个路由器都将自己知道的到达所有路由器的距离告知邻居,每个路由器也能从邻居那里得到类似的信息。
每个路由器根据收集的信息,计算和其他路由器的距离,比如自己的一个邻居距离目标路由器的距离是M,而自己距离邻居是N,则自己距离目标路由器是M+N。
这个算法比较简单,但是存在问题。
第一个问题是好消息传得快,坏消息传得慢。
如果一个路由器加入了一个网络,它的邻居很快就能发现它,然后将消息广播出去,不用一会,整个网络就都知道了。但是一旦这个路由器挂了,这个时候是没有广播的,其他路由器想向它传递消息的时候发现原来的道路到不了了,于是通过其他的路径访问,直到试遍了所有路径,才发现这个路由器是真挂了。
举个例子:
原来的网络只有A和B两个节点。A加入了网络,它的邻居B很快发现了它,于是将自己和A的距离设置为1,同样C也发现了A,于是将自己和A的距离设置为2。但是如果A挂掉了,情况就不妙了。B本来和A是邻居,发现连不上A了,但是C能连上,C和A的距离是2,于是将自己和A的距离设置为3。其实C的距离2是基于B和A的距离是1,自己和B的距离是1,推算出来的。C发现自己也连不上A了,并发现B设置为3,于是自己的距离改为4。这样数值会越来越大,直到超过一个阈值,才能断定A真的挂了。
这个算法的第二个问题是,每次发送的时候,要发送整个全局路由表。网络如果很大,谁也受不了,最早的路由协议RIP就是使用这个算法。它适用于小型网络。
以上两个问题,限制了距离矢量路由的网络规模。
2. 链路状态路由算法
第二大类算法是链路状态路由算法(link state routing),基于Dijkstra算法。
这种算法的基本思路是:当一个路由器启动的时候,首先发现邻居,向邻居say hello,邻居都回复。然后计算和邻居的距离,发送一个echo,要求马上返回,除以二就是距离。然后将自己和邻居之间的链路状态包广播出去,发送到整个网络的每个路由器。这样每个路由器都能收到它和邻居之间的关系的信息。因而,每个路由器都能在本地构建一个完整的图,然后针对这个图使用Dijkstra算法,找到两点之间的最短路径。
网络更新时,不像距离矢量路由那样发送整个路由表。链路状态协议只广播更新的网络拓扑,这使得更新信息更小。一旦一个路由器挂了,它的邻居会广播这个消息,可以使得坏消息迅速收敛。
动态路由协议
1. 基于链路状态的路由算法OSPF
OSPF(Open Shortest Path First,开放式最短路径优先),是广泛应用在数据中心的协议。由于主要用在数据中心内部,用于路由决策,所以称为内部网关协议(Interior Gateway Protocol, 简称IGP)。
内部网关协议的重点就是找到最短的路径。在一个组织内部,路径最短往往最优。如果发现多个最短路径,可以在这多个路径中进行负载均衡,这称为等价路由。
有了等价路由,到一个地方有两个路西那,可以分摊流量,还可以一条路不通的时候走另外一条路。
2. 基于距离矢量的路由算法BGP
外网的路由协议,称为外网路由协议(Broder Gateway Protocol,简称BGP)。
每个数据中心都设置自己的策略。例如,哪些外部的IP可以让内部知晓,哪些内部的IP可以让外部知晓,哪些能通过,哪些不能通过。
在网络世界,分为许多自治系统AS(Autonomous System)。自治系统分几种类型:
- Stub AS:对外只有一个连接。这类AS不会传输其他AS的包。例如,个人的网络
- Multihomed AS:可能有多个连接连到其他AS,但是大多拒绝帮助其他的AS传包。例如一些大型公司的网络。
- Transit AS:有多个连接连到其他AS,并且可以帮助其他AS传输包。例如主干网。
每个自治系统都有边界路由器,通过它和外面的世界建立联系。
BGP分两类,eBGP和iBGP。自治系统间,边界路由器之间使用eBGP广播路由。内部路由器也需要访问其他的自治系统。边界路由器如何将BGP学习到的路由导入到内部网络呢?就是通过iBGP,使得内部的路由器能够找到到达外网目的地的最好的边界路由器。
BGP协议使用的算法是路径矢量路由协议(path-vector protocol)。它是距离矢量路由协议的升级版。
小结
- 路由分静态路由和动态路由,静态路由可以配置复杂的策略路由,控制转发策略;
- 动态路由主流算法有两种,距离矢量算法和链路状态算法。基于两种算法产生两种协议,BGP协议和OSPF协议。
1. 路由协议要在路由器之间交换信息,这些信息的交换需要走路由器吗?不是死锁了吗?
2. 路由器之间信息的交换使用什么协议呢?报文格式是什么样的呢?