# Peering and BGP Configuration Requirements for Alanet

[[_TOC_]]

Before we start peering there are some questions we need to answer and we need a way to store global configuration.

# Network Questions

We need to decide:

* What [ASN](https://en.wikipedia.org/wiki/Autonomous_system_(Internet)) range we will use for ourselves. Since 
[RFC 4893](https://www.rfc-editor.org/rfc/rfc4893.html), ASNs are 32-bit numbers so we have plenty for the future ;).
[RFC 6996](https://www.rfc-editor.org/rfc/rfc6996.html) (heh) designated ASNs in the range `42XXXXXXXX` as "private". So
we just need to determine a prefix and go with that. `dn42` ASNs are `424242XXXX` which is a little small with only 10k.
  * e.g. we could use `4255500000` and get 100k ASNs.
* What network do we use? I like sticking to `02::/8`. That's pretty large and memorable, and keeps `03::/8` available
for the future mesh network :). It'd be nice to not share space with `dn42` in case we want to peer with them.
  * Here's a [list](https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml) of ipv6 address space.
  `0200::/7` was deprecated in 2004, which is why I was thinking of using that. `dn42` uses `fd::/8`.
* How large of a prefix do we want to give people? Each hex char in an address adds 4 to the prefix len.
  * `02::/8` since there's two chars "02" at the start. We could do `/16` for now. That's 256 at the start and limit to
  one per AS. If we get above say `127` unique ASNs, then we can bump it up to a `/32`.
    * With a `/16` prefix, addresses would look like `2XX::/16`. I was using `255::/16` and `200::/16` for my tests. 
  * Another option is to do `02XX:XX:X0::/32` where `X` is your ASN number suffix. That's kinda fun but then we don't get nice,
  short addresses.
  
Think about it what you want to do! Everyone has a say!

The rest of the document discusses our configuration requirements.

# What Config Information Do We Need?

We need global information about the router and information per-peer.

## Router Config

The router config is essentially the constants for configuring bird.

- **ASN**: the router's ASN. Some number in some range `42XXXXXXXX`.
- **internal ip**: the router's alanet internal IPv6 addr.
- **subnet**: the internal subnet that this router controls/routes to.
- **router id**: the router's IPv4 unique ID. Can be generated or calculated manually. Does not have to be public.

We can combine the internal IP and subnet pretty easily using cidr notation. e.g. `255:10::1/16` is the host 
`255:10::1` and the network is `255::/16`. 

The router id can be calculated from the host and network. We take the set prefix of `255:10::1/16` which is `255::/16`
and convert that to a 128-bit integer. We then shift that integer right 96 bits and convert the lower 32 bits to an IPv4
address. If the lowest byte of that new IPv4 addr is 0, we add 1.

```
255:: >> 96 = 0x02_55_00_00 (same as ::255:0)
0x02550000 + 1 = 0x02_55_00_01 (+1 since last byte was 0)
0x02550001 = 2.85.0.1 (unique IPv4 addr)
```

As long as we give people IPv6 prefixes that are shorter than 32 bits, the above algorithm will generate a unique IPv4 
addr per ASN. Another option is for people to use their public IPv4 addresses, but that requires people to have an 
IPv4 capable server. Or, people just generate a random 32-bit number and we add that as part of the global ASN list.

In any case, we can reduce the necessary per-router bird configuration to two things, the ASN and the host-with-cidr.

## Peer Config (setting up BGP)

BFP config for a peer is pretty simple.

We just need:
- **Peer ASN**: the ASN of the peer.
- **Peer Internal IP**: the internal IP of the peer.
- **Peer Name**: some kind of friendly name (not neccessary, but nice to have).

That's it.

## Peer Config (connecting with WG)

WireGuard config for a peer is dependent on some shared agreement between two parties.

We need the:
- **Peer's PublicKey**: the public key of the peer. This could be globally configured.
- **Peer's endpoint**: the public endpoint, host with port, that we can reach this peer at. The port is different per-peer.

The port is only different per-peer since we give each peer a separate interface. This makes things much easier from a 
management and security perspective at the cost of making the port unknown. 

# What Are Our Automation Goals?

Maybe not necessary for the near-future, but these goals should guide our implementation.

* Only a single command to refresh or add a peer with a simple configuration format.
* Simple way to add public router information (asn, internal ip, subnet).
* Only exchange per-peer information _once_. I give you an endpoint and key, you give me an endpoint and key, done.

See [[dn42_notes]] for an overview of how dn42 solves the above problems. TLDR; git repo.

# Potential Implementation

## Git Repo

I like the git repo approach for global router information. People just open a PR and add a new block with their ASN.
The repo represents the source of truth and before you add a peer, you `git pull` the registry repo. This also lets us
generate a `Route Origin Authorization` (ROA) table that we can use to actually authenticate advertised routes.

For peering we could do a similar git approach. We would all have public repos or folders. To Peer with someone, you open
a PR against their repo and then they open a PR against yours. Once both are merged, you pull the repo and run some sort
of tool that sets up the WG tunnel and bird. This doesn't have to be public and can be done over matrix or something,
but I like how git can act as a back up _and_ the tool could even manage the repo for you.

## Matrix Room?

Could we use matrix to share peering information, using the room state keys? Running a matrix user/bot might be taxing
on the super cheap VPS I'm using. Maybe there's another way.

## Automatic Peering

Not really a way to implement the above, but interesting nonetheless.

This would be incredibly useful. There's some dn42 peers that provide a UI or custom wg server that's 100% self serve. 
The custom wg server is interesting since your connection port is the last 5 digits of your ASN which is really nice and
makes it very easy to peer with someone else. This makes me feel like peering should not be public and we might want to
eventually develop some sort of automatic peering solution.

> I guess the automatic peering could be public, open a PR that's auto-merged if it passes. Once merged, a daemon builds
> something and the change is then live.

## Other WG Implementations

See [Identity Management for WireGuard](https://lwn.net/Articles/910766/).

# Conclusion

We need to answer the questions at the very beginning and figure out how to store ASN information. We could honestly 
just answer the initial quesitions and just peer manually and not try to make anything fancy. Or we make it fancy :)