概述

路由是指在网络中选择路径,将数据包从一个主机转移到另一个主机的过程。

路由如何工作

看一个基本的配置例子,说明路由是如何在两个本地网络之间转发数据包并传送到互联网的。

在这个设置中,有几个网络:

  • 两个客户网络(192.168.2.0/24和192.168.1.0/24);

  • 一个连接路由器的网络(172.16.1.0/30),通常称为主干网;

  • 最后一个网络(10.1.1.0/24)将网关路由器(Router1)连接到互联网。

Router2:

/ip address
add address=172.16.1.2/30 interface=ether1
add address=192.168.2.1/24 interface=bridge2

Router1(网关),ether1连接到互联网:

/ip address
add address=10.1.1.2/24 interface=ether1
add address=172.16.1.1/30 interface=ether2
add address=192.168.1.1/24 interface=bridge1

如果看一下Router1的路由表,可以看到该路由器只知道直接连接的网络。因此当LAN1的客户试图到达LAN2的客户(192.168.2.0/24)时,数据包将在路由器上被丢弃,因为目的地对特定的路由器来说是未知的:

[admin@MikroTik] > /ip/route> print
Flags: D - dynamic; X - disabled, I - inactive, A - active; C - connect, S - static, r - ri
p, b - bgp, o - ospf, d - dhcp, v - vpn
Columns: DST-ADDRESS, GATEWAY, Distance
    DST-ADDRESS    GATEWAY D
DAC 10.1.1.0/24    ether1  0
DAC 172.16.1.0/30  ether2  0
DAC 192.168.1.0/24 bridge1 0

为了解决这个问题,要添加一个路由,告诉路由器什么是网络中到达目的地的下一个设备。 在这个例子中,下一跳是Router2,所以要添加一个指向Router2连接地址的网关的路由:

[admin@MikroTik] > /ip route add dst-address=192.168.2.0/24 gateway=172.16.1.2
[admin@MikroTik] > /ip/route> print
Flags: D - dynamic; X - disabled, I - inactive, A - active; C - connect, S - static, r - ri
p, b - bgp, o - ospf, d - dhcp, v - vpn
Columns: DST-ADDRESS, GATEWAY,       Distance
        DST-ADDRESS    GATEWAY       D
    DAC 10.1.1.0/24    ether1        0
    DAC 172.16.1.0/30  ether2        0
    DAC 192.168.1.0/24 bridge1       0
0   AS  192.168.2.0/24 172.16.1.2

此时,来自LAN1的数据包成功转发到LAN2,但还没有结束。Router2不知道如何到达LAN1,所以来自LAN2的任何数据包都会在Router2上丢弃。

再看一下网络图,可以清楚地看到,Router2只有一个出口点。可以认为,所有其他未知的网络都应该通过与Router1的链接到达。最简单的方法是添加一个 default route: 要添加一个默认路由,设置目的地为0.0.0.0/0或留空:

/ip route add gateway=172.16.1.1

正如设置的例子中看到的,不同的路由组基于它们的来源和属性。

路由信息

RouterOS的路由信息由两个主要部分组成:

  • FIB (转发信息库),用于做出数据包转发决定。它包含必要的路由信息的副本。

  • RIB (路由信息库)包含所有从路由协议(连接的、静态的、BGP、RIP、OSPF)学到的前缀。

路由信息库

路由信息库是一个数据库,列出了特定网络目的地的条目及其网关(沿路下一个设备的地址或简称下一跳)。路由表中的一个这样的条目被称为route。

当一个数据包从一个网段传到另一个网段时,就发生了一跳。

默认情况下,所有的路由都被组织在一个主路由表中。可以设置一个以上的路由表,将在本文中进一步讨论,但现在为了简单起见,假设只有一个主路由表。

RIB表包含完整的路由信息,包括用户配置的静态路由和策略路由规则、从动态路由协议(RIP、OSPF、BGP)学到的路由信息,以及连接网络的信息。

它的目的不仅仅是存储路由,还包括过滤路由信息以计算每个目标前缀的最佳路由,建立和更新转发信息库,以及在不同路由协议之间分配路由。

连接的路由

连接的路由代表了可以直接到达主机的网络(直接附加到第二层广播域)。这些路由是为每个至少有一个启用的接口连接到它的IP网络自动创建的(如在 /ip address/ipv6 address 配置中指定)。RIB跟踪连接路由的状态,但不修改它们。对于每个连接的路由,有一个IP地址:

  • 连接路由的 dst-addressaddress 部分等于一个网络的IP地址项。

  • 连接路由的 dst-addressnetmask 部分等于IP地址项目的地址的netmask部分。

  • 连接路由的 网关 等于IP地址项的实际 _interface_(与接口相同,但桥接接口端口除外),代表一个可以到达特定第三层网络的直接连接主机的接口。

