问题回放

我在 CCR 2004 和 CHR 之间运行了一个 eBGP 会话,ROS 版本均为 7.20.5

以下是 CCR 的配置:

1
2
3
4
5
6
7
8
routing bgp instance
add as=0001 disabled=no name=bgp-instance-0001 router-id=1.1.1.1

/routing bgp connection
add afi=ip as=0001 input.affinity=alone input.filter=chain_from_hex \
instance=bgp-instance-0001 local.address=1.1.1.1 local.role=ebgp \
name=bgp-01 output.affinity=alone remote.address=1.1.1.2 remote.as=0000 \
routing-table=main

通过这个 BGP 会话,CHR 向我(CCR2004)通告了完整的路由表,此时我需要引入 input 过滤器来过滤一些不必要的路由。

以下是过滤器配置:

1
2
3
4
/routing filter rule
add chain=chain_from_hex disabled=no rule="if (dst == 0.0.0.0/0) { reject; }"
add chain=chain_from_hex comment=GitHub disabled=no rule="if (bgp-as-path \"^36459\") { accept; }"
add chain=chain_from_hex disabled=no rule="reject;"

我的期望是路由器应该只学习 AS_PATH 以 36459 开头的 BGP 路由。但是,我仍然收到完整的路由表。

我还尝试将输入过滤器设置为一个简单的规则:

1
add chain=chain_from_hex disabled=no rule="reject;"

按照预期,我应该不会学习到任何路由信息,因为他们会被过滤掉。但实际上仍然学习到了完整的路由表。

这时候,我还尝试对这个 BGP 会话不配置过滤器。现象依旧,我仍然可以学习到完整路由表。

这些行为让我很困惑,我知道 Mikrotik 在 v7 的 BGP 功能上引入了很多 features。这使得它似乎和 v6 版本的逻辑产生了很多出入。根据 RouterOS v7 版本的文档,当没有明确应用过滤器时,应该具有“全部拒绝”的默认行为。不应该学习完整的路由表。

问题解决

网络上很多例子要么上基于 ROSv6 的,要么没在使用 ASPath 的过滤器功能。

和 ROSv6 有些不同。在 BGP 会话中,我们可以指定 output.filter-chain、output.filter-select、input.filter 以及多个 input.accept-* 选项。

目前只有 input.accept-* 允许在消息解析和写入路由表之前直接过滤,使用 input.accept-* 过滤器可以大大减少路由器的内存占用,以及路由器中路由表的条目数。

其他的路由过滤器只能拒绝路由,拒绝的意思是路由条目仍然会保存到路由表中,但是状态显示为“not active, filtered”使之不生效。

这就和之前的现象对应上了,input.filter 会学习路由条目,但被过滤的条目不会被激活。

目前,只有 comunities、ext-comunities、large-comunities、nlri、unknown 这几个过滤器支持在写入路由表前将路由条目过滤掉。暂时不支持过滤 AS-PATH。

参考:

过滤器编码小技巧

ROS v7 的过滤器语法也进行了调整,使得写过滤器有点像编程的逻辑代码。这种改法在一定程度上增加了编写过滤器的复杂度,目前有个小工具可以辅助大家编写过滤器,它就是 “Filter Wizard”。

他就在 Routing -> Filter -> Rule -> 右侧 Action。

可以直接通过界面圈圈点点来实现对 OSPF 或 BGP 路由的过滤。

Filter Wizard