RouterOS v7 路由过滤器学习笔记
|
RouterOS v7 中 routing filter(路由过滤器) 的工作方式、语法结构、匹配属性、可执行动作、社区匹配、AS-PATH 正则、RPKI 与选择规则与 RouterOS v6 中存在较大的差异,本文整理通过 ChatGPT 5.4 Thinking 模型对这部分内容进行了整理。[1][2]
注意:该内容由人工智能(ChatGPT 5.4 Thinking 模型)进行生成。
RouterOS v7 的路由过滤器已经从 v6 那种偏“参数式”的风格,演进成一套更接近策略脚本语言的模型。其基本形式为:
if ( [matchers] ) { [actions] } else { [actions] }
过滤器规则不再只是简单的“匹配一个条件然后设置一个值”,而是支持布尔表达式、属性修改、跳转子链、返回父链、追加或删除 communities 等完整流程控制。[2]
对实际使用来说,最重要的理解是:
- 先匹配,再执行动作;
- 并不是所有属性都能修改,有些属性只能用于匹配;
- 过滤链默认动作为 reject,没有显式
accept的路由最终会被拒绝; - 社区、扩展社区、大社区在 v7 中都有统一的匹配与修改机制;
- AS-PATH 正则在 v7 中语义已经变化,不能直接照搬 v6/Cisco 写法。[1][2]
v6 到 v7 的核心变化
协议配置结构变化
在 BGP 方面,ROS v7 不再沿用 ROS v6 的 instance / peer 模型,而是重构为 connection、template、session 三部分。官方说明,这样做是为了将“连接相关参数”和“BGP 协议本身参数”明确分离,使配置结构更清晰。[1]
同时,v7 中很多原本分散的路由策略控制,也被统一到新的 /routing filter 框架里。BGP 会通过 input.filter-chain、output.filter-chain 等方式将策略链挂接到会话输入与输出过程上。[1]
routing filter 的职责增强
在 OSPF 示例中,官方明确说明虽然 redistribution knob 在后续版本中回来了,但如果需要进一步控制哪些路由能被引入、以及修改 metric/type 等属性,仍然要使用 routing filter。[1]
这意味着在 ROS v7 中,协议负责挂载过滤器,过滤器负责做细粒度策略决策。[1]
v7 过滤器的执行模型
规则是脚本字符串
官方示例展示,v7 的过滤器规则是通过 rule="..." 的形式编写在字符串中的,例如:
/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}"
也就是说,规则本身是一段脚本,内部包含:
- 条件表达式
- 动作块
- 可选的
else - 若干以分号结尾的语句。[2]
链默认拒绝
官方在 v6→v7 迁移文档中明确强调:routing filter chain 的默认动作是 reject。[1]
这点非常关键。实际效果是:如果一条路由走完整条链都没有遇到 accept,那么即使没有显式写 reject,它最终也不会被接受。[1][2]
accept / reject / jump / return
官方文档列出的主要控制动作包括:
acceptrejectjumpreturn
它们分别用于:
accept:接受当前路由并停止当前链处理;reject:拒绝当前路由;jump:跳到其他过滤链继续处理;return:从被跳转的子链返回父链。[2]
因此,复杂策略推荐拆成“主链 + 子链”的结构,而不是写成一条很长的 if 语句。[2]
属性分类:只读与可读写
官方明确将路由过滤属性分为两类:[2]
只读属性
只能用于匹配,不允许修改。常见如:
dst-lenbgp-path-lenbgp-input-remote-asbgp-output-remote-asactiveafiprotocolospf-dn
这些属性适合出现在 if (...) 里作为判断条件。[2]
可读写属性
既能匹配,也能通过 set、append、unset 等动作修改。常见如:
distancebgp-weightbgp-local-prefbgp-medbgp-out-medbgp-igp-metricbgp-path-prependbgp-path-peer-prependgwgw-llbgp-communitiesbgp-ext-communitiesbgp-large-communities
这类属性通常用于 BGP 策略控制、出口打社区、调整本地优先级、修改下一跳等场景。[2]
常用匹配语法
基本判断
官方示例表明,v7 支持布尔表达式与比较操作,例如:
if ( protocol connected ) { accept }
if ( bgp-med < 30 ) { accept }
if ( ospf-dn ) { reject }
这说明:
- 某些 flag/布尔属性可以直接判断;
- 数值属性可以用
<、>、==等比较; - 多条件可以用
&&、||组合。[2]
前缀匹配与 in
在前缀过滤中,dst in 192.168.1.0/24 表示当前路由前缀是否属于该网络范围。[2]
这对于常见的“允许某个聚合块及其子前缀输出”非常有用,例如:
if (dst in 2a05:dfc1:7100::/40 && dst-len <= 48) { accept; }
address-list 的坑
官方特别提醒:如果使用 dst in list_name,而该 list_name 是 address-list,那么其匹配逻辑源于 host-address 设计,可能会把 /32 也纳入命中范围。官方建议必要时同时加入 dst-len 约束,例如:
if (dst in list_name && dst-len < 32) { ... }
这对于做白名单输出控制或黑名单过滤时尤其重要。[2]
常用动作语法
set / unset
set 用于设置可写属性,例如:
set bgp-local-pref 200;
set distance +1;
官方也支持在原值基础上增减,例如 +1、-1,甚至从其他数值属性读取值参与计算。[2]
unset 用于清空属性,官方文档中提到可用于如 pref-src、bgp-med、bgp-out-med、bgp-local-pref 等属性。[2]
append
append 用于向可追加属性中增加内容,典型场景就是 communities:
append bgp-communities 65000:100;
append bgp-large-communities 64999:1100:6939;
这也是 large community 正确的使用方法之一。[2]
delete / filter
官方说明:
delete:删除指定内容;filter:删除“除指定值之外”的内容,相当于反向过滤。[2]
这些动作可以应用于:
- 普通 communities
- 扩展 communities
- large communities
- comment 等属性。[2]
BGP 场景最重要的几个属性
bgp-local-pref
用于 iBGP 内部优先级控制,是最常见的入口策略属性之一。例如按上游 ASN 给某个入口更高本地优先级:
if (bgp-input-remote-as == 6939) {
set bgp-local-pref 200;
accept;
}
该用法基于官方列出的 bgp-input-remote-as(只读)和 bgp-local-pref(可写)属性。[2]
bgp-path-prepend
官方说明,bgp-path-prepend 用于在 BGP output 时为本地 ASN 执行 prepend。也就是说,这是“我方向外发时,额外重复自己的 ASN 次数”的控制方式。[2]
bgp-path-peer-prepend
这个属性和上一个很容易混淆。官方说明它主要关联从对端收到的 prepend 信息,可以用于 input 中匹配“对方 prepend 过多”的路由,也可在某些场景下覆盖收到的 peer prepend 值。[2]
因此:
- 我要对外 prepend 自己的 ASN:用
bgp-path-prepend - 我要检查对端 prepend 是否异常:看
bgp-path-peer-prepend。[2]
gw / gw-ll
官方说明,gw 和 gw-ll 用于修改网关/下一跳,但在 BGP output 中并不是任何场景都能自由修改。尤其在 output 阶段,是否允许修改 next-hop,取决于会话属性、是否是 route reflector、是否启用了 nexthop-choice=propagate、是否为非 eBGP 且无 force-self 等上下文条件。[2]
因此,语法能写不等于一定能生效,这一点需要在实际出站策略中重点验证。[2]
Communities / Large Communities 的匹配与处理
社区匹配操作符
官方列出了多种社区匹配方式,包括:[2]
equalequal-listanyany-listincludesincludes-listsubsetsubset-listany-regexp
在工程实践中常见理解如下:
any:只要包含其中任意一个社区即可命中;includes:必须包含指定的全部社区;equal:当前社区集合必须与指定值完全一致;subset:当前社区集合是给定集合的子集关系判断。[2]
使用社区列表
官方支持预定义:
/routing/filter/community-list/routing/filter/community-ext-list/routing/filter/community-large-list
这些列表可以被用于:
- 匹配
- 追加
- 设置。[2]
对复杂网络策略来说,推荐把经常复用的上游控制社区、blackhole 社区、large communities 定义为 list,再在规则里调用,而不是每条规则都手写常量。[2]
大社区的正确写法
在 ROS v7 中,大社区属于 bgp-large-communities 这个属性。要给路由加 large community,应写成:
if (dst == 2a05:dfc1:710e::/48) {
append bgp-large-communities 64999:1100:6939;
accept;
}
而不能把 64999:1100:6939 直接裸写成“动作”。因为官方动作体系中并不存在“把一个 large community 常量直接当 action 执行”的语法,必须通过 set 或 append 作用到 bgp-large-communities 属性上。[2]
删除和清洗 communities
官方单独说明了 delete 对不同社区类型的支持范围:[2]
普通 communities
可删除:
wkother- regexp 匹配项
- 指定的 community-list。[2]
扩展 communities
可删除:
rtsooother- regexp 匹配项
- 指定 ext-community list。[2]
Large communities
可删除:
all- regexp 匹配项
- 指定 large-community list。[2]
这在出口策略中非常有用,例如:
- 删除内部标记后再对外发布;
- 对客户前缀清洗不应透传的内部社区;
- 保留必要 RT / SoO,删除其它无关社区。[2]
AS-PATH 正则:v7 与 v6 不兼容
这是迁移时非常关键的一点。官方明确警告:不能把 ROS v6 或 Cisco 的 AS-PATH 正则直接复制到 ROS v7 中使用,因为 v7 的 AS-PATH 正则语义已经改变。[2]
官方举例说明:
- 在旧语义中,
1234[5-9]可能被理解为字符串片段匹配; - 在 v7 中,它表达的是基于 ASN token 的匹配关系,即
1234后面跟一个范围在5-9的 ASN。[2]
官方还指出:
- 只有在 AS-PATH 存在时,正则才会匹配;
- 不能用
^$去匹配空 AS-PATH; - 如果要匹配“空路径”,应该使用
bgp-path-len。[2]
官方还提供了 /routing/filter/test-as-path-regexp 工具用于测试正则表达式。[2]
RPKI 与 select-rule
RPKI
官方在可执行动作中列出了 rpki-verify rpki_group_name,说明在过滤链中可以直接启用指定 RPKI 组进行验证。[2]
这意味着 RPKI 校验可以直接融入输入过滤链逻辑中,与 accept/reject、社区处理、标签标记等策略联动。[2]
select-rule
官方还介绍了 /routing/filter/select-rule,它并不是普通的 input/output filter,而是用于从候选路由集中挑选出符合条件的项。官方示例中甚至可以通过单独的 chain 去表达“只选 active 路由”的逻辑。[2]
这一机制对于高级选路与输出控制场景有较强扩展性,但日常 BGP 邻居入站/出站策略中用得相对少一些。[2]
filter wizard 辅助生成过滤规则
官方文档提到,从 v7.20 开始提供 /routing/filter/filter-wizard,用于帮助用户生成过滤规则。这从侧面说明 v7 的过滤器虽然功能更强,但语法和心智负担也明显高于 v6。[2]
因此在生产环境中,推荐:
- 通过子链进行模块化设计;
- 通过 community list / large-community list 进行对象复用;
- 避免在 CLI 中临时手写非常长的
rule="..."字符串; - 在变更前先验证语法与逻辑路径。[2]
面向 BGP 实战的推荐写法
按 AFI 分流
官方支持 afi 作为匹配属性,可识别 ipv4、ipv6、l2vpn、vpnv4、vpnv6 等地址族。[2]
因此,在双栈 BGP 策略中,建议先在主链按 AFI 分流,再分别跳转到 IPv4 / IPv6 子链中处理:
/routing/filter/rule
add chain=bgp_in rule="if (afi ipv4) { jump v4_in; } else { jump v6_in; }"
先匹配,再修改,再 accept
推荐统一采用下列风格:
if (条件) {
set/append/delete ...;
accept;
}
这样最符合 v7 的执行模型,也最不容易出现“语法看起来像对,实际上动作块不成立”的问题。[2]
next-hop 改写前先确认条件
由于官方明确说明 gw / gw-ll 的生效受 output 上下文约束,因此在设计 set gw ... 或 set gw-ll ... 时,需要同时检查:
- 邻居是 eBGP 还是 iBGP;
- 是否 reflector;
nexthop-choice是什么;- 是否 force-self;
- 是否在 output 阶段改写。[2]
实战示例
按 IPv6 前缀打 large community
/routing/filter/rule
add chain=bgp_out rule="if (dst == 2a05:dfc1:710e::/48) { append bgp-large-communities 64999:1100:6939; accept; }"
说明:对指定 IPv6 前缀增加 large community,再接受输出。[2]
限制对端过度 prepend
/routing/filter/rule
add chain=bgp_in rule="if (bgp-path-peer-prepend > 4) { reject; }"
说明:对方 prepend 过多时直接拒绝,适用于清理异常路径。[2]
按来源 ASN 提高本地优先级
/routing/filter/rule
add chain=bgp_in rule="if (bgp-input-remote-as == 6939) { set bgp-local-pref 200; accept; }"
add chain=bgp_in rule="accept"
说明:来自 AS6939 的路由提高 local-pref,其余默认接受。[2]
限制可发布的前缀块与掩码长度
/routing/filter/rule
add chain=bgp_out rule="if (dst in 2a05:dfc1:7100::/40 && dst-len <= 48) { accept; }"
add chain=bgp_out rule="reject"
说明:只允许指定聚合块内、且不超过 /48 的前缀输出。[2]
清洗不应对外发布的社区
/routing/filter/rule
add chain=bgp_out rule="delete bgp-communities wk,other; accept;"
说明:将普通 communities 中的 well-known 或 other 类项清洗后再输出。是否这样删,需要按实际策略决定。[2]
最容易踩的坑
忘写 accept
因为链默认是 reject,所以少写一个 accept 就可能导致整个策略链“看起来正常,实际上全丢”。[1][2]
把 large community 当动作写
正确写法是:
append bgp-large-communities 64999:1100:6939;
而不是裸写 64999:1100:6939。后者不符合 v7 的动作语法。[2]
直接照抄 v6/Cisco 的 AS-PATH 正则
官方明确不建议这么做,因为语义已变,可能造成严重误匹配。[2]
误以为 set gw 必然生效
官方已说明 BGP output 的 next-hop 改写受会话上下文限制,因此必须结合具体 BGP 角色与会话属性判断。[2]
address-list 误匹配 host route
使用 dst in list_name 时,应根据需要补充 dst-len 限定,避免匹配到不希望处理的 /32。[2]
结论
RouterOS v7 的 routing filter 已经不再只是一个“附加条件的小工具”,而是一套覆盖匹配、修改、流程控制、社区处理、RPKI 验证、路由选择的完整策略语言框架。[2]
对于生产环境,推荐采用以下实践:
- 主链负责分流,子链负责细分策略;
- 所有出口、入口策略都显式写
accept/reject; - 将 communities、large communities 做成 list 复用;
- 对 next-hop、prepend、local-pref 等属性的修改,严格区分 input 与 output 语义;
- 所有 AS-PATH 正则先用官方测试工具验证,再上线;
- 迁移 v6 配置时,不要机械照抄旧语法,要按 v7 逻辑重新审视。[1][2]
参考来源
[1] MikroTik. Moving from ROSv6 to v7 with examples. RouterOS Documentation. Last updated Feb 19, 2026. Available at: https://help.mikrotik.com/docs/spaces/ROS/pages/30474256/Moving+from+ROSv6+to+v7+with+examples
[2] MikroTik. Route Selection and Filters. RouterOS Documentation. Last updated Feb 09, 2026. Available at: https://help.mikrotik.com/docs/spaces/ROS/pages/74678285/Route+Selection+and+Filters