对于连接的路由,首选源 不再使用。FIB根据输出接口来选择源地址。这使得在ROS v6和更早的版本中的设置被认为是无效的。更多细节请见 示例

默认路由

当目的地不能被路由表中的任何其他路由解决时,就会使用默认路由。在RouterOS中,默认路由的 dst-address0.0.0.0/0 (用于IPv4)和 :/0 (用于IPv6)路由。如果路由表包含一个活跃的默认路由,那么在这个表中的路由表查询就不会失败。

通常情况下,家庭路由器的路由表只包含连接的网络和一个默认路由,将所有出站流量转发到ISP的网关:

[admin@TempTest] /ip/route> print
Flags: D - dynamic; X - disabled, I - inactive, A - active; C - connect, S - static, r - ri
p, b - bgp, o - ospf, d - dhcp, v - vpn
Columns: DST-ADDRESS, GATEWAY, Distance
#      DST-ADDRESS     GATEWAY      D
   DAd 0.0.0.0/0       10.155.125.1 1
   DAC 10.155.125.0/24 ether12      0
   DAC 192.168.1.0/24  vlan2        0

多路径(ECMP)路由

为了实现某些设置,如负载平衡,可能需要使用一个以上的路径到达指定的目的地。

ECMP(等价多路径)路由有多个网关(下一跳)值。所有可到达的下一跳都被复制到FIB,并用于转发数据包。

这些路由可以手动创建,也可以由任何动态路由协议(OSPF、BGP、RIP)动态创建。通往同一目的地的多条同样优先的路由将被分配+标志,并由RouterOS自动分组(见下面的例子)。

[admin@TempTest] /ip/route> print
Flags: D - DYNAMIC; I - INACTIVE, A - ACTIVE; C - CONNECT, S - STATIC, m - MODEM; + - ECMP
Columns: DST-ADDRESS, GATEWAY, DISTANCE
#       DST-ADDRESS      GATEWAY       D
0   AS+ 192.168.2.0/24   10.155.125.1  1
1   AS+ 192.168.2.0/24   172.16.1.2    1

路线选择

从各种路由协议和静态配置中收到的同一目的地的路由可能有多条,但只有一个(最佳)目的地可用于数据包的转发。为了确定最佳路径,RIB运行一个路由选择算法,从每个目的地的所有候选路由中挑选出最佳路由。

只有满足以下条件的路由才能参与路由选择过程:

  • 路由没有被禁用。

  • 如果路由的类型是 _unicast_,它必须至少有一个可到达的下一跳。(如果一个网关来自连接的网络,并且有连接的路由处于活动状态,那么该网关被认为是可到达的)

  • 路由不应该是合成的。

具有最低距离的候选路由成为活动路由。如果有一个以上的候选路由具有相同的距离,那么活动路由的选择是任意的。

联网查询

下一跳查询是路由选择过程的一部分。其主要目的是找到一个可直接到达的网关地址(下一跳)。只有在选择了一个有效的下一跳后,路由器才知道使用哪个接口来转发数据包。

如果路由的网关地址离这个路由器有几跳的距离(例如iBGP、多跳eBGP),那么下一跳的查找就变得更加复杂。在下一跳选择算法确定了可直接到达的网关地址(即时下一跳)之后,这样的路由会被安装在FIB中。

有必要限制可用于查找即时下一跳的路由集。例如,RIP或OSPF路由的Nexthop值应该是可以直接到达的,并且应该只使用连接的路由来查询。这是用范围和目标范围属性实现的。

范围大于最大接受值的路由不会被用于下一跳的查找。每个路由都在target-scope属性中为其nextthop指定最大接受范围值。这个属性的默认值只允许通过连接的路由来查找节点,但iBGP路由除外,它的默认值较大,也可以通过IGP和静态路由来查找节点。

RouterOS v7的nexthop查询有变化。

路由是按范围顺序处理的,对范围较大的路由的更新不能影响范围较小的路由的节点查询状态。

考虑一下 v6 的一个例子:

/ip route add dst-address=10.0.1.0/24 gateway=10.0.0.1
    scope=50 target-scope=30 comment=A
/ip route add dst-address=10.0.2.0/24 gateway=10.0.0.1
    scope=30 target-scope=20 comment=B
/ip route add dst-address=10.0.0.0/24 scope=20 gateway=WHATEVER
    comment=C

网关10.0.0.1通过C使用最小的引用范围(来自路由B的范围20)递归解析,两条路由都是活动的。现在我们同时改变A和B:

/ip route set A target-scope=10

突然间,对路由A的更新使得路由B的网关不活跃。这是因为在v6中,每个地址只有一个网关对象。

v7为每个地址保留多个网关对象,范围和网关检查的每个组合都有一个。

