ROA Setup
By default, BIRD inherently trusts all routes that have been announced to it by its' peers. This means that a bad actor would be able to enter the network, and announce routes that it doesn't actually own. To partially solve this problem, you can use ROA (Route Origin Authorization).
To set up ROA, you first need an ROA file. As a part of the NX3 network we maintain a registry (https://git.brettb.xyz/nx3/registry). If you so desired, you could generate ROA files by hand, but that's no fun. Instead, you can get pre-made ROA files for BIRD from the registry explorer.
| URL |
Purpose |
| https://explorer.nx3.xu2.cc/api/roa/bird/2/4.conf | IPv4 ROA BIRD2 Configuration |
| https://explorer.nx3.xu2.cc/api/roa/bird/2/6.conf | IPv6 ROA BIRD2 Configuration |
| https://explorer.nx3.xu2.cc/api/roa/bird/2/46.conf | IPv4 + IPv6 ROA BIRD2 Configuration |
In order to enable ROA in the BIRD configuration, you'll want to uncomment these sections:
roa4 table nx3_roa;
roa6 table nx3_roa_v6;
protocol static {
roa4 { table nx3_roa; };
include "/etc/bird/roa_nx3.conf";
};
protocol static {
roa6 { table nx3_roa_v6; };
include "/etc/bird/roa_nx3_v6.conf";
};
as well as modify the nxpeers template to reflect the changes:
template bgp nxpeers {
local as OWNAS;
multihop;
ipv4 {
import filter {
if is_valid_network() && !is_self_net() then {
if (roa_check(nx3_roa, net, bgp_path.last) != ROA_VALID) then {
# Reject when unknown or invalid according to ROA
print "[nx3] ROA check failed for ", net, " ASN ", bgp_path.last;
reject;
} else accept;
# accept;
} else reject;
};
export filter { if is_valid_network() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; };
import limit 9000 action block;
};
ipv6 {
import filter {
if is_valid_network_v6() && !is_self_net_v6() then {
if (roa_check(nx3_roa_v6, net, bgp_path.last) != ROA_VALID) then {
# Reject when unknown or invalid according to ROA
print "[nx3] ROA check failed for ", net, " ASN ", bgp_path.last;
reject;
} else accept;
# accept;
} else reject;
};
export filter { if is_valid_network_v6() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; };
import limit 9000 action block;
};
}
To automate the pulling and updating of the ROA tables, we can use a timer and systemd service file:
# /etc/systemd/system/roa-update.service
[Unit]
Description=Update ROAs of NX3
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'curl -sfSLR {-o,-z}/etc/bird/roa6_nx3.conf "https://explorer.nx3.xu2.cc/api/roa/bird/2/6.conf" && curl -sfSLR {-o,-z}/etc/bird/roa4_nx3.conf "https://explorer.nx3.xu2.cc/api/roa/bird/2/4.conf" && sed -i "s/roa/route/g" /etc/bird/roa{4,6}_nx3.conf && birdc configure'
# /etc/systemd/system/roa-update.timer
[Unit]
Description=Update ROAs of NX3
[Timer]
OnUnitActiveSec=10m
[Install]
WantedBy=timers.target
And in order to start the automatic ROA update process, you'll want to run:
systemctl daemon-reload
systemctl enable roa-update.timer
systemctl restart roa-update.timer
Following these instructions, your ROA files will automatically be updated every 10 minutes, reloading BIRD after the updates.