Quagga OSPF DR/BDR 不匹配:丢失路由

网络工程 路由 虚拟专用网 ospf 第3层 斑驴
2021-07-27 05:37:01

我在 OSPF over DMVPN 环境中遇到路由丢失问题。我正在运行带有 Quagga 0.99.22.4 和 OpenNHRP 0.14.1 的 ubuntu 服务器 14.04。

虽然从技术上讲 DMVPN 网络是 NBMA 网络,但 NHRP 协议进行模拟广播(捕获多播流量,并复制到其他已知/配置节点的单播)。这允许将 DMVPN 子网配置为 OSPF 中的广播网络。这种配置是做动态辐条到辐条隧道的要求,而这又是我的项目的要求。

我不确定我面临的问题是 OSPF 设计缺陷还是 quagga 错误,但我一直无法想出正确的搜索短语组合来找到有类似问题的人。

在这个 DMVPN 网络上,我有三个路由器:两个数据中心各有一个集线器节点,分支中有一个分支节点(当我将它们迁移到 DMVPN 时,会有很多很多分支)。每个节点后面都有几个可路由的子网,每个数据中心节点后面的子网可以通过其他路径相互路由。该设计允许任一集线器节点关闭,并且 OSPF 重新收敛以允许在整个 AS 中进行完全通信。这一切都完美无缺。

当我的 DMVPN 有部分连接时,问题就出现了。如果从辐条到主集线器(即 DR)存在通信问题,则辐条会从邻居表中删除该集线器,并假定辅助集线器为新的 DR。然而,在这种特殊情况下,辅助集线器与辐条和主集线器的通信都没有问题,因此仍然很高兴地认为自己BDR,而主要集线器是 DR。

在使用几个 iptables 规则来模拟这个问题以丢弃进出主集线器的流量时,我可以看到辐条内主集线器的失效计时器到期,并且在那一刻 quagga 从辐条的路由表中删除所有 ospf 路由。

从辐条中,我仍然可以看到与辅助集线器完全邻接的邻居关系,并且辐条假定该集线器现在是 DR(请注意,我已经手动更改了路由器 ID、主机名和地址):

spoke-router# sh ip ospf neigh

Neighbor ID     Pri State             Dead Time Address       Interface            RXmtL RqstL DBsmL
1.1.1.2         254 Full/DR           35.184s   10.10.10.2    gre1:10.10.10.3          0     0     0

如果我看看仍然可以与其他两个节点通信的辅助集线器,它讲述了一个不同的故事。

secondary-hub# sh ip ospf neigh gre1

Neighbor ID Pri State           Dead Time Address         Interface            RXmtL RqstL DBsmL
1.1.1.1     255 Full/DR         36.513s   10.10.10.1      gre1:10.10.10.2          0     0     0
1.1.1.3       0 Full/DROther    35.387s   10.10.10.3      gre1:10.10.10.2          0     0     0

您可能可以预测主集线器的邻居表:

primary-hub# sh ip ospf neigh gre1

Neighbor ID Pri State           Dead Time Address         Interface            RXmtL RqstL DBsmL
1.1.1.2     254 Full/Backup     37.067s   10.10.10.2      gre1:10.10.10.1          0     0     0

根据 tcpdump,我仍在辐条和辅助集线器之间发送和接收 hello 数据包。然而,在通信中断之后,hello 数据包包含一些有趣的数据。

自然,DR 和 BDR 地址不匹配,我只能假设这就是分支路由器删除所有 ospf 学习路由的原因。辐条路由器的 hello 数据包将 DRBDR 列为10.10.10.2(我对 OSPF 的有限了解使我假设从它的角度来看,BDR 应该设置为0.0.0.0)。辅助集线器的 hello 数据包10.10.10.1列为 DR 和0.0.0.0BDR(同样,从它的角度来看,我会假设 BDR 将列为自身:10.10.10.2。这是通信失败之前的情况)。

因此,您可以看到这有点令人沮丧,因为辐条路由器仍然有一条通过辅助集线器到达整个 AS 的完全可行的路径,但 OSPF 完全丢弃了所有已知路由以到达那里。

谁能告诉我这是OSPF的缺点还是quagga bug?是否有配置设置允许我忽略 hello 数据包中不匹配的 DR/BDR?那会比它的价值更危险吗?

我知道我可以通过在每个数据中心执行一个只有一个 DR 的双云 DMVPN 来解决这个问题,但这需要更多的复杂性、管理开销和性能开销。如果可能的话,我真的更愿意坚持使用单云双集线器部署。

如果您需要我提供更多信息,请告诉我!(我尝试创建 DMVPN 作为标签,但我在这里还没有足够的声誉。)

快速说明:

show ip ospf database在分支路由器上发出 a仍然显示整个 AS 的完整链路状态数据库,但 quagga 仍然没有将路由提交到内核路由表。

更多信息:

从分支路由器的角度来看 OSPF Hello 数据包的 tcpdump(手动更改 IP 地址和路由器 ID,单独复制/粘贴,因此忽略时间戳):