在v7中改变一个路由的目标范围或网关检查,不会影响其他路由,就像在v6中一样。在v7中,target-scope和gateway-check是内部附加在网关上的属性,而不是附加在路由上。

路由存储

路由信息的存储是为了在普通情况下尽可能少地占用内存。这些优化有非明显的最坏情况和对性能的影响。

所有的路由和网关都按前缀/地址保存在一个单一的层次结构中。

Dst [4]/0 1/0+4                             18  <-- number of prefixes
     ^  ^ ^ ^ ^
     |  | | | |
     |  | | | \- bytes taken by Route distinguisher or Interface Id
     |  | | \--- vrf/routing table
     |  | \----- AFI
     |  \------- netmask length of prefix
     \---------- bytes taken by prefix value

     [stuff subject to change without notice]

每个 "Dst" 都对应于一个独特的"dst-address "路由或网关地址。每个"Dst"也需要一个或多个 "T2Node" 对象。

所有具有相同 "dst-address "的路由被保存在Dst中,并按路由优先级排序。 注意: 最糟糕的情况是:有很多具有相同"dst-address "的路由真的很慢!即使它们是不活动的!因为更新一个有数万个元素的排序列表很慢

只有当路由属性改变时,路由顺序才会改变。如果路由变得活跃/不活跃,顺序不会改变。

每个路由有三份路由属性:

  • private – 在通过in-filters之前,从对等体收到的东西。

  • updated – 应用in-filters的结果。

  • current – 路由当前使用的属性是什么。

定期 update 属性会从 private 属性中计算出来。这发生在收到路由更新时,或者是in-filter被更新时。

当路由表被重新计算时,current 属性被设置为 updated 属性的值。

这意味着,通常情况下,如果没有改变路由属性的内置过滤器,privateupdatedcurrent 共享相同的值。

路由属性保存在几个组中:

  • L1数据 - 所有标志、额外属性列表、as-path;

  • L2数据 - nexthops、RIP、OSPF、BGP度量、路由标签、发起人等。

  • L3数据 - 距离、范围、内核类型、MPLS东西

  • 额外的属性 - 社区、发起人、聚集者-ID、群集-列表、未知数

例如,有许多不同的 distancescope 路由属性的组合,将使用更多的内存

使用regexp匹配社区或as-path会缓存结果,以加快过滤速度。每个as-path或社区值都有一个所有regexp的缓存,它按需填充匹配结果。

注意: 最坏的情况是:在in-filter中改变属性会使路由程序使用更多的内存 因为’私有’和’更新’的属性将是不同的! 有很多不同的表达式会使匹配速度变慢,并使用大量的内存! 因为每个值都会有一个有成千上万个条目的缓存!

关于路由协议使用的内存的详细信息可以在 /routing stats memory 菜单中看到

转发信息库

FIB(转发信息库)包含数据包转发所需的信息副本:

  • 所有活动路由

  • 策略路由规则

每个路由都有 dst-address 属性,它指定了这个路由可用于的所有目标地址。如果有几个路由适用于一个特定的IP地址,则使用最具体的一个(有最大的网络掩码)。这个操作(找到与给定地址相匹配的最具体的路由)被称为 "路由表查询"。

只有一个最佳路由可用于数据包的转发。在路由表包含有几条具有相同 dst-address 的路由的情况下,所有同样最好的路由被合并成一条 ECMP 路由。最佳路由被安装到FIB中,并被标记为 "活动"。

当转发决定使用额外的信息,如数据包的源地址,它被称为 策略路由。策略路由是以策略路由规则列表的形式实现的,它根据目的地址、源地址、源接口和数据包的路由标记(可由防火墙 mangle规则改变)选择不同的路由表。

Routing table lookup

FIB使用数据包的以下信息来确定其目的地:

  • 源地址

  • 目的地址

  • 源接口

  • 路由标记

可能的路由决定是

  • 本地接收数据包

  • 丢弃数据包(默许或向数据包的发送者发送ICMP消息)

  • 将数据包发送到特定接口上的特定IP地址

运行路由决策:

  • 检查数据包是否必须在本地交付(目的地址是路由器的地址)。

  • 处理隐含的策略路由规则

  • 处理由用户添加的策略路由规则

  • 处理隐含的万能规则,在 "主 "路由表中查找目的地。

  • 返回的结果是 "网络不可达"。

路由决定的结果可以是:

  • nexthop的IP地址+接口

  • 点对点接口

  • 本地发送

  • 丢弃

  • ICMP禁止

  • ICMP主机不可达

  • ICMP网络不可达

不匹配当前数据包的规则会被忽略。如果一个规则有动作:

  • dropunreachable,那么它将作为路由决策过程的结果返回。

  • lookup 数据包的目的地址就会在规则中指定的路由表中查找。如果查找失败(没有匹配数据包目的地址的路由),那么FIB就会进入下一条规则。

  • lookup-only 类似于 lookup,但如果表中没有任何路由与数据包匹配,则查找失败。

