Skip to main content

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.