merge existing and new documentation for bird

Signed-off-by: Marek Küthe <m.k@mk16.de>
This commit is contained in:
Marek Küthe 2023-01-02 00:47:52 +01:00
parent 482c896bfc
commit 666df1ec72
No known key found for this signature in database
GPG Key ID: 7E869146699108C7
5 changed files with 519 additions and 481 deletions

View File

@ -1,273 +0,0 @@
# Alternative bird configuration
This is an alternative bird configuration.
Due to the low complexity of the CRXN network, all configuration data is written to a file. It is also possible to split them into several files.
## Configuration
```
define OWNIP = <OWNIP>;
define OWNNET = <OWNNET>;
define OWNNETSET = [<OWNNET>+];
define RID = <RID>;
define HOSTNAME = "<HOSTNAME>";
router id RID;
hostname HOSTNAME;
ipv6 table crxn;
function is_self_net() {
return net ~ OWNNETSET;
}
function is_valid_network() {
return net ~ [
fd00::/8{44,64}
];
}
function reject_default_route() {
if (net = fd00::/8 || net = ::/0) then
reject;
}
function crxn_import_filter() {
if (net.type != NET_IP6 || ! is_valid_network() || is_self_net()) then
reject;
reject_default_route();
accept;
}
function crxn_export_filter() {
if ( ! is_valid_network() ) then
reject;
if (source !~ [RTS_STATIC, RTS_BABEL]) then
reject;
reject_default_route();
accept;
}
protocol static ownnet {
route OWNNET unreachable;
ipv6 {
table crxn;
export all;
};
}
protocol kernel {
ipv6 {
table crxn;
import none;
export filter {
krt_prefsrc = OWNIP;
accept;
};
};
}
protocol babel crxn_net {
interface "crxn_peer1" {
type wired;
rxcost 30;
};
ipv6 {
table crxn;
import where crxn_import_filter();
import limit 2000 action block;
export where crxn_export_filter();
};
}
protocol device {}
```
`<OWNIP>` is replaced by an IP address from its own subnet. Often `xxxx::1` is used for the router. `<OWNNET>` is replaced by its subnet or the part you want to propagate. If you have only one node, you can enter your whole /48 network. If you have several nodes and want to give each node a smaller network (e.g. /56 or /52), enter it here.
`<RID>` is a random IPv4 address which is used as unique identifier of the bird instance. You cannot peer with a peer that has the same router ID.
`<HOSTNAME>` can be replaced with the hostname of the router. This can be any string.
```
router id RID;
hostname HOSTNAME;
```
Here the router ID and hostname bird entered above is communicated.
```
ipv6 table crxn;
```
Here an IPv6 routing table with the name `crxn` is created. Alternatively, you can also use the default routing table `master6`. You do not have to create the `master6` table separately.
Next comes a set of utility functions that will later help us build the filters.
```
function is_self_net() {
return net ~ OWNNETSET;
}
```
This function returns `true` if the net is the own, otherwise `false`.
```
function is_valid_network() {
return net ~ [
fd00::/8{44,64}
];
}
```
The CRXN network uses IP addresses in the ULA range (`fd80::/8`). Here it is checked whether the network is in this range. This function can be used if you want to prevent clearnet addresses from being imported. Furthermore two limits are set with `{44,64}`: A net may have a maximum size of 64 and a minimum size of 44. The limitation of `/64` is to prevent the routing table from becoming too large. For example, someone could otherwise carry out an attack by propagating very many `/128` addresses. This prevents such an attack.
```
function reject_default_route() {
if (net = fd00::/8 || net = ::/0) then
reject;
}
```
If a router is misconfigured, it may happen that a default route is exported. A default route is `::/0` in the Clearnet and `fd00::/8` in the ULA range. If you propagate this, you say that you can reach any address. However, if an address is unknown, you want to get an ICMP unreachable or an ICMP No route. If you now import a default route, you would export the request to the peer that sends the default route, which would result in not getting an ICMP message.
Next we build the import and export filters:
```
function crxn_import_filter() {
if (net.type != NET_IP6 || ! is_valid_network() || is_self_net()) then
reject;
reject_default_route();
accept;
}
```
There are three creteria where we do not want to import a route: 1) It is not an IPv6 route. CRXN is an IPv6 network. This setting prevents misconfiguration. 2) The network is not in ULA range. 3) It is the own network.
You yourself what best how to reach your own network. One exports it to others. However, someone can try to hjack your network. For example by exporting a smaller (and therefore more precise) prefix. There are several ways to prevent this. One is to not participate in the attack on yourself. Therefore, not to import your own network from others.
Furthermore, we reject the Default Routes. If the route still exists afterwards, we import it.
```
function crxn_export_filter() {
if ( ! is_valid_network() ) then
reject;
if (source !~ [RTS_STATIC, RTS_BABEL]) then
reject;
reject_default_route();
accept;
}
```
To prevent misconfiguration on our own router, we filter out any non-ULA network and default route during export.
Furthermore, we only export routes which we have learned statically (see below) (`RTS_STATIC`) or which we have learned over others via Babel (`RTS_BABEL`).
```
protocol static ownnet {
route OWNNET unreachable;
ipv6 {
table crxn;
export all;
};
}
```
Next, we create a static route for our own network and export it to the routing table `crxn`. If you use the table `master6` you can omit the `table crxn;` statement. We say bird that our own network is not reachable. This ensures that bird now knows a route to our network and exports it. However, we ourselves can still reach devices on our network because they have a more precise prefix and longest prefix match applies.
```
protocol kernel {
ipv6 {
table crxn;
import none;
export filter {
krt_prefsrc = OWNIP;
accept;
};
};
}
```
In routing, a distinction is made between "Control Plane" and "Forwarding Plane". The control plane calculates the routes and passes them on to the forwarding plane. The forwarding plane then accepts the packets and forwards them accordingly. On a Linux router, bird is the control plane and the kernel is the forwarding plane, since the kernel is responsible for forwarding IP packets.
With `krt_prefsrc` we specify our source IP address. This is the addresses defined above. This address must exist on an interface. It is generally bound to a dummy interface.
Advantage and disadvantage of `persist`:
The keyword `persist` can be used to prevent bird from deleting routes from the forwarding plane. Only routes will be updated. The advantage of this is that when bird is terminated, the forwarding plane still knows the routes to the destinations. The disadvantage is that routes that are no longer propagated are retained. If the control plane no longer knows a route to a particular prefix, using `persist` will not delete the route from the forwarding plane. This can lead to some strange routing.
```
protocol babel crxn_net {
interface "crxn_peer1" {
type wired;
rxcost 30;
};
ipv6 {
table crxn;
import where crxn_import_filter();
import limit 2000 action block;
export where crxn_export_filter();
};
}
```
Here we create the Babel protocol, which is used to communicate with other CRXN routers. The protocol consists of `interface` and `ipv6` among others. The `interface` can occur several times, `ipv6` not.
In `ipv6` our import/export filters and our routing table `crxn` are defined accordingly. Furthermore an import limit of 2000 routes is set. If a malicious actor now tries to crash a router, for example by propagating a lot of routes, we protect ourselves with this. If 2000 routes are imported via CRXN, every further route is blocked. Although we protect our memory with this, a high rejection of routes can lead to an increased CPU load.
With `interface "crxn*";` you can mark any interface starting with `crxn` as a peer, but then you cannot fine-tune a peer.
Therefore it makes sense to define a separate interface for each peer. As `type` there are `wired` and `wireless`. In general `wired` is always used. According to the `type` parameter babel is adjusted. With `rxcost` we define the "cost", which a peer needs to us. Without specification this is 96. Here it is recommended to take the latency as cost. If you want to avoid that packets are routed through you, you can increase the cost.
In this example, there is a connection to our peer via the interface `crxn_peer1`. This is a wired connection with a latency of 30ms.
```
protocol device {}
```
The protocol `device` is mandatory in bird. This allows bird to communicate with the router. This is necessary for bird to get information about interfaces and the like.
## Network
Babel uses port 6696/udp and the multicast address `ff02::1:6`. Accordingly, port 6696/udp must be enabled locally.
## Control
These commands can be entered with in `birdc`:
To display all Babel peers you can use the following:
```
show babel neighbors
```
or
```
show babel n
```
View all CRXN routes:
```
show route protocol crxn
```
View all CRXN routes with details:
```
show route protocol crxn all
```
Display all the routes that you export:
```
show route export crxn
```
Display all the routes that you export with details:
```
show route export crxn all
```
Reload configuration:
```
configure
```
or
```
c
```
Help can be obtained by typing the command and then a `?`.

