BGP 路由泄露防护实战:RPKI、ASPA 与前缀过滤的完整防线
BGP 是互联网的"地图协议"——几十万个自治系统靠它互相宣告"我这边能到哪些网段"。它设计于信任优先的年代,默认相信邻居说的话。一旦某个网络配错或故意宣告了不属于自己的路由,流量就会被牵着鼻子走,轻则自己变慢,重则整片区域断网。这些年闹过的事故不少:某国电信把谷歌、推特的流量导到自己网络绕了一圈,某运营商把路由泄露到上游让半个互联网抖动,还有云厂商的 BGP 会话被误配导致大面积不可达。
路由泄露(route leak)和路由劫持(hijack)常被混为一谈,但防护思路不同:劫持是"冒领"别人的前缀,泄露是"乱传"本不该由自己转发的路由。本文不讲怎么抢前缀,只讲怎么让"不该出现的路由"在你的网络里进不来、出不去、传不开,给一套从源验证到路径验证、从过滤到监控的多层防线。
1. 路由泄露是怎么发生的
先弄清敌人长什么样,才好布防。常见泄露有三类:
- 对等关系错用:两家本该只交换自己及客户的路由(peer-to-peer),结果一方把从别处收到的全网路由也转发给对方,等于把自己当成了 transit。这是最典型的"泄露"定义。
- 没有出口过滤:下游客户宣告了超出授权范围的前缀,上游没做 prefix-list 校验就照单全收并继续广播。
- 配置翻转:把
import和export策略贴反,或者no-exportcommunity 没生效,导致本该内部消化的路由漏到了外部。
根因几乎都是同一件事:没有对邻居宣告的内容做验证和限制。所以防护的第一性原理就是——凡是对外宣告或接收的路由,都必须经过明确的策略过滤,而不是"邻居说什么我都信"。
2. 第一层:RPKI ROV 源验证
RPKI(资源公钥基础设施)解决"这个前缀到底该由哪个 AS 起源"的问题。网络运营者用自己的证书给"某前缀 + 某源 AS"签一个授权对象(ROA),放在全球依赖方仓库里。路由器通过 RTR 协议(RPKI to Router)从验证缓存拉取这些记录,对收到的每条路由做源验证,得出三种状态:
- Valid:源 AS 与 ROA 匹配。
- Invalid:前缀存在 ROA,但当前宣告的源 AS 不在授权列表里——典型的源冒充。
- Unknown:该前缀没有对应的 ROA——目前互联网上仍是大多数。
实战建议:先开启"屏幕模式"只观测不丢弃。在 Cisco 上用 route-map 给 Invalid 打 community 或本地偏好,Juniper 用 validation-state invalid 匹配;观察两周,确认 Invalid 的来源确实是异常宣告,再切到真正丢弃。FRR 和 BIRD 都原生支持 RPKI,配一个 rpki 段落指向缓存(如 Routinator、OctoRPKI)即可。
3. 第二层:ASPA 路径验证
RPKI 只管"源",不管"路径"。ASPA( Autonomous System Provider Authorization)补上这一刀:它声明"我的 AS 的上游/对等是谁",路由器据此检查 AS_PATH 里每一对相邻 AS 的上下游关系是否真实。如果一条路径里出现了"本应是客户却放在提供商位置"的异常相邻关系,就判定为路径型泄露并拦下。
ASPA 目前处在逐步部署阶段,不像 ROV 那么普及,但价值很高:它能挡住"用自己合法 AS 起源、却绕了不该经过的链路"的高级泄露。部署方式类似 RPKI,由 CA 签发 ASPA 对象,路由器消费后做路径校验。建议在有 RPKI 基础后逐步启用,对新接入的对等优先级高。
4. 第三层:IRR 与精确前缀过滤
光有加密验证还不够,因为你根本不该收一堆无关的明细路由。IRR(Internet Routing Registry)是各 NCC/RIR 维护的路由对象库,网络运营者登记自己要宣告的前缀。最佳实践是对每个邻居套一个 prefix-list(Cisco)或 prefix-list/policy-options(Juniper),只放行它"应该"宣告的段:
- 对上游运营商:通常只收默认路由或它自己及客户的聚合。
- 对 Peer:只收对方及其客户的路由,绝不收 transit 来的第三方。
- 对下游客户:严格按合同里登记的前缀白名单,多一条都不收。
很多团队把 IRR 对象当摆设、过期不更新,结果过滤器和实际宣告对不上,要么漏过、要么误杀。纪律是:IRR 对象和 RPKI ROA 一起作为白名单源,CI 里加校验,改前缀前先改登记。
5. 第四层:max-prefix 接收限速
即便前面都做了,bug 和误操作仍可能让一个邻居突然塞给你几万条路由,撑爆 RIB 或 CPU。max-prefix(前缀数量上限)是最后一道保险:
- 软上限(warning):达到阈值只告警,方便你介入看是不是正常增长。
- 硬上限(超限动作):可以选"断开会话"或"停止接收新路由但保留已有",后者更稳,避免震荡。
阈值怎么定?拉邻居过去 30 天通告量的峰值,软限取 1.2-1.5 倍,硬限取 1.8-2 倍。对上游可宽、对 Peer 和客户要严。这条配置改一次能管很久,但"增长时忘了调"是常见坑,所以巡检里要把"阈值余量"列为固定检查项。
6. 第五层:peer-lock 与 bogon 过滤
两个低成本高收益的底线动作:
- bogon/martian 过滤:在全部 eBGP 入方向丢弃 RFC1918 私网、文档段(192.0.2.0/24 等)、未分配段、以及明显非法的源。这是 ISP 边界的标配,不做就是失职,因为它直接关系到源地址伪造和反射攻击。
- peer-lock:把"只发给特定邻居"的路由显式锁死,防止策略贴反导致本该内部的路由外泄。在 Juniper 里常用
export策略配合then community add no-export,在 FRR 里用route-map的community动作。核心是"默认不导出,白名单才导出"的零信任思路。
7. 配置片段速查
下面给出各平台的骨架,具体数值按你的拓扑填:
Cisco(RPKI + 丢弃 Invalid):
router bgp 65001
bgp rpki server 192.0.2.10 port 323 refresh 300
route-map RPKI-IN permit 10
match rpki invalid
set community 666:1
route-map RPKI-IN permit 20
neighbor 203.0.113.1 route-map RPKI-IN in
Juniper(按验证状态匹配):
policy-options policy-statement RPKI-IN
term invalid
from validation-state invalid
then reject
term else
then accept
FRR(原生 RPKI):
rpki
rpki polling-period 300
rpki cache 192.0.2.10 323
exit
route-map RPKI-IN deny 10
match rpki invalid
BIRD(rpki 协议 + 过滤器):
protocol rpki RPKI {
roa4 { table roa_table; };
remote 192.0.2.10 port 323;
}
filter bgp_in { if (roa_check(roa_table, net, from) = ROA_INVALID) then reject; accept; }
8. 监控与异常检测
防线布好不等于万事大吉,得能"看见"异常:
- 持续统计每天 Invalid/Unknown 占比,占比突增往往意味着某处 ROA 配错或被攻击。
- 监控每个邻居的路由条数,超过 max-prefix 软限即告警。
- 对关键前缀(你自己的、重要客户的)做可达性探测,一旦路径突然变长或下一跳异常就告警。
- 订阅 RPKI 仓库和 IRR 的变更通知,前置发现可能影响你的改动。
告警要接进现有的监控体系(Prometheus + Alertmanager 或直接发到值班群),别让告警沉睡在日志里。
9. 上线后的巡检与防退化纪律
路由过滤是"会悄悄退化"的配置,一次错误的策略回滚、一次 IRR 对象过期、一次工程师手滑贴反 import/export,防线就没了。建立以下纪律:
- 每周:跑一次全邻居 ROV 状态统计,确认 Invalid 仍在丢弃、Unknown 占比无异常飙升。
- 每月:核对 IRR 登记对象与实际宣告是否一致,过期对象触发整改工单。
- 每次变更前:在 staging 或只读会话里先
show验证策略效果,再上生产;变更后立刻复核收到的路由条数和状态分布。 - 每次扩前缀/加邻居:先改 IRR 和 RPKI ROA,再改路由器 prefix-list,顺序不能反,改完用
show route receive-protocol确认生效。 - 红线:禁止"先放行再补过滤"。任何新邻居接入默认 deny-all,白名单一条条加;任何 export 默认 no-export,要导出显式授权。