RPKI ROA配置BGP:创建ROA,在BIRD2和FRR中验证路由
在RIPE NCC门户中创建IPv4和IPv6 ROA,安装Routinator作为RTR缓存,在BIRD2和FRRouting中配置RPKI路由源验证,使用bgp.tools和RIPE Stat验证前缀状态。
没有RPKI,任何ASN都可以宣告任何前缀。Route Origin Authorization(ROA)以密码学方式将你的前缀绑定到你的ASN,而路由源验证(ROV)使路由器能够拒绝无效公告。本教程涵盖完整链路:在RIPE NCC门户创建ROA、运行Routinator作为本地RPKI缓存、在BIRD2和FRRouting中配置验证,以及确认一切正常。
前置条件:一个已注册的ASN、已分配的IP前缀(PA或PI)、一个在Linux VPS上正常运行的BGP会话(在VPS上使用自有IP进行BGP),以及已经运行的BIRD2(BIRD2 BGP配置)或FRR(FRR BGP配置)。
什么是RPKI?为什么你的BGP前缀需要ROA?
Resource Public Key Infrastructure(RPKI)是RFC 6480定义的密码学框架,通过区域互联网注册机构签发的X.509证书将互联网号码资源(IP前缀、ASN)与其合法持有者绑定。Route Origin Authorization(ROA)是一个签名对象,声明"ASN X被授权以最大前缀长度Z宣告前缀Y"。验证器获取这些ROA,并通过RPKI-to-Router(RTR)协议(RFC 8210)将结果传递给路由器。
当路由器收到BGP更新时,它会根据本地ROA表检查源ASN和前缀。每个前缀获得以下三种验证状态之一:
| 状态 | 含义 | 建议操作 |
|---|---|---|
| Valid | 存在ROA且与源ASN和前缀长度匹配 | 接受 |
| Invalid | 存在ROA但源ASN或前缀长度不匹配 | 拒绝 |
| Not Found | 没有ROA覆盖此前缀 | 接受(可选择降低local-pref) |
没有ROA,你的前缀显示为"Not Found"。这比"Invalid"好,但执行ROV的网络在两者都可用时会优先选择对等方的"Valid"路由而非你的"Not Found"公告。创建ROA是第一步。验证入站路由可以保护你的网络免于接受被劫持的前缀。
如何在RIPE NCC门户中创建IPv4和IPv6 ROA?
登录RIPE NCC门户,导航到Resources,然后RPKI Dashboard。如果你还未初始化RPKI,选择"Hosted"证书颁发机构。RIPE NCC为你管理CA和签名。Hosted CA激活后,切换到BGP Announcements标签页。RIPE会根据你当前的BGP公告预填ROA建议。
- 点击Create ROA(或ROA标签页中的**+ New ROA**)。
- 将Origin ASN设置为你的AS号码(例如
AS213279)。 - 将Prefix设置为你的IPv4分配(例如
192.0.2.0/24)。 - 将Maximum Length设置为等于前缀长度(
/24)。不要增大此值。参见下方maxLength部分。 - 点击Publish。
- 为你的IPv6前缀重复操作(例如
2001:db8::/48,最大长度/48)。
在RPKI Dashboard中确认ROA状态显示"Published"。向验证器的传播通常需要10到20分钟,取决于其刷新间隔。
双栈提醒: 每个前缀创建一个ROA。如果你宣告192.0.2.0/24和2001:db8::/48,需要两个ROA。如果你宣告额外的more-specific(从/24中划分的/25),每个都需要自己的ROA和ASN绑定。
如何在Linux上安装Routinator作为RPKI-RTR缓存?
Routinator是NLnet Labs开发的RPKI依赖方(验证器)。它从所有五个RIR信任锚获取并验证ROA,然后通过RTR协议向路由器提供Validated ROA Payloads(VRP)。当前稳定版本:0.15.1。
从NLnet Labs仓库安装
在Debian 12或Ubuntu 24.04上:
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release
添加NLnet Labs签名密钥和仓库:
curl -fsSL https://packages.nlnetlabs.nl/aptkey.asc | sudo gpg --dearmor -o /usr/share/keyrings/nlnetlabs-archive-keyring.gpg
Debian:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/nlnetlabs-archive-keyring.gpg] https://packages.nlnetlabs.nl/linux/debian $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/nlnetlabs.list > /dev/null
Ubuntu:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/nlnetlabs-archive-keyring.gpg] https://packages.nlnetlabs.nl/linux/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/nlnetlabs.list > /dev/null
安装Routinator:
sudo apt update
sudo apt install -y routinator
软件包安装一个自动启动的systemd服务。Routinator以routinator用户身份运行。
验证服务
sudo systemctl status routinator
你应该看到active (running)。首次同步需要2到5分钟,期间Routinator获取所有信任锚证书并验证全球ROA集合。
通过查询HTTP API确认初始同步已完成(打包版本以syslog方式记录日志且细节较少,HTTP API是可靠来源):
curl -s http://127.0.0.1:8323/api/v1/status | python3 -c "import sys,json; d=json.load(sys.stdin); print(f'IPv4 VRPs: {d[\"payload\"][\"routeOriginsIPv4\"][\"final\"]}, IPv6 VRPs: {d[\"payload\"][\"routeOriginsIPv6\"][\"final\"]}')"
如果同步仍在进行,计数器将为零。等待2到5分钟后重试。当你看到非零计数(IPv4数十万,IPv6数万),初始同步已完成。
配置
软件包配置位于/etc/routinator/routinator.conf。默认值是安全的:RTR监听127.0.0.1:3323,HTTP监听127.0.0.1:8323。两者都只绑定到localhost。
关键设置:
| 选项 | 默认值 | 用途 |
|---|---|---|
rtr-listen |
["127.0.0.1:3323"] |
路由器RTR服务器 |
http-listen |
["127.0.0.1:8323"] |
HTTP界面和API |
refresh |
600 | RPKI同步间隔(秒) |
retry |
600 | 同步失败后重试等待(秒) |
expire |
7200 | 缓存VRP过期时间(秒) |
如果BIRD2或FRR运行在同一台机器上(VPS BGP设置的典型情况),保持默认的127.0.0.1绑定。无需修改防火墙。
如果你在单独的服务器上运行Routinator,绑定到私有IP并限制访问:
sudo ufw allow from 10.0.0.0/24 to any port 3323 proto tcp comment "RTR from routers"
检查HTTP界面:
curl -s http://127.0.0.1:8323/api/v1/status | head -20
返回包含当前VRP计数、上次同步时间和验证器状态的JSON。
如何在BIRD2中配置RPKI验证?
BIRD2通过rpki协议原生支持RPKI(自BIRD 2.0起可用;Ubuntu 24.04提供BIRD 2.14)。它通过RTR连接到Routinator,填充ROA表,并为导入过滤器提供roa_check()函数。无需外部库。
将以下内容添加到你的BIRD2配置中(通常是/etc/bird/bird.conf):
定义ROA表
roa4 table roa_v4;
roa6 table roa_v6;
配置RPKI协议
protocol rpki rpki_routinator {
roa4 { table roa_v4; };
roa6 { table roa_v6; };
remote 127.0.0.1 port 3323;
retry keep 90;
refresh keep 600;
expire keep 7200;
}
keep关键字告诉BIRD优先使用服务器提供的计时器值,回退到指定的默认值。retry 90表示BIRD在RTR会话断开后90秒重新连接。
向导入过滤器添加ROA验证
filter bgp_import_v4 {
if (roa_check(roa_v4, net, bgp_path.last_nonaggregated) = ROA_INVALID) then {
print "RPKI INVALID: ", net, " from AS", bgp_path.last;
reject;
}
if (roa_check(roa_v4, net, bgp_path.last_nonaggregated) = ROA_VALID) then {
bgp_local_pref = 200;
}
accept;
}
filter bgp_import_v6 {
if (roa_check(roa_v6, net, bgp_path.last_nonaggregated) = ROA_INVALID) then {
print "RPKI INVALID: ", net, " from AS", bgp_path.last;
reject;
}
if (roa_check(roa_v6, net, bgp_path.last_nonaggregated) = ROA_VALID) then {
bgp_local_pref = 200;
}
accept;
}
bgp_path.last_nonaggregated比bgp_path.last更安全,因为它跳过聚合产生的AS_SET条目。无效路由被拒绝。有效路由获得更高的local-pref。Not Found路由以默认local-pref通过。
将过滤器应用到BGP对等
protocol bgp upstream_v4 {
local as 213279;
neighbor 198.51.100.1 as 64500;
ipv4 {
import filter bgp_import_v4;
import table;
export where source ~ [RTS_STATIC, RTS_BGP];
};
}
import table指令很重要。它使BIRD在ROA表变化时重新评估已过滤的路由,无需完全重置会话。
重新加载并验证
sudo birdc configure
检查RPKI会话:
sudo birdc show protocols all rpki_routinator
在输出中查找Established。然后检查ROA表内容:
sudo birdc show route table roa_v4 count
你应该看到数十万条目(2026年初全球ROA表超过800,000个VRP)。
检查特定前缀的验证:
sudo birdc show route 192.0.2.0/24 all
输出包含ROA字段,显示valid、invalid或unknown(not found)。
如何在FRRouting中配置RPKI验证?
FRRouting通过rpki模块支持RPKI,底层使用librtr(Ubuntu 24.04提供FRR 8.4.4;FRR 9.x+和10.x也受支持)。该模块连接到Routinator的RTR服务器并与BGP route-map集成。
安装RPKI模块
在已安装FRR的Debian/Ubuntu上:
sudo apt install -y frr-rpki-rtrlib
启用模块
编辑/etc/frr/daemons,在bgpd选项中添加-M rpki:
bgpd_options=" -A 127.0.0.1 -M rpki"
重启FRR:
sudo systemctl restart frr
验证bgpd加载了模块:
sudo vtysh -c "show rpki cache-server"
如果命令无错误执行(配置缓存之前输出可能为空),模块已加载。如果你得到% Unknown command,-M rpki标志缺失或frr-rpki-rtrlib未安装。
配置RTR缓存
进入vtysh并配置:
sudo vtysh
configure terminal
rpki
rpki cache 127.0.0.1 3323 preference 1
rpki polling_period 300
rpki expire_interval 7200
rpki retry_interval 600
exit
注意:FRR 9.x+使用语法rpki cache tcp 127.0.0.1 3323 preference 1(带有显式tcp关键字)。FRR 8.x使用rpki cache 127.0.0.1 3323 preference 1,不带该关键字。使用vtysh -c "show version"检查你的版本。
为RPKI状态创建route-map
route-map rpki-filter permit 10
match rpki valid
set local-preference 200
exit
route-map rpki-filter deny 20
match rpki invalid
exit
route-map rpki-filter permit 30
match rpki notfound
exit
这接受有效路由并提升local-pref,拒绝无效路由,以默认local-pref接受not-found路由。
将route-map应用到BGP邻居
router bgp 213279
neighbor 198.51.100.1 remote-as 64500
address-family ipv4 unicast
neighbor 198.51.100.1 route-map rpki-filter in
neighbor 198.51.100.1 soft-reconfiguration inbound
exit-address-family
address-family ipv6 unicast
neighbor 2001:db8::1 route-map rpki-filter in
neighbor 2001:db8::1 soft-reconfiguration inbound
exit-address-family
exit
soft-reconfiguration inbound是必需的。没有它,FRR无法在RPKI缓存更新时重新评估现有路由。FRR存储从对等方收到的未修改路由,并在VRP变化时重新应用route-map。
保存配置:
write memory
end
验证
检查RTR连接:
sudo vtysh -c "show rpki cache-connection"
在输出中查找(connected)。然后检查前缀表:
sudo vtysh -c "show rpki prefix-table" | head -20
按验证状态过滤BGP路由:
sudo vtysh -c "show bgp ipv4 unicast rpki valid" | head -20
sudo vtysh -c "show bgp ipv4 unicast rpki invalid"
invalid输出应显示你正在拒绝的路由。
BIRD2与FRR RPKI配置对比
| 特性 | BIRD2 | FRR |
|---|---|---|
| 模块安装 | 内置(无需额外包) | frr-rpki-rtrlib包 + -M rpki标志 |
| RTR配置 | 带remote的protocol rpki块 |
vtysh中的rpki cache命令 |
| ROA表 | 显式roa4/roa6表 |
内部,不直接暴露 |
| 过滤机制 | 导入过滤器中的roa_check() |
route-map中的match rpki |
| 自动重新评估 | import table指令 |
soft-reconfiguration inbound |
| 显示ROA计数 | birdc show route table roa_v4 count |
vtysh show rpki prefix-table |
| 显示验证 | birdc show route ... all(ROA字段) |
vtysh show bgp rpki valid/invalid/notfound |
如何验证前缀的RPKI状态?
创建ROA并配置验证后,从多个角度进行验证。
本地验证
在路由器上确认你自己的前缀显示为有效:
BIRD2:
sudo birdc show route 192.0.2.0/24 all | grep -i roa
FRR:
sudo vtysh -c "show rpki prefix-table 192.0.2.0/24"
两者都应显示你的ASN为授权源。
Routinator HTTP API
curl -s "http://127.0.0.1:8323/api/v1/validity/AS213279/192.0.2.0/24"
返回包含验证状态、匹配VRP和源信任锚的JSON。
bgp.tools
在浏览器中打开https://bgp.tools/prefix/192.0.2.0/24。RPKI列显示绿色盾牌表示Valid,红色表示Invalid,灰色表示Not Found。ROA创建后15到30分钟外部工具才能检测到变化。
RIPE Stat
查询RPKI验证API:
curl -s "https://stat.ripe.net/data/rpki-validation/data.json?resource=AS213279&prefix=192.0.2.0/24" | python3 -m json.tool
在响应中查找"status": "valid"。RIPE Stat还会显示哪些ROA覆盖了该前缀以及maxLength是否匹配。
对IPv6重复
使用你的IPv6前缀运行相同的检查。上述每个命令都接受IPv6前缀。将192.0.2.0/24替换为2001:db8::/48,验证两个地址族都被覆盖。
为什么应避免将maxLength设置为大于前缀长度?
将maxLength设置为等于你的前缀长度。这是RFC 9319(更新并扩展了RFC 7115)的建议。
当你在/20的ROA上将maxLength设置为/24时,你授权你的ASN宣告/20以及到/24的每个more-specific。这意味着16个/24被覆盖。攻击者以你的ASN为源劫持其中一个/24将通过RPKI验证为"Valid"。被劫持的more-specific通过最长匹配路由获胜,ROA无法帮助你,因为你授权了该长度。
这被称为伪造源子前缀劫持(forged-origin sub-prefix hijack)。RFC 9319引用的2017年测量发现,使用maxLength的ROA中84%容易受到此攻击。
具体示例:
| ROA | 授权内容 |
|---|---|
192.0.2.0/20, maxLength /20 |
仅你的ASN的192.0.2.0/20。安全。 |
192.0.2.0/20, maxLength /24 |
你的ASN的/20、/21、/22、/23、/24。任何/24都可以通过伪造你的源ASN被劫持。 |
何时maxLength > 前缀长度可接受? 仅当你在生产中确实进行去聚合时(例如宣告/20和特定/24用于流量工程),且每个去聚合的前缀需要验证。在这种情况下,为每个宣告的前缀创建单独的ROA,而不是一个宽maxLength的ROA。每个公告一个ROA是最安全的模式。
DDoS缓解例外: 如果你使用清洗中心等服务,该服务从你的ASN重新宣告你的more-specific,你可能需要maxLength来覆盖这些前缀。记录此例外并定期审计。
RPKI缓存宕机时会发生什么?
当Routinator停止或不可达时,路由器的行为取决于过期计时器。
BIRD2将最后已知的ROA表保留在内存中,持续时间为expire(默认7200秒/2小时)。在此窗口内,验证使用过期数据正常继续。过期后,BIRD删除所有ROA条目,每条路由回退为"Not Found"。不会因无效而拒绝路由,但也不会获得有效的local-pref加成。
FRR行为类似。rpki expire_interval控制RTR连接断开后缓存VRP保持可用的时间。
降低风险
运行第二个Routinator实例或在单独的机器上使用不同的验证器(StayRTR、Fort)。将两者都配置为RTR源。
BIRD2支持多个protocol rpki块:
protocol rpki rpki_backup {
roa4 { table roa_v4; };
roa6 { table roa_v6; };
remote 10.0.0.2 port 3323;
retry keep 90;
refresh keep 600;
expire keep 7200;
}
FRR支持多个具有不同偏好的缓存服务器:
rpki
rpki cache 127.0.0.1 3323 preference 1
rpki cache 10.0.0.2 3323 preference 2
exit
偏好值较低的优先尝试。主服务器宕机时FRR回退到备用服务器。
监控Routinator健康状态。 使用你的监控系统检查systemctl status routinator和HTTP API状态端点。VRP计数骤降(突然降至零意味着同步失败)和RTR连接丢失(在journalctl -u routinator中可见)时发出告警。
故障排除
创建后ROA显示"Not Found"。 传播需要10到20分钟。Routinator默认每10分钟同步一次(refresh = 600)。强制重启同步:sudo systemctl restart routinator,然后等待初始同步完成。
birdc显示ROA表中有0条目。 检查birdc show protocols all rpki_routinator。如果状态不是"Established",验证Routinator正在运行并监听3323端口:ss -tlnp | grep 3323。
FRR的rpki显示"Unknown command"。 /etc/frr/daemons中缺少-M rpki标志或frr-rpki-rtrlib未安装。安装软件包,添加标志,重启FRR。
ROA变更后路由未重新评估。 在BIRD2中,向BGP通道添加import table;。在FRR中,在邻居上启用soft-reconfiguration inbound。
所有路由显示Invalid。 你的ROA可能有错误的ASN或前缀。在RIPE门户中仔细检查。同时确认路由器的ASN与ROA中填写的一致。
后续步骤:将RPKI验证与prefix-list和AS-path过滤器结合以实现纵深防御 。使用BGPalerter监控前缀的RPKI invalid告警 。
Copyright 2026 Virtua.Cloud. All rights reserved.