View File

@ -15,10 +15,6 @@ differs slightly but we recommend (and for the rest of this document we will be)
Bird 2 as it comes with many bug fixes and improvements and most distributions (including Debian)
now have support for it.
## Alternative bird configuration
A guide to an alternative configuration with similar functionality can be found at [here](bird-alternative).
## Installation
In order to install the BIRD daemon on your machine you should look for a package named `bird2` or something
@ -39,254 +35,280 @@ This will ensure that the routing daemon starts on boot.
## Configuration
In this section we will be configuring two files:
Due to the low complexity of the CRXN network, all configuration data is written to a file. It is also possible to split them into several files.
1. `bird.conf`
* For general BIRD configuration e.g. _router IDs_, _device protocol_ and _includes_
2. `crxn.conf`
* For CRXN-specific details
### Full example
### Basics
`<OWNIP>` is replaced by an IP address from its own subnet. Often `xxxx::1` is used for the router. `<OWNNET>` is replaced by its subnet or the part you want to propagate. If you have only one node, you can enter your whole /48 network. If you have several nodes and want to give each node a smaller network (e.g. /56 or /52), enter it here.
`<RID>` is a random IPv4 address which is used as unique identifier of the bird instance. You cannot peer with a peer that has the same router ID.
`<HOSTNAME>` can be replaced with the hostname of the router. This can be any string.
There are some basic definition that we are required to add to our configuration file. BIRD is normally configured to use the base configuration stored at something like `/etc/bird/bird.conf` or `/etc/bird.conf`, so open that file up and add the following to it.
#### Router ID
Every BIRD daemon is required to have what is known as a router ID which is written in the form of an IPv4 address. Now this does not actually need to be a valid IPv4 address in the sense of one you actually use but rather it just needs to follow the format, hence a router ID such as `1.1.1.1` is fine, despite you not "owning it".
Define the router ID as the first line in the configuration file like so:
BIRD is normally configured to use the base configuration stored at something like `/etc/bird/bird.conf` or `/etc/bird.conf`, so open that file up and add the following to it.
```
router id 1.1.1.1;
```
define OWNIP = <OWNIP>;
define OWNNET = <OWNNET>;
define OWNNETSET = [<OWNNET>+];
TODO: These need to be unique - check how much this applies etc
define RID = <RID>;
define HOSTNAME = "<HOSTNAME>";
These router IDs are required to be unique as they are used in the various protocols that BIRD supports in order to determine where a route advertisement came from - see them as a unique identifier of your BIRD router. Failing to do so will cause issues when routing on CRXN **and** a banning (TODO: see how we can enforce this).
router id RID;
hostname HOSTNAME;
#### Device protocol
ipv6 table crxn;
BIRD supports many protocols which are used to import routing data from and export routing data to. However, the most basic of protocols which BIRD supports is known as the `device` protocol. The job of this protocol is just to provide basic device information to BIRD over time, it is required but luckily does not require much setup.
All that is required for this protocol to work is the following:
```
protocol device
{
# Optional parameters go here
function is_self_net() {
return net ~ OWNNETSET;
}
function is_valid_network() {
return net ~ [
fd00::/8{44,64}
];
}
function reject_default_route() {
if (net = fd00::/8 || net = ::/0) then
reject;
}
function crxn_import_filter() {
if (net.type != NET_IP6 || ! is_valid_network() || is_self_net()) then
reject;
reject_default_route();
accept;
}
function crxn_export_filter() {
if ( ! is_valid_network() ) then
reject;
if (source !~ [RTS_STATIC, RTS_BABEL]) then
reject;
reject_default_route();
accept;
}
protocol static ownnet {
route OWNNET unreachable;
ipv6 {
table crxn;
export all;
};
}
protocol kernel {
ipv6 {
table crxn;
import none;
export filter {
krt_prefsrc = OWNIP;
accept;
};
};
}
protocol babel crxn_net {
interface "crxn_peer1" {
type wired;
rxcost 30;
};
ipv6 {
table crxn;
import where crxn_import_filter();
import limit 2000 action block;
export where crxn_export_filter();
};
}
protocol device {}
```
You can adjust [scan times and such](https://bird.network.cz/?get_doc&v=20&f=bird-6.html#ss6.4) but the kernel normally will signal any changes to BIRD.
#### Includes
BIRD allows one to source configuration file contents from other files. Seeing that we will configure the CRXN-specific parts next we will want to include that file in the main entry file (`bird.conf`), this can be accomplished by placing this line at the bottom of said file:
### Explanation
```
include "/etc/crxn.conf";
router id RID;
hostname HOSTNAME;
```
### CRXN-specific setup
The below sections all apply to the CRXN-specific configuration and are to be placed in the file `/etc/crxn.conf`.
### Tables
We need to define the routing tables that BIRD will use in its process to store the routes that we want to learn from other routers and also advertise. Such a definition looks as follows:
Here the router ID and hostname bird entered above is communicated.
```
# Define the IPv6 BIRD table
ipv6 table crxn;
```
Here an IPv6 routing table with the name `crxn` is created. Alternatively, you can also use the default routing table `master6`. You do not have to create the `master6` table separately.
You can choose any name for the table you want but you will just need to remember it such that you can refer to it later when it is needed.
### Filters
We need to define a filter which will be used to filter out any incorrect routes we want to advertise _to_ the network but also prevents any incorrect routes that are being propagated _from_ any misconfigured BIRD instances on the network:
Next comes a set of utility functions that will later help us build the filters.
```
filter crxnFilter
{
if (net ~ fd00::/8) then accept;
reject;
function is_self_net() {
return net ~ OWNNETSET;
}
```
TODO: Add a check about not installing RTD_UNREACHABLEs which babel will generate sometimes and which BIRD reportedly has undefined behavior with
### Direct protocol
This provides BIRD with a manner of picking up the `subnet/prefix` pair that is assigned to local interfaces such that these can be imported into BIRD and later advertised.
This function returns `true` if the net is the own, otherwise `false`.
```
protocol direct crxnDirect
{
ipv6
{
table crxn;
import filter crxnFilter;
};
# Interfaces to find neighbors on
interface "eth*";
function is_valid_network() {
return net ~ [
fd00::/8{44,64}
];
}
```
### Kernel protocol
We need to sync the routes from the BIRD routing table `crxn` to the actual kernel's routing table such that it can be used in forwarding decisions. This is accomplished with the following declaration:
The CRXN network uses IP addresses in the ULA range (`fd80::/8`). Here it is checked whether the network is in this range. This function can be used if you want to prevent clearnet addresses from being imported. Furthermore two limits are set with `{44,64}`: A net may have a maximum size of 64 and a minimum size of 44. The limitation of `/64` is to prevent the routing table from becoming too large. For example, someone could otherwise carry out an attack by propagating very many `/128` addresses. This prevents such an attack.
```
protocol kernel crxnKernel
{
function reject_default_route() {
if (net = fd00::/8 || net = ::/0) then
reject;
}
```
If a router is misconfigured, it may happen that a default route is exported. A default route is `::/0` in the Clearnet and `fd00::/8` in the ULA range. If you propagate this, you say that you can reach any address. However, if an address is unknown, you want to get an ICMP unreachable or an ICMP No route. If you now import a default route, you would export the request to the peer that sends the default route, which would result in not getting an ICMP message.
Next we build the import and export filters:
```
function crxn_import_filter() {
if (net.type != NET_IP6 || ! is_valid_network() || is_self_net()) then
reject;
reject_default_route();
accept;
}
```
There are three creteria where we do not want to import a route: 1) It is not an IPv6 route. CRXN is an IPv6 network. This setting prevents misconfiguration. 2) The network is not in ULA range. 3) It is the own network.
You yourself what best how to reach your own network. One exports it to others. However, someone can try to hjack your network. For example by exporting a smaller (and therefore more precise) prefix. There are several ways to prevent this. One is to not participate in the attack on yourself. Therefore, not to import your own network from others.
Furthermore, we reject the Default Routes. If the route still exists afterwards, we import it.
```
function crxn_export_filter() {
if ( ! is_valid_network() ) then
reject;
if (source !~ [RTS_STATIC, RTS_BABEL]) then
reject;
reject_default_route();
accept;
}
```
To prevent misconfiguration on our own router, we filter out any non-ULA network and default route during export.
Furthermore, we only export routes which we have learned statically (see below) (`RTS_STATIC`) or which we have learned over others via Babel (`RTS_BABEL`).
```
protocol static ownnet {
route OWNNET unreachable;
ipv6 {
# bird's crxn table -> kernel
table crxn;
export filter crxnFilter;
export all;
};
persist;
}
```
1. The `persist` option means that when BIRD exits it will not flush the routing table. This is useful if you want to do maintenance and still want to allow forwarding of traffic for a little while (of course other routers may expire routes to you but at least not that fast)
---
Old stuff below WIP):
TODO: Re-do this sections
The configuration template is constructed out of the following files:
1. `filters.conf`
* Filter functions and the filter itself
2. `networks.conf`
* Advertisement of ULA
3. `tables.conf`
* The table definitions
4. `router.conf`
* This contains the needed protocol definition for discovering
your interface's prefixes and generating routes form them
* It also contains the needed protocol definitions to sync bird
routes into the Linux kernel's routing table (so you cna forward
packets based on the routes from Bird)
5. `protocols.conf`
* Depending on what protocol you want to use this will contains
configurations for each
All of these will be included in a file saved at `/etc/bird/bird.conf` like so:
Next, we create a static route for our own network and export it to the routing table `crxn`. If you use the table `master6` you can omit the `table crxn;` statement. We say bird that our own network is not reachable. This ensures that bird now knows a route to our network and exports it. However, we ourselves can still reach devices on our network because they have a more precise prefix and longest prefix match applies.
```
router id <ipv4>;
include "/etc/bird/crxn/tables.conf";
include "/etc/bird/crxn/filters.conf";
include "/etc/bird/crxn/router.conf";
include "/etc/bird/crxn/networks.conf";
```
Additionally, add the files for the route distribution protocol which we configure in the next steps.
```
include "/etc/bird/crxn/babel.conf"; # For babel routing
include "/etc/bird/crxn/ospfv3.conf"; # For OSPFv3 routing
```
Remember to set a unique router ID in `<ipv4>`, make it anything - it doesn't have to even be an address you own.
#### `filters.conf`
This file holds all the required functions for subnet matching and also
filters that match to the specific prefix aggregates (regional subnets)
that CRXN uses.
```
filter crxnFilter
{
if (net ~ fd00::/8) then accept;
reject;
}
```
#### `tables.conf`
This file holds all table definitions. There are only two actually.
The table `crxn` is the one we actually use, `master` is optional
and is only present because if one uses `bird-lg-go` (the looking glass
we use) then it, by default, only shows routes in the `master` table.
It is meant to have the same routes as the `crxn` table.
```
# CRXN table
ipv6 table crxn;
```
#### `router.conf`
This contains an instance of the `direct` protocol which reads the address
and prefix assigned to your AF_INET6 interfaces and generates routes from
those that represent routes to directly atrtached networks those interfaces
are on. The reason for this is that the `kernel` protocol never learns routes
in the Linux kernel's routing table that have the `kernel` protocol which
is what you get when you assign interfaces addresses and prefixes. This
doesn't even need those, it gets them from the interface.
```
# The kernel protocol doesn't grab kernel routes that are added by you when you assign an
# address and prefix. So instead of reading this from all routes with `proto kernel` this just
# yeets the routes off of the interface structure itself (even if you didn't have a route for your
# directly attached networks - i.e. nexthop = 0.0.0.0)
protocol direct crxnDirect
{
ipv6
{
table crxn;
import filter crxnFilter;
};
# Interfaces to find neighbours on
interface "eth*";
}
protocol device {
}
```
The second part is for syncing routes from Bird to the Linux kernel's routing
table such that you can forward traffic based on the routes in Bird.
TODO: Check, defualt `learn` should learn non `kernel` and non-`bird` routes
```
# CRXN Kernel protocol
# We import any routes from the kernel table other than `proto bird` and `proto kernel`,
# could be `proto static` for example. By default it will learn these.
# Of course we also then export all routes from our Bird tables into the kernel so you can actually forward packets
protocol kernel crxnKernel
{
protocol kernel {
ipv6 {
# bird's crxn table -> kernel
table crxn;
export filter crxnFilter;
import none;
export filter {
krt_prefsrc = OWNIP;
accept;
};
};
}
```
In routing, a distinction is made between "Control Plane" and "Forwarding Plane". The control plane calculates the routes and passes them on to the forwarding plane. The forwarding plane then accepts the packets and forwards them accordingly. On a Linux router, bird is the control plane and the kernel is the forwarding plane, since the kernel is responsible for forwarding IP packets.
With `krt_prefsrc` we specify our source IP address. This is the addresses defined above. This address must exist on an interface. It is generally bound to a dummy interface.
#### `networks.conf`
This is just something we normally add. Usually you would assign a `/64` within your ULA `/48` but you also want to claim the whole `/48` by advertising a blackhole for it. Here our `/48`/ULA is `fd40:ec65:5b4c::/48`.
Advantage and disadvantage of `persist`:
The keyword `persist` can be used to prevent bird from deleting routes from the forwarding plane. Only routes will be updated. The advantage of this is that when bird is terminated, the forwarding plane still knows the routes to the destinations. The disadvantage is that routes that are no longer propagated are retained. If the control plane no longer knows a route to a particular prefix, using `persist` will not delete the route from the forwarding plane. This can lead to some strange routing.
```
protocol static crxnStatic
{
# Advertise your /48 with a blackhole
route fd40:ec65:5b4c::/48 blackhole;
protocol babel crxn_net {
interface "crxn_peer1" {
type wired;
rxcost 30;
};
ipv6 {
import filter crxn6;
table crxn;
}
ipv6 {
table crxn;
import where crxn_import_filter();
import limit 2000 action block;
export where crxn_export_filter();
};
}
```
Here we create the Babel protocol, which is used to communicate with other CRXN routers. The protocol consists of `interface` and `ipv6` among others. The `interface` can occur several times, `ipv6` not.
In `ipv6` our import/export filters and our routing table `crxn` are defined accordingly. Furthermore an import limit of 2000 routes is set. If a malicious actor now tries to crash a router, for example by propagating a lot of routes, we protect ourselves with this. If 2000 routes are imported via CRXN, every further route is blocked. Although we protect our memory with this, a high rejection of routes can lead to an increased CPU load.
With `interface "crxn*";` you can mark any interface starting with `crxn` as a peer, but then you cannot fine-tune a peer.
Therefore it makes sense to define a separate interface for each peer. As `type` there are `wired` and `wireless`. In general `wired` is always used. According to the `type` parameter babel is adjusted. With `rxcost` we define the "cost", which a peer needs to us. Without specification this is 96. Here it is recommended to take the latency as cost. If you want to avoid that packets are routed through you, you can increase the cost.
In this example, there is a connection to our peer via the interface `crxn_peer1`. This is a wired connection with a latency of 30ms.
```
protocol device {}
```
The protocol `device` is mandatory in bird. This allows bird to communicate with the router. This is necessary for bird to get information about interfaces and the like.
## Control
These commands can be entered with in `birdc`:
To display all Babel peers you can use the following:
```
show babel neighbors
```
or
```
show babel n
```
View all CRXN routes:
```
show route protocol crxn
```
View all CRXN routes with details:
```
show route protocol crxn all
```
Display all the routes that you export:
```
show route export crxn
```
Display all the routes that you export with details:
```
show route export crxn all
```
Reload configuration:
```
configure
```
or
```
c
```
Help can be obtained by typing the command and then a `?`.
## Babel
Babel uses port 6696/udp and the multicast address `ff02::1:6`. Accordingly, port 6696/udp must be enabled locally.
## Old bird configurations
Old configuration can be found [here](old-configuration).
Very old configuration can be found [here](very-old-configuration).

