分类: 网络与安全
2010-01-15 13:07:26
应用策略路由,可以使多链路下的路由表管理更为清晰,而且能满足未来更为复杂的需求。
本文简单介绍策略路由,然后分析如何通过策略路由来管理多链路下的路由表。
1. 策略路由
1.1. 简介
传统的路由算法可以描述为:
根据数据包的目的地址,通过最长匹配算法,选择一条路由规则;路由的结果是找到下一跳地址以及对应的输出接口。
但是在复杂情况下,我们希望不仅仅根据目的地址,还能根据源地址,IP 协议,端口,TOS,甚至 packet payload 来进行路由选择,这就是策略路由。
Linux 从 2.1 内核就开始支持策略路由.
策略路由使用多张路由表,查找路由过程分为两个阶段:
1. 首先根据策略来确定路由表。策略主要包括源地址、目的地址、TOS 和 incoming interface。例如凡是从某个源地址来的数据包都要从某个路由表中查找路由。
2. 然后在这个选定的路由表中,根据源地址、目的地址、TOS 等来选定路由规则,这个过程和我们通常了解的路由查找过程是一致的。
1.2. Linux 对策略路由的支持
Linux 最多可以支持 255 张路由表,其中有 3 张表是内置的,不能删除。
表255 本地路由表(Local table):本地接口地址,广播地址,已及NAT地址都放在这个表。该路由表由系统自动维护,管理员不能直接修改。
表254 主路由表(Main table) :如果没有指明路由所属的表,所有的路由都默认都放在这个表里。旧的路由工具(如route)所添加的路由都会加到这个表。
表253 默认路由表 (Default table):这个表的作用不清楚,一般也用不到
表 0 保留
Linux 通过 /etc/iproute2/rt_tables 文件来管理路由表
要增加一个新的路由表 GPRS_TBL, 可以这样:
echo “100 GPRS_TBL” >> /etc/iproute2/rt_tables
其中 100 是表的索引号, GPRS_TBL 是表的名称
通过 ip rule ls 可以看到 Linux 默认的路由策略:
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
可以看到:
1. 有三条策略,它们的优先级分别是 0,32766 和 32767;
2. 这些策略都是根据源地址来选择路由表,它们适用于任何源地址的情况(from all);
3. 0 级的策略优先级最高,它选定 local 表,这适应于目的地址是本机地址或者广播地址的情况。
4. 32766 级的策略选定 main 表,它适用于目的地址为普通地址的情况,这张表也就是通过工具 ‘route’ 看到的那张路由表。
2. 应用策略路由
2.1. 多链路的需求
多链路情况下,通常有如下需求:
1. 应用能指定从某个链路发送数据
2. 应用不指定链路的情况下,可从默认链路发送数据
3. 对于从某个链路上进入的数据包的响应,应仍从这个链路发送出去
单张路由表也可以满足这些需求,但缺点是理解起来不清晰,管理起来也有点混乱,而且可能无法满足将来更多的需求。
2.2. 应用策略路由来满足多链路的需求
假设手机上同时存在两条链路:
1、 GPRS 链路: 网络接口 gprs0,IP 地址
2、 WiFi 链路: 网络接口 eth0,IP 地址
3、 WiFi 链路是默认链路
再假设某个应用有如下多个 socket:
1、 Client socket S1,指定从 GPRS 链路收发数据
2、 Client socket S2,指定从 WiFi 链路收发数据
3、 Client socket S3,不指定链路,希望从默认链路收发数据
4、 Server socket S4,它要求能接收从所有网络接口来的请求
思路是:
¨ 为每条链路单独维护一张路由表
¨ 同时维护默认的 main 表
¨ 根据数据包的源地址作为选择路由表的依据:
¨ 源地址是某条链路的地址时,选择链路所对应的路由表;
¨ 其它的源地址,选择默认的 main 表
下面针对这个场景,看看如何具体配置路由:
1、 添加两张路由表 GPRS_TBL 和 WIFI_TBL
echo 100 GPRS_TBL >> /etc/iproute2/rt_tables
echo 101 WIFI_TBL >> /etc/iproute2/rt_tables
2、 为 GPRS 表设置路由,包括网段路由和默认路由
ip route add
ip route add default via
3、 为 WiFi 表设置路由,包括网段路由和默认路由
ip route add
ip route add default via
4、 为 main 表设置路由,包括网段路由和默认路由
ip route add
ip route add
ip route add default vi
5、 根据源地址来设置选择路由表的策略,也就是源地址路由策略
ip rule add from
ip rule add from
2.3. 满足需求:应用指定从某个链路收发数据
这要求应用显示调用 bind(), 将 socket 的源地址绑定到指定网络接口的 IP 地址上
在这个场景中,应用需要把 S1 绑定到
在路由过程中,由于源地址已经确定,因此可以选择到对应的路由表,进而选择到正确的路由规则。
2.4. 满足需求:应用不指定链路时,从默认链路收发数据
对于很多 open source 或者第三方的应用,很可能不会调用 bind() 来指定源地址,而是交给内核选择源地址。
在这个场景中, S3 socket 没有调用绑定,它的源地址是
在 main 表中查找路由时,主要有三种情况:
1. 如果目的地址是
2. 如果目的地址是
3. 对于其它的目的地址,选择默认路由
2.5. 满足需求:对于从某个链路上进入的数据包的响应,应仍从这个链路发送出去
如果手机上存在某个 server,能为外部应用提供服务,就会有这种需求。对于 P2P 应用,以及将来可能出现的新的应用,这种情况是存在的。
在这个场景中的 S4 socket 就是这样的 server,它要求对于从 GPRS 链路上来的请求,响应数据应从 GPRS 链路上发送,而不至于从 WiFi 链路上发送;同样,对于从 WiFi 链路来的请求,响应应从 WiFi 链路发送。
对于这种响应包,因为是根据请求包来构造的,所以它的源地址是可以知道的,就是进入的网络接口的地址,因此这种响应包的路由过程和“应用指定链路”的情况是一样的。
2.6. 应用不指定链路,不允许收发数据
也可能会有这样的需求,对于不指定链路的应用,不允许收发数据。可以通过清空 main 表来在一定程度上满足这种需求。
3. 应用策略路由可能存在的问题
3.1 应用能否不调用 bind() ?
应用必须显式调用 bind(),能否省略这一步?例如根据 socket 所属的应用,找到对应的链路?
我认为这个 bind() 是无法避免的。
首先,一个应用可以有多个 socket,而不同的 socket 又可能希望从不同的链路发送数据,因此无法根据一个 socket 属于的应用程序来决定这个 socket 上的数据应该从哪个链路发送。
其次,应用必须通过一个显式的手段来指定 socket 对应的链路,不用 bind() 也必须有其它方式。通过 bind() 指定源地址,从而指定链路,只是一种方式而已。
3.2 两个链路具有相同的源地址怎么办?
在这个场景中,我们仅仅根据源地址作为策略来选择路由表,这要求不同的链路必须具有不同的源地址。但在一些特殊情况下,例如 GPRS 的 primary PDP 和second PDP,两个网络接口具有相同的地址,这时候无法仅仅通过源地址来区分不同的链路,怎么办?
因为 Primary PDP 和 Secondary PDP 具有不同的 TOS,因此可以将 TOS 作为一个策略加进来。