Route Selection and Filtering
MikroTik RouterOS 中的路由过滤使用类似脚本的语法来匹配前缀,并基于条件修改路由距离,其属性分为只读和可读/可写两类,供匹配器和动作使用。
路由选择与过滤
路由过滤
过滤语法
路由过滤规则使用类似脚本的语法。以下示例匹配来自子网 192.168.1.0/24 且前缀长度大于 24 的前缀,并将默认距离加 1。如果没有匹配,则将默认距离减 1。
/routing/filter/rule
add chain=myChain \
rule="if (dst in 192.168.1.0/24 && dst-len>24) {set distance +1; accept} else {set distance -1; accept}"
一条过滤规则可以由多个匹配器和动作组成:
if ( [matchers] ) { [actions] } else { [actions] }
属性有两种类型:
- 只读 — 值只读且不能重写的属性。它们只能由匹配器使用。
- 可读/可写 — 值可读且可写的属性。它们可以由过滤动作和匹配器使用。
仅对于数值属性,可读属性可以通过其他可读属性或使用布尔运算符的常量值进行匹配。
[matchers]:
[prop readable] [bool operator] [prop readable]
[actions]:
[action] [prop writeable] [value]
如果匹配器只有一种可能的操作,则不需要布尔运算符。
不带布尔运算符的示例:
if ( protocol connected ) { accept }
带布尔运算符的示例:
if ( bgp-med < 30 ) { accept }
对于可读标志属性,匹配器不需要布尔运算符或值。
if ( ospf-dn ) { reject }
信息
路由过滤链的默认动作是
reject。
只读属性
| Property | Type | Description |
|---|---|---|
| Numeric properties | ||
dst-len | 目标前缀长度 | |
bgp-path-len | BGP AS-PATH 的当前长度 | |
bgp-input-local-as | 前缀被发送到的本地对端的 AS 号 | |
bgp-input-remote-as | 前缀从其接收的远程对端的 AS 号 | |
bgp-output-local-as | 将通告该前缀的对端的 AS 号 | |
bgp-output-remote-as | 该前缀将被通告到的对端的 AS 号 | |
ospf-metric | 当前 OSPF 度量值 | |
ospf-tag | 当前 OSPF 标记 | |
rip-metric | 当前 RIP 度量值 | |
rip-tag | 当前 RIP 标记 | |
| Flag properties | ||
active | 指示该路由是否为活动路由 | |
bgp-atomic-aggregate | ||
bgp-communities-empty | 指示 BGP Communities 属性是否为空 | |
bgp-ext-communities-empty | 指示 BGP Extended Communities 属性是否为空 | |
bgp-large-communities-empty | 指示 BGP Large Communities 属性是否为空 | |
bgp-network | 指示该前缀是否源自 BGP networks | |
ospf-dn | 指示该 OSPF 路由是否设置了 DN 位。 | |
| Prefix properties | ||
dst | 目标 | |
ospf-fwd | 当前 OSPF 转发地址 | |
bgp-input-local-addr | 前缀被发送到的本地对端的 IP 地址 | |
bgp-input-remote-addr | 前缀从其接收的远程对端的 IP 地址 | |
bgp-output-local-addr | 将通告该前缀的对端的 IP 地址 | |
bgp-output-remote-addr | 该前缀将被通告到的对端的 IP 地址 | |
| Other Properties | ||
afi | ipv4 | ipv6 | l2vpn | l2vpn-cisco | vpnv4 | vpnv6 | 该路由的地址族。 |
bgp-as-path | numeric_regexp | AS path regexp matching |
bgp-as-path-slow-legacy | string_regexp | 已弃用。极其缓慢的旧式 AS path 匹配。此参数只应在从旧 ROS v6 配置迁移时作为临时匹配器使用。 Read more>> |
chain | chain_name | |
origin | string | 匹配路由的源实例,例如,它可以匹配从特定 OSPF 实例导入的路由:if (origin <instance_name>) {} |
ospf-type | ext1 | ext2 | inter | intra | nssa1 | nssa2 | OSPF 路由的类型:ext1 - 带 type1 度量的外部路由(Type 5 LSA)ext2 - 带 type2 度量的外部路由(Type 5 LSA)inter - 区域间路由(Type 3 LSA)intra - 区域内路由(Type 1/2 LSA)nssa1 - 带 type1 度量的 Type 7 LSAnssa2 - 带 type2 度量的 Type 7 LSA |
protocol | bgp | connected | dhcp | fantasy | modem | ospf | rip | static | slaac | vpn | 该路由从其导入的协议类型。 |
rpki | invalid | unknown | valid | unverified | 该前缀的 RPKI 验证状态 |
rtab | routing_table_name | 该路由从其导入的路由表名称 |
vrf | vrf_name | 该路由从其导入的 VRF 名称 |
可写属性
| Property | Type | Description |
|---|---|---|
| Numeric properties | ||
distance | 路由距离 | |
scope | ||
scope-target | 目标 scope | |
bgp-weight | BGP WEIGHT 属性 | |
bgp-med | BGP MED 属性是路由器本地的。它也会用于 iBGP 对端的输出。 | |
bgp-out-med | 要发送到远程对端的 BGP MED 属性。应在 eBGP 对端的输出链中使用。 | |
bgp-local-pref | BGP LOCALPREF 属性 | |
bgp-igp-metric | BGP IGP METRIC | |
bgp-path-peer-prepend | 前置最后接收到的远程对端的 ASN。如果该前缀源自本路由器,则此参数在路由器输出上不会做任何事,因为 ASN 尚不存在。 如果在 BGP 输入中用作匹配器,则可以过滤超过一定前置次数的前缀。例如,如果远程对端将其 ASN 前置 5 次,但我们希望最多允许前置 4 次 ASN,那么可以使用:if (bgp-path-peer-prepend > 4) {reject} 此参数还会覆盖从远程对端收到的任何前置,例如,如果远程对端将其 AS 前置 3 次,我们可以通过在 BGP 输入中设置 bgp-path-peer-prepend 1 来移除此前置 | |
bgp-path-prepend | 前置路由器的 ASN,应在 BGP 输出中使用。 | |
ospf-ext-metric | OSPF 外部路由度量值 | |
ospf-ext-tag | OSPF 外部路由标记 | |
rip-ext-metric | RIP 外部路由度量值 | |
rip-ext-tag | RIP 外部路由标记 | |
| Flag properties | ||
ospf-ext-dn | 外部 OSPF 路由的 DN 位 | |
blackhole | Blackhole 路由 | |
suppress-hw-offload | 是否 suppress L3 HW offloading | |
use-te-nexthop | ||
| Other properties | ||
gw | ipv4/6 address | IPv4/IPv6 地址或接口名称。在 BGP 输出的情况下,可以在以下配置中调整网关:是 BGP reflector且 nexthop-choice 设置为 propagate且不是 eBGP 且未设置 nexthop-choice=force-self。 |
gw-ll | ipv6 address | ipv6 链路本地 nexthop 属性。在 BGP 输出的情况下,可以在以下配置中调整网关:是 BGP reflector且 nexthop-choice 设置为 propagate且不是 eBGP 且未设置 nexthop-choice=force-self。 |
gw-interface | interface_name | 网关的接口部分。如果需要为 next-hop 附加特定接口,例如(1.2.3.4%ether1),则应使用此参数 |
gw-check | none | arp | icmp | bfd | bfd-mh | |
pref-src | ipv4/6 address | |
bgp-origin | igp | egp | incomplete | |
ospf-ext-fwd | ipv4/6 address | 外部 OSPF 路由的转发地址 |
ospf-ext-type | type1 | type2 | OSPF 外部路由类型 |
comment | string | |
bgp-communities | inline_community_set | community_list_name | BGP Communities 属性定义于 RFC 1997。每个 community 的大小为 32 位。 |
bgp-ext-communities | inline_ext_community_set | ext_community_list_name | BGP Extended Communities 属性定义于 RFC 4360。RouterOS 会解析 site-of-origin(前缀为 soo:)和 route-target(前缀为 rt:)扩展 community。例如,set bgp-ext-communities rt:1111:2.3.4.5; 可以设置/匹配 64 位十六进制的 RAW 扩展 community 值,例如,set bgp-ext-communities 0x.........; |
bgp-large-communities | inline_large_community_set | large_community_list_name | BGP Large Communities 属性定义于 RFC 8092。适用于包括 32 位 ASN 在内的所有 ASN。每个 community 长度为 12 字节,由 3 部分组成:global_admin:local_part_1:local_part_2。 |
命令
| Command | Params | Description |
|---|---|---|
accept | 接受匹配的前缀并停止处理该链。 | |
reject | 拒绝匹配的前缀并停止处理该链,该前缀将作为 "filtered" 存储在内存中,不会成为被选为最佳路径的候选。 | |
return | 返回到父链 | |
jump | jump chain_name | 跳转到指定的链 |
unset | unset prop_name | 用于取消设置以下属性的值:pref-src, bgp-med, bgp-out-med, bgp-local-pref |
append | 追加到列表或字符串的末尾。可以追加以下属性值:bgp-communities, bgp-ext-communities, bgp-large-communities, comment | |
filter | delete 动作的逆操作(删除除指定值之外的所有内容)。可以过滤以下属性的值:bgp-communities, bgp-ext-communities, bgp-large-communities | |
delete | 删除指定属性的值。可以删除以下属性的值:bgp-communities, bgp-ext-communities, bgp-large-communities | |
set | prop_writeable value | 该命令用于为可写属性设置新值。值可以从其他可读且类型匹配的属性中设置。对于数值属性,可以在值前添加 +/-,这会将当前属性值增加或减少给定数量。例如,set bgp-local-pref +1 会将当前 LOCAL_PREF 加一,或者从另一个可读数值属性中提取值,set distance +ospf-ext-metric |
rpki-verify | rpki_group_name | 从指定的 RPKI 组在当前链中启用 RPKI 验证。 |
运算符
匹配器运算符
| Operator | Description | Example |
|---|---|---|
&& | 逻辑 AND 运算符 | if (dst in 192.168.0.0/16 && dst-len in 16-32) {reject;} |
|| | 逻辑 OR 运算符 | if (dst in 192.168.0.0/16 || dst-len in 16-32) {reject;} |
not | 逻辑 NOT 运算符 | if (not bgp-network) {reject; } |
数值属性运算符
| Operator | Description |
|---|---|
in | 如果值在所提供的数值范围内,则返回 true。数值范围可以按以下格式书写:{int..int}, {int-int} |
== | 如果数值相等,则返回 true |
!= | 如果数值不相等,则返回 true |
> | 如果左侧数值大于右侧数值,则返回 true |
< | 如果左侧数值小于右侧数值,则返回 true |
>= | 如果左侧数值大于或等于右侧数值,则返回 true |
<= | 如果左侧数值小于或等于右侧数值,则返回 true |
前缀运算符
| Operator | Description |
|---|---|
in | 如果前缀是所提供网络的子网,则返回 true。如果使用运算符从地址列表中匹配前缀(例如 dst in list_name),则它只会匹配精确的前缀。 |
!= | 如果前缀不等于所提供的值,则返回 true |
== | 如果前缀等于所提供的值,则返回 true |
信息
地址列表按设计匹配主机地址,这意味着它也会匹配属于地址列表中任何范围的 /32 前缀。从通告中排除 /32 前缀的变通方法是使用 dst-len
if (dst in list_name && dst-len < 32) {}
BGP Community 运算符
| Operator | Description | Example |
|---|---|---|
equal | 如果所提供的 communities 等于路由的属性值,则返回 true | |
equal-list | 如果所提供的 community-list 中的 communities 等于路由的属性值,则返回 true | |
any | 如果路由的属性值包含至少一个所提供的 community,则返回 true | |
any-list | 如果路由的属性值包含所提供列表中的至少一个 community,则返回 true | |
includes | 如果路由的属性值包含指定的 communities,则返回 true | |
includes-list | 如果路由的属性值包含指定 communities-list 中的所有 communities,则返回 true | |
subset | 如果路由的 community 子集与列表中的 communities 匹配,则返回 true | 1:1,3:3 will match 1:1,2:2,3:3 |
subset-list | 与 subset 相同,但匹配 community 列表中的 communities。 | |
any-regexp | 与 any 相同,但通过 regexp 匹配 | |
subset-regexp | 与 subset 相同,但通过 regexp 匹配 |
字符串运算符
| Operator | Description |
|---|---|
find | 检查所提供的子字符串是否是属性值的一部分 |
regexp | 匹配属性值的字符串 regexp |
删除 BGP Communities
路由过滤器允许通过使用 delete 命令清除 BGP communities。delete 命令根据 community 类型接受多个参数:
- communities:
wk- 将匹配并移除 well-known communities。other- 将匹配并移除非 well-known 的其他 communities。regexp- 用于匹配应删除的 communities 的 regexp 模式。<community-list name>- 从指定的community-list删除 communities。
- ext-communities:
rt- 将匹配并移除 RouteTarget。soo- 将匹配并移除 Site-of-Origin。other- 将匹配并移除不是 RT 或 SOO 的其他 ext communities。regexp- 用于匹配应删除的 ext communities 的 regexp 模式。<community-ext-list name>- 从指定的community-ext-list删除 communities。
- large-communities:
all- 移除所有内容。regexp- 用于匹配应删除的 large communities 的 regexp 模式。<community-large-list name>- 从指定的community-large-list删除 large communities。
可以指定多种 community 类型,例如从 community-ext 列表中删除所有 SOO、其他类型的 ext communities 和特定的 RT:
/routing/filter/community-ext-list
add list=myRTList communities="rt:1.1.1.1:222"
/routing/filter/rule
add chain=myChain rule="delete bgp-ext-communities soo,other,myRTList;"
AS-PATH Regexp 匹配
AS path 是自治系统号(ASN)的序列。例如,AS path 123 456 789 表示该路由源自 AS 789,并在到达目的地之前经过了 AS 456。要应用路由策略,可通过使用正则表达式(regexp)来匹配 AS path 中特定的 AS 号或 AS 号集合。
处理 AS path 数据有两种常见方式:
- 将整个 AS path 转换为字符串,让 regexp 在字符串上操作(ROS v6 或 Cisco 风格)。
- 让 regexp 将每个 AS path 条目作为数字进行操作(ROS v7,Juniper 风格)。
第一种方法按字符匹配。第二种方法按 AS 号匹配。第二种方法比字符串匹配方法更快且使用的资源更少。
这一变化要求管理员使用新的 regexp 策略。来自 RouterOS v6 的旧 regexp 模式不能直接复制粘贴,因为它们可能导致语法错误或意外结果。
以这条基本的 AS path 过滤规则为例:
/routing/filter/rule
add chain=myChain rule="if (bgp-as-path .1234.) {accept}"
此 regexp 模式匹配 AS path 中间任意位置的 ASN 1234。使用旧式字符串匹配方法时,同一模式会匹配任何包含至少六个字符的 ASN 且包含子字符串 1234 的 AS path。等效的旧式模式是 ._1234_.。
例如,旧字符串风格模式 1234[5-9] 会匹配字符串中任意位置的 12345 到 12349。这会产生诸如 12345 3434 和 11 9123467 22 之类的匹配。使用新式匹配器时,同一模式会匹配包含精确 ASN 1234 后跟 5 到 9 的 ASN 的 AS path,例如 1234 7 111 或 111 1234 5 222。它不会匹配 12345 3434。
危险
在不同实现之间复制 regexp 模式可能会产生意外或危险的结果。
不要直接从 ROS v6 或 Cisco 配置中复制 Regex 模式,它们并不直接兼容。在某些场景下,这可能导致意外甚至危险的配置。 信息
AS-Path 参数必须存在,regexp 匹配器才会被应用。这意味着无法使用正则表达式(即
^$)匹配不存在(空)的 AS-Path。应改用bgp-path-len。
Regex 测试工具
RouterOS 有一个内置的 regexp 检查工具,可帮助管理员验证 regexp。该工具还支持 num-list 值,因此你可以在将 regexp 应用到路由过滤器之前,针对任何 AS path 对其进行测试。
/routing/filter/num-list/add list=test range=100-1500
/routing/filter/test-as-path-regexp regexp="[[:test:]]5678\$" as-path="1234,5678"
支持的运算符
| Operator | Description | Example | Example Explained | Example Matches |
|---|---|---|---|---|
^ | 表示路径的开头 | ^1234 | 将匹配以 ASN 1234 开头的 AS-path | |
$ | 表示路径的结尾 | 1234$ | 将匹配源 ASN 1234 的 AS-path | |
* | 所列 ASN 出现零次或多次 | ^1234*$ | 将匹配空 AS-path 或 ASN 1234 可能出现零次或多次的 AS-path | Match: 1234 1234 1234 1234 Null path No Match: 1234 5678 |
+ | 所列 ASN 出现一次或多次 | 1234+ | 将匹配 ASN 1234 至少出现一次的 AS-path | Match: 1234 3 1234 6 No match: 12345 678 |
? | 所列 ASN 出现零次或一次 | ^1234? 5678 | 将匹配可能以 ASN 1234 出现一次开头、也可能不这样开头的 AS-path。 | Match: 5678 1234 5678 No match: 1234 1234 5678 12345 5678 |
. | 任一 ASN 出现一次 | ^.$ | 将匹配长度为 1 的任何 AS-path。 | Match: 12345 45678 No match: 1234 5678 |
| | 匹配两侧两个 ASN 之一 | ^(1234|5678) | 将匹配以 ASN 1234 或 5678 开头的 AS-path | Match: 1234 5678 1234 5678 No Match: 91011 |
[ ] [^ ] | 表示 AS 号的集合,其中列表中必须有一个 AS 号匹配。 在左括号后使用 ^ 可对集合取反。 也可以使用 [[:numset_name:]] 引用预定义的 num-lists,参见 num-list | ^[1234 5678 1-100] | 将匹配以 1234 或 5678 开头,或从 1 到 100 范围内开头的 AS-path | Match: 1234 99 5678 No Match: 101 |
() | 要匹配的 regexp 项分组 | ^(1234$|5678) | 将匹配以 1234 开头和结尾的 AS-path,或以 5678 开头的 AS-path | Match: 1234 5678 9999 No Match: 1234 5678 |
警告
不支持重复范围 {}。
Community 和 Num 列表
常用数字列表可以从 /routing/filter/num-list 菜单配置。这些数字列表可以在过滤规则中使用,以简化过滤器设置过程。
以类似的方式,你也可以定义 community、extended community 和 large community 列表。Community 集合可用于匹配、追加和设置。
例如,匹配列表中的 communities 并清除该属性:
/routing/filter/community-list
add communities=111:222 list=myCommunityList
/routing/filter/rule
add chain=myChain rule="if (bgp-communities equal-list myCommunityList) {delete bgp-communities wk,other; accept;}"
路由选择
路由选择规则控制如何从可用的候选路由中选择输出路由。默认情况下,如果未设置任何选择规则,输出会选择最佳路由。
以下路由表显示了两条候选路由和一条最佳路由。默认情况下,当 BGP 选择要发送的路由时,它会选择活动路由。
[admin@4] /routing/route> print where dst-address=1.0.0.0/24
Flags: A - ACTIVE; b, y - COPY
Columns: DST-ADDRESS, GATEWAY, AFI, DISTANCE, SCOPE, TARGET-SCOPE, IMMEDIATE-GW
DST-ADDRESS GATEWAY AFI DISTANCE SCOPE TARGET-SCOPE IMMEDIATE-GW
b 1.0.0.0/24 10.155.101.217 ip4 19 40 30 10.155.109.254%ether1
Ab 1.0.0.0/24 10.155.101.232 ip4 20 40 30 10.155.109.254%ether1
b 1.0.0.0/24 10.155.101.231 ip4 20 40 30 10.155.109.254%ether1
如果你需要对非活动路由给予偏好,请使用选择规则。
RouterOS 中的选择规则从 /routing/filter/select-rule 菜单配置。
选择规则也可以调用路由过滤器,从而通过过滤规则来选择路由。例如,要模拟默认的输出选择,请使用以下规则集:
/routing/filter/rule
add chain=get_active rule="if (active) {accept}"
/routing/filter/select-rule
add chain=my_select_chain do-where=get_active
选择规则也可以用于限制为 BGP Add-path 选取多少条额外路径,例如最多 3 条路径:
/routing/filter/select-rule add chain=select-for-addpath do-take=3
路由过滤向导
由于使用类似脚本的语法编写过滤规则更为复杂,因此引入了路由过滤向导,它可生成具有类似 ROSv6 语法的过滤规则。
快速演示:
[admin@CCR2004_2XS_111] /routing/filter> filter-wizard <tab>
action dst ospf-type scope-target set-gw-check use-te-nexthop
afi dst-len protocol set-bgp-... set-scope
bgp-... gateway routing-table set-blackhole set-scope-target
blackhole jump-target-chain rpki set-comment set-suppress-hw-offload
chain match-chain rpki-verify set-distance set-use-te-nexthop
distance ospf-metric scope set-gateway suppress-hw-offload
[admin@CCR2004_2XS_111] /routing/filter> filter-wizard action=accept chain=vpn-in afi=vpnv4 set-bgp-ext-communities=rt:2:2
result: Filter rule 'if (afi vpnv4) { set bgp-ext-communities rt:2:2; accept; }' added
[admin@CCR2004_2XS_111] /routing/filter> /routing/filter/rule/print
Flags: X - disabled, I - inactive
0 ;;; added by filter-wizard
chain=vpn-in rule="if (afi vpnv4) { set bgp-ext-communities rt:2:2; accept; }"
过滤向导会将其规则添加到列表的末尾,并为其添加注释 added by filter-wizard。
当你尝试添加带有不可接受值的过滤器时返回的错误会打印在 CLI 中,并以 route,error 主题记录在系统日志中。
[admin@CCR2004_2XS_111] /routing/filter> filter-wizard action=accept chain=vpn-in afi=vpnv4 match-chain=vpn-in
result: Error adding 'if (chain vpn-in && afi vpnv4) { accept; }'match with 'vpn-in' creates chain loop (6)
[admin@CCR2004_2XS_111] /routing/filter> /log/print
2025-05-19 13:05:15 route,error Error adding 'if (chain vpn-in && afi vpnv4) { accept; }'match with 'vpn-in' creates chain loop (6)