View File

@ -2,5 +2,6 @@
# bird routing daemon
- [Configuring Bird2](bird)
- [Alternative bird configuration](bird-alternative)
- [Old bird configuration](old-configuration)
- [Very old bird configuration](very-old-configuration)
- [`max-len` filter](maxlen-filter)

View File

@ -0,0 +1,156 @@
# Configuring Bird2
We now need to configure the routing daemon for your router which will allow you to
exchange routes with other routers over the tunnels you will setup later. This is at
the core of what makes CRXN an inter-network.
The software we use for this procedure is known as BIRD or _BIRD Internet Routing Daemon_,
of which there are two versions:
1. Bird 1.6
2. Bird 2
You can use Bird 1.6 but you are on your own then in terms of configuration, the syntax
differs slightly but we recommend (and for the rest of this document we will be) using
Bird 2 as it comes with many bug fixes and improvements and most distributions (including Debian)
now have support for it.
## Alternative bird configuration
A guide to an alternative configuration with similar functionality can be found at [here](bird-alternative).
The old configuration can be found [here](very-old-configuration)
## Installation
In order to install the BIRD daemon on your machine you should look for a package named `bird2` or something
similar (some repositories name it slightly differently - such as _just_ `bird`). On a Debian-based system you
can use:
```bash
sudo apt install bird2 -y
```
You can confirm that the version of BIRD you installed is version 2 with the command `bird -v`. If that shows the correct version number then continue to the next step:
```bash
sudo systemctl enable --now bird
```
This will ensure that the routing daemon starts on boot.
## Configuration
In this section we will be configuring two files:
1. `bird.conf`
* For general BIRD configuration e.g. _router IDs_, _device protocol_ and _includes_
2. `crxn.conf`
* For CRXN-specific details
### Basics
There are some basic definition that we are required to add to our configuration file. BIRD is normally configured to use the base configuration stored at something like `/etc/bird/bird.conf` or `/etc/bird.conf`, so open that file up and add the following to it.
#### Router ID
Every BIRD daemon is required to have what is known as a router ID which is written in the form of an IPv4 address. Now this does not actually need to be a valid IPv4 address in the sense of one you actually use but rather it just needs to follow the format, hence a router ID such as `1.1.1.1` is fine, despite you not "owning it".
Define the router ID as the first line in the configuration file like so:
```
router id 1.1.1.1;
```
TODO: These need to be unique - check how much this applies etc
These router IDs are required to be unique as they are used in the various protocols that BIRD supports in order to determine where a route advertisement came from - see them as a unique identifier of your BIRD router. Failing to do so will cause issues when routing on CRXN **and** a banning (TODO: see how we can enforce this).
#### Device protocol
BIRD supports many protocols which are used to import routing data from and export routing data to. However, the most basic of protocols which BIRD supports is known as the `device` protocol. The job of this protocol is just to provide basic device information to BIRD over time, it is required but luckily does not require much setup.
All that is required for this protocol to work is the following:
```
protocol device
{
# Optional parameters go here
}
```
You can adjust [scan times and such](https://bird.network.cz/?get_doc&v=20&f=bird-6.html#ss6.4) but the kernel normally will signal any changes to BIRD.
#### Includes
BIRD allows one to source configuration file contents from other files. Seeing that we will configure the CRXN-specific parts next we will want to include that file in the main entry file (`bird.conf`), this can be accomplished by placing this line at the bottom of said file:
```
include "/etc/crxn.conf";
```
### CRXN-specific setup
The below sections all apply to the CRXN-specific configuration and are to be placed in the file `/etc/crxn.conf`.
### Tables
We need to define the routing tables that BIRD will use in its process to store the routes that we want to learn from other routers and also advertise. Such a definition looks as follows:
```
# Define the IPv6 BIRD table
ipv6 table crxn;
```
You can choose any name for the table you want but you will just need to remember it such that you can refer to it later when it is needed.
### Filters
We need to define a filter which will be used to filter out any incorrect routes we want to advertise _to_ the network but also prevents any incorrect routes that are being propagated _from_ any misconfigured BIRD instances on the network:
```
filter crxnFilter
{
if (net ~ fd00::/8) then accept;
reject;
}
```
TODO: Add a check about not installing RTD_UNREACHABLEs which babel will generate sometimes and which BIRD reportedly has undefined behavior with
### Direct protocol
This provides BIRD with a manner of picking up the `subnet/prefix` pair that is assigned to local interfaces such that these can be imported into BIRD and later advertised.
```
protocol direct crxnDirect
{
ipv6
{
table crxn;
import filter crxnFilter;
};
# Interfaces to find neighbors on
interface "eth*";
}
```
### Kernel protocol
We need to sync the routes from the BIRD routing table `crxn` to the actual kernel's routing table such that it can be used in forwarding decisions. This is accomplished with the following declaration:
```
protocol kernel crxnKernel
{
ipv6 {
# bird's crxn table -> kernel
table crxn;
export filter crxnFilter;
};
persist;
}
```
1. The `persist` option means that when BIRD exits it will not flush the routing table. This is useful if you want to do maintenance and still want to allow forwarding of traffic for a little while (of course other routers may expire routes to you but at least not that fast)

View File

@ -0,0 +1,132 @@
TODO: Re-do this sections
The configuration template is constructed out of the following files:
1. `filters.conf`
* Filter functions and the filter itself
2. `networks.conf`
* Advertisement of ULA
3. `tables.conf`
* The table definitions
4. `router.conf`
* This contains the needed protocol definition for discovering
your interface's prefixes and generating routes form them
* It also contains the needed protocol definitions to sync bird
routes into the Linux kernel's routing table (so you cna forward
packets based on the routes from Bird)
5. `protocols.conf`
* Depending on what protocol you want to use this will contains
configurations for each
All of these will be included in a file saved at `/etc/bird/bird.conf` like so:
```
router id <ipv4>;
include "/etc/bird/crxn/tables.conf";
include "/etc/bird/crxn/filters.conf";
include "/etc/bird/crxn/router.conf";
include "/etc/bird/crxn/networks.conf";
```
Additionally, add the files for the route distribution protocol which we configure in the next steps.
```
include "/etc/bird/crxn/babel.conf"; # For babel routing
include "/etc/bird/crxn/ospfv3.conf"; # For OSPFv3 routing
```
Remember to set a unique router ID in `<ipv4>`, make it anything - it doesn't have to even be an address you own.
#### `filters.conf`
This file holds all the required functions for subnet matching and also
filters that match to the specific prefix aggregates (regional subnets)
that CRXN uses.
```
filter crxnFilter
{
if (net ~ fd00::/8) then accept;
reject;
}
```
#### `tables.conf`
This file holds all table definitions. There are only two actually.
The table `crxn` is the one we actually use, `master` is optional
and is only present because if one uses `bird-lg-go` (the looking glass
we use) then it, by default, only shows routes in the `master` table.
It is meant to have the same routes as the `crxn` table.
```
# CRXN table
ipv6 table crxn;
```
#### `router.conf`
This contains an instance of the `direct` protocol which reads the address
and prefix assigned to your AF_INET6 interfaces and generates routes from
those that represent routes to directly atrtached networks those interfaces
are on. The reason for this is that the `kernel` protocol never learns routes
in the Linux kernel's routing table that have the `kernel` protocol which
is what you get when you assign interfaces addresses and prefixes. This
doesn't even need those, it gets them from the interface.
```
# The kernel protocol doesn't grab kernel routes that are added by you when you assign an
# address and prefix. So instead of reading this from all routes with `proto kernel` this just
# yeets the routes off of the interface structure itself (even if you didn't have a route for your
# directly attached networks - i.e. nexthop = 0.0.0.0)
protocol direct crxnDirect
{
ipv6
{
table crxn;
import filter crxnFilter;
};
# Interfaces to find neighbours on
interface "eth*";
}
protocol device {
}
```
The second part is for syncing routes from Bird to the Linux kernel's routing
table such that you can forward traffic based on the routes in Bird.
TODO: Check, defualt `learn` should learn non `kernel` and non-`bird` routes
```
# CRXN Kernel protocol
# We import any routes from the kernel table other than `proto bird` and `proto kernel`,
# could be `proto static` for example. By default it will learn these.
# Of course we also then export all routes from our Bird tables into the kernel so you can actually forward packets
protocol kernel crxnKernel
{
ipv6 {
# bird's crxn table -> kernel
table crxn;
export filter crxnFilter;
};
}
```
#### `networks.conf`
This is just something we normally add. Usually you would assign a `/64` within your ULA `/48` but you also want to claim the whole `/48` by advertising a blackhole for it. Here our `/48`/ULA is `fd40:ec65:5b4c::/48`.
```
protocol static crxnStatic
{
# Advertise your /48 with a blackhole
route fd40:ec65:5b4c::/48 blackhole;
ipv6 {
import filter crxn6;
table crxn;
}
}
```