blob: ff58ea33549bceb3c26aae91c5a147440b99dc1d [file] [log] [blame]
Serge Bazanski6abe4fa2020-10-03 00:18:34 +02001# Main configuration file for edge01.waw.bgp.wtf.
2# This includes everything needed to run the machine, except for hardware
3# configuration, which is defined in //bgpwtf/machines/
4# edge01.waw.bgp.wtf-hardware.nix.
5#
6# Any changes here can be tested in a local NixOS test by running the following:
7#
8# nix-build -A bgpwtf.machines.tests.edge01-waw
9#
10# To deploy changes, see //ops:machines.nix.
11
12{ config, pkgs, ... }:
13
14with builtins;
15
16let
17 passwords = import ./secrets/plain/passwords.nix;
18
19in rec {
20 networking.hostName = "edge01";
21 networking.domain = "waw.bgp.wtf";
22
23 imports = [
24 ./modules/router.nix
Bartosz Stebelc7267982020-12-10 15:38:29 +010025 ./modules/anchorvm.nix
Serge Bazanski6abe4fa2020-10-03 00:18:34 +020026 # Private configuration data - notably, customer data.
27 ./secrets/plain/edge01.waw.bgp.wtf-private.nix
28 ];
29
30 # TODO(q3k): make this generic, move to modules/router.nix.
31 services.unbound = {
32 enable = true;
33 interfaces = [
34 "185.236.240.1"
35 "2a0d:eb00:2137::1"
36 "127.0.0.1"
37 ];
38 allowedAccess = [
39 "185.236.240.0/22"
40 "2a0d:eb00::0/29"
41 "127.0.0.0/8"
42 ];
43 extraConfig = ''
44 outgoing-interface: 185.236.240.1
45 outgoing-interface: 2a0d:eb00:2137::1
46 cache-max-negative-ttl: 30
47
48 # Disable DoH in Firefox
49 local-zone: "use-application-dns.net" static
50
51 # Rejestr Stron Hazardowych.
52 # Populated by the rsh-unbound daemon.
53 include: "/var/lib/unbound/rsh.conf"
Serge Bazanski767f0312021-12-08 14:07:39 +000054
55 remote-control:
56 control-enable: yes
57 control-interface: /var/run/unbound.ctl
Serge Bazanski6abe4fa2020-10-03 00:18:34 +020058 '';
59 };
Serge Bazanski767f0312021-12-08 14:07:39 +000060 # Fix `systemctl reload unbound`.
61 systemd.services.unbound.reload = "${pkgs.unbound}/bin/unbound-control -c /var/lib/unbound/unbound.conf reload";
Serge Bazanski6abe4fa2020-10-03 00:18:34 +020062 hscloud.rsh = {
63 enable = true;
64 out = "/var/lib/unbound/rsh.conf";
65 };
66
Serge Bazanskia5b0c132021-10-07 18:47:51 +000067 networking.wireguard.interfaces = {
Serge Bazanski82fc1312021-12-08 14:09:51 +000068 wg-fmt = {
Serge Bazanskia5b0c132021-10-07 18:47:51 +000069 ips = [
70 "185.236.240.68/31"
71 "2a0d:eb00:2137:1::e/127"
72 ];
73 allowedIPsAsRoutes = false;
74 listenPort = 51820;
75 generatePrivateKeyFile = true;
Serge Bazanski82fc1312021-12-08 14:09:51 +000076 privateKeyFile = "/root/fmt-wg";
Serge Bazanskia5b0c132021-10-07 18:47:51 +000077 peers = [
78 {
Serge Bazanski82fc1312021-12-08 14:09:51 +000079 publicKey = "zxL/1Jr0LLwJwXDm8ZOWkuY3ZkHO3sC7TdSBh89CsWc=";
Serge Bazanskia5b0c132021-10-07 18:47:51 +000080 allowedIPs = [
Serge Bazanski82fc1312021-12-08 14:09:51 +000081 "0.0.0.0/0"
82 "::/0"
Serge Bazanskia5b0c132021-10-07 18:47:51 +000083 ];
Serge Bazanski82fc1312021-12-08 14:09:51 +000084 endpoint = "[2a00:6340:4000:10::10]:41521";
Serge Bazanskia5b0c132021-10-07 18:47:51 +000085 }
86 ];
87 };
88 };
89
Serge Bazanski6abe4fa2020-10-03 00:18:34 +020090 hscloud.renameInterfaces = {
91 # Link to Nitronet CPE.
92 e1-nnet.mac = "ac:1f:6b:1c:d7:ae";
93 # Link to HSWAW Customs.
94 e2-customs.mac = "ac:1f:6b:1c:d7:af";
95 # Link to management switch.
96 e3-mgmt.mac = "ac:1f:6b:1c:d7:b0";
97 # Link to oob1.
98 e4-oob.mac = "ac:1f:6b:1c:d7:b1";
99 e5.mac = "ac:1f:6b:1c:d7:b2";
100 e6.mac = "ac:1f:6b:1c:d7:b3";
101 # Link to dcsw01.hswaw.net
102 e7-dcsw.mac = "ac:1f:6b:1c:db:06";
103 e8.mac = "ac:1f:6b:1c:db:07";
104 };
105 networking.interfaces.e7-dcsw.mtu = 9000;
106
107 networking.vlans = {
108 "vl-globalmix" = { interface = "e1-nnet"; id = 466; };
109 "vl-polmix" = { interface = "e1-nnet"; id = 2486; };
110 "vl-openpeering" = { interface = "e1-nnet"; id = 992; };
111
112 "vl-dcsw-l3" = { interface = "e7-dcsw"; id = 4001; };
113 "vl-dist-l3" = { interface = "e7-dcsw"; id = 3006; };
114
115 # Extra vlans contained in //bgpwtf/machines/secrets/plain/edge01.waw.bgp.wtf-private.nix
116 };
117 networking.interfaces = {
118 lo = {
119 ipv4.addresses = [ { address = "185.236.240.1"; prefixLength = 32; } ];
120 ipv6.addresses = [ { address = "2a0d:eb00:2137::1"; prefixLength = 64; } ];
121 };
122 ## EPIX links via Nitronet.
123 "vl-globalmix" = {
124 ipv4.addresses = [ { address = "185.235.70.45"; prefixLength = 31; } ];
125 ipv6.addresses = [ { address = "2001:67c:778:fd40::b9eb:462d"; prefixLength = 127; } ];
126 };
127 "vl-polmix" = {
128 ipv4.addresses = [ { address = "94.246.185.175"; prefixLength = 31; } ];
129 ipv6.addresses = [ { address = "2001:67c:778:fa40::5ef6:b9af"; prefixLength = 127; } ];
130 };
131 "vl-openpeering" = {
132 ipv4.addresses = [ { address = "89.46.145.61"; prefixLength = 21; } ];
133 ipv6.addresses = [ { address = "2001:678:3ac::313"; prefixLength = 48; } ];
134 };
135
136 ## L3/mgmt links..
137 # To customs.hackerspace.pl.
138 "e2-customs" = {
139 ipv4.addresses = [ { address = "185.236.240.4"; prefixLength = 31; } ];
140 ipv6.addresses = [ { address = "2a0d:eb00:2137:1::2"; prefixLength = 127; } ];
141 };
142 # To mgmt.
143 "e3-mgmt" = {
144 ipv4.addresses = [ { address = "10.10.10.1"; prefixLength = 24; } ];
145 };
146 # To obb1.
147 "e4-oob" = {
148 ipv4.addresses = [ { address = "185.236.240.74"; prefixLength = 29; } ];
149 };
150 # To dcsw01, L3 (BGP).
151 "vl-dcsw-l3" = {
152 mtu = 9000;
153 ipv4.addresses = [ { address = "185.236.240.6"; prefixLength = 31; } ];
154 ipv6.addresses = [ { address = "2a0d:eb00:2137:1::6"; prefixLength = 127; } ];
155 };
156 # To dist02, L3 (BGP).
157 "vl-dist-l3" = {
158 ipv4.addresses = [ { address = "185.236.240.14"; prefixLength = 31; } ];
159 ipv6.addresses = [ { address = "2a0d:eb00:2137:1::a"; prefixLength = 127; } ];
160 };
Bartosz Stebelc7267982020-12-10 15:38:29 +0100161 # VM bridge
162 "br0" = {
163 ipv4.addresses = [ { address = "185.236.240.17"; prefixLength = 29; } ];
164 ipv6.addresses = [ { address = "2a0d:eb00:2137:3::1"; prefixLength = 64; } ];
165 };
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200166
167 # Extra interface configs contained in //bgpwtf/machines/secrets/plain/edge01.waw.bgp.wtf-private.nix
168 };
Bartosz Stebelc7267982020-12-10 15:38:29 +0100169 networking.bridges = {
170 "br0" = {
171 interfaces = [];
172 };
173 };
174 hscloud.anchorvm = {
175 bridge = "br0";
176 };
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200177
178 hscloud.routing.enable = true;
179 hscloud.routing.routerID = "185.236.240.1";
180 hscloud.routing.asn = 204880;
181 # Use default master4/master6 tables so that `birdc show route` works.
182 hscloud.routing.tables.master.program = true;
183 hscloud.routing.tables.master.programSourceV4 = "185.236.240.1";
184 hscloud.routing.tables.master.programSourceV6 = "2a0d:eb00:2137::1";
185
186 hscloud.routing.extra = ''
187 function net_martian_v4() {
188 return net ~ [ 169.254.0.0/16+, 172.16.0.0/12+, 192.168.0.0/16+, 10.0.0.0/8+,
189 127.0.0.0/8+, 224.0.0.0/4+, 240.0.0.0/4+, 0.0.0.0/32-, 0.0.0.0/0{25,32}, 0.0.0.0/0{0,7} ];
190 }
191 function net_as204480_waw_v4() {
192 return net ~ [ 185.236.240.0/23+ ];
193 }
194 function net_martian_v6() {
195 return net ~ [ fc00::/7+, fec0::/10+, ::/128-, ::/0{0,15}, ::/0{49,128} ];
196 }
197 function net_as204480_waw_v6() {
198 return net ~ [ 2a0d:eb00::/32 ];
199 }
200
201 '';
202 hscloud.routing.originate = {
203 # WAW prefixes, exposed into internet BGP table.
Serge Bazanskia5b0c132021-10-07 18:47:51 +0000204 v4.waw = { table = "internet"; address = "185.236.240.0"; prefixLength = 23; };
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200205 v6.waw = { table = "internet"; address = "2a0d:eb00::"; prefixLength = 32; };
206
207 # Default gateway via us, exposed into aggregated table.
208 v4.default = { table = "aggregate"; address = "0.0.0.0"; prefixLength = 0; };
209 v6.default = { table = "aggregate"; address = "::"; prefixLength = 0; };
Serge Bazanski82fc1312021-12-08 14:09:51 +0000210
211 # Loopbacks for IGP table.
212 # Alternatively we could add 'lo' as a stub interface into IGP OSPF, but
213 # that would also add 127.0.0.1...
214 v4.loopbacks = { table = "igp"; address = "185.236.240.1"; prefixLength = 32; };
215 v6.loopbacks = { table = "igp"; address = "2a0d:eb00:2137::1"; prefixLength = 128; };
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200216 };
217 hscloud.routing.pipe = let
Serge Bazanskid9a63652020-10-16 19:07:41 +0200218 copySourcesToKernel = sources: table: extra: {
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200219 table = "master";
220 peerTable = table;
221 filterIn = ''
Serge Bazanskid9a63652020-10-16 19:07:41 +0200222 ${extra}
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200223 ${concatStringsSep "\n" (map (v: "if source = RTS_${v} then accept;") sources)}
224 reject;
225 '';
226 };
227 in {
Serge Bazanskid9a63652020-10-16 19:07:41 +0200228 v4."internet_to_kernel" = copySourcesToKernel ["BGP" "OSPF"] "internet" "";
Serge Bazanski81e7fba2021-09-08 23:29:52 +0200229 v4."aggregate_to_kernel" = copySourcesToKernel ["BGP" "OSPF"] "aggregate" ''
230 # Static v4 routes for customers.
231 if proto ~ "static_static_ipv4_customer_*" then accept;
232 '';
Serge Bazanskid9a63652020-10-16 19:07:41 +0200233 v6."internet_to_kernel" = copySourcesToKernel ["BGP" "OSPF"] "internet" "";
234 v6."aggregate_to_kernel" = copySourcesToKernel ["BGP" "OSPF"] "aggregate" ''
235 # Static v6 routes for customers.
236 if proto ~ "static_static_ipv6_customer_*" then accept;
237 '';
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200238 };
239
240 hscloud.routing.ospf.v6.main = {
241 area."0.0.0.0".interfaces = {
242 "e2-customs" = {
243 type = "bcast";
244 };
245 "e4-oob" = {
246 type = "bcast";
247 stub = true;
248 };
249 };
250 table = "aggregate";
251 filterIn = ''
252 # hswaw prefix from e2-customs
Serge Bazanskie9f2c9d2020-11-08 16:31:11 +0100253 if net ~ [ 2a0d:eb00:4242::/48+ ] then accept;
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200254 # e2-customs link
255 if net ~ [ 2a0d:eb00:2137:1::2/127+ ] then accept;
256 '';
257 };
258 hscloud.routing.ospf.v4.main = {
259 area."0.0.0.0".interfaces = {
260 "e4-oob" = {
261 type = "bcast";
262 stub = true;
263 };
264 };
265 table = "aggregate";
266 filterIn = ''
267 # e4-oob link
268 if net ~ [ 185.236.240.72/29+ ] then accept;
269 '';
270 };
Serge Bazanski82fc1312021-12-08 14:09:51 +0000271 hscloud.routing.ospf.v6.igp = {
272 area."0.0.0.0".interfaces = {
273 "wg-fmt" = {
274 type = "ptmp";
275 neighbors = [
276 "2a0d:eb00:2137:1::f"
277 ];
278 };
279 };
280 table = "igp";
281 filterIn = ''
282 # fmt networks
283 if net ~ [ 2a0d:eb01::/48+ ] then accept;
284 '';
285 };
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200286
287 hscloud.routing.bgpSessions.v4 = let
288 filterInUpstream = ''
289 if net_martian_v4() then reject;
290 if net_as204480_waw_v4() then reject;
291 accept;
292 '';
293 filterOutUpstream = ''
294 # Accept AS204880-announced prefixes.
295 if (net ~ [ 185.236.240.0/22+ ]) then accept;
296 reject;
297 '';
298 in {
299 "waw_globalmix" = {
300 description = "UPSTREAM EPIX.WAR GlobalMix";
301 table = "internet";
302 local = "185.235.70.45";
303 neighbors = [
304 { address = "185.235.70.44"; asn = 62081; }
305 ];
306 prepend = 2; pref = 100;
307 filterIn = filterInUpstream;
308 filterOut = filterOutUpstream;
309 };
310 "waw_polmix" = {
311 description = "UPSTREAM EPIX.WAR PolMix";
312 table = "internet";
313 local = "94.246.185.175";
314 neighbors = [
315 { address = "94.246.185.174"; asn = 201054; }
316 ];
317 prepend = 1; pref = 200;
318 filterIn = filterInUpstream;
319 filterOut = filterOutUpstream;
320 };
321 "waw_openpeering" = {
322 description = "IXP EPIX.WAR OpenPeering";
323 table = "internet";
324 local = "89.46.145.61";
325 neighbors = [
326 { address = "89.46.144.11"; asn = 48850; }
327 { address = "89.46.144.12"; asn = 48850; }
328 ];
329 prepend = 0; pref = 300;
330 filterIn = filterInUpstream;
331 filterOut = filterOutUpstream;
332 };
333 "waw_google" = {
334 description = "PEER Google AS15169 (EPIX)";
335 table = "internet";
336 local = "89.46.145.61";
337 neighbors = [
338 # TODO(q3k): secretify the password.
339 { address = "89.46.144.185"; asn = 15169; password = passwords."edge01.waw-bgp-google"; }
340 ];
341 prepend = 0; pref = 300;
342 filterIn = filterInUpstream;
343 filterOut = filterOutUpstream;
344 };
345 # hscloud spine switch (dcsw01.hswaw.net).
346 "waw_hscloud" = {
347 description = "AGGREGATE CUSTOMER hscloud/dcsw01";
348 table = "aggregate";
349 local = "185.236.240.6";
350 asn = 65000;
351 neighbors = [
352 { address = "185.236.240.7"; asn = 65001; }
353 ];
354 filterIn = ''
355 # wieloryb prefix
356 if net ~ [ 185.236.240.8/31+ ] then accept;
357 # dcsw01 l2 general purpose
358 if net ~ [ 185.236.240.24/29+ ] then accept;
359 # hscloud l2 general purpose
360 if net ~ [ 185.236.240.32/28+ ] then accept;
361 # k0 metallb pools
362 if net ~ [ 185.236.240.48/28+, 185.236.240.112/28+ ] then accept;
Serge Bazanski1c80bd72021-06-30 23:22:38 +0200363 # dcsw01.hswaw.net / dcr03sw48.hswaw.net
364 if net ~ [ 185.236.240.66/31 ] then accept;
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200365 reject;
366 '';
367 };
368 # bgp.wtf internet customer router on W2A, floor 3 (dist02.bgp.wtf).
369 "waw_dist02" = {
370 description = "AGGREGATE CUSTOMER bgpwtf/dist02";
371 table = "aggregate";
372 local = "185.236.240.14";
373 asn = 65000;
374 neighbors = [
375 { address = "185.236.240.15"; asn = 65002; }
376 ];
377 filterIn = ''
378 # dist02 customer routed
379 if net ~ [ 185.236.240.80/28+ ] then accept;
380 reject;
381 '';
382 };
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200383 # backup LTE link to edge01.fra
384 "fra_edge01" = {
385 description = "IBGP edge01.fra";
386 table = "internet";
387 local = "185.236.240.74";
388 direct = true;
389 neighbors = [
390 { address = "185.236.240.75"; asn = 204880; }
391 ];
392 pref = 50;
393 filterIn = filterInUpstream;
394 filterOut = filterOutUpstream;
395 };
396 };
397 hscloud.routing.bgpSessions.v6 = let
398 filterInUpstream = ''
399 if net_martian_v6() then reject;
400 if net_as204480_waw_v6() then reject;
401 accept;
402 '';
403 filterOutUpstream = ''
404 # Accept AS204880-announced prefixes.
405 if (net ~ [ 2a0d:eb00::/29+ ]) then accept;
406 reject;
407 '';
408 in {
409 "waw_globalmix" = {
410 description = "UPSTREAM EPIX.WAR GlobalMix";
411 table = "internet";
412 local = "2001:67c:778:fd40::b9eb:462d";
413 neighbors = [
414 { address = "2001:67c:778:fd40::b9eb:462c"; asn = 62081; }
415 ];
416 prepend = 2; pref = 100;
417 filterIn = filterInUpstream;
418 filterOut = filterOutUpstream;
419 };
420 "waw_polmix" = {
421 description = "UPSTREAM EPIX.WAR PolMix";
422 table = "internet";
423 local = "2001:67c:778:fa40::5ef6:b9af";
424 neighbors = [
425 { address = "2001:67c:778:fa40::5ef6:b9ae"; asn = 201054; }
426 ];
427 prepend = 1; pref = 200;
428 filterIn = filterInUpstream;
429 filterOut = filterOutUpstream;
430 };
431 "waw_openpeering" = {
432 description = "IXP EPIX.WAR OpenPeering";
433 table = "internet";
434 local = "2001:678:3ac::313";
435 neighbors = [
436 { address = "2001:678:3ac::11"; asn = 48850; }
437 { address = "2001:678:3ac::12"; asn = 48850; }
438 ];
439 prepend = 0; pref = 300;
440 filterIn = filterInUpstream;
441 filterOut = filterOutUpstream;
442 };
443 "waw_google" = {
444 description = "PEER Google AS15169 (EPIX)";
445 table = "internet";
446 local = "2001:678:3ac::313";
447 neighbors = [
448 { address = "2001:678:3ac::185"; asn = 15169; password = passwords."edge01.waw-bgp-google"; }
449 ];
450 prepend = 0; pref = 300;
451 filterIn = filterInUpstream;
452 filterOut = filterOutUpstream;
453 };
454 # hscloud spine switch (dcsw01.hswaw.net).
455 "waw_hscloud" = {
456 description = "AGGREGATE CUSTOMER dcsw01.hswaw.net";
457 table = "aggregate";
458 local = "2a0d:eb00:2137:1::6";
459 asn = 65000;
460 neighbors = [
461 { address = "2a0d:eb00:2137:1::7"; asn = 65001; }
462 ];
463 filterIn = ''
464 # dcsw01 l2 general purpose
465 if net ~ [ 2a0d:eb00:2137::/48+ ] then accept;
Serge Bazanski400e03f2021-07-20 17:57:49 +0200466 # customer
467 if net ~ [ 2a0d:eb00:8004::/48+ ] then accept;
Serge Bazanski6abe4fa2020-10-03 00:18:34 +0200468 reject;
469 '';
470 };
471 # bgp.wtf internet customer router on W2A, floor 3 (dist02.bgp.wtf).
472 "waw_dist02" = {
473 description = "AGGREGATE CUSTOMER dist02.bgp.wtf";
474 table = "aggregate";
475 local = "2a0d:eb00:2137:1::a";
476 asn = 65000;
477 neighbors = [
478 { address = "2a0d:eb00:2137:1::b"; asn = 65002; }
479 ];
480 filterIn = ''
481 # dist02 customers.
482 if net ~ [ 2a0d:eb00:8002::/48 ] then accept;
483 reject;
484 '';
485 };
486 };
487}