depot/ops/nixos/etheroute-lon01/default.nix
Luke Granger-Brown 6e746fb2cf etheroute-lon01: use gre rather than ipip
Cloudflare Magic Transit appears to become Very Unhappy when you blast it with IPIP.

Use GRE instead, which it is happier with.
2022-04-30 16:48:28 +01:00

406 lines
12 KiB
Nix

# SPDX-FileCopyrightText: 2020 Luke Granger-Brown <depot@lukegb.com>
#
# SPDX-License-Identifier: Apache-2.0
{ depot, lib, pkgs, config, ... }:
let
makeIPIPInterface = {
name,
underlayDevice,
localIP,
remoteIP
}: {
description = "IPIP interface ${name}";
wantedBy = [ "network-setup.service" "sys-subsystem-net-devices-${underlayDevice}.device" ];
bindsTo = [ "sys-subsystem-net-devices-${underlayDevice}.device" ];
partOf = [ "network-setup.service" ];
after = [ "network-pre.target" "sys-subsystem-net-devices-${underlayDevice}.device" "network-addresses-${underlayDevice}.service" ];
before = [ "network-setup.service" ];
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = true;
path = [ pkgs.iproute2 ];
script = ''
echo "Removing old interface"
ip link show "${name}" >/dev/null 2>&1 && ip link del "${name}"
echo "Adding interface"
ip link add name "${name}" type ipip local "${localIP}" remote "${remoteIP}"
echo "Bringing up interface"
ip link set "${name}" up
'';
preStop = ''
echo "Removing interface"
ip link set "${name}" down || true
ip link del "${name}" || true
'';
reload = ''
ip link set dev "${name}" type ipip local "${localIP}" remote "${remoteIP}"
'';
reloadIfChanged = true;
};
in {
imports = [
../lib/bgp.nix
../lib/zfs.nix
];
boot.initrd = {
availableKernelModules = [
"ehci_pci"
"ahci"
"usbhid"
"usb_storage"
"sd_mod"
"sr_mod"
"bnx2" # ethernet
];
network = {
enable = true;
ssh = {
enable = true;
hostKeys = ["/persist/etc/ssh/ssh_host_ed25519_key"];
authorizedKeys = map builtins.readFile config.users.users.lukegb.openssh.authorizedKeys.keyFiles;
};
postCommands = ''
echo "zfs load-key -a; killall zfs" >> /root/.profile
'';
};
};
boot.kernelParams = [
"ip=83.97.19.68::83.97.19.65:255.255.255.224:etheroute-lon01:eno1:none"
];
boot.kernelModules = [ "kvm-intel" ];
boot.kernel.sysctl = {
"net.ipv4.conf.all.forwarding" = true;
"net.ipv4.conf.default.forwarding" = true;
};
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
powerManagement.cpuFreqGovernor = lib.mkDefault "performance";
services.zfs.rollbackOnBoot = {
enable = true;
snapshot = "tank/local/root@blank";
};
fileSystems = let
zfs = device: {
device = device;
fsType = "zfs";
};
in {
"/" = zfs "tank/local/root";
"/nix" = zfs "tank/local/nix";
"/tmp" = zfs "tank/local/tmp";
"/persist" = zfs "tank/safe/persist";
"/home" = zfs "tank/safe/home";
"/boot" = {
device = "/dev/disk/by-partlabel/ESP";
fsType = "vfat";
};
};
nix.settings.max-jobs = lib.mkDefault 8;
# Networking!
networking = {
hostName = "etheroute-lon01";
domain = "as205479.net";
hostId = "420bee1b";
nameservers = [
"2001:4860:4860::8888"
"2001:4860:4860::8844"
"8.8.8.8"
"8.8.4.4"
];
defaultGateway = {
address = "83.97.19.65";
interface = "eno1";
};
defaultGateway6 = {
address = "2a07:242:800:64::1";
interface = "eno1";
};
interfaces.eno1 = {
ipv4.addresses = [{ address = "83.97.19.68"; prefixLength = 27; }];
ipv6.addresses = [{ address = "2a07:242:800:64::68"; prefixLength = 64; }];
};
interfaces.quadv1-4 = {
ipv4.addresses = [{ address = "92.118.31.254"; prefixLength = 24; }];
virtual = true;
};
firewall.allowedTCPPorts = [ 80 443 ];
firewall.extraCommands = ''
# Flush old rules.
ip46tables -D FORWARD -j lukegb-forward 2>/dev/null || true
for chain in lukegb-forward lukegb-fwd-accept lukegb-fwd-reject; do
ip46tables -F "$chain" 2>/dev/null || true
ip46tables -X "$chain" 2>/dev/null || true
done
ip46tables -N lukegb-fwd-accept
ip46tables -A lukegb-fwd-accept -j ACCEPT
ip46tables -N lukegb-fwd-reject
ip46tables -A lukegb-fwd-reject -p tcp ! --syn -j REJECT --reject-with tcp-reset
ip46tables -A lukegb-fwd-reject -j REJECT
ip46tables -N lukegb-forward
# Accept from "trusted" quadv1-4 interface
ip46tables -A lukegb-forward -i quadv1-4 -j lukegb-fwd-accept
# Accept from established/related connections.
ip46tables -A lukegb-forward -m conntrack --ctstate ESTABLISHED,RELATED -j lukegb-fwd-accept
# Set up the firewall.
ip46tables -A lukegb-forward -j lukegb-fwd-reject
ip46tables -A FORWARD -j lukegb-forward
'';
};
my.ip.tailscale = "100.111.191.21";
networking.greTunnels.quadv1-4 = {
remote = "82.163.116.114";
local = "83.97.19.68";
dev = "eno1";
type = "tun";
};
services.openssh.hostKeys = [
{
path = "/persist/etc/ssh/ssh_host_ed25519_key";
type = "ed25519";
}
{
path = "/persist/etc/ssh/ssh_host_rsa_key";
type = "rsa";
bits = 4096;
}
];
users.users = {
lukegb.extraGroups = [ "bird2" ];
};
services.lukegbgp = let local = {
asn = 205479;
}; in {
enable = true;
config = {
local = {
routerID = "83.97.19.68";
};
export.v4 = [ "92.118.31.0/24" ];
peering = {
etheroute = {
local = local // {
v4 = "83.97.19.68";
v6 = "2a07:242:800:64::68";
};
remote = {
asn = 3170;
export_community = 4000;
routers = [{
v4 = "83.97.19.65";
v6 = "2a07:242:800:64::1";
}];
};
};
bgptoolscollector = {
local = local // {
v4 = "83.97.19.68";
v6 = "2a07:242:800:64::68";
};
remote = {
asn = 212232;
export_community = 5000;
is_route_collector = true;
routers = [{
v4 = "185.230.223.39";
v6 = "2a0c:2f07:9459::b3";
multihop = 64;
}];
prefix_limit.v4 = 0;
prefix_limit.v6 = 0;
};
};
};
};
};
systemd.mounts = let
bindMount' = dir: {
unitConfig.RequiresMountsFor = dir;
options = "bind";
what = "/persist${dir}";
where = dir;
};
bindMountSvc = dir: svc: (bindMount' dir) // {
bindsTo = [svc];
partOf = [svc];
};
bindMountSvcDynamic = dir: svc: (bindMount' "/var/lib/private/${dir}") // {
requiredBy = [svc];
before = [svc];
wantedBy = ["multi-user.target"];
};
bindMount = dir: (bindMount' dir) // {
wantedBy = ["multi-user.target"];
};
in [
(bindMountSvc "/var/lib/tailscale" "tailscaled.service")
];
services.redis.servers."" = {
enable = true;
bind = "127.0.0.1";
};
services.pomerium = {
enable = true;
secretsFile = config.my.vault.secrets.pomerium.path;
settings = {
address = ":443";
http_redirect_addr = ":80";
idp_provider = "google";
idp_client_id = "136257844546-qsa6hi1oqqoq2bnt93deo4e70ggbn1p8.apps.googleusercontent.com";
idp_request_params = {
hd = "lukegb.com";
login_hint = "lukegb@lukegb.com";
};
jwt_claims_headers = [
"email"
"user"
];
timeout_read = "0"; # We have some long-lived connections...
timeout_write = "0";
timeout_idle = "0";
databroker_storage_type = "redis";
databroker_storage_connection_string = "redis://127.0.0.1:6379/15";
forward_auth_url = "https://fwdauth.int.lukegb.com";
authenticate_service_url = "https://auth.int.lukegb.com";
signout_redirect_url = "https://logged-out.int.lukegb.com";
certificates = [
{ cert = "/var/lib/acme/lukegb.com/fullchain.pem"; key = "/var/lib/acme/lukegb.com/privkey.pem"; }
];
policy = let
baseConfig = {
allowed_domains = [ "lukegb.com" ];
pass_identity_headers = true;
timeout = "30s";
};
service = server: hostName: extraConfig: baseConfig // {
from = "https://${hostName}";
to = "http://${server}";
preserve_host_header = true;
} // extraConfig;
secureService = server: hostName: extraConfig: service server hostName ({
to = "https://${server}";
tls_server_name = hostName;
} // extraConfig);
public = extraConfig: {
allow_public_unauthenticated_access = true;
allowed_domains = null;
} // extraConfig;
in [
(service "clouvider-fra01.int.as205479.net" "int.lukegb.com" {})
(service "clouvider-fra01.int.as205479.net" "logged-out.int.lukegb.com" (public {}))
(service "clouvider-fra01.int.as205479.net" "sonarr.int.lukegb.com" {})
(service "clouvider-fra01.int.as205479.net" "radarr.int.lukegb.com" {})
(service "clouvider-fra01.int.as205479.net" "deluge.int.lukegb.com" {})
(service "clouvider-fra01.int.as205479.net" "content.int.lukegb.com" {})
(service "totoro.int.as205479.net:9090" "prometheus.int.lukegb.com" {})
(service "totoro.int.as205479.net:9093" "alertmanager.int.lukegb.com" {})
(service "totoro.int.as205479.net:3000" "grafana.int.lukegb.com" {})
(secureService "swann.int.as205479.net:8443" "unifi.int.lukegb.com" {
tls_skip_verify = true;
allow_websockets = true;
timeout = "0";
})
(service "blade-tuvok.int.as205479.net:7480" "objdump.zxcvbnm.ninja" (public {
timeout = "30m"; # Uploads can take a while; bump the timeout.
}))
(secureService "totoro.int.as205479.net" "invoices.lukegb.com" (public {
regex = "^/((third_party|ajax|client_area|pdf)/.*|[a-zA-Z0-9]{8})$";
tls_skip_verify = true;
}))
(secureService "totoro.int.as205479.net" "invoices.lukegb.com" {
tls_skip_verify = true;
})
(baseConfig // {
from = "https://httpbin.int.lukegb.com";
to = "https://verify.pomerium.com";
})
(service "bvm-twitterchiver.int.as205479.net:8080" "twitterchiver.int.lukegb.com" {})
(service "bvm-twitterchiver.int.as205479.net:8080" "twitterchiver.lukegb.com" {})
(service "bvm-nixosmgmt.int.as205479.net:4440" "rundeck.int.lukegb.com" {
set_request_headers = {
"X-Forwarded-Roles" = "pomerium";
};
})
(service "bvm-ipfs.int.as205479.net:5001" "ipfs.int.lukegb.com" {})
(service "bvm-ipfs.int.as205479.net:8080" "ipfs-gw.int.lukegb.com" {})
(service "bvm-netbox.int.as205479.net:80" "netbox.int.lukegb.com" {})
(service "localhost:9901" "envoy-debug.int.lukegb.com" {})
(service "bvm-paperless.int.as205479.net:28981" "paperless.int.lukegb.com" {
regex = "^/ws/.*";
allow_websockets = true;
timeout = "0";
})
(service "bvm-paperless.int.as205479.net:28981" "paperless.int.lukegb.com" {
regex = "^/api/.*";
timeout = "0";
})
(service "bvm-paperless.int.as205479.net:28981" "paperless.int.lukegb.com" {})
];
};
};
systemd.services.pomerium = {
wants = lib.mkAfter [ "redis.service" ];
after = lib.mkAfter [ "redis.service" ];
serviceConfig = {
SupplementaryGroups = [ "acme" ];
ReadOnlyPaths = [ "/var/lib/acme" ];
};
};
my.vault.acmeCertificates."lukegb.com" = {
hostnames = [
"lukegb.com"
"*.lukegb.com"
"*.int.lukegb.com"
"objdump.zxcvbnm.ninja"
];
reloadOrRestartUnits = [ "pomerium.service" ];
};
my.vault.secrets.pomerium = {
template = ''
{{ with secret "kv/apps/pomerium" }}
COOKIE_SECRET={{ .Data.data.cookieSecret }}
SHARED_SECRET={{ .Data.data.sharedSecret }}
IDP_CLIENT_SECRET={{ .Data.data.idpClientSecret }}
SIGNING_KEY={{ .Data.data.signingKey }}
IDP_SERVICE_ACCOUNT={{ .Data.data.googleServiceAccount }}
{{ end }}
'';
group = "root";
reloadOrRestartUnits = [ "pomerium.service" ];
};
users.groups.acme = {};
system.stateVersion = "20.09";
}