21:13:43.643160 IP (tos 0xc0, ttl 1, id 25083, offset 0, flags [none], proto OSPF (89), length 68)
10.10.10.3 > 224.0.0.5: OSPFv2, Hello, length 48
Router-ID 1.1.1.3, Backbone Area, Authentication Type: none (0)
Options [External]
  Hello Timer 10s, Dead Timer 40s, Mask 255.255.255.0, Priority 0
  Designated Router 10.10.10.2, Backup Designated Router 10.10.10.2
  Neighbor List:
    1.1.1.2
21:13:37.736761 IP (tos 0xc0, ttl 1, id 32711, offset 0, flags [none], proto OSPF (89), length 72)
10.10.10.2 > 224.0.0.5: OSPFv2, Hello, length 52
Router-ID 1.1.1.2, Backbone Area, Authentication Type: none (0)
Options [External]
  Hello Timer 10s, Dead Timer 40s, Mask 255.255.255.0, Priority 254
  Designated Router 10.10.10.1
  Neighbor List:
    1.1.1.1
    1.1.1.3

另一个编辑:

我能够将 Cisco 2801 作为上述 DMVPN 拓扑中的另一个辐条引入。模拟部分连接会导致Cisco 辐条上的行为与我在 Quagga 辐条上的体验完全相同一直到 Cisco 和辅助集线器之间的 hello 数据包的内容。

是的,更多编辑:

在看到辅助集线器的 hello 数据包的内容发生变化后,即使它是连接性的没有改变,我想尝试不同的 OSPF 实现。具体而言,在模拟通信故障期间,辅助集线器的 hello 数据包已将主集线器列为 DR,而没有将任何内容列为 BDR。即使它很高兴仍然充当 BDR。我的想法是,也许不同的 OSPF 实现仍会在它的 hello 数据包中发送正确的信息。我尝试按照其中一个答案中的建议使用“bird”,但是它不允许我覆盖 NBMA 网络类型进行广播,因此它不会参与我的 OSPF 环境。所以接下来的测试是将 Cisco 路由器配置为辅助集线器。我经历了所有设置的过程,然后模拟了通信失败。

正如我所怀疑的那样,从它的角度来看,Cisco 路由器仍然正确地宣传了它的 hello 数据包:主集线器作为 DR,辅助集线器作为 BDR。我希望在来自辐条的 hello 数据包中至少有两个正确匹配(都设置到辅助集线器,记住)足以让辐条路由器将路由安装到内核以允许流量流动通过辅助集线器到达网络的其余部分。不幸的是,情况并非如此。

应要求提供更多详细信息:

              xxxxxxx xxxx xx                   xxxxxxx xxxx xx
            xx              xxxx              xx              xxxx
            xx                 xxx            xx                 xxx
              x   Other Subnets  +--------------+   Other Subnets  x
               xx               xx               xx               xx
                 xxxxxxx+xxxxxxxx                 xxxxxxx+xxxxxxxx
                        |                                |
               +--------+--------+               +-------+----------+
               |                 |               |                  |
               |  Primary Hub    |               |  Secondary Hub   |
               |  id: 1.1.1.1    |               |  id: 1.1.1.2     |
               |                 |               |                  |
               +------+----------+               +-----------+------+
                      | .1                               .2  |
                      |        xxxxx xx                      |
                      |       xxxxxxx xxxx xx                |
                      |     xx              xxxx             |
                      |     xx                 xxx           |
                      +------+x    DMVPN Cloud   +-----------+
                              xxx  10.10.10.0/24 x
                                xx               xx
                                 xxxxxxx++xxxxxxxx
                                        |
                                        |
                                        | .3
                             +----------+-----------+
                             |                      |
                             |                      |
                             |     Spoke            |
                             |     id: 1.1.1.3      |
                             |                      |
                             |                      |
                             +----------------------+

连接到 DMVPN 子网的所有接口都是“gre1”。是的,在 GRE 子网层查看此图时,该图确实如此简单。辐条后面也有可路由的存根网络。我可以看到 OSPF 的设计和不同实现可能从未考虑单个广播域上节点到节点故障从物理上讲,在本地第 2 层网络中,这种类型的故障极不可能发生……可能但不太可能。但是因为在这种情况下广播域是虚拟的,并且在 Internet 上扩展,上面描述的故障场景的可能性要大得多(我在过去一年左右的时间里见过两次)。请记住,从 OSPF 的角度来看,DMVPN 只是用作传输网络的普通第 2 层广播域。

DMVPN 有两个主要目的。一是减轻枢纽站点的配置和维护负担。如果需要或需要,您实际上可以在动态 IP 上运行分支,并且集线器只需要一个配置……而不是每个分支都需要一个配置。其次是该技术允许动态建立直接的加密的通过互联网进行辐条连接(即使是动态 IP 上的分支)。本质上是一个全网状 VPN,没有全网状配置的噩梦。这两个目的对这个项目都很重要,因为当我将这个网络从一个辐条扩展到 80 个辐条时,我不会有那么高的管理负担。而且,当一个分支通过 VoIP 呼叫另一个分支时,媒体数据包将采用尽可能短的路径,而不必通过中心站点发夹。

为了让 OSPF 正确建立直接路由,GRE 子网必须充当虚拟广播域。允许它在互联网上工作的是 NHRP 协议,为了论证,可以将其视为第 3 层到第 3 层 arp。

根据要求,以下是相关的 OSPF 配置:

辐:

router ospf
 ospf router-id 1.1.1.3
 auto-cost reference-bandwidth 1024
 passive-interface default
 no passive-interface gre1
 network <branch-subnet>/24 area 0.0.0.0
 network 10.10.10.0/24 area 0.0.0.0

主要枢纽:

router ospf
 ospf router-id 1.1.1.1
 auto-cost reference-bandwidth 1024
 passive-interface default
 no passive-interface eth0
 no passive-interface gre1
 network 10.10.10.0/24 area 0.0.0.0
 network <primary-transit-supernet>/26 area 0.0.0.0

次要枢纽:

router ospf
 ospf router-id 1.1.1.2
 auto-cost reference-bandwidth 1024
 passive-interface default
 no passive-interface eth0
 no passive-interface gre1
 network 10.10.10.0/24 area 0.0.0.0
 network <secondary-transit-supernet>/26 area 0.0.0.0
3个回答

要直接回答您的问题,这是 OSPF 的预期行为,而不是 Quagga 中的错误。

首先,让我们看一下 RFC 的 DR/BDR 部分。

Designated Router
    The Designated Router selected for the attached network.  The
    Designated Router is selected on all broadcast and NBMA networks
    by the Hello Protocol.  Two pieces of identification are kept
    for the Designated Router: its Router ID and its IP interface
    address on the network.  The Designated Router advertises link
    state for the network; this network-LSA is labelled with the
    Designated Router's IP address.  The Designated Router is
    initialized to 0.0.0.0, which indicates the lack of a Designated
    Router.
Backup Designated Router
    The Backup Designated Router is also selected on all broadcast
    and NBMA networks by the Hello Protocol.  All routers on the
    attached network become adjacent to both the Designated Router
    and the Backup Designated Router.  The Backup Designated Router
    becomes Designated Router when the current Designated Router
    fails.  The Backup Designated Router is initialized to 0.0.0.0,
    indicating the lack of a Backup Designated Router.

如果Hello报文头中的BDR字段设置为0.0.0.0,则表示您没有选举BDR。

在您的情况下,这是因为您将其他路由器的优先级设置为 0,这使得路由器没有资格成为 BDR(这就是您看到“DROther”而不是“BDR”的原因)。您只需要将其他路由器的优先级设置为不为 0 的值。

这是 RFC 中的另一篇文章,了解更多上下文。

Router Priority
    An 8-bit unsigned integer.  When two routers attached to a
    network both attempt to become Designated Router, the one with
    the highest Router Priority takes precedence.  A router whose
    Router Priority is set to 0 is ineligible to become Designated
    Router on the attached network.  Advertised in Hello packets
    sent out this interface.

https://www.ietf.org/rfc/rfc2328.txt

我被要求提供这个问题的答案,以关闭它。我可能对细节有点模糊,因为我们现在已经接近 3 年前了。

基本上我们解决了这个问题。我们最终将所需的代码更改添加到了bird(感谢@drookie的建议),并切换到使用它。我们喜欢这样一个事实,即它是一个带有配置文件的 *nix 风格的服务(使配置管理更容易),而不是一个 cisco 模拟器。

我不记得我们是否曾经用 Bird 测试过这种确切的失败场景,但我猜我们已经测试过了,它以类似的方式失败了,因为我们最终创建了一个双层 dmvpn。

每个虚拟广播域(DMVPN 云)在每个数据中心包含 2 个集线器(而不是如上图所示的一个集线器),每个集线器都位于不同的 Internet 子网上,以防止出现一次性 Internet 路由问题。

我最初担心的管理负担减轻了,因为项目要求发生了变化,不再需要支持基于 cisco 的辐条,同时我们部署了一个组织范围的配置管理基础设施。

我希望我能对这个问题提供更直接的答案,但这就是我们解决这个问题的方式。感谢那些试图提供帮助的人。

Quagga 失去路线是我转向鸟的主要原因。一段时间以来,我运行着一个拥有数百个分支机构的企业 VPN,通过 ipsec/gre/任何点对点隧道连接。在一些分支机构,我使用的是 FreeBSD/quagga 设置。问题是 - 在像 A - B - C 这样的 OSPF 路由器链中,源自 A 的前缀出现在 B 上,但没有出现在 C 上。经过数月的挣扎,没有找到解决方案,并且看到这种情况自发地出现并自行清除quagga(并且没有像 Cisco 或 Juniper 这样的专有供应商)和各种前缀,我改用了 Bird。现在问题消失了。

你可以说这是蹩脚的。你可能会说我应该报告这个问题并帮助社区修复它。但对我来说,quagga 和它的 bugtracker 似乎在很长一段时间内都是某种后核沙漠,在那里可能会遇到零星的友好开发人员团体,但更有可能你会死于脱水或一些错误。Bird 的开发更加密集,它的邮件列表中包含更多的开发人员和实际帮助。