mirror of
https://gerrit.hackerspace.pl/hscloud
synced 2025-03-17 20:54:53 +00:00
bgpwtf/machines: init edge01.waw
This configures our WAW edge router using NixOS. This replaces our previous Ubuntu installation. Change-Id: Ibd72bde66ec413164401da407c5b268ad83fd3af
This commit is contained in:
parent
2efb698d22
commit
6abe4fa771
14 changed files with 1683 additions and 0 deletions
36
bgpwtf/machines/edge01.waw.bgp.wtf-hardware.nix
Normal file
36
bgpwtf/machines/edge01.waw.bgp.wtf-hardware.nix
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Hardware configuration of edge01. Generated by nixos-generate-config.
|
||||
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "ahci" "usb_storage" "usbhid" ];
|
||||
boot.initrd.kernelModules = [ "dm-snapshot" ];
|
||||
boot.kernelModules = [ "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
system.stateVersion = "20.03";
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/b1b85556-8f3b-4695-8ad5-2159c93c76de";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
# Pendrive.
|
||||
# Real boot is at D8BA-345D.
|
||||
{ device = "/dev/disk/by-uuid/D8BA-345D";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-uuid/5dadcff4-fcd4-4e8d-81f6-be68fb630396"; }
|
||||
];
|
||||
|
||||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
||||
}
|
413
bgpwtf/machines/edge01.waw.bgp.wtf.nix
Normal file
413
bgpwtf/machines/edge01.waw.bgp.wtf.nix
Normal file
|
@ -0,0 +1,413 @@
|
|||
# Main configuration file for edge01.waw.bgp.wtf.
|
||||
# This includes everything needed to run the machine, except for hardware
|
||||
# configuration, which is defined in //bgpwtf/machines/
|
||||
# edge01.waw.bgp.wtf-hardware.nix.
|
||||
#
|
||||
# Any changes here can be tested in a local NixOS test by running the following:
|
||||
#
|
||||
# nix-build -A bgpwtf.machines.tests.edge01-waw
|
||||
#
|
||||
# To deploy changes, see //ops:machines.nix.
|
||||
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
with builtins;
|
||||
|
||||
let
|
||||
passwords = import ./secrets/plain/passwords.nix;
|
||||
|
||||
in rec {
|
||||
networking.hostName = "edge01";
|
||||
networking.domain = "waw.bgp.wtf";
|
||||
|
||||
imports = [
|
||||
./modules/router.nix
|
||||
|
||||
# Private configuration data - notably, customer data.
|
||||
./secrets/plain/edge01.waw.bgp.wtf-private.nix
|
||||
];
|
||||
|
||||
# TODO(q3k): make this generic, move to modules/router.nix.
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
interfaces = [
|
||||
"185.236.240.1"
|
||||
"2a0d:eb00:2137::1"
|
||||
"127.0.0.1"
|
||||
];
|
||||
allowedAccess = [
|
||||
"185.236.240.0/22"
|
||||
"2a0d:eb00::0/29"
|
||||
"127.0.0.0/8"
|
||||
];
|
||||
extraConfig = ''
|
||||
outgoing-interface: 185.236.240.1
|
||||
outgoing-interface: 2a0d:eb00:2137::1
|
||||
cache-max-negative-ttl: 30
|
||||
|
||||
# Disable DoH in Firefox
|
||||
local-zone: "use-application-dns.net" static
|
||||
|
||||
# Rejestr Stron Hazardowych.
|
||||
# Populated by the rsh-unbound daemon.
|
||||
include: "/var/lib/unbound/rsh.conf"
|
||||
'';
|
||||
};
|
||||
hscloud.rsh = {
|
||||
enable = true;
|
||||
out = "/var/lib/unbound/rsh.conf";
|
||||
};
|
||||
|
||||
hscloud.renameInterfaces = {
|
||||
# Link to Nitronet CPE.
|
||||
e1-nnet.mac = "ac:1f:6b:1c:d7:ae";
|
||||
# Link to HSWAW Customs.
|
||||
e2-customs.mac = "ac:1f:6b:1c:d7:af";
|
||||
# Link to management switch.
|
||||
e3-mgmt.mac = "ac:1f:6b:1c:d7:b0";
|
||||
# Link to oob1.
|
||||
e4-oob.mac = "ac:1f:6b:1c:d7:b1";
|
||||
e5.mac = "ac:1f:6b:1c:d7:b2";
|
||||
e6.mac = "ac:1f:6b:1c:d7:b3";
|
||||
# Link to dcsw01.hswaw.net
|
||||
e7-dcsw.mac = "ac:1f:6b:1c:db:06";
|
||||
e8.mac = "ac:1f:6b:1c:db:07";
|
||||
};
|
||||
networking.interfaces.e7-dcsw.mtu = 9000;
|
||||
|
||||
networking.vlans = {
|
||||
"vl-globalmix" = { interface = "e1-nnet"; id = 466; };
|
||||
"vl-polmix" = { interface = "e1-nnet"; id = 2486; };
|
||||
"vl-openpeering" = { interface = "e1-nnet"; id = 992; };
|
||||
|
||||
"vl-dcsw-l3" = { interface = "e7-dcsw"; id = 4001; };
|
||||
"vl-dist-l3" = { interface = "e7-dcsw"; id = 3006; };
|
||||
|
||||
# Extra vlans contained in //bgpwtf/machines/secrets/plain/edge01.waw.bgp.wtf-private.nix
|
||||
};
|
||||
networking.interfaces = {
|
||||
lo = {
|
||||
ipv4.addresses = [ { address = "185.236.240.1"; prefixLength = 32; } ];
|
||||
ipv6.addresses = [ { address = "2a0d:eb00:2137::1"; prefixLength = 64; } ];
|
||||
};
|
||||
## EPIX links via Nitronet.
|
||||
"vl-globalmix" = {
|
||||
ipv4.addresses = [ { address = "185.235.70.45"; prefixLength = 31; } ];
|
||||
ipv6.addresses = [ { address = "2001:67c:778:fd40::b9eb:462d"; prefixLength = 127; } ];
|
||||
};
|
||||
"vl-polmix" = {
|
||||
ipv4.addresses = [ { address = "94.246.185.175"; prefixLength = 31; } ];
|
||||
ipv6.addresses = [ { address = "2001:67c:778:fa40::5ef6:b9af"; prefixLength = 127; } ];
|
||||
};
|
||||
"vl-openpeering" = {
|
||||
ipv4.addresses = [ { address = "89.46.145.61"; prefixLength = 21; } ];
|
||||
ipv6.addresses = [ { address = "2001:678:3ac::313"; prefixLength = 48; } ];
|
||||
};
|
||||
|
||||
## L3/mgmt links..
|
||||
# To customs.hackerspace.pl.
|
||||
"e2-customs" = {
|
||||
ipv4.addresses = [ { address = "185.236.240.4"; prefixLength = 31; } ];
|
||||
ipv6.addresses = [ { address = "2a0d:eb00:2137:1::2"; prefixLength = 127; } ];
|
||||
};
|
||||
# To mgmt.
|
||||
"e3-mgmt" = {
|
||||
ipv4.addresses = [ { address = "10.10.10.1"; prefixLength = 24; } ];
|
||||
};
|
||||
# To obb1.
|
||||
"e4-oob" = {
|
||||
ipv4.addresses = [ { address = "185.236.240.74"; prefixLength = 29; } ];
|
||||
};
|
||||
# To dcsw01, L3 (BGP).
|
||||
"vl-dcsw-l3" = {
|
||||
mtu = 9000;
|
||||
ipv4.addresses = [ { address = "185.236.240.6"; prefixLength = 31; } ];
|
||||
ipv6.addresses = [ { address = "2a0d:eb00:2137:1::6"; prefixLength = 127; } ];
|
||||
};
|
||||
# To dist02, L3 (BGP).
|
||||
"vl-dist-l3" = {
|
||||
ipv4.addresses = [ { address = "185.236.240.14"; prefixLength = 31; } ];
|
||||
ipv6.addresses = [ { address = "2a0d:eb00:2137:1::a"; prefixLength = 127; } ];
|
||||
};
|
||||
|
||||
# Extra interface configs contained in //bgpwtf/machines/secrets/plain/edge01.waw.bgp.wtf-private.nix
|
||||
};
|
||||
|
||||
hscloud.routing.enable = true;
|
||||
hscloud.routing.routerID = "185.236.240.1";
|
||||
hscloud.routing.asn = 204880;
|
||||
# Use default master4/master6 tables so that `birdc show route` works.
|
||||
hscloud.routing.tables.master.program = true;
|
||||
hscloud.routing.tables.master.programSourceV4 = "185.236.240.1";
|
||||
hscloud.routing.tables.master.programSourceV6 = "2a0d:eb00:2137::1";
|
||||
|
||||
hscloud.routing.extra = ''
|
||||
function net_martian_v4() {
|
||||
return net ~ [ 169.254.0.0/16+, 172.16.0.0/12+, 192.168.0.0/16+, 10.0.0.0/8+,
|
||||
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} ];
|
||||
}
|
||||
function net_as204480_waw_v4() {
|
||||
return net ~ [ 185.236.240.0/23+ ];
|
||||
}
|
||||
function net_martian_v6() {
|
||||
return net ~ [ fc00::/7+, fec0::/10+, ::/128-, ::/0{0,15}, ::/0{49,128} ];
|
||||
}
|
||||
function net_as204480_waw_v6() {
|
||||
return net ~ [ 2a0d:eb00::/32 ];
|
||||
}
|
||||
|
||||
'';
|
||||
hscloud.routing.originate = {
|
||||
# WAW prefixes, exposed into internet BGP table.
|
||||
v4.waw = { table = "internet"; address = "185.236.240.0"; prefixLength = 23; };
|
||||
v6.waw = { table = "internet"; address = "2a0d:eb00::"; prefixLength = 32; };
|
||||
|
||||
# Default gateway via us, exposed into aggregated table.
|
||||
v4.default = { table = "aggregate"; address = "0.0.0.0"; prefixLength = 0; };
|
||||
v6.default = { table = "aggregate"; address = "::"; prefixLength = 0; };
|
||||
};
|
||||
hscloud.routing.pipe = let
|
||||
copySourcesToKernel = sources: table: {
|
||||
table = "master";
|
||||
peerTable = table;
|
||||
filterIn = ''
|
||||
${concatStringsSep "\n" (map (v: "if source = RTS_${v} then accept;") sources)}
|
||||
reject;
|
||||
'';
|
||||
};
|
||||
in {
|
||||
v4."internet_to_kernel" = copySourcesToKernel ["BGP" "OSPF"] "internet";
|
||||
v4."aggregate_to_kernel" = copySourcesToKernel ["BGP" "OSPF"] "aggregate";
|
||||
v6."internet_to_kernel" = copySourcesToKernel ["BGP" "OSPF"] "internet";
|
||||
v6."aggregate_to_kernel" = copySourcesToKernel ["BGP" "OSPF"] "aggregate";
|
||||
};
|
||||
|
||||
hscloud.routing.ospf.v6.main = {
|
||||
area."0.0.0.0".interfaces = {
|
||||
"e2-customs" = {
|
||||
type = "bcast";
|
||||
};
|
||||
"e4-oob" = {
|
||||
type = "bcast";
|
||||
stub = true;
|
||||
};
|
||||
};
|
||||
table = "aggregate";
|
||||
filterIn = ''
|
||||
# hswaw prefix from e2-customs
|
||||
if net ~ [ 2a0d:eb00:4242::/64+ ] then accept;
|
||||
# e2-customs link
|
||||
if net ~ [ 2a0d:eb00:2137:1::2/127+ ] then accept;
|
||||
'';
|
||||
};
|
||||
hscloud.routing.ospf.v4.main = {
|
||||
area."0.0.0.0".interfaces = {
|
||||
"e4-oob" = {
|
||||
type = "bcast";
|
||||
stub = true;
|
||||
};
|
||||
};
|
||||
table = "aggregate";
|
||||
filterIn = ''
|
||||
# e4-oob link
|
||||
if net ~ [ 185.236.240.72/29+ ] then accept;
|
||||
'';
|
||||
};
|
||||
|
||||
hscloud.routing.bgpSessions.v4 = let
|
||||
filterInUpstream = ''
|
||||
if net_martian_v4() then reject;
|
||||
if net_as204480_waw_v4() then reject;
|
||||
accept;
|
||||
'';
|
||||
filterOutUpstream = ''
|
||||
# Accept AS204880-announced prefixes.
|
||||
if (net ~ [ 185.236.240.0/22+ ]) then accept;
|
||||
reject;
|
||||
'';
|
||||
in {
|
||||
"waw_globalmix" = {
|
||||
description = "UPSTREAM EPIX.WAR GlobalMix";
|
||||
table = "internet";
|
||||
local = "185.235.70.45";
|
||||
neighbors = [
|
||||
{ address = "185.235.70.44"; asn = 62081; }
|
||||
];
|
||||
prepend = 2; pref = 100;
|
||||
filterIn = filterInUpstream;
|
||||
filterOut = filterOutUpstream;
|
||||
};
|
||||
"waw_polmix" = {
|
||||
description = "UPSTREAM EPIX.WAR PolMix";
|
||||
table = "internet";
|
||||
local = "94.246.185.175";
|
||||
neighbors = [
|
||||
{ address = "94.246.185.174"; asn = 201054; }
|
||||
];
|
||||
prepend = 1; pref = 200;
|
||||
filterIn = filterInUpstream;
|
||||
filterOut = filterOutUpstream;
|
||||
};
|
||||
"waw_openpeering" = {
|
||||
description = "IXP EPIX.WAR OpenPeering";
|
||||
table = "internet";
|
||||
local = "89.46.145.61";
|
||||
neighbors = [
|
||||
{ address = "89.46.144.11"; asn = 48850; }
|
||||
{ address = "89.46.144.12"; asn = 48850; }
|
||||
];
|
||||
prepend = 0; pref = 300;
|
||||
filterIn = filterInUpstream;
|
||||
filterOut = filterOutUpstream;
|
||||
};
|
||||
"waw_google" = {
|
||||
description = "PEER Google AS15169 (EPIX)";
|
||||
table = "internet";
|
||||
local = "89.46.145.61";
|
||||
neighbors = [
|
||||
# TODO(q3k): secretify the password.
|
||||
{ address = "89.46.144.185"; asn = 15169; password = passwords."edge01.waw-bgp-google"; }
|
||||
];
|
||||
prepend = 0; pref = 300;
|
||||
filterIn = filterInUpstream;
|
||||
filterOut = filterOutUpstream;
|
||||
};
|
||||
# hscloud spine switch (dcsw01.hswaw.net).
|
||||
"waw_hscloud" = {
|
||||
description = "AGGREGATE CUSTOMER hscloud/dcsw01";
|
||||
table = "aggregate";
|
||||
local = "185.236.240.6";
|
||||
asn = 65000;
|
||||
neighbors = [
|
||||
{ address = "185.236.240.7"; asn = 65001; }
|
||||
];
|
||||
filterIn = ''
|
||||
# wieloryb prefix
|
||||
if net ~ [ 185.236.240.8/31+ ] then accept;
|
||||
# dcsw01 l2 general purpose
|
||||
if net ~ [ 185.236.240.24/29+ ] then accept;
|
||||
# hscloud l2 general purpose
|
||||
if net ~ [ 185.236.240.32/28+ ] then accept;
|
||||
# k0 metallb pools
|
||||
if net ~ [ 185.236.240.48/28+, 185.236.240.112/28+ ] then accept;
|
||||
reject;
|
||||
'';
|
||||
};
|
||||
# bgp.wtf internet customer router on W2A, floor 3 (dist02.bgp.wtf).
|
||||
"waw_dist02" = {
|
||||
description = "AGGREGATE CUSTOMER bgpwtf/dist02";
|
||||
table = "aggregate";
|
||||
local = "185.236.240.14";
|
||||
asn = 65000;
|
||||
neighbors = [
|
||||
{ address = "185.236.240.15"; asn = 65002; }
|
||||
];
|
||||
filterIn = ''
|
||||
# dist02 customer routed
|
||||
if net ~ [ 185.236.240.80/28+ ] then accept;
|
||||
reject;
|
||||
'';
|
||||
};
|
||||
# backup LTE link to edge01.fra
|
||||
"fra_edge01" = {
|
||||
description = "IBGP edge01.fra";
|
||||
table = "internet";
|
||||
local = "185.236.240.74";
|
||||
direct = true;
|
||||
neighbors = [
|
||||
{ address = "185.236.240.75"; asn = 204880; }
|
||||
];
|
||||
pref = 50;
|
||||
filterIn = filterInUpstream;
|
||||
filterOut = filterOutUpstream;
|
||||
};
|
||||
};
|
||||
hscloud.routing.bgpSessions.v6 = let
|
||||
filterInUpstream = ''
|
||||
if net_martian_v6() then reject;
|
||||
if net_as204480_waw_v6() then reject;
|
||||
accept;
|
||||
'';
|
||||
filterOutUpstream = ''
|
||||
# Accept AS204880-announced prefixes.
|
||||
if (net ~ [ 2a0d:eb00::/29+ ]) then accept;
|
||||
reject;
|
||||
'';
|
||||
in {
|
||||
"waw_globalmix" = {
|
||||
description = "UPSTREAM EPIX.WAR GlobalMix";
|
||||
table = "internet";
|
||||
local = "2001:67c:778:fd40::b9eb:462d";
|
||||
neighbors = [
|
||||
{ address = "2001:67c:778:fd40::b9eb:462c"; asn = 62081; }
|
||||
];
|
||||
prepend = 2; pref = 100;
|
||||
filterIn = filterInUpstream;
|
||||
filterOut = filterOutUpstream;
|
||||
};
|
||||
"waw_polmix" = {
|
||||
description = "UPSTREAM EPIX.WAR PolMix";
|
||||
table = "internet";
|
||||
local = "2001:67c:778:fa40::5ef6:b9af";
|
||||
neighbors = [
|
||||
{ address = "2001:67c:778:fa40::5ef6:b9ae"; asn = 201054; }
|
||||
];
|
||||
prepend = 1; pref = 200;
|
||||
filterIn = filterInUpstream;
|
||||
filterOut = filterOutUpstream;
|
||||
};
|
||||
"waw_openpeering" = {
|
||||
description = "IXP EPIX.WAR OpenPeering";
|
||||
table = "internet";
|
||||
local = "2001:678:3ac::313";
|
||||
neighbors = [
|
||||
{ address = "2001:678:3ac::11"; asn = 48850; }
|
||||
{ address = "2001:678:3ac::12"; asn = 48850; }
|
||||
];
|
||||
prepend = 0; pref = 300;
|
||||
filterIn = filterInUpstream;
|
||||
filterOut = filterOutUpstream;
|
||||
};
|
||||
"waw_google" = {
|
||||
description = "PEER Google AS15169 (EPIX)";
|
||||
table = "internet";
|
||||
local = "2001:678:3ac::313";
|
||||
neighbors = [
|
||||
{ address = "2001:678:3ac::185"; asn = 15169; password = passwords."edge01.waw-bgp-google"; }
|
||||
];
|
||||
prepend = 0; pref = 300;
|
||||
filterIn = filterInUpstream;
|
||||
filterOut = filterOutUpstream;
|
||||
};
|
||||
# hscloud spine switch (dcsw01.hswaw.net).
|
||||
"waw_hscloud" = {
|
||||
description = "AGGREGATE CUSTOMER dcsw01.hswaw.net";
|
||||
table = "aggregate";
|
||||
local = "2a0d:eb00:2137:1::6";
|
||||
asn = 65000;
|
||||
neighbors = [
|
||||
{ address = "2a0d:eb00:2137:1::7"; asn = 65001; }
|
||||
];
|
||||
filterIn = ''
|
||||
# dcsw01 l2 general purpose
|
||||
if net ~ [ 2a0d:eb00:2137::/48+ ] then accept;
|
||||
reject;
|
||||
'';
|
||||
};
|
||||
# bgp.wtf internet customer router on W2A, floor 3 (dist02.bgp.wtf).
|
||||
"waw_dist02" = {
|
||||
description = "AGGREGATE CUSTOMER dist02.bgp.wtf";
|
||||
table = "aggregate";
|
||||
local = "2a0d:eb00:2137:1::a";
|
||||
asn = 65000;
|
||||
neighbors = [
|
||||
{ address = "2a0d:eb00:2137:1::b"; asn = 65002; }
|
||||
];
|
||||
filterIn = ''
|
||||
# dist02 customers.
|
||||
if net ~ [ 2a0d:eb00:8002::/48 ] then accept;
|
||||
reject;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
77
bgpwtf/machines/modules/bootstrap.nix
Normal file
77
bgpwtf/machines/modules/bootstrap.nix
Normal file
|
@ -0,0 +1,77 @@
|
|||
# Functionality that used to live in bootstrap.hswaw.net, a VM.
|
||||
# PXE boot support has been removed and the functionality moved back to
|
||||
# edge01.waw.bgp.wtf.
|
||||
|
||||
{ config, pkgs, ... }: {
|
||||
networking.bridges.bootstrap.interfaces = [];
|
||||
networking.interfaces.bootstrap.ipv4.addresses = [
|
||||
{ address = "185.236.240.18"; prefixLength = 32; }
|
||||
];
|
||||
services.dhcpd4 = {
|
||||
enable = true;
|
||||
interfaces = [ "bootstrap" "vl-dcsw-l3" ];
|
||||
extraConfig = ''
|
||||
# ISC DHCP is trash. We only use it in relay mode, yet we have to do
|
||||
# this.
|
||||
subnet 185.236.240.18 netmask 255.255.255.255 {}
|
||||
|
||||
subnet 185.236.240.6 netmask 255.255.255.254 {}
|
||||
|
||||
subnet 185.236.240.24 netmask 255.255.255.248 {
|
||||
option routers 185.236.240.25;
|
||||
range 185.236.240.29 185.236.240.30;
|
||||
option domain-name-servers 8.8.8.8;
|
||||
}
|
||||
|
||||
subnet 185.236.240.32 netmask 255.255.255.240 {
|
||||
range 185.236.240.45 185.236.240.46;
|
||||
option routers 185.236.240.33;
|
||||
option domain-name-servers 8.8.8.8;
|
||||
}
|
||||
|
||||
host bc01n01 {
|
||||
hardware ethernet 00:23:ae:fe:83:20;
|
||||
fixed-address 185.236.240.35;
|
||||
option host-name "bc01n01";
|
||||
}
|
||||
host bc01n02 {
|
||||
hardware ethernet 00:23:ae:fe:83:c4;
|
||||
fixed-address 185.236.240.36;
|
||||
option host-name "bc01n02";
|
||||
}
|
||||
host bc01n03 {
|
||||
hardware ethernet 00:23:ae:fe:42:80;
|
||||
fixed-address 185.236.240.37;
|
||||
option host-name "bc01n03";
|
||||
}
|
||||
host boston-packets {
|
||||
hardware ethernet 00:23:ae:fe:45:8c;
|
||||
fixed-address 185.236.240.38;
|
||||
option host-name "boston-packets.hackerspace.pl";
|
||||
#filename "ipxe.efi";
|
||||
}
|
||||
host dcr01s22 {
|
||||
hardware ethernet 90:1b:0e:08:12:b8;
|
||||
fixed-address 185.236.240.39;
|
||||
option host-name "dcr01s22";
|
||||
#filename "ipxe.efi";
|
||||
}
|
||||
host dcr01s24 {
|
||||
hardware ethernet 90:1b:0e:31:bb:6a;
|
||||
fixed-address 185.236.240.40;
|
||||
option host-name "dcr01s24";
|
||||
#filename "ipxe.efi";
|
||||
}
|
||||
host dsctf {
|
||||
hardware ethernet 00:23:ae:fe:45:50;
|
||||
fixed-address 185.236.240.41;
|
||||
option host-name "dsctf";
|
||||
}
|
||||
host dcr03s32b1 {
|
||||
hardware ethernet 02:01:87:4a:9a:b9;
|
||||
fixed-address 185.236.240.26;
|
||||
option host-name "dcr03s32b1";
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
75
bgpwtf/machines/modules/eoip.nix
Normal file
75
bgpwtf/machines/modules/eoip.nix
Normal file
|
@ -0,0 +1,75 @@
|
|||
# A small Ethernet-over-IP service implementation.
|
||||
# Yes, that's the Mikrotik EoIP implementation. This one is somewhat sketchy
|
||||
# (notably, it pumps huge zero-padded frames into tap), so doesn't use it for
|
||||
# production. We currently only use it in the edge01.waw test framework to
|
||||
# bring vlans across test VMs.
|
||||
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
eoip = pkgs.stdenv.mkDerivation {
|
||||
pname = "eoip";
|
||||
version = "20180119";
|
||||
nativeBuildInputs = with pkgs; [ cmake ];
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "amphineko";
|
||||
repo = "eoiptapd";
|
||||
rev = "5573a905bcbc001b503308665f098e82f451dc33";
|
||||
sha256 = "0np9dzcw5w6jarzdv2yh3mbzz0wgw10sjqyi6pxan4ipr75v1b8s";
|
||||
};
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp eoiptapd $out/bin/eoiptapd
|
||||
'';
|
||||
};
|
||||
|
||||
cfg = config.hscloud.eoip;
|
||||
|
||||
in {
|
||||
options.hscloud.eoip = {
|
||||
interfaces = mkOption {
|
||||
type = with types; attrsOf (submodule {
|
||||
options = {
|
||||
localV4 = mkOption {
|
||||
type = types.str;
|
||||
description = "Local outer IPv4 address";
|
||||
};
|
||||
remoteV4 = mkOption {
|
||||
type = types.str;
|
||||
description = "Remote outer IPv4 address";
|
||||
};
|
||||
id = mkOption {
|
||||
type = types.int;
|
||||
description = "Tunnel ID";
|
||||
};
|
||||
parent = mkOption {
|
||||
type = types.str;
|
||||
description = "Parent/outer device";
|
||||
};
|
||||
};
|
||||
});
|
||||
description = ''
|
||||
EoIP interfaces to create.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config.systemd.services = mapAttrs' (name: value: nameValuePair "${name}-eoip" {
|
||||
wantedBy = [ "network.target" ];
|
||||
wants = [
|
||||
"${name}-netdev.service"
|
||||
"network-addresses-${value.parent}.service"
|
||||
];
|
||||
after = [
|
||||
"network-addresses-${value.parent}.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${eoip}/bin/eoiptapd -i ${name} -l ${value.localV4} -r ${value.remoteV4} -t ${toString value.id}";
|
||||
Restart = "always";
|
||||
RestartSec = "1";
|
||||
};
|
||||
}) cfg.interfaces;
|
||||
}
|
57
bgpwtf/machines/modules/prometheus.nix
Normal file
57
bgpwtf/machines/modules/prometheus.nix
Normal file
|
@ -0,0 +1,57 @@
|
|||
# Prometheus configuration for a BIRD-enabled router.
|
||||
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
nodeExporterPort = 9100;
|
||||
birdExporterPort = 9101;
|
||||
|
||||
birdExporter = pkgs.buildGoModule rec {
|
||||
pname = "bird-exporter";
|
||||
version = "1.2.5";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "czerwonk";
|
||||
repo = "bird_exporter";
|
||||
rev = version;
|
||||
sha256 = "1qrhncy1f119f5rfgn2d1l6nvapaqkld4zb9bxzdqmmw6kicc7bs";
|
||||
};
|
||||
|
||||
vendorSha256 = null;
|
||||
};
|
||||
|
||||
in {
|
||||
systemd.services.bird_exporter = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${birdExporter}/bin/bird_exporter -format.new=true -bird.v2=true -web.listen-address=127.0.0.1:${toString birdExporterPort}";
|
||||
Restart = "always";
|
||||
RestartSec = "60";
|
||||
};
|
||||
};
|
||||
|
||||
services.prometheus.exporters.node = {
|
||||
enable = true;
|
||||
listenAddress = "127.0.0.1";
|
||||
port = nodeExporterPort;
|
||||
};
|
||||
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts."${config.networking.hostName}.${config.networking.domain}" = let
|
||||
allowMonitoring = ''
|
||||
allow 209.250.231.127; # monitoring.hackerspace.pl
|
||||
deny all;
|
||||
'';
|
||||
in {
|
||||
locations."/metrics-node" = {
|
||||
proxyPass = "http://127.0.0.1:${toString nodeExporterPort}/metrics";
|
||||
extraConfig = allowMonitoring;
|
||||
};
|
||||
locations."/metrics-bird" = {
|
||||
proxyPass = "http://127.0.0.1:${toString birdExporterPort}/metrics";
|
||||
extraConfig = allowMonitoring;
|
||||
};
|
||||
};
|
||||
}
|
29
bgpwtf/machines/modules/rename-interfaces.nix
Normal file
29
bgpwtf/machines/modules/rename-interfaces.nix
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Sketchy little module to renamei interfaces by MAC.
|
||||
# This only works on startup.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.hscloud.renameInterfaces;
|
||||
in {
|
||||
options.hscloud.renameInterfaces = mkOption {
|
||||
type = with types; attrsOf (submodule {
|
||||
options = {
|
||||
mac = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
MAC address to match by, in hexadecimal form (ie. ac:1f:6b:1c:d7:ae).
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
description = ''
|
||||
Interfaces to rename by property (eg. MAC address).
|
||||
'';
|
||||
};
|
||||
|
||||
config.services.udev.extraRules = concatStringsSep "\n" (mapAttrsToList (n: v: ''
|
||||
ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="${v.mac}", ATTR{addr_assign_type}=="0", NAME="${n}"
|
||||
'') cfg);
|
||||
}
|
54
bgpwtf/machines/modules/router.nix
Normal file
54
bgpwtf/machines/modules/router.nix
Normal file
|
@ -0,0 +1,54 @@
|
|||
# Generic configuration for any bgpwtf router.
|
||||
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with builtins;
|
||||
|
||||
rec {
|
||||
imports = [
|
||||
./routing.nix
|
||||
./rename-interfaces.nix
|
||||
./rsh-unbound.nix
|
||||
./bootstrap.nix
|
||||
./prometheus.nix
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
tcpdump htop dstat file strace gdb mtr
|
||||
vim wget curl htop dstat whois bind
|
||||
rxvt_unicode.terminfo dhcpcd efibootmgr
|
||||
];
|
||||
networking.useDHCP = false;
|
||||
networking.firewall.enable = false;
|
||||
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
||||
boot.kernel.sysctl."net.ipv4.conf.*.accept_redirects" = 0;
|
||||
boot.kernel.sysctl."net.ipv4.conf.*.send_redirects" = 0;
|
||||
boot.kernel.sysctl."net.ipv4.conf.*.accept_source_route" = 0;
|
||||
boot.kernel.sysctl."net.ipv4.conf.*.proxy_arp" = 0;
|
||||
boot.kernel.sysctl."net.ipv4.conf.*.secure_redirects" = 1;
|
||||
boot.kernel.sysctl."net.ipv4.conf.*.bootp_relay" = 0;
|
||||
boot.kernel.sysctl."net.ipv4.conf.*.arp_filter" = 1;
|
||||
boot.kernel.sysctl."net.ipv4.conf.*.arp_ignore" = 1;
|
||||
boot.kernel.sysctl."net.ipv4.conf.*.arp_announce" = 2;
|
||||
boot.kernel.sysctl."net.ipv4.conf.*.rp_filter" = 0;
|
||||
boot.kernel.sysctl."net.ipv6.conf.*.forwarding" = 1;
|
||||
boot.kernel.sysctl."net.ipv6.conf.*.accept_ra" = 0;
|
||||
boot.kernel.sysctl."net.ipv6.conf.*.autoconf" = 0;
|
||||
boot.kernel.sysctl."net.ipv6.conf.*.router_solicitations" = 0;
|
||||
|
||||
# Use Chrony instead of systemd-timesyncd
|
||||
time.timeZone = "Europe/Warsaw";
|
||||
services.chrony.enable = true;
|
||||
networking.nameservers = [ "8.8.8.8" ];
|
||||
|
||||
# Enable the OpenSSH daemon.
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDD4VJXAXEHEXZk2dxNwehneuJcEGkfXG/U7z4fO79vDVIENdedtXQUyLyhZJc5RTEfHhQj66FwIqzl7mzBHd9x9PuDp6QAYXrkVNMj48s6JXqZqBvF6H/weRqFMf4a2TZv+hG8D0kpvmLheCwWAVRls7Jofnp/My+yDd57GMdsbG/yFEf6WPMiOnA7hxdSJSVihCsCSw2p8PD4GhBe8CVt7xIuinhutjm9zYBjV78NT8acjDUfJh0B1ODTjs7nuW1CC4jybSe2j/OU3Yczj4AxRxBNWuFxUq+jBo9BfpbKLh+Tt7re+zBkaicM77KM/oV6943JJxgHNBBOsv9scZE7 q3k@amnesia"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG599UildOrAq+LIOQjKqtGMwjgjIxozI1jtQQRKHtCP q3k@mimeomia"
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQb3YQoiYFZLKwvHYKbu1bMqzNeDCAszQhAe1+QI5SLDOotclyY/vFmOReZOsmyMFl71G2d7d+FbYNusUnNNjTxRYQ021tVc+RkMdLJaORRURmQfEFEKbai6QSFTwErXzuoIzyEPK0lbsQuGgqT9WaVnRzHJ2Q/4+qQbxAS34PuR5NqEkmn4G6LMo3OyJ5mwPkCj9lsqz4BcxRaMWFO3mNcwGDfSW+sqgc3E8N6LKrTpZq3ke7xacpQmcG5DU9VO+2QVPdltl9jWbs3gXjmF92YRNOuKPVfAOZBBsp8JOznfx8s9wDgs7RwPmDpjIAJEyoABqW5hlXfqRbTnfnMvuR informatic@InformaticPC"
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDGkMgEVwQM8yeuFUYL2TwlJIq9yUNBmHnwce46zeL2PK2CkMz7sxT/om7sp/K5XDiqeD05Nioe+Dr3drP6B8uI33S5NgxPIfaqQsRS+CBEgk6cqFlcdlKETU/DT+/WsdoO173n7mgGeafPInEuQuGDUID0Fl099kIxtqfAhdeZFMM6/szAZEZsElLJ8K6dp1Ni/jmnXCZhjivZH3AZUlnqrmtDG7FY1bgcOfDXAal45LItughGPtrdiigXe9DK2fW3+9DBZZduh5DMJTNlphAZ+nfSrbyHVKUg6WsgMSprur4KdU47q1QwzqqvEj75JcdP1jOWoZi4F6VJDte9Wb9lhD1jGgjxY9O6Gs4CH35bx15W7CN9hgNa0C8NbPJe/fZYIeMZmJ1m7O2xmnYwP8j+t7RNJWu7Pa3Em4mOEXvhBF07Zfq+Ye/4SluoRgADy5eII2x5fFo5EBhInxK0/X8wF6XZvysalVifoCh7T4Edejoi91oAxFgYAxbboXGlod0eEHIi2hla8SM9+IBHOChmgawKBYp2kzAJyAmHNBF+Pah9G4arVCj/axp/SJZDZbJQoI7UT/fJzEtvlb5RWrHXRq+y6IvjpUq4pzpDWW04+9UMqEEXRmhWOakHfEVM9rN8h3aJBflLUBBnh0Z/hVsKNh8bCRHaKtah8TrD9i+wMw== patryk.jakuszew@gmail.com"
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC33naG1ptCvUcRWX9cj9wXM1nW1lyQC4SvMJzWlr9aMD96O8hQ2JMkuIUgUJvorAY02QRplQ2BuoVoVkdkzwjMyi1bL3OdgcKo7Z1yByClGTTocqNJYY0lcUb6EJH8+6e6F9ydrQlSxNzL1uCaA7phZr+yPcmAmWbSfioXn98yXNkE0emHxzJv/nypJY56sDCMC2IXDRd8L2goDtPwgPEW7bWfAQdIFMJ75xOidZOTxJ8eqyXLw/kxY5UlyX66jdoYz1sE5XUHuoQl1AOG9UdlMo0aMhUvP4pX5l7r7EnA9OttKMFB3oWqkVK/R6ynZ52YNOU5BZ9V+Ppaj34W0xNu+p0mbHcCtXYCTrf/OU0hcZDbDaNTjs6Vtcm2wYw9iAKX7Tex+eOMwUwlrlcyPNRV5BTot7lGNYfauHCSIuWJKN4NhCLR/NtVNh4/94eKkPTwJsY6XqDcS7q49wPAs4DAH7BJgsbHPOqygVHrY0YYEfz3Pj0HTxJHQMCP/hQX4fXEGt0BjgoVJbXPAQtPyeg0JuxiUg+b4CgVVfQ6R060MlM1BZzhmh+FY5MJH6nJppS0aHYCvSg8Z68NUlCPKy0jpcyfuAIWQWwSGG1O010WShQG2ELsvNdg5/4HVdCGNl5mmoom6JOd72FOZyQlHDFfeQUQRn9HOeCq/c51rK99SQ== bartek@IHM"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICTR292kx/2CNuWYIsZ6gykQ036aBGrmheIuZa6S1D2x implr@thonk"
|
||||
];
|
||||
}
|
440
bgpwtf/machines/modules/routing.nix
Normal file
440
bgpwtf/machines/modules/routing.nix
Normal file
|
@ -0,0 +1,440 @@
|
|||
# Declarative routing configuration. Usees BIRD2 underneath.
|
||||
#
|
||||
# The mapping from declarative configuration to BIRD is quite straightforward,
|
||||
# however, we take a few liberties:
|
||||
# - we introduce an 'originate' protocol for originating prefixes (using the
|
||||
# static protocol).
|
||||
# - routing tables in the configuration are referred to by a common name for
|
||||
# IPv4 and IPv4 - while in BIRD, two tables are created (suffixed by '4' and
|
||||
# '6', following the two default 'master4' and 'master6' tables).
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.hscloud.routing;
|
||||
|
||||
originateType = af: let
|
||||
v4 = af == "ipv4";
|
||||
v6 = af == "ipv6";
|
||||
pretty = if v4 then "IPv4" else "IPv6";
|
||||
in with types; mkOption {
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
table = mkOption {
|
||||
type = nullOr str;
|
||||
description = "BIRD table to which session should be connected.";
|
||||
};
|
||||
address = mkOption {
|
||||
type = str;
|
||||
description = "Address part of prefix to announce.";
|
||||
};
|
||||
prefixLength = mkOption {
|
||||
type = int;
|
||||
description = "Prefix length to announce.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
description = "${pretty} prefixes to unconditionally inject into a table.";
|
||||
};
|
||||
|
||||
originateRender = af: n: v: let
|
||||
name = "static_originate_${af}_${n}";
|
||||
ip = if af == "ipv4" then "4" else "6";
|
||||
in ''
|
||||
protocol static ${name} {
|
||||
${af} {
|
||||
table ${v.table}${ip};
|
||||
import all;
|
||||
export none;
|
||||
};
|
||||
|
||||
route ${v.address}/${toString v.prefixLength} blackhole;
|
||||
}
|
||||
'';
|
||||
|
||||
ospfType = af: let
|
||||
v4 = af == "ipv4";
|
||||
v6 = af == "ipv6";
|
||||
pretty = if v4 then "IPv4" else "IPv6";
|
||||
ospf = if v4 then "OSPFv2" else "OSPFv3";
|
||||
in with types; mkOption {
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
table = mkOption {
|
||||
type = nullOr str;
|
||||
description = "BIRD table to which session should be connected.";
|
||||
};
|
||||
filterIn = mkOption {
|
||||
type = str;
|
||||
default = "accept;";
|
||||
description = "BIRD filter definition for received routes.";
|
||||
};
|
||||
filterOut = mkOption {
|
||||
type = str;
|
||||
default = "accept;";
|
||||
description = "BIRD filter definition for sent routes.";
|
||||
};
|
||||
area = mkOption {
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
interfaces = mkOption {
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
cost = mkOption {
|
||||
type = int;
|
||||
default = 10; # 1Gbps
|
||||
description = "Interface cost (10e9/iface_speed_in_bps).";
|
||||
};
|
||||
type = mkOption {
|
||||
type = enum ["bcast" "nbma" "ptp" "ptmp"];
|
||||
description = "Interface type (dictates BIRD behaviour).";
|
||||
};
|
||||
stub = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = "Interface is stub (do not HELLO).";
|
||||
};
|
||||
};
|
||||
});
|
||||
description = "Interface configuration";
|
||||
};
|
||||
};
|
||||
});
|
||||
description = "Area configuration";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
description = "${ospf} configuration";
|
||||
};
|
||||
|
||||
ospfRender = af: n: v: let
|
||||
v4 = af == "ipv4";
|
||||
v6 = af == "ipv6";
|
||||
ip = if v4 then "4" else "6";
|
||||
name = "ospf_${af}_${n}";
|
||||
|
||||
interfaces = mapAttrsToList (iface: ifaceConfig: ''
|
||||
interface "${iface}" {
|
||||
type ${ifaceConfig.type};
|
||||
cost ${toString ifaceConfig.cost};
|
||||
${if ifaceConfig.stub then "stub yes;" else ""}
|
||||
};
|
||||
'');
|
||||
areas = mapAttrsToList (area: areaConfig: ''
|
||||
area ${area} {
|
||||
${concatStringsSep "\n" (interfaces areaConfig.interfaces)}
|
||||
};
|
||||
'') v.area;
|
||||
in ''
|
||||
filter ${name}_in {
|
||||
${v.filterIn}
|
||||
};
|
||||
filter ${name}_out {
|
||||
${v.filterOut}
|
||||
};
|
||||
protocol ospf ${if v4 then "v2" else "v3"} ${name} {
|
||||
${af} {
|
||||
table ${v.table}${ip};
|
||||
import filter ${name}_in;
|
||||
export filter ${name}_out;
|
||||
};
|
||||
${concatStringsSep "\n" areas}
|
||||
}
|
||||
'';
|
||||
|
||||
pipeType = af: with types; mkOption {
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
table = mkOption {
|
||||
type = nullOr str;
|
||||
description = "BIRD table to which session should be connected.";
|
||||
};
|
||||
peerTable = mkOption {
|
||||
type = nullOr str;
|
||||
description = "BIRD 'remote' table to which session should be connected.";
|
||||
};
|
||||
filterIn = mkOption {
|
||||
type = str;
|
||||
default = "accept";
|
||||
description = "BIRD filter definition for routes received from peerTable";
|
||||
};
|
||||
filterOut = mkOption {
|
||||
type = str;
|
||||
default = "reject;";
|
||||
description = "BIRD filter definition for routes sent to peerTable";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
description = "${pretty} prefixes to pipe from one table to another.";
|
||||
};
|
||||
|
||||
pipeRender = af: n: v: let
|
||||
name = "pipe_${af}_${n}";
|
||||
v4 = af == "ipv4";
|
||||
v6 = af == "ipv6";
|
||||
ip = if v4 then "4" else "6";
|
||||
in ''
|
||||
filter ${name}_in {
|
||||
${v.filterIn}
|
||||
};
|
||||
filter ${name}_out {
|
||||
${v.filterOut}
|
||||
};
|
||||
protocol pipe ${name} {
|
||||
table ${v.table}${ip};
|
||||
peer table ${v.peerTable}${ip};
|
||||
import filter ${name}_in;
|
||||
export filter ${name}_out;
|
||||
}
|
||||
'';
|
||||
|
||||
bgpSessionsType = af: let
|
||||
v4 = af == "ipv4";
|
||||
v6 = af == "ipv6";
|
||||
pretty = if v4 then "IPv4" else "IPv6";
|
||||
in with types; mkOption {
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
description = mkOption {
|
||||
type = str;
|
||||
description = "Session description (for BIRD).";
|
||||
};
|
||||
table = mkOption {
|
||||
type = nullOr str;
|
||||
description = "BIRD table to which session should be connected.";
|
||||
};
|
||||
local = mkOption {
|
||||
type = str;
|
||||
description = "${pretty} address of this router.";
|
||||
};
|
||||
asn = mkOption {
|
||||
type = int;
|
||||
description = "ASN of local router - will default to hscloud.routing.asn.";
|
||||
default = cfg.asn;
|
||||
};
|
||||
prepend = mkOption {
|
||||
type = int;
|
||||
default = 0;
|
||||
description = "How many times to prepend this router's ASN on the link.";
|
||||
};
|
||||
pref = mkOption {
|
||||
type = int;
|
||||
default = 100;
|
||||
description = "Preference (BGP local_pref) for routes from this session.";
|
||||
};
|
||||
direct = mkOption {
|
||||
type = nullOr bool;
|
||||
default = null;
|
||||
};
|
||||
filterIn = mkOption {
|
||||
type = str;
|
||||
default = "accept;";
|
||||
description = "BIRD filter definition for received routes.";
|
||||
};
|
||||
filterOut = mkOption {
|
||||
type = str;
|
||||
default = "accept;";
|
||||
description = "BIRD filter definition for sent routes.";
|
||||
};
|
||||
neighbors = mkOption {
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
address = mkOption {
|
||||
type = str;
|
||||
description = "${pretty} address of neighbor.";
|
||||
};
|
||||
asn = mkOption {
|
||||
type = int;
|
||||
description = "ASN of neighbor.";
|
||||
};
|
||||
password = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "BGP TCP MD5 secret.";
|
||||
};
|
||||
};
|
||||
});
|
||||
description = "BGP Neighbor configuration";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
description = "BGP Sesions for ${pretty}";
|
||||
};
|
||||
|
||||
bgpSessionRender = af: n: v: let
|
||||
name = "bgp_${af}_${n}";
|
||||
ip = if af == "ipv4" then "4" else "6";
|
||||
filters = ''
|
||||
filter ${name}_in {
|
||||
if bgp_path.len > 64 then reject;
|
||||
bgp_local_pref = ${toString v.pref};
|
||||
${v.filterIn}
|
||||
}
|
||||
|
||||
filter ${name}_out {
|
||||
${if v.prepend > 0 then
|
||||
(concatStringsSep "\n"
|
||||
(map (_: "bgp_path.prepend(${toString v.asn});") (range 0 (v.prepend - 1)))
|
||||
)
|
||||
else ""}
|
||||
${v.filterOut}
|
||||
}
|
||||
'';
|
||||
peer = ix: peer: ''
|
||||
protocol bgp ${name}_${toString ix} {
|
||||
description "${v.description}";
|
||||
|
||||
${af} {
|
||||
table ${v.table}${ip};
|
||||
import filter ${name}_in;
|
||||
export filter ${name}_out;
|
||||
};
|
||||
|
||||
local ${v.local} as ${toString v.asn};
|
||||
neighbor ${peer.address} as ${toString peer.asn};
|
||||
${if peer.password != null then "password \"${peer.password}\";" else ""}
|
||||
${if v.direct == true then "direct;" else ""}
|
||||
}
|
||||
'';
|
||||
in "${filters}\n${concatStringsSep "\n" (imap1 peer v.neighbors)}";
|
||||
|
||||
tablesFromProtoAF =
|
||||
af: p: filter (el: el != null) (
|
||||
mapAttrsToList (_: v: "${af} table ${v.table}${if af == "ipv4" then "4" else "6"};") p);
|
||||
tablesFromProto = p: (tablesFromProtoAF "ipv4" p.v4) ++ (tablesFromProtoAF "ipv6" p.v6);
|
||||
tables =
|
||||
unique (
|
||||
(tablesFromProto cfg.bgpSessions) ++
|
||||
(tablesFromProto cfg.originate) ++
|
||||
(tablesFromProto cfg.pipe) ++
|
||||
(tablesFromProto cfg.ospf)
|
||||
# TODO(q3k): also slurp in peer tables from pipes.
|
||||
);
|
||||
tablesRender = ''
|
||||
${concatStringsSep "\n" tables}
|
||||
'';
|
||||
tablesProgram = mapAttrsToList (n: _: n) (filterAttrs (n: v: v.program == true) cfg.tables);
|
||||
tableProgram =
|
||||
if (length tablesProgram) != 1 then
|
||||
(abort "exactly one table must be set to be programmed")
|
||||
else
|
||||
(head tablesProgram);
|
||||
|
||||
in {
|
||||
options.hscloud.routing = {
|
||||
enable = mkEnableOption "declarative routing";
|
||||
routerID = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Default Router ID for dynamic routing protocols, eg. IPv4 address from
|
||||
loopback interface.
|
||||
'';
|
||||
};
|
||||
asn = mkOption {
|
||||
type = types.int;
|
||||
description = "Default ASN for BGP.";
|
||||
};
|
||||
extra = mkOption {
|
||||
type = types.lines;
|
||||
description = "Extra configuration lines.";
|
||||
};
|
||||
bgpSessions = {
|
||||
v4 = bgpSessionsType "ipv4";
|
||||
v6 = bgpSessionsType "ipv6";
|
||||
};
|
||||
originate = {
|
||||
v4 = originateType "ipv4";
|
||||
v6 = originateType "ipv6";
|
||||
};
|
||||
pipe = {
|
||||
v4 = pipeType "ipv4";
|
||||
v6 = pipeType "ipv6";
|
||||
};
|
||||
ospf = {
|
||||
v4 = ospfType "ipv4";
|
||||
v6 = ospfType "ipv6";
|
||||
};
|
||||
tables = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
program = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "This is the primary table programmed in to the kernel.";
|
||||
};
|
||||
programSourceV4 = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "If set, programmed routes will have source set to this address.";
|
||||
};
|
||||
programSourceV6 = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "If set, programmed routes will have source set to this address.";
|
||||
};
|
||||
};
|
||||
});
|
||||
description = "Routing table configuration.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.bird2.enable = true;
|
||||
services.bird2.config = ''
|
||||
log syslog all;
|
||||
debug protocols { states, interfaces, events }
|
||||
|
||||
router id ${cfg.routerID};
|
||||
|
||||
${cfg.extra}
|
||||
|
||||
${tablesRender}
|
||||
|
||||
protocol device {
|
||||
scan time 10;
|
||||
};
|
||||
|
||||
protocol kernel kernel_v4 {
|
||||
scan time 60;
|
||||
ipv4 {
|
||||
table ${tableProgram}4;
|
||||
import none;
|
||||
export filter {
|
||||
${let src = cfg.tables."${tableProgram}".programSourceV4; in if src != null then ''
|
||||
krt_prefsrc = ${src};
|
||||
'' else ""}
|
||||
accept;
|
||||
};
|
||||
};
|
||||
}
|
||||
protocol kernel kernel_v6 {
|
||||
scan time 60;
|
||||
ipv6 {
|
||||
table ${tableProgram}6;
|
||||
import none;
|
||||
export filter {
|
||||
${let src = cfg.tables."${tableProgram}".programSourceV6; in if src != null then ''
|
||||
krt_prefsrc = ${src};
|
||||
'' else ""}
|
||||
accept;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
${concatStringsSep "\n" (mapAttrsToList (bgpSessionRender "ipv4") cfg.bgpSessions.v4)}
|
||||
${concatStringsSep "\n" (mapAttrsToList (bgpSessionRender "ipv6") cfg.bgpSessions.v6)}
|
||||
${concatStringsSep "\n" (mapAttrsToList (originateRender "ipv4") cfg.originate.v4)}
|
||||
${concatStringsSep "\n" (mapAttrsToList (originateRender "ipv6") cfg.originate.v6)}
|
||||
${concatStringsSep "\n" (mapAttrsToList (pipeRender "ipv4") cfg.pipe.v4)}
|
||||
${concatStringsSep "\n" (mapAttrsToList (pipeRender "ipv6") cfg.pipe.v6)}
|
||||
${concatStringsSep "\n" (mapAttrsToList (ospfRender "ipv4") cfg.ospf.v4)}
|
||||
${concatStringsSep "\n" (mapAttrsToList (ospfRender "ipv6") cfg.ospf.v6)}
|
||||
|
||||
'';
|
||||
};
|
||||
}
|
70
bgpwtf/machines/modules/rsh-unbound.nix
Normal file
70
bgpwtf/machines/modules/rsh-unbound.nix
Normal file
|
@ -0,0 +1,70 @@
|
|||
# Run service that spits out an unbound-compatible blocklist of websites,
|
||||
# as mandated by polish telecommunications law.
|
||||
#
|
||||
# https://sip.lex.pl/akty-prawne/dzu-dziennik-ustaw/gry-hazardowe-17581037/art-15-f
|
||||
# Dz.U.2019.847 t.j.
|
||||
# Art. 15f. [Rejestr domen służących do oferowania gier hazardowych niezgodnie z ustawą]
|
||||
# 5. Przedsiębiorca telekomunikacyjny świadczący usługi dostępu do sieci
|
||||
# Internet jest obowiązany do:
|
||||
# 1) nieodpłatnego uniemożliwienia dostępu do stron internetowych
|
||||
# wykorzystujących nazwy domen internetowych wpisanych do Rejestru
|
||||
# poprzez ich usunięcie z systemów teleinformatycznych przedsiębiorców
|
||||
# telekomunikacyjnych, służących do zamiany nazw domen internetowych na
|
||||
# adresy IP, nie później niż w ciągu 48 godzin od dokonania wpisu do
|
||||
# Rejestru;
|
||||
# 2) nieodpłatnego przekierowania połączeń odwołujących się do nazw domen
|
||||
# internetowych wpisanych do Rejestru do strony internetowej prowadzonej
|
||||
# przez ministra właściwego do spraw finansów publicznych, zawierającej
|
||||
# komunikat, skierowany do odbiorców usługi dostępu do Internetu
|
||||
# obejmujący w szczególności informacje o lokalizacji Rejestru, wpisaniu
|
||||
# szukanej nazwy domeny internetowej do tego Rejestru, listę podmiotów
|
||||
# legalnie oferujących gry hazardowe na terytorium Rzeczypospolitej
|
||||
# Polskiej, a także powiadomienie o grożącej odpowiedzialności
|
||||
# karno-skarbowej uczestnika gier urządzanych wbrew przepisom ustawy;
|
||||
# 3) nieodpłatnego umożliwienia dostępu do stron internetowych
|
||||
# wykorzystujących nazwy domen wykreślonych z Rejestru, nie później niż w
|
||||
# ciągu 48 godzin od wykreślenia nazwy domeny internetowej z Rejestru.
|
||||
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
rshUnbound = pkgs.buildGoModule {
|
||||
pname = "rsh-unbound";
|
||||
version = "20200926";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "q3k";
|
||||
repo = "rsh-unbound";
|
||||
rev = "3d98c754adadddfae59387d033aef531f47dee5d";
|
||||
sha256 = "1ia33893m1dknw36vss97limlb1d28z5nkrkw6b4mp1igdgqsfcz";
|
||||
};
|
||||
|
||||
vendorSha256 = "1w94g2dwhf47jmds95frb26ypjmis5zhyy85rmd124v0nz3axzhf";
|
||||
};
|
||||
|
||||
cfg = config.hscloud.rsh;
|
||||
|
||||
in {
|
||||
options.hscloud.rsh = with types; {
|
||||
enable = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = "Enable the RSH-Unboudn service.";
|
||||
};
|
||||
out = mkOption {
|
||||
type = str;
|
||||
description = "Output file for generated unbound config.";
|
||||
};
|
||||
};
|
||||
|
||||
config.systemd.services.rsh = mkIf cfg.enable {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${rshUnbound}/bin/rsh-unbound -output ${cfg.out} -register_endpoint https://hazard.mf.gov.pl/api/Register";
|
||||
Restart = "always";
|
||||
RestartSec = "60";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
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
|
||||
MZ/1vrhwOkOdDIh5spJJKXwYpBUivr/XLaQ=
|
||||
=b7js
|
||||
-----END PGP MESSAGE-----
|
40
bgpwtf/machines/secrets/cipher/passwords.nix
Normal file
40
bgpwtf/machines/secrets/cipher/passwords.nix
Normal file
|
@ -0,0 +1,40 @@
|
|||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
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
|
||||
=d5Gq
|
||||
-----END PGP MESSAGE-----
|
2
bgpwtf/machines/secrets/plain/.gitignore
vendored
Normal file
2
bgpwtf/machines/secrets/plain/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
288
bgpwtf/machines/tests/edge01-waw.nix
Normal file
288
bgpwtf/machines/tests/edge01-waw.nix
Normal file
|
@ -0,0 +1,288 @@
|
|||
# Smoke test edge01.waw in a multi-VM NixOS test.
|
||||
#
|
||||
# This brings up three VMs:
|
||||
# - dut/edge01
|
||||
# - bgpspeaker, which simulates bgp upstreams
|
||||
# - customs, which simulates customs.hackerspace.pl.
|
||||
#
|
||||
# We use EoIP to build up virtual ethernet links between the machines, and
|
||||
# to run VLANs on that. We don't just use plain 'vlans' from NixOS tests as
|
||||
# we actually want to run 802.1q ourselves from the edge01 config.
|
||||
#
|
||||
# Everything else is pretty much straightforward. Bring up everything, ping
|
||||
# stuff. We don't really test much else than internet routing.
|
||||
#
|
||||
# To run this:
|
||||
# nix-build -A bgpwtf.machines.tests.edge01-waw
|
||||
#
|
||||
# To debug this:
|
||||
# nix-build -A bgpwtf.machines.tests.edge01-waw.driver && result/bin/nixos-test-driver
|
||||
# >>> start_all()
|
||||
|
||||
{ hscloud, pkgsSrc, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
mkBGPSpeaker = let
|
||||
in { config, pkgs, ... }: {
|
||||
networking.hostName = "bgpspeaker";
|
||||
virtualisation.memorySize = 1024;
|
||||
virtualisation.vlans = [ 1 ];
|
||||
imports = [
|
||||
../modules/eoip.nix
|
||||
];
|
||||
|
||||
hscloud.eoip.interfaces."nnet" = {
|
||||
parent = "eth1";
|
||||
localV4 = "192.168.1.3";
|
||||
remoteV4 = "192.168.1.2";
|
||||
id = 100;
|
||||
};
|
||||
networking.interfaces."nnet" = {
|
||||
virtual = true;
|
||||
virtualType = "tap";
|
||||
};
|
||||
networking.vlans = {
|
||||
"vl-globalmix" = { interface = "nnet"; id = 466; };
|
||||
};
|
||||
networking.interfaces."vl-globalmix" = {
|
||||
ipv4.addresses = [{ address = "185.235.70.44"; prefixLength = 31; }];
|
||||
ipv6.addresses = [{ address = "2001:67c:778:fd40::b9eb:462c"; prefixLength = 127; }];
|
||||
};
|
||||
|
||||
services.bird2 = {
|
||||
enable = true;
|
||||
config = ''
|
||||
log syslog all;
|
||||
debug protocols { states, interfaces, events }
|
||||
router id 185.235.70.44;
|
||||
|
||||
protocol device {
|
||||
scan time 10;
|
||||
};
|
||||
protocol kernel kernel_v4 {
|
||||
ipv4 {
|
||||
import none;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
protocol kernel kernel_v6 {
|
||||
ipv6 {
|
||||
import none;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
ipv4 table globalmix4;
|
||||
ipv6 table globalmix6;
|
||||
|
||||
protocol pipe pipe_globalmix4 {
|
||||
table master4;
|
||||
peer table globalmix4;
|
||||
import all;
|
||||
export none;
|
||||
};
|
||||
protocol pipe pipe_globalmix6 {
|
||||
table master6;
|
||||
peer table globalmix6;
|
||||
import all;
|
||||
export none;
|
||||
};
|
||||
|
||||
protocol static static_globalmix_originate_v4 {
|
||||
ipv4 {
|
||||
table globalmix4;
|
||||
import all;
|
||||
};
|
||||
route 8.8.8.0/24 blackhole;
|
||||
}
|
||||
protocol static static_globalmix_originate_v6 {
|
||||
ipv6 {
|
||||
table globalmix6;
|
||||
import all;
|
||||
};
|
||||
route 2a00:1450:4016::/48 blackhole;
|
||||
}
|
||||
protocol bgp bgp_globalmix_v4 {
|
||||
ipv4 {
|
||||
table globalmix4;
|
||||
export all;
|
||||
import all;
|
||||
};
|
||||
local 185.235.70.44 as 62081;
|
||||
neighbor 185.235.70.45 as 204880;
|
||||
};
|
||||
protocol bgp bgp_globalmix_v6 {
|
||||
ipv6 {
|
||||
table globalmix6;
|
||||
export all;
|
||||
import all;
|
||||
};
|
||||
local 2001:67c:778:fd40::b9eb:462c as 62081;
|
||||
neighbor 2001:67c:778:fd40::b9eb:462d as 204880;
|
||||
};
|
||||
'';
|
||||
};
|
||||
networking.firewall.enable = false;
|
||||
networking.useDHCP = false;
|
||||
networking.interfaces.lo.ipv4.addresses = [ { address = "8.8.8.1"; prefixLength = 32; } ];
|
||||
networking.interfaces.lo.ipv6.addresses = [ { address = "2a00:1450:4016:801::200e"; prefixLength = 128; } ];
|
||||
environment.systemPackages = with pkgs; [
|
||||
tcpdump htop dstat file
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
|
||||
test = import "${pkgsSrc}/nixos/tests/make-test-python.nix" ({ pkgs, libs, ... }: {
|
||||
name = "test-edge01-waw-e2e";
|
||||
|
||||
nodes = {
|
||||
dut = { config, pkgs, ... }: {
|
||||
imports = [
|
||||
../edge01.waw.bgp.wtf.nix
|
||||
../modules/eoip.nix
|
||||
];
|
||||
virtualisation.memorySize = 1024;
|
||||
virtualisation.vlans = [
|
||||
1 2
|
||||
];
|
||||
|
||||
hscloud.eoip.interfaces = {
|
||||
"e1-nnet" = { parent = "eth1"; localV4 = "192.168.1.2"; remoteV4 = "192.168.1.3"; id = 100; };
|
||||
"e2-customs" = { parent = "eth2"; localV4 = "192.168.2.2"; remoteV4 = "192.168.2.1"; id = 200; };
|
||||
"e3-mgmt" = { parent = "eth2"; localV4 = "192.168.2.2"; remoteV4 = "192.168.2.111"; id = 300; }; # not connected
|
||||
"e4-oob" = { parent = "eth2"; localV4 = "192.168.2.2"; remoteV4 = "192.168.2.112"; id = 400; }; # not connected
|
||||
"e7-dcsw" = { parent = "eth2"; localV4 = "192.168.2.2"; remoteV4 = "192.168.2.113"; id = 500; }; # not connected
|
||||
};
|
||||
networking.interfaces = {
|
||||
"e1-nnet" = { virtual = true; virtualType = "tap"; };
|
||||
"e2-customs" = { virtual = true; virtualType = "tap"; };
|
||||
"e3-mgmt" = { virtual = true; virtualType = "tap"; };
|
||||
"e4-oob" = { virtual = true; virtualType = "tap"; };
|
||||
"e7-dcsw" = { virtual = true; virtualType = "tap"; };
|
||||
};
|
||||
};
|
||||
|
||||
speaker = mkBGPSpeaker;
|
||||
|
||||
customs = { config, pkgs, ... }: {
|
||||
imports = [
|
||||
../modules/eoip.nix
|
||||
];
|
||||
environment.systemPackages = with pkgs; [
|
||||
tcpdump htop dstat file dhcpcd
|
||||
];
|
||||
virtualisation.memorySize = 1024;
|
||||
virtualisation.vlans = [
|
||||
2
|
||||
];
|
||||
networking.firewall.enable = false;
|
||||
networking.useDHCP = false;
|
||||
networking.defaultGateway = "185.236.240.4";
|
||||
networking.defaultGateway6 = "2a0d:eb00:2137:1::2";
|
||||
networking.interfaces."edge" = {
|
||||
virtual = true;
|
||||
virtualType = "tap";
|
||||
ipv4.addresses = [{ address = "185.236.240.5"; prefixLength = 31; }];
|
||||
ipv6.addresses = [{ address = "2a0d:eb00:2137:1::3"; prefixLength = 127; }];
|
||||
};
|
||||
hscloud.eoip.interfaces."edge" = {
|
||||
parent = "eth2";
|
||||
localV4 = "192.168.2.1";
|
||||
remoteV4 = "192.168.2.2";
|
||||
id = 200;
|
||||
};
|
||||
networking.bridges."lan".interfaces = [];
|
||||
networking.interfaces."lan" = {
|
||||
ipv4.addresses = [{ address = "10.8.1.2"; prefixLength = 23; }];
|
||||
ipv6.addresses = [{ address = "2a0d:eb00:4242::1"; prefixLength = 64; }];
|
||||
};
|
||||
services.bird2 = {
|
||||
enable = true;
|
||||
config = ''
|
||||
log syslog all;
|
||||
debug protocols { states, interfaces, events }
|
||||
router id 185.236.240.5;
|
||||
|
||||
protocol device {
|
||||
scan time 10;
|
||||
};
|
||||
protocol kernel kernel_v4 {
|
||||
ipv4 {
|
||||
import none;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
protocol kernel kernel_v6 {
|
||||
ipv6 {
|
||||
import none;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
|
||||
protocol ospf v3 ospf_hswaw {
|
||||
ipv6 {
|
||||
import all;
|
||||
export all;
|
||||
};
|
||||
area 0.0.0.0 {
|
||||
interface "edge" {
|
||||
cost 10;
|
||||
type bcast;
|
||||
};
|
||||
interface "lan" {
|
||||
cost 10;
|
||||
stub yes;
|
||||
type bcast;
|
||||
check link no;
|
||||
};
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
edge01.wait_for_unit("bird2.service")
|
||||
# Wait for BGP to settle.
|
||||
edge01.wait_until_succeeds("ping 185.235.70.44 -c 1 -w 2")
|
||||
edge01.wait_until_succeeds("birdc show route for 8.8.8.1 table all | grep via")
|
||||
edge01.wait_until_succeeds(
|
||||
"birdc show route for 2a00:1450:4016:801::200e table all | grep via"
|
||||
)
|
||||
edge01.succeed("ping 8.8.8.1 -c 1 -w 2")
|
||||
|
||||
# ping from customs to globalmix must succeed.
|
||||
customs.succeed("ping 8.8.8.1 -c 1 -w 2")
|
||||
customs.succeed("ping 2a00:1450:4016:801::200e -c 1 -w 2")
|
||||
|
||||
# edge01 must announce exactly one v4 prefix.
|
||||
bgpspeaker.succeed("birdc show route protocol bgp_globalmix_v4 | grep unicast")
|
||||
bgpspeaker.fail(
|
||||
"birdc show route protocol bgp_globalmix_v4 | grep unicast | grep -v 185.236.240.0/23"
|
||||
)
|
||||
|
||||
# edge01 must announce exactly one v6 prefix.
|
||||
bgpspeaker.succeed("birdc show route protocol bgp_globalmix_v6 | grep unicast")
|
||||
bgpspeaker.fail(
|
||||
"birdc show route protocol bgp_globalmix_v6 | grep unicast | grep -v 2a0d:eb00::/32"
|
||||
)
|
||||
|
||||
# customer networks must be reachable from globalmix
|
||||
bgpspeaker.succeed("ping 185.236.240.10 -c 1 -w 2")
|
||||
bgpspeaker.succeed("ping 2a0d:eb00:8000::1 -c 1 -w 2")
|
||||
bgpspeaker.succeed("ping 185.236.240.12 -c 1 -w 2")
|
||||
bgpspeaker.succeed("ping 185.236.240.105 -c 1 -w 2")
|
||||
bgpspeaker.succeed("ping 2a0d:eb00:8003::1 -c 1 -w 2")
|
||||
|
||||
# dhcp agent must be reachable
|
||||
customs.succeed("ping 185.236.240.18 -c 1 -w 2")
|
||||
'';
|
||||
});
|
||||
|
||||
in test { inherit pkgs; inherit (pkgs) libs; }
|
53
ops/machines.nix
Normal file
53
ops/machines.nix
Normal file
|
@ -0,0 +1,53 @@
|
|||
# Top-level file aggregating all machines managed from hscloud.
|
||||
#
|
||||
# This allows to have a common attrset of machines that can be deployed
|
||||
# in the same way.
|
||||
#
|
||||
# Currently building/deployment is still done in a half-assed way:
|
||||
#
|
||||
# machine=edge01.waw.bgp.wtf
|
||||
# nix-build -A 'ops.machines."'$machine'"'.toplevel
|
||||
#
|
||||
# This spits out a derivation path that correponds to the built config of that
|
||||
# machine. To deploy it:
|
||||
#
|
||||
# d=/nix/store/nkdfoobarbazl0ybhazkmeyaylmaoqcr-nixos-system-edge01-20.09pre-git
|
||||
# nix-copy-closure --to root@$machine $d
|
||||
# ssh root@$machine $d/bin/switch-to-configuration
|
||||
#
|
||||
# TODO(q3k): merge this with //cluster/clustercfg - this should be unified!
|
||||
|
||||
{ hscloud, pkgs, ... }:
|
||||
|
||||
let
|
||||
# Stopgap measure to import //cluster/nix machine definitions into new
|
||||
# //ops/machines infrastructure.
|
||||
# TODO(q3k): inject defs-cluster-k0.nix / defs-machines.nix content via
|
||||
# nixos options instead of having module definitions loading it themselves,
|
||||
# deduplicate list of machines below with defs-machines.nix somehow.
|
||||
mkClusterMachine = name: pkgs.nixos ({ config, pkgs, ... }: {
|
||||
# The hostname is used by //cluster/nix machinery to load the appropriate
|
||||
# config from defs-machines into defs-cluster-k0.
|
||||
networking.hostName = name;
|
||||
imports = [
|
||||
../cluster/nix/modules/base.nix
|
||||
../cluster/nix/modules/kubernetes.nix
|
||||
];
|
||||
});
|
||||
|
||||
mkMachine = paths: pkgs.nixos ({ config, pkgs, ... }: {
|
||||
imports = paths;
|
||||
});
|
||||
|
||||
in {
|
||||
"bc01n01.hswaw.net" = mkClusterMachine "bc01n01";
|
||||
"bc01n02.hswaw.net" = mkClusterMachine "bc01n02";
|
||||
"bc01n03.hswaw.net" = mkClusterMachine "bc01n03";
|
||||
"dcr01s22.hswaw.net" = mkClusterMachine "dcr01s22";
|
||||
"dcr01s24.hswaw.net" = mkClusterMachine "dcr01s24";
|
||||
|
||||
"edge01.waw.bgp.wtf" = mkMachine [
|
||||
../bgpwtf/machines/edge01.waw.bgp.wtf.nix
|
||||
../bgpwtf/machines/edge01.waw.bgp.wtf-hardware.nix
|
||||
];
|
||||
}
|
Loading…
Add table
Reference in a new issue