bird-filter/README.md

302 lines
9.3 KiB
Markdown
Raw Normal View History

2023-09-16 22:29:30 -04:00
# Quantum's `bird` Filter Library
This is meant to be a starter repository containing sample `bird` 2.x config
files that you can use to build your own BGP filters. Filters are provided as
composable `bird` functions and enables you to harness the full power of the
`bird` filter mini-programming language, as an alternative to a more declarative
solution like [PathVector][pv].
## Quick start
1. Make sure `bird` 2.x is installed, e.g. on Debian or Ubuntu, through
`sudo apt install bird2`. This library has not been tested on versions
older than 2.0.13, so you may run into syntax errors on earlier versions.
In these cases, you'll need to look into backports or PPAs for a newer
version.
2023-09-16 22:29:30 -04:00
2. Clone this repository:
```
git clone https://github.com/quantum5/bird-filter.git
cd bird-filter
```
3. Customize [`filter_bgp.conf`][filter] by editing it. Pay special attention
to anything tagged `FIXME`.
4. Install `filter_bgp.conf` into your `bird` configuration directory
(`/etc/bird` by default):
```
sudo cp filter_bgp.conf /etc/bird
```
## Defining BGP sessions
2023-10-07 00:48:28 -04:00
You can use [`skeleton.conf`][skeleton] as a basic `bird` starting config.
Remember to read the `NOTE`s and change the things marked `FIXME`.
Also note that in this config, static protocol routes are internal to `bird`
and will not be exported to the kernel routing table. You can change this by
changing the export rules for `protocol kernel`.
2023-09-16 22:29:30 -04:00
This filter library makes use of two basic static protocols:
* `node_v4`: IPv4 routes to be exported by the `export_cone` helper.
* `node_v6`: IPv6 routes to be exported by the `export_cone` helper.
For example, to advertise `198.51.100.0/24` and `2001:db8:1000::/36`:
```
protocol static node_v4 {
ipv4 {};
route 198.51.100.0/24 reject;
}
protocol static node_v6 {
ipv6 {};
route 2001:db8:1000::/36 reject;
}
```
Two additional static protocols are used to aid with traffic engineering for
anycast prefixes:
* `node_v4_anycast`: IPv4 routes to be exported by the `export_anycast` helper.
* `node_v6_anycast`: IPv6 routes to be exported by the `export_anycast` helper.
You can add `protocol` blocks to this config for each BGP neighbour. This is
dependent on the neighbour type.
In the follow examples, we assume the following local preferences:
* 50 for upstreams;
* 90 for IXPs;
* 100 for direct peers; and
* 120 for downstreams.
### Upstreams
```
protocol bgp example_upstream_v4 {
description "Example Upstream (IPv4)";
local 192.0.2.25 as 64500;
neighbor 192.0.2.24 as 64501;
default bgp_local_pref 50;
ipv4 {
import keep filtered;
import where import_transit(64501, false);
export where export_cone(64501);
};
}
protocol bgp example_upstream_v6 {
description "Example Upstream (IPv6)";
local 2001:db8:2000::2 as 64500;
neighbor 2001:db8:2000::1 as 64501;
default bgp_local_pref 50;
ipv6 {
import keep filtered;
import where import_transit(64501, false);
export where export_cone(64501);
};
}
```
The example above assumes you are AS64500 and establishes BGP sessions over
both IPv4 and IPv6 with an upstream AS64501 and exports your entire cone. It
also assumes your upstream is sending you a full table and filters out the
default route. If you expect a default route instead, use
`import where import_transit(64501, true)`.
To export your anycast as well, you can simply do
`export where export_cone(64501) || export_anycast()`.
### Peers
```
protocol bgp example_peer_v4 {
description "Example Peer (IPv4)";
local 192.0.2.25 as 64500;
neighbor 192.0.2.28 as 64502;
default bgp_local_pref 100;
ipv4 {
import keep filtered;
import where import_peer_trusted(64502);
export where export_cone(64502);
};
}
protocol bgp example_peer_v6 {
description "Example Peer (IPv6)";
local 2001:db8:2000::2 as 64500;
neighbor 2001:db8:2000::10 as 64502;
default bgp_local_pref 100;
ipv6 {
import keep filtered;
import where import_peer_trusted(64502);
export where export_cone(64502);
};
}
```
The example above assumes you are AS64500 and establishes BGP sessions over
both IPv4 and IPv6 with a peer AS64502 and exports your entire cone. It assumes
your peer is trusted and doesn't provide any IRR filtering. If you don't trust
your peer, see the [IRR filtering](#irr-filtering) section below.
### IXP route servers
```
protocol bgp example_ixp_v4 {
description "Example IXP Route Servers (IPv4)";
local 203.0.113.3 as 64500;
neighbor 203.0.113.1 as 64503;
default bgp_local_pref 90;
ipv4 {
import keep filtered;
import where import_ixp_trusted(64503);
export where export_cone(64503);
};
}
protocol bgp example_ixp_v6 {
description "Example IXP Route Servers (IPv6)";
local 2001:db8:3000::3 as 64500;
neighbor 2001:db8:3000::1 as 64503;
default bgp_local_pref 90;
ipv6 {
import keep filtered;
import where import_ixp_trusted(64503);
export where export_cone(64503);
};
}
```
The example above assumes you are AS64500 and establishes BGP sessions over
both IPv4 and IPv6 with the IXP route server whose ASN is 64503 and exports
your entire cone. It assumes your IXP is trusted and doesn't provide any IRR
filtering. If you don't trust your IXP, see the [IRR filtering](#irr-filtering)
section below.
### Downstreams
```
protocol bgp example_downstream_v4 {
description "Example Downstream (IPv4)";
local 203.0.113.3 as 64500;
neighbor 203.0.113.7 as 64504;
default bgp_local_pref 120;
ipv4 {
import keep filtered;
import where import_downstream(64504, IRR_DOWNSTREAM_V4, IRR_DOWNSTREAM_ASN);
export where export_to_downstream();
};
}
protocol bgp example_downstream_v6 {
description "Example Downstream (IPv6)";
local 2001:db8:3000::3 as 64500;
neighbor 2001:db8:3000::7 as 64504;
default bgp_local_pref 120;
ipv6 {
import keep filtered;
import where import_downstream(64504, IRR_DOWNSTREAM_V6, IRR_DOWNSTREAM_ASN);
export where export_to_downstream();
};
}
```
The example above assumes you are AS64500 and establishes BGP sessions over
both IPv4 and IPv6 with a downstream whose ASN is 64504 and exports all your
routes. For your protection, downstream imports without IRR is *not* supported.
For details about setting up IRR, see the [IRR filtering](#irr-filtering)
section below.
2023-09-29 02:15:19 -04:00
### Route collectors
```
protocol bgp route_collector {
description "Exaple Route Collector";
local 2001:db8:2000::2 as 64500;
neighbor 2001:db8:9000::1 as 64505;
multihop;
ipv4 {
add paths on;
import none;
export where export_monitoring();
};
ipv6 {
add paths on;
import none;
export where export_monitoring();
};
}
```
The example above assumes you are AS64500 and establishes a multihop BGP
session with your route collector over IPv6, using multiprotocol BGP to export
routes for both IPv4 and IPv6 in a single session, using `add paths` to also
all routes instead of the best routes available.
2023-09-16 22:29:30 -04:00
## BGP communities
The following large informational communities are implemented by default:
* `YOUR_ASN:1:x`: route received from IXP with ID x;
* `YOUR_ASN:2:x`: route received from neighbour with ASN x;
* `YOUR_ASN:3:100`: route received from peer;
* `YOUR_ASN:3:101`: route received from IXP route server;
* `YOUR_ASN:3:102`: route received from upstream; and
* `YOUR_ASN:3:103`: route received from downstream.
The following large control communities are implemented by default and can be
used by downstreams:
* `YOUR_ASN:10:x`: do not export route to ASx;
* `YOUR_ASN:11:x`: prepend `YOUR_ASN` once upon export to ASx;
* `YOUR_ASN:12:x`: prepend `YOUR_ASN` twice upon export to ASx; and
* `YOUR_ASN:12:x`: prepend `YOUR_ASN` thrice upon export to ASx.
## IRR filtering
1. Follow [`irr-filters.example`][irr-conf] and create `/etc/bird/irr-filters`
for the peers you would like to filter. (To use alternative locations, edit
[`make-irr-filter`][irr-script] accordingly.)
2. Run `make-irr-filter` to re-generate IRR filters.
3. Add `include "filter_irr.conf";` into your `bird.conf`.
4. Instead of `import_peer_trusted(asn)` or `import_ixp_trusted(ixp_id)`, use
`import_peer(asn, IRR_PEER_V4, IRR_PEER_ASN)` or
`import_peer(asn, IRR_PEER_V6, IRR_PEER_ASN)`, and similarly for IXPs.
5. Create a cron job that runs `make-irr-filter` followed by `birdc configure`.
Daily is a reasonable cadence.
2023-09-26 21:07:17 -04:00
## RPKI filtering
While this filter library implements RPKI, you still need to populate the
`rpki4` and `rpki6` routing tables via an `rpki` protocol in `bird`. Otherwise,
all routes will be treated as RPKI unknown. This can be configured as follows:
```
protocol rpki {
roa4 { table rpki4; };
roa6 { table rpki6; };
transport tcp;
remote "127.0.0.1" port 9001;
retry keep 90;
refresh keep 900;
expire keep 172800;
}
```
The example above assumes you are running the RTR protocol on `127.0.0.1:9001`.
This may be provided by something like Routinator, `rtrtr`, `gortr`, or
something similar. I recommend using `rtrtr` to pull a JSON feed from someone's
Routinator instance over HTTPS.
2023-09-16 22:29:30 -04:00
[pv]: https://pathvector.io/
[filter]: filter_bgp.conf
[skeleton]: skeleton.conf
[irr-conf]: irr-filters.example
[irr-script]: make-irr-filter