howto/OpenBGPD.md
... ...
@@ -1,135 +1,220 @@
1 1
This guide describes a simple configuration for [OpenBGPD](https://openbgpd.org) running on [OpenBSD](https://openbsd.org).
2 2
The [portable version](https://openbgpd.org/ftp.html) should run with little to no configuration changes on other operating systems as well.
3 3
4
-# Setup
5
-Only IPv6 is used for the sake of simplicity.
6
-Neighbors use ULA addresses (/127 transfer net) assigned from one of the peer's allocation.
4
+Other than the
5
+[`bgpd.conf(5)`](https://man.openbsd.org/bgpd.conf.5) and
6
+[`bgpd(8)`](http://man.openbsd.org/bgpd.8) man pages and the
7
+OpenBSD
8
+[`/etc/examples/bgpd.conf`](http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/etc/examples/bgpd.conf?rev=HEAD&content-type=text/plain&only_with_tag=MAIN),
9
+you might also find useful reference or ideas in the
10
+[Bird2](/howto/Bird2) page (even if you don't use Bird), as
11
+it likely presents the most widespread dn42 router setup.
12
+
13
+# Example configuration
14
+When copying from the below configuration, be sure to at
15
+least replace the various `<PLACEHOLDER>`s with your own
16
+numbers.
17
+
18
+Concrete configuration examples can also be found elsewhere,
19
+e.g.:
20
+
21
+[https://smrk.net/text/openbsd-dn42-setup.txt](https://smrk.net/text/openbsd-dn42-setup.txt)
22
+
23
+[https://kaizo.org/2024/01/03/openbsd-bgpd/](https://kaizo.org/2024/01/03/openbsd-bgpd/)
24
+
25
+Given OpenBGPD's limited support for multiprotocol sessions
26
+(no extended next hop (RFC8950)) and
27
+[some](https://marc.info/?l=openbgpd-users&m=159983144408845&w=2)
28
+[issues](https://marc.info/?l=openbgpd-users&m=165605427017298&w=2)
29
+with IPv6 link-local nexthops, we configure separate IPv4
30
+and IPv6 sessions for each peer, and for IPv6 we adjust
31
+nexthop to a "global" address (i.e., one from our dn42 IPv6
32
+allocation) assigned to each peering (Wireguard) interface
33
+(each interface gets its own).
34
+
35
+To avoid burning a dn42 IPv4 address for each peering, we'll
36
+put the router's dn42 IPv4 address on the loopback interface
37
+and peer using an RFC1918 subnet (192.168.42/24) NATed to
38
+the loopback address (the NAT is only used in case of
39
+actively opening an IPv4 BGP session, it does not affect
40
+routing or incoming connections).
41
+
42
+## `/etc/hostname.lo0`
7 43
8
-The goal is to have a small, yet complete setup for all peers with ROA validation and other safety measures in place.
9
-
10
-# Configuration
11
-[`/etc/bgpd.conf`](https://man.openbsd.org/bgpd.conf.5) contains all information and may include further (automatically generated) files, as is done in this guide.
12
-
13
-As per the manual, configuration is divided into logical sections; [`/etc/examples/bgpd.conf`](http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/etc/examples/bgpd.conf?rev=HEAD&content-type=text/plain&only_with_tag=MAIN) is a complete and commented example which this guide is roughly based on.
14
-
15
-By default, [bgpd(8)](http://man.openbsd.org/bgpd.8) listens on all local addresses (on the current default [`routing domain`](http://man.openbsd.org/rdomain.4)), but this guide explicitly listens on the configured transfer ULA only for each peer to better illustrate this setup.
16
-
17
-## local host
18
-Information such as ASN, router ID and allocated networks are required:
19 44
```conf
20
-# macros
21
-ASN="4242421234"
45
+alias <YOUR-ROUTER-DN42-IPv4>
46
+```
22 47
23
-# global configuration
24
-AS $ASN
25
-router-id 1.2.3.4
48
+## `/etc/hostname.wg1234`
49
+(one example; similar for each peer)
26 50
27
-prefix-set mynetworks {
28
- fd00:12:34::/48
29
-}
51
+```conf
52
+inet 192.168.42.1/32
53
+inet6 fe80::1 64 # this is the address your peer will want to know
54
+# (and connect to); the following address is only really needed
55
+# to provide a non-link-local IPv6 address for the nexthop setting;
56
+# you can pick it "arbitrarily" from your dn42 IPv6 allocation
57
+inet6 <YOUR-DN42-IPv6-OF-PEER1-INTERFACE> 64
58
+group my_dn
59
+wgport 21234 wgkey <PRIVKEY-BASE64>
60
+wgpeer <PEER1-PUBKEY-BASE64> \
61
+ wgdescr "dn42 peer1" \
62
+ wgaip fe80::/64 wgaip fd00::/8 wgaip 10.0.0.0/8 wgaip 172.20.0.0/14 \
63
+ wgendpoint <PEER1-HOSTNAME-OR-IP> 24321
64
+up
65
+# add a static IPv4 route to the peer
66
+!route -nq add <PEER1-IPv4> 192.168.42.1
30 67
```
31 68
32
-These can be used in subsequent filter rules.
33
-The local peer's announcements is then defined as follows:
69
+## `/etc/pf.conf`
70
+(only the dn42-related snippet)
71
+
34 72
```conf
35
-# Generate routes for the networks our ASN will originate.
36
-# The communities (read 'tags') are later used to match on what
37
-# is announced to EBGP neighbors
38
-network prefix-set mynetworks set large-community $ASN:1:1
73
+pass in quick proto {icmp icmp6} max-pkt-rate 30/3
74
+dn42_self = <YOUR-ROUTER-DN42-IPv4>
75
+table <dn42etc> const {172.20/14 172.31/16 10/8 fd00::/8 fe80::/64}
76
+table <dn42peers> const {<PEER1-IPv4> fe80::/64}
77
+pass in quick on egress proto udp to port 21234
78
+pass in quick on my_dn proto tcp from <dn42peers> \
79
+ to {$dn42_self (my_dn)} port bgp
80
+# block everything (except for ICMP above) destined to the
81
+# router itself; only dn42 transit and BGP sessions are allowed
82
+block in log quick on my_dn to {$dn42_self (my_dn)}
83
+pass out on my_dn from 192.168.42/24 nat-to $dn42_self
84
+pass on my_dn from <dn42etc> to <dn42etc>
39 85
```
40 86
41
-## neighbors
42
-For each neighbor its ASN and transfer ULA is required.
43
-An optional description is provided such that [bgpctl(8)](http://man.openbsd.org/bgpctl.8) for example can be used with mnemonic names instead of AS numbers:
87
+## `/etc/bgpd.conf`
44 88
```conf
45
-# peer A, transport over IPSec/GRE
46
-$A_local="fd00:12:34:A::1"
47
-$A_remote="fd00:12:34:A::2"
48
-$A_ASN="4242425678"
89
+ASN = "<YOUR-AS-NUMBER>"
49 90
50
-listen on $A_local
91
+AS $ASN
92
+router-id <YOUR-ROUTER-DN42-IPv4>
51 93
52
-neighbor $A_remote {
53
- remote-as $A_ASN
54
- descr "A"
94
+# list of networks that may be originated by our ASN
95
+prefix-set mydn42 {
96
+ <YOUR-DN42-IPv4-PREFIX>
97
+ <YOUR-DN42-IPv6-PREFIX>
55 98
}
56
-```
57
-
58
-## filter rules
59
-**bgpd** blocks all BGP __UPDATE__ messages by default.
60
-The filter rules are evaluated in sequential order, from first to last.
61
-The last matching allow or deny rule decides what action is taken.
62
-
63
-Start off with basic protection and sanity rules:
64
-```conf
65
-# deny more-specifics of our own originated prefixes
66
-deny quick from ebgp prefix-set mynetworks or-longer
67 99
68
-# filter out too long paths, establish more peerings instead
69
-deny quick from any max-as-len 8
70
-```
100
+# https://dn42.eu/howto/Bird2#example-configuration
101
+prefix-set dn42etc {
102
+ 172.20.0.0/14 prefixlen 21 - 29 # dn42
103
+ 172.20.0.0/24 prefixlen 28 - 32 # dn42 Anycast
104
+ 172.21.0.0/24 prefixlen 28 - 32 # dn42 Anycast
105
+ 172.22.0.0/24 prefixlen 28 - 32 # dn42 Anycast
106
+ 172.23.0.0/24 prefixlen 28 - 32 # dn42 Anycast
107
+ 172.31.0.0/16 or-longer # ChaosVPN
108
+ 10.100.0.0/14 or-longer # ChaosVPN
109
+ 10.127.0.0/16 prefixlen 16 - 32 # neonetwork
110
+ 10.0.0.0/8 prefixlen 15 - 24 # Freifunk.net
111
+ fd00::/8 prefixlen 44 - 64 # dn42
112
+}
71 113
72
-`quick` rules are considered the last matching rule, and evaluation of subsequent rules is skipped.
114
+# https://dn42.burble.com/services/public/#roa-data
115
+# https://dn42.burble.com/roa/dn42_roa_obgpd_46.conf
116
+# see the crontab snippet and an update script further below
117
+include "/var/db/openbgpd/dn42_roa_obgpd_46.conf"
118
+
119
+network prefix-set mydn42 set {
120
+ # https://dn42.dev/howto/BGP-communities
121
+ # e.g., for Germany this could read
122
+ # community 64511:41
123
+ # community 64511:1276
124
+ community 64511:<READ-THE-LINK-ABOVE>
125
+ community 64511:<READ-THE-LINK-ABOVE>
126
+ large-community $ASN:1:1
127
+}
73 128
74
-Allow own announcements:
75
-```conf
76
-# Outbound EBGP: only allow self originated networks to ebgp peers
77
-# Don't leak any routes from upstream or peering sessions. This is done
78
-# by checking for routes that are tagged with the large-community $ASN:1:1
79
-allow to ebgp prefix-set mynetworks large-community $ASN:1:1
80
-```
129
+listen on <YOUR-ROUTER-DN42-IPv4>
130
+listen on <PEER1-IPv6-LOCAL> # e.g. fe80::1%wg1234
131
+
132
+group dn42peers {
133
+ # RFC7454 sec. 8
134
+ # (currently no peer sends more than 800 prefixes for
135
+ # a single address family; increase this if using
136
+ # multi-protocol BGP (or when the network grows)!)
137
+ max-prefix 1000 restart 60
138
+ neighbor <PEER1-IPv4> {
139
+ descr peer1_4
140
+ remote-as <PEER1-ASN>
141
+ }
142
+ neighbor <PEER1-IPv6-REMOTE> { # e.g. fe80::2%wg1234
143
+ descr peer1_6
144
+ remote-as <PEER1-ASN>
145
+ set nexthop <YOUR-DN42-IPv6-OF-PEER1-INTERFACE>
146
+ }
147
+}
81 148
82
-Allow all remaining UPDATES based on **O**rigin **V**alidation **S**tates:
83
-```conf
84
-# enforce ROA
85
-allow from ebgp ovs valid
86
-```
149
+# deny EBGP UPDATEs to our own originated prefixes
150
+deny quick from ebgp prefix-set mydn42 or-longer
151
+# filter out overlong paths
152
+deny quick from any max-as-len 10
87 153
88
-Note how the `ovs` filter requires the `roa-set {...}` to be defined; see the `ROA` section below.
154
+allow from group dn42peers prefix-set dn42etc ovs valid
155
+allow to group dn42peers prefix-set dn42etc
89 156
90
-### path attributes
91
-Besides `allow` and `deny` statements, filter rules can modify UPDATE messages, e.g.
92
-```conf
93
-# Scrub normal and large communities relevant to our ASN from EBGP neighbors
94
-# https://tools.ietf.org/html/rfc7454#section-11
157
+# scrub communities relevant to our ASN from EBGP neighbors
158
+# (RFC7454 sec. 11)
159
+# match from ebgp set { community delete $ASN:* }
95 160
match from ebgp set { large-community delete $ASN:*:* }
96 161
97
-# Honor requests to gracefully shutdown BGP sessions
98
-# https://tools.ietf.org/html/rfc8326
162
+# honor requests to gracefully shutdown BGP sessions (RFC8326)
99 163
match from any community GRACEFUL_SHUTDOWN set { localpref 0 }
100 164
```
101 165
102
-# ROA
166
+## ROA
103 167
104
-An roa-set can be generated from the registry directly or you can use the following pre-built tables.
168
+The `roa-set` for route origin validation (`ovs valid` in
169
+the config above) can be generated from the dn42 registry;
170
+here we use
171
+[data](https://dn42.burble.com/services/public/#roa-data)
172
+conveniently provided by BURBLE-MNT.
105 173
106
-One single `roa-set` may be defined, against which **bgpd** will validate the origin of each prefix; this allows filter rules to use the `ovs` keyword as demonstrated above.
174
+If using the update script below, don't forget to create the
175
+`/var/db/openbgpd/` directory first.
107 176
108
-ROA files generated by [dn42regsrv](https://git.dn42.dev/burble/dn42regsrv) are available from burble.dn42:
177
+### `/root/openbgpd-roa-update.sh`
178
+```sh
179
+#!/bin/sh
109 180
110
-|URL|&nbsp;IPv4/IPv6&nbsp;|
111
-|---|---|
112
-| <https://dn42.burble.com/roa/dn42_roa_obgpd_46.conf> &nbsp; | &nbsp;Both&nbsp; |
113
-| <https://dn42.burble.com/roa/dn42_roa_obgpd_4.conf> &nbsp; | &nbsp;IPv4 Only&nbsp; |
114
-| <https://dn42.burble.com/roa/dn42_roa_obgpd_6.conf> &nbsp; | &nbsp;IPv6 Only&nbsp; |
115
-
116
-`/etc/dn42.roa-set` is the generated set:
117
-```conf
118
-roa-set {
119
- fd00:12:34::/48 source-as 4242421234
120
- fd00:ab:cd::/44 maxlen 64 source-as 4242427890
121
- ...
181
+die() {
182
+ >&2 printf '%s: %s\n' "${0##*/}" "$*"
183
+ exit 1
122 184
}
185
+
186
+# Unfortunately, burble regenerates the ROA files (hourly?)
187
+# even when nothing changed, so If-Modified-Since doesn't
188
+# help (similar story for .meta).
189
+
190
+metafile=/var/db/openbgpd/registry.meta
191
+err=$(ftp -o "$metafile" \
192
+ https://explorer.burble.com/api/registry/.meta 2>&1 >/dev/null) ||
193
+ die "/api/registry/.meta download failed: $err"
194
+
195
+if ! cmp -s "$metafile" "$metafile".old >/dev/null 2>&1; then
196
+ mv "$metafile" "$metafile".old
197
+ roafile=/var/db/openbgpd/dn42_roa_obgpd_46.conf
198
+ if err=$(ftp -To "$roafile".new \
199
+ https://dn42.burble.com/roa/dn42_roa_obgpd_46.conf \
200
+ 2>&1 >/dev/null); then
201
+ mv "$roafile".new "$roafile"
202
+ bgpctl reload
203
+ else
204
+ die "ROA download failed: $err"
205
+ fi
206
+else
207
+ logger -cisp user.info "${0##*/}: registry unchanged, not reloading"
208
+fi
123 209
```
124 210
125
-Include it in `/etc/bgpd.conf`:
211
+### `/var/cron/tabs/root`
126 212
```conf
127
-# defines roat-set, see _rpki-client crontab
128
-include "/etc/dn42.roa-set"
213
+~ * * * * -ns /root/openbgpd-roa-update.sh
129 214
```
130 215
131 216
# Looking glass
132 217
This is mostly OpenBSD specific since [bgplg(8)](http://man.openbsd.org/bgplg.8) and [httpd(8)](http://man.openbsd.org/httpd.8) ship as part of the operating system.
133
-The **bgplg** manual contains the few steps and example [httpd.conf(5)](http://man.openbsd.org/httpd.conf.5) required to enable the looking glass.
218
+The **bgplg** manual contains the steps and example [httpd.conf(5)](http://man.openbsd.org/httpd.conf.5) required to enable the looking glass.
134 219
135 220
See <https://t4-2.high5.nl/bgplg> for a running instance operating within DN42.