Linux操作系统被广泛应用于服务器、路由器,从家用小型无线路由器到连接ISP的企业路由器,再到连接国家/地区的Internet骨干网的核心路由器,涉及领域极广。至于路由器的重要性,可以毫不夸张地说,没有路由器,就不会有互联网。
一般位于同一个局域网的主机通过二/三层交换设备互联,主机之间直接进行二层通信,不需要路由功能。但是当局域网与互联网连接时就需要使用路由器,局域网内的主机访问互联网时,所有的流量均通过路由器转发。图1-1是一个典型的局域网组网,局域网内的计算机通过交换机直接连接到一起,局域网内所有计算机通过路由器R与外部Internet网络连接。
图1-1 典型局域网组网
一般情况下,局域网内的主机会将路由器作为自己的默认网关。
登录图1-1中的exp主机,查看该主机的路由信息,如下:
该命令输出了exp主机的所有路由条目,每行代表一条路由。
路由的参数说明如下。
➢ 目的网络(Destination和Genmask): 两个字段分别代表了目的网络和网络掩码,当目的地址和掩码全都是0时,此条目为默认路由。
➢ 出口设备(Iface): 用于指示内核,匹配此路由条目后,外发的报文从哪个接口设备发出。本例默认路由的出口设备为enp0s8。
➢ 网关(Gateway): 当外发报文的目的IP地址不是本地网络的地址时,需要通过网关进行转发,网关也被称为“下一跳”。对于本例来说,exp主机的默认网关为路由器R。
用户既可以使用route命令查看路由,也可以使用ip命令进行查看。ip命令呈现的结果更加详细,但是不如route命令呈现的结果直观。
下面是通过ip命令显示的路由信息:
对命令输出结果的说明如下。
➢命令输出的第一段表示目的网络,取值为default(与0.0.0.0/0等价)时表示默认路由。
➢ via 172.16.0.1: 表示匹配到本路由条目后通过哪个地址转发,即下一跳地址。
➢ dev enp0s8: 表示匹配到本条路由后通过enp0s8设备进行发送。
➢ proto kernel: 表示该路由条目由内核添加。
➢ scope link: 表示本路由的作用范围,取值为link时表示二层直连。
➢ src 172.16.0.3: 表示当外发报文匹配本路由条目时,如果用户未指定源地址,则内核使用src参数指定的地址作为源地址。
route和ip命令的执行效果差异较大,后面将根据需要使用route或者ip命令查看路由配置。
图1-2展示了exp主机发送给路由器R的IP报文,此报文经由路由器转发到外部网络。报文的目的mac地址为路由器R的P1端口的mac地址,源mac地址为exp主机设备的mac地址。
图1-2 exp主机发送给路由器R的IP报文
路由器R从P1端口收到报文后,再通过P2端口向外转发。路由器在执行转发时会修改图1-2中灰底的三个字段(不计校验和字段)。
➢将 目的mac地址 修改为路由器的下一跳IP地址所对应的mac地址。
➢将 源mac地址 修改为路由器的P2端口的mac地址。
➢使 TTL值 减1,并且每经过一次路由转发,均使TTL值减1。当TTL值减到0时,报文将被丢弃。
路由器R通过P2端口发出去的报文格式参考图1-3。
图1-3 路由器R的P2端口发出的报文
现在回到基本概念上,什么是路由(Route)?路由是将数据报文从源地址传递到目的地址的路径,数据报文会沿着这条路径传播,实现源和目的之间的双向通信。既然存在路径,那么必然存在选择路径的过程,选择路径的过程即为路由匹配过程,路由匹配的目的是找到接收此报文的下一跳地址。
Linux内核将报文转发所需的信息全部存储在一个名为 转发信息库 (Forwarding Information Base,FIB)的数据库中,这个数据库就是 路由表 (Route Table)。路由表是整个路由子系统的核心,内核根据路由表的配置转发报文。
内核收到报文后,根据报文的目的地址进行路由匹配(不启用策略路由)。
➢若报文的目的地址为本机,则将报文直接上送到内核协议栈进行处理。
➢若报文的目的地址不是本机,则根据目的地址查找路由,查找成功则将报文转发给下一跳地址,查找失败则将报文丢弃。
外发报文的路由查找过程与接收报文的流程类似,只不过外发报文的路由查找操作位于发送报文流程的最前端,内核首先根据报文的目的地址查找路由,查找成功后才继续转发报文。
用户可以使用“ip route”命令管理系统路由,执行增、删路由命令时不需要指定路由表。这可能令人误以为系统中只有一张路由表,但事实并非如此。开启策略路由功能后,Linux内核支持多达255张路由表,每张路由表有自己唯一的ID,配置文件/etc/iproute2/rt_tables描述了路由表ID和表名的映射关系。
以exp主机为例,配置文件内容如下:
默认情况下,Linux主机只有上述4张路由表,各表的功能说明见表1-1。
表1-1 Linux的默认路由表
1.main表
主路由表,描述了本机访问特定网络的路由。通过“ip route list [table<tableName>]”命令可以查看指定路由表的数据,如果命令中不指定“table<tableName>”参数,则默认操作main表。例如,下面两个命令均可以显示main表的数据:
对路由条目的说明如下。
➢第一条是默认路由,网关地址为172.16.0.1,匹配不到其他路由条目时就使用本条目。
➢第二条为172.16.0.0/24网络的直连路由,访问本网段的地址可直接进行二层通信。
➢第三条为172.24.1.0/24网络的单播路由,对于目的地址位于此网段的报文,其下一跳地址为172.24.1.0,从flannel.1设备发出。
2.local表
local表描述了本机IP地址和loopback地址的路由,这些路由仅在本机范围内有效。local表由内核自动维护,用户不可以向local表中添加路由条目,但是可以删除条目(注意删除操作有风险)。
下面是exp主机local表的数据:
与main表的内容相比,上述输出中多了第一列。其路由条目的第一列数据描述了本条路由的类型,有local和broadcast两种。
(1)local类型(本地类型)
local类型的路由可以按地址类型进行二次分类,第一类是loopback地址路由,第二类是配置在设备上的有效IP地址路由。
➢ loopback地址路由: 位于127.0.0.0/8网段的地址为loopback地址,内核将目的地址为此类地址的报文直接上送到协议栈处理。
➢ 本地地址路由: 对于配置在本机网络设备上的有效IP地址,如exp主机的enp0s8网卡配置的地址为172.16.0.3,内核会产生一条目标地址为172.16.0.3的本地路由。每个本地地址均对应一条scope值为host的本地路由,此类路由仅在本机范围内使用。
(2)broadcast类型(广播类型)
广播地址有两种:全1子网和全0子网。例如,enp0s8设备配置的IP地址为172.16.0.3/24,它的全0广播地址为172.16.0.0,全1广播地址为172.16.0.255。按照惯例,应用程序仅使用全1广播地址。
内核在生成路由时,可以同时生成全1广播地址和全0广播地址的路由:
广播类型的路由scope值为link,表示直连网络路由。关于scope字段的含义,请参考1.2.3节。
3.unspec表
unspec表并不是真正存在的表。查看此表的内容时,内核将呈现所有表的汇总数据。unspec表的ID为0,所以下面这三条命令是等价的:
在exp主机上执行以上命令,显示结果如下:
结果显示的是local表和main表的合集。
理解了路由表后,可以继续深入分析路由管理功能了。
路由管理分为通用路由管理和策略路由管理两部分。
➢ 通用路由: 根据报文的目标地址进行路由匹配,此过程仅涉及内核提供的默认路由表。
➢ 策略路由: 提供更多的高级选项。例如,可以根据源IP地址、端口号等信息进行路由匹配,以及指定路由表匹配等。
通用路由管理是基础,策略路由管理是锦上添花。本书将分两节来分别描述通用路由管理和策略路由管理。
首先介绍通用路由管理。
使用“ip route”命令执行通用路由管理,其命令帮助信息如下:
为方便理解路由原理,下面借助实验的方式来讲解,实验环境如图1-4所示。
图1-4 ip route实验组网
本网络由三台主机和两台交换机组成,组网情况说明如下。
➢每台主机均部署一个管理网络网卡enp0s3,占用10.0.0.0/24网段,外部管理系统通过此网段连接主机。所有主机的网关设置为10.0.0.1/24,关联enp0s3设备。
➢exp主机部署了一个业务网卡,设备名称为enp0s8,IP地址为172.16.0.3/24。
➢aux主机部署了两个业务网卡:设备enp0s8与exp主机二层直连,IP地址为172.16.0.4/24;设备enp0s9与aux主机二层直连,IP地址为192.168.20.3/24
。
➢aux2主机部署了一个业务网卡,设备名称为enp0s9,IP地址为192.168.20.1/24。
而“ip route”命令的参数比较多,这里选取部分常用的参数介绍。
1.type参数
type参数用于指定路由类型。
命令格式:
参数取值:
对type参数的说明见表1-2。
表1-2 “ip route”命令中type参数说明
下面对unicast、unreachable和prohibit三种类型的路由进行细化分析。
(1)unicast(单播路由)
其组网情况参考图1-4。exp主机在没有增加任何路由的前提下,无法通过ping命令成功访问aux主机的192.168.20.3地址。
其失败原因在于,exp主机的网关位于管理网络,而管理网络无法访问192.168.20.0/24网段。
对此的解决方案是,在exp主机上增加访问192.168.20.0/24网段的路由,并将下一跳地址设置为172.16.0.4。
执行“ip route add...”命令增加路由:
执行完成后查看exp主机的路由配置:
结果显示在系统中增加了一条目的网络为192.168.20.0/24的路由,下一跳地址为aux主机enp0s8设备的地址。
再次尝试执行“ping 192.168.20.3”命令,结果表示网络通信正常。
(2)unreachable/prohibit(网络不可达/禁止访问)
匹配到unreachable类型的路由后,内核向发送端发送ICMP unreachable消息。匹配到prohibit类型的路由后,内核向发送端发送ICMP communication administratively prohibited消息。下面使用图1-4中的三台主机验证unreachable/prohibit路由功能。
①实验1:exp通过aux访问aux2
在exp主机上增加访问192.168.20.0/24网段的路由,配置如下:
在aux2主机上增加访问172.16.0.0/24网段的路由,配置如下:
exp主机发起访问aux2主机的请求,“ping 192.168.20.1”命令的执行结果如下:
结果显示网络通信正常。exp主机向aux发送ping请求报文后,aux主机发现此报文需要转发,于是将报文转发给了aux2设备。回程报文的路径与此路径刚好相反,报文转发过程参考图1-5。
图1-5 ip route实验:网络通信正常
②实验2:exp通过aux访问aux2,aux设置unreachable路由
在aux主机上增加192.168.20.0/24网段地址的不可达路由,然后在exp主机上发起对192.168.20.1的ping测试,查看测试结果。
在aux主机上增加unreachable路由:
在exp主机上发起“ping 192.168.20.1”请求:
命令结果显示目标主机不可达(Destination Host Unreachable)。此应答报文是由aux主机发出的,所以ping报文并没有发送到aux2主机上,报文转发过程参考图1-6。
图1-6 ip route实验:aux配置unreachable路由
③实验3:exp通过aux访问aux2,aux设置prohibit路由
在aux主机上增加192.168.20.0/24网段的禁止访问路由,然后从exp主机发起对192.168.20.1的ping测试,查看测试结果。
在aux主机上增加如下配置:
在exp主机上发起“ping 192.168.20.1”请求:
结果显示目标主机不可访问(Packet filtered),报文转发过程参考图1-7。
图1-7 ip route实验:aux配置prohibit路由
2.dev参数
dev参数指定本路由关联的设备。
命令格式:
参数取值:NAME为设备名,如enp0s8。
配置示例:
此路由关联的设备为enp0s8。如果主机上只有一个网络设备二层直连172.16.0.4,那么此时可以不指定设备,内核会自动找到最合适的设备。
3.metric参数
metric参数表示路由度量值,系统根据此字段计算到达目的网络的最佳路径。metric值是一个数字,数值越小则表示网络质量越好,对应的优先级也越高。
命令格式:
下面是exp主机的路由配置:
前三条是系统自动生成的,metric值不为0;最后一条是用户手工配置的路由,配置时没有指定metric参数,所以最后一条的metric值为0。
4.protocol参数
protocol参数表示协议类型,标识当前路由条目是通过何种方式添加进来的,/etc/iproute2/rt_protos文件定义了协议类型列表。
命令格式:
参数取值:
RTPROTO参数取值说明如下。
1)kernel(内核),表示本条路由是内核自动配置的,用户配置一个新地址到接口设备上,内核就会自动添加一条kernel属性的路由。例如,向enp0s8设备增加地址172.16.1.3/24,系统自动增加如下路由:
2)boot(启动,默认值),表示此路由是在系统启动过程中添加进来的,或者是用户通过命令添加的非静态路由,此类型的路由在系统重启后会丢失。例如,向系统中增加一条目的网段为192.168.20.0/24、网关为172.16.0.4的路由,使用“ip route”命令查看路由信息,如果没有显示proto字段则表示该条目为boot类型。
3)static(静态),表示静态路由,此类型路由在系统重启后不会丢失。例如,向系统中增加一条目的网段为192.168.20.0/24、网关为172.16.0.4的路由,并设置路由属性为静态路由:
使用“ip route”命令查看路由信息,proto字段显示为static类型:
即便发生系统重启,此路由依旧存在。
4)NUMBER(路由类型编号),用于指定路由类型编号,在配置文件/etc/iproute2/rt_protos中保存了系统中支持的路由协议类型:
一般,除了static和boot类型外,其他类型很少使用,这里就不一一介绍了。
5.scope参数
scope参数表示路由范围,用来告诉内核本路由在什么范围内是有意义的。
命令格式:
常用的scope参数有以下几种。
1)host(主机范围),只用于本机内部通信的路由,不适用于本机以外的网络。
2)link(直连路由),用于本地二层直连网络。例如,本机地址是172.16.0.3/24,那么系统中存在一条目的网络为172.16.0.3/24、scope为link的路由:
此路由表示本网段二层直连,不需要下一跳。内核会自动为每个本机地址生成一条scope值为link的路由,用户无须关心。
3)global(全局路由),是指当目的网络不是本机的二层直连网络时,其路由范围为全局。
用户在配置路由时可以不指定scope,系统根据用户配置的目的网络自动设置scope,规则如下。
➢当用户配置路由的目的网络为本机内部地址时,scope取值为host。
➢当用户配置的网段不是本机的二层直连网络时,scope取值为global。
6.src参数
src参数表示匹配到本路由后,如果外发报文时未指定源地址,则内核自动使用src参数指定的地址作为源地址。
命令格式:
在enp0s8网卡上配置第二个地址172.16.0.103/24,此地址将作为辅地址,配置完成后呈现如下:
在exp主机上增加访问192.168.20.0/24的路由,并发起ping包测试:
在aux主机上进行抓包,抓包显示从exp主机发起的ping请求的源地址为172.16.0.3:
用户配置路由时,如果不指定源地址,则内核默认使用出口设备的主地址作为报文的源地址。如果用户期望使用辅地址作为源地址,那么可以在创建路由时通过src参数指定源地址。例如,下面的命令指定172.16.0.103地址为默认源地址:
查看系统生成的路由信息,源地址已经指定为172.16.0.103:
在exp上再次发起ping包测试,并在aux上执行抓包:
抓包显示ping请求的源地址为172.16.0.103。
7.via参数
via参数用于指定路由的下一跳地址,当scope参数为global时,路由必须设置via参数。外发报文匹配到本路由条目后,内核将此报文转发给下一跳。
命令格式:
在exp主机上配置两条路由,第一条路由同时指定下一跳地址和出口设备,第二条路由仅指定下一跳地址:
内核生成的两条路由如下:
配置第二条路由时并没有指定出口设备,但是因为指定了via参数,所以内核会自动判断访问172.16.0.4地址时从哪个设备发出报文,最终生成的路由中的dev参数同样是enp0s8。
8.nexthop参数
配置单路径路由(目的网络只有一个下一跳地址)时可以直接使用via参数指定下一跳地址。如果配置多路径路由(目的网络可以通过多个下一跳地址进行访问),则可以通过nexthop参数配置多个下一跳地址。
命令格式:
假设exp主机发送到192.168.20.0/24网络的报文,可以使用172.16.0.4和172.16.0.5作为下一跳地址,且两个地址的权重分别是1和2,则配置路由的命令:
查看执行结果:
权重参数表示匹配本路由时选中当前下一跳地址的概率。假设下一跳地址NH1的权重为w1,NH2的权重为w2,则发送报文的概率如下。
➢通过NH1发送报文的概率为w1/(w1+w2)×100%。
➢通过NH2发送报文的概率为w2/(w1+w2)×100%。
默认情况下,内核根据目的地址匹配路由,但是有些时候需要根据IP报文的其他参数来进行路由匹配。例如,ISP运营商希望根据“源IP地址+端口”的方式来判断当前报文归属哪个用户,然后对该用户的报文做特殊的路由管理。此功能可以通过策略路由实现。
策略路由提供了灵活的数据报文路由机制,其核心为策略路由数据库RPDB(Routing Policy DataBase)。该数据库中保存了报文匹配规则和对应的处理机制。在策略路由数据库中,每条规则都包括SELECTOR(选择子)和ACTION(动作)。
➢ SELECTOR: 报文匹配规则,可以根据报文的源地址、目的地址、入口设备、tos、fwmark等参数进行报文匹配。如果匹配成功,则执行该条目对应的动作;如果未匹配成功,则继续匹配下一优先级的规则。
➢ ACTION: 规则匹配成功后执行的动作,例如,指定使用哪个路由表执行路由匹配。
Linux启动时内核自动创建三条规则,用户可以使用“ip rule”命令查看规则列表。下面是exp主机的默认规则:
具体来说,每条规则由如下三段数据组成。
➢优先级:规则数据中第一列数字为优先级,通过“:”与后续字段分隔,值越小则优先级越高。
➢选择子:本例为“from all”,表示按源地址匹配,匹配所有报文。
➢动作:本例为“lookup xx”,表示通过哪张路由表执行路由查找。
内核按照规则的优先级顺序进行匹配,匹配成功后则执行该规则对应的动作。
1.ip rule命令说明
用户可以使用“ip rule”命令管理策略路由数据库,其命令帮助信息如下:
下面对其中的关键字段进行说明。
(1)SELECTOR
SELECTOR表示选择子,用于描述报文匹配规则。
命令格式:
可选择的操作类型参考表1-3。
表1-3 “ip rule”命令中SELECTOR参数介绍
(续)
(2)ACTION
ACTION用于描述规则匹配成功后执行的动作。
命令格式:
可选择的动作类型参考表1-4。
表1-4 “ip rule”命令中ACTION参数介绍
2.策略路由实验
(1)实验目的
验证系统是否按照规则优先级执行路由匹配。
(2)实验准备
继续使用1.2.3节中的组网,参考图1-4。在aux主机上增加192.168.20.0/24网段的unreachable和prohibit路由,分别放入不同的路由表。通过“ip rule”命令配置策略路由,内核根据策略路由选择路由表,验证通信情况。
(3)实验过程
1)在aux主机中增加路由。路由内容如下:
在main表中增加unreachable路由,在10号表中增加prohibit路由,查看路由表:
2)进行ping测试。目前路由规则数据库中只有默认规则,所以此时一定会匹配到main表中的路由。在exp主机上对192.168.20.1发起ping请求:
aux主机回复消息“Destination Host Unreachable”,证明匹配的是main表中的路由。此时路由表和路由规则的对应关系如图1-8所示。
图1-8 默认规则下路由表和路由规则的对应关系
没有任何规则引用10号路由表,所以table 10中的路由条目并不生效。
3)在aux主机上增加路由规则。增加匹配目的地址192.168.20.1/32的路由规则,该规则的动作是在10号路由表中执行路由查找。命令执行过程如下:
新增加的路由规则优先级为32765,增加完成后规则与路由表的关系如图1-9所示。新增加的规则将10号路由表的查找优先级提前到第二优先级上,也就是发往目的地址192.168.20.1的报文优先使用10号路由表的路由。
图1-9 增加新规则后路由表和路由规则的对应关系
4)再次在exp主机上执行ping测试。在exp主机上执行“ping 192.168.20.1”命令,此时exp主机回复消息“Packet filtered”,证明匹配的是10号路由表中的路由。
(4)实验总结
前面只是通过简单的例子了解了策略路由的基本用法,实际上策略路由的功能远不止这些。使用“ip rule”命令创建策略路由的灵活性很高,但是灵活性往往与性能成反比,路由规则越多,那么查找路由所需的时间就越长,所以如果没有特殊要求,则应尽量减少规则数。