Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1332901
  • 博文数量: 436
  • 博客积分: 7854
  • 博客等级: 少将
  • 技术积分: 3225
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-18 16:30
文章分类

全部博文(436)

文章存档

2013年(2)

2012年(56)

2011年(70)

2010年(308)

分类: 网络与安全

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 对策略路由的支持

 1.2.1.              内置的路由表

 Linux 最多可以支持 255 张路由表,其中有 3 张表是内置的,不能删除。

255 本地路由表(Local table):本地接口地址,广播地址,已及NAT地址都放在这个表。该路由表由系统自动维护,管理员不能直接修改。

254 主路由表(Main table :如果没有指明路由所属的表,所有的路由都默认都放在这个表里。旧的路由工具(如route)所添加的路由都会加到这个表。

253 默认路由表 Default table):这个表的作用不清楚,一般也用不到

0 保留

1.2.2.              增加一个路由表

Linux 通过 /etc/iproute2/rt_tables 文件来管理路由表

要增加一个新的路由表 GPRS_TBL 可以这样:

echo “100  GPRS_TBL”     >>  /etc/iproute2/rt_tables

其中  100 是表的索引号, GPRS_TBL 是表的名称



1.2.3.              默认的路由策略

通过  ip rule ls 可以看到 Linux 默认的路由策略:

0:                            from all lookup local

32766:                   from all lookup main

32767:                   from all lookup default

可以看到:

1.       有三条策略,它们的优先级分别是  032766 32767

2.       这些策略都是根据源地址来选择路由表,它们适用于任何源地址的情况(from all);

3.       0 级的策略优先级最高,它选定 local 表,这适应于目的地址是本机地址或者广播地址的情况。

4.       32766 级的策略选定 main 表,它适用于目的地址为普通地址的情况,这张表也就是通过工具 ‘route’ 看到的那张路由表。

 

2.   应用策略路由

 2.1.                    多链路的需求


多链路情况下,通常有如下需求:

 1.       应用能指定从某个链路发送数据

2.       应用不指定链路的情况下,可从默认链路发送数据

3.       对于从某个链路上进入的数据包的响应,应仍从这个链路发送出去


单张路由表也可以满足这些需求,但缺点是理解起来不清晰,管理起来也有点混乱,而且可能无法满足将来更多的需求。

 

2.2.                    应用策略路由来满足多链路的需求

2.2.1.              多链路的典型场景

假设手机上同时存在两条链路:

1  GPRS 链路: 网络接口 gprs0IP 地址  10.0.0.2,网关地址 10.0.0.1

2  WiFi 链路:  网络接口 eth0IP 地址 20.0.0.2,网关地址 20.0.0.1

3  WiFi 链路是默认链路

再假设某个应用有如下多个 socket

1  Client socket S1,指定从 GPRS 链路收发数据

2  Client socket S2,指定从 WiFi 链路收发数据

3  Client socket S3,不指定链路,希望从默认链路收发数据

4  Server socket S4,它要求能接收从所有网络接口来的请求

2.2.2.              配置策略路由

思路是:

¨       为每条链路单独维护一张路由表

¨       同时维护默认的 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 10.0.0.0/24  dev gprs0 src 10.0.0.2 table GPRS_TBL

ip route add  default via  10.0.0.1 table GPRS_TBL

 

3  WiFi 表设置路由,包括网段路由和默认路由

ip route add 20.0.0.0/24  dev gprs0 src 20.0.0.2 table WIFI_TBL

ip route add  default via  20.0.0.1 table WIFI_TBL

 

4  main 表设置路由,包括网段路由和默认路由

ip route add 10.0.0.0/24  dev gprs0 src 10.0.0.2

ip route add 20.0.0.0/24  dev gprs0 src 20.0.0.2

ip route add default via 20.0.0.1

 

5  根据源地址来设置选择路由表的策略,也就是源地址路由策略

ip rule add from 10.0.0.2 table GPRS_TBL

ip rule add from 20.0.0.2 table WIFI_TBL

 

2.3.                    满足需求:应用指定从某个链路收发数据

这要求应用显示调用  bind() socket  的源地址绑定到指定网络接口的 IP 地址上

在这个场景中,应用需要把 S1 绑定到 10.0.0.2 上,把 S2 绑定到 20.0.0.2

在路由过程中,由于源地址已经确定,因此可以选择到对应的路由表,进而选择到正确的路由规则。

 

2.4.                    满足需求:应用不指定链路时,从默认链路收发数据

 对于很多 open source 或者第三方的应用,很可能不会调用 bind() 来指定源地址,而是交给内核选择源地址。

在这个场景中, S3 socket 没有调用绑定,它的源地址是 0.0.0.0,因此在路由过程中,会选择到 main 路由表。

main 表中查找路由时,主要有三种情况:

 1.       如果目的地址是  10.0.0.0/24 网段的,则选择第一条路由

2.       如果目的地址是  20.0.0.0/24 网段的,则选择第二条路由

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 作为一个策略加进来。

 

阅读(773) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~