否则:

  • 如果该路由的类型是 黑洞禁止 或 _不可达_,那么返回这个动作作为路由决策结果;

  • 如果这是一个连接的路由或以一个接口为 网关 值的路由,那么返回这个接口和数据包的目的地址作为路由决策结果;

  • 如果这个路由有一个IP地址作为 网关 的值,那么返回这个地址和相关的接口作为路由决策结果;

  • 如果这个路由有多个nexthop的值,那么就以轮流的方式选择其中一个。

显示路由

在RouterOS中,你有三个菜单可以查看路由表中的路由的当前状态:

  • /ip route - 列出IPv4路由和基本属性

  • /ipv6路由 - 列出IPv6路由和基本属性

  • /routing route - 列出所有具有扩展属性的路由

/routing route 菜单目前是只读的。要添加或删除路由,应该使用 /ip(ipv6)route 菜单。

示例输出

[admin@MikroTik] /ip/route> print
Flags: D - dynamic; X - disabled, I - inactive, A - active; C - connect, S - stati
c, r - rip, b - bgp, o - ospf, d - dhcp, v - vpn
Columns: DST-ADDRESS, GATEWAY, DIstance
#       DST-ADDRESS      GATEWAY      DI
0   XS   10.155.101.0/24  1.1.1.10
1   XS                    11.11.11.10
   D d   0.0.0.0/0        10.155.101.1 10
2   AS   0.0.0.0/0        10.155.101.1 1
3   AS + 1.1.1.0/24       10.155.101.1 10
4   AS + 1.1.1.0/24       10.155.101.2 10
5   AS   8.8.8.8          2.2.2.2      1
   DAC   10.155.101.0/24  ether12      0


|  ||| |   |                 |         |
|  ||| |   |                 |         \----Distance
|  ||| |   |                 \--Configured gateway
|  ||| |   \-- dst prefix
|  ||| \----- ECMP flag
|  ||\------- protocol flag (bgp, osf,static,connected etc.)
|  |\-------- route status flag (active, inactive, disabled)
|  \--------- shows if route is dynamic
\----------- console order number (shown only for static editable routes)

routing route 的输出与ip route非常相似,只是它在一个菜单中显示所有地址族的路由,同时也列出了过滤的路由。

[admin@MikroTik] /routing/route> print
Flags: X - disabled, I - inactive, F - filtered, U - unreachable, A - active; c - connect, s - static,
r - rip, b - bgp, o - ospf, d - dhcp, v - vpn, a - ldp-address, l - ldp-mapping
Columns: DST-ADDRESS, GATEWAY, DIStance, SCOpe, TARget-scope, IMMEDIATE-GW
     DST-ADDRESS            GATEWAY      DIS SCO TAR IMMEDIATE-GW
Xs   10.155.101.0/24
Xs
d    0.0.0.0/0              10.155.101.1 10  30  10  10.155.101.1%ether12
As   0.0.0.0/0              10.155.101.1 1   30  10  10.155.101.1%ether12
As   1.1.1.0/24             10.155.101.1 10  30  10  10.155.101.1%ether12
As   8.8.8.8                2.2.2.2      1   254 254 10.155.101.1%ether12
Ac   10.155.101.0/24        ether12      0   10      ether12
Ic   2001:db8:2::/64        ether2       0   10
Io   2001:db8:3::/64        ether12      110 20  10
Ic   fe80::%ether2/64       ether2       0   10
Ac   fe80::%ether12/64      ether12      0   10      ether12
Ac   fe80::%bridge-main/64  bridge-main  0   10      bridge-main
A    ether12                             0   250
A    bridge-main                         0   250

Routing route print detail 显示更多的高级信息,对调试有用。

[admin@MikroTik] /routing route> print detail
Flags: X - disabled, I - inactive, F - filtered, U - unreachable, A - active;
c - connect, s - static, r - rip, b - bgp, o - ospf, d - dhcp, v - vpn, a - ldp-address, l - ldp-ma>
+ - ecmp
Xs dst-address=10.155.101.0/24
Xs
d afi=ip4 contribution=best-candidate dst-address=0.0.0.0/0 gateway=10.155.101.1
immediate-gw=10.155.101.1%ether12 distance=10 scope=30 target-scope=10
belongs-to="DHCP route" mpls.in-label=0 .out-label=0 debug.fwp-ptr=0x201C2000

As afi=ip4 contribution=active dst-address=0.0.0.0/0 gateway=10.155.101.1
immediate-gw=10.155.101.1%ether12 distance=1 scope=30 target-scope=10
belongs-to="Static route" mpls.in-label=0 .out-label=0 debug.fwp-ptr=0x201C2000