我在 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 数据包将 DR和BDR 列为10.10.10.2
(我对 OSPF 的有限了解使我假设从它的角度来看,BDR 应该设置为0.0.0.0
)。辅助集线器的 hello 数据包10.10.10.1
列为 DR 和0.0.0.0
BDR(同样,从它的角度来看,我会假设 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