4. Junos路由策略语言基础
Junos 的路由策略不是“在协议里随手加几个过滤条件”,而是一门独立的策略语言。它由 policy-statement 组织,内部用 term 划分判断分支,每个 term 又由 from 匹配条件和 then 执行动作组成。理解这套结构,是后续做 BGP 路由过滤、属性修改和流量工程的前提。
policy-statement 的整体结构
一条策略语句的基本骨架如下:
policy-options {
policy-statement PS-EXAMPLE {
term T1 {
from {
protocol bgp;
neighbor 192.0.2.1;
route-filter 10.10.0.0/16 exact;
}
then {
local-preference 200;
community add NO-EXPORT;
accept;
}
}
term T2 {
from {
protocol bgp;
}
then reject;
}
}
}
这里 policy-statement 是策略的名字,term 是内部按顺序排列的判断分支,from 描述“什么样的路由会被这个 term 命中”,then 描述“命中后做什么”。一个 policy-statement 可以包含多个 term,Junos 会从上到下依次评估,一旦某个 term 的 from 条件全部满足,就执行该 term 的 then 动作;如果 then 中没有 accept 或 reject,则继续向下评估后续 term。
from 匹配条件
from 是策略的“入口条件”,常见匹配对象包括:
- 协议与邻居:
protocol bgp、neighbor 192.0.2.1,用于限定路由来源。 - 前缀:
route-filter 10.10.0.0/16 exact,支持exact、orlonger、longer、upto /24等匹配方式。 - AS_PATH:
as-path AS-PATH-NAME,配合正则表达式匹配 AS 号序列。 - 社区:
community COMMUNITY-NAME,可匹配标准社区、扩展社区或大社区。 - 其他属性:
local-preference、metric、next-hop、interface等。
多个 from 条件之间是“与”关系,必须同时满足才会命中该 term。例如同时写 protocol bgp 和 neighbor 192.0.2.1,表示只匹配来自该邻居的 BGP 路由。
then 动作
then 决定命中后的处理方式,常见动作分为三类:
- 终止类:
accept接受路由,reject拒绝路由并返回通知,discard静默丢弃。 - 属性修改类:
local-preference 200、metric 50、community add NO-EXPORT、as-path prepend 65001 65001。 - 跳转类:
next term继续下一个 term,next policy跳到下一条策略。
需要特别注意:如果 then 中只写了属性修改而没有 accept/reject,Junos 会继续评估后续 term。因此通常会在最后一个 term 中显式写 then reject,形成“默认拒绝”的兜底逻辑。
策略链与 apply-path
多条 policy-statement 可以组成策略链,通过 import 或 export 按顺序引用:
protocols bgp {
group EBGP {
import [ PS-FILTER-BOGON PS-SET-LP PS-ACCEPT ];
export [ PS-EXPORT-OWN ];
}
}
策略链按列表顺序执行,前一条策略的结果会影响后一条。如果某条策略中执行了 accept/reject,链就终止;如果只是修改属性而没有终止动作,则继续执行下一条策略。
apply-path 是 Junos 中一个非常实用的“动态引用”机制。它可以从配置中自动提取一组对象,而不需要手工维护列表。例如:
apply-path "protocols bgp group <*> neighbor <*>"
这条语句会自动收集所有 BGP group 下配置的 neighbor 地址,生成一个动态列表。当新增或删除邻居时,引用该列表的策略会自动更新,避免手工同步遗漏。
正则表达式匹配 AS_PATH 与社区
AS_PATH 正则表达式是 BGP 策略中最常用的匹配手段之一。Junos 使用 as-path 定义正则表达式,常用符号包括:
^表示 AS_PATH 开头,$表示结尾。.匹配任意单个 AS 号,.*匹配任意长度序列。()分组,|表示“或”。{m,n}表示重复次数范围。
例如,匹配“从 AS 65001 始发、且 AS_PATH 中只包含 65001”的路由:
as-path AS-ORIGIN-65001 "^65001$";
匹配“经过 65001 且后面还有任意 AS”的路由:
as-path AS-TRANSIT-65001 "^65001 .*";
匹配“AS_PATH 中出现 65001 两次以上”的路由:
as-path AS-LOOP-65001 "65001{2,}";
社区匹配则通常配合 community 定义和 from community 使用。标准社区格式为 AS:VALUE,例如 65001:100。可以定义社区列表:
community NO-EXPORT members 65001:100;
community FROM-CUSTOMER members [ 65001:200 65001:201 ];
然后在 from 中引用:from community FROM-CUSTOMER。对于大社区,Junos 支持 large-community,格式为 AS:VALUE1:VALUE2,匹配方式与标准社区类似。
show route receive-protocol bgp <neighbor> detail 观察实际 AS_PATH,再根据观察结果编写正则,避免凭记忆写出错误表达式。正则表达式中的空格在 Junos 中表示 AS 号分隔,不能随意省略。
策略评估流程可视化
下面这张图展示了从 BGP 路由进入策略链,到最终 accept/reject 的完整判断路径,包括 term 顺序、from 条件匹配、then 动作执行以及策略链的衔接关系。
图中可以看到,策略链中的每条 policy-statement 按顺序执行,term 内部按 from 条件匹配、then 动作执行。PS-FILTER-BOGON 负责过滤 bogus 前缀和 AS_PATH,PS-SET-LP 负责根据社区设置 local-preference,PS-ACCEPT 负责最终接受合法 BGP 路由并默认拒绝其余路由。这种“过滤—修改—兜底”的三段式结构,是 Junos 策略链中最常见的组织方式。
常见配置要点与排错思路
在实际配置中,有几个容易出错的点值得注意:
- term 顺序:Junos 按 term 从上到下匹配,先匹配到的 term 先执行。如果宽泛条件写在前面,后面的精确条件可能永远不会命中。
- 隐式继续:then 中没有 accept/reject 时,策略会继续向下评估。如果忘记写终止动作,可能导致路由被后续 term 意外处理。
- 策略链顺序:import/export 列表中的策略按顺序执行,前一条策略的 accept/reject 会终止整个链。
- 正则表达式转义:AS_PATH 正则中的
^、$、.、*等符号需要按 Junos 语法书写,空格表示 AS 号分隔。 - apply-path 动态引用:使用 apply-path 时,确保引用的配置路径存在且格式正确,否则生成的列表可能为空。
show route receive-protocol bgp <neighbor> detail 确认路由的实际属性(AS_PATH、community、local-preference),再用 show policy-options 检查策略定义,最后用 test policy PS-NAME <prefix> 模拟策略执行结果。test policy 命令可以显示路由经过每条策略和每个 term 时的匹配情况,是定位策略问题的首选工具。