{ config, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; boot = { kernelPackages = pkgs.linuxPackages_latest; kernelParams = [ "arm-smmu.disable_bypass=0" "pci=pcie_bus_perf" "iommu.passthrough=1" ]; # Setup SFP+ network interfaces early so systemd can pick everything up. initrd.extraUtilsCommands = '' copy_bin_and_libs ${pkgs.restool}/bin/restool copy_bin_and_libs ${pkgs.restool}/bin/ls-main copy_bin_and_libs ${pkgs.restool}/bin/ls-addni # Patch paths sed -i "1i #!$out/bin/sh" $out/bin/ls-main ''; initrd.postDeviceCommands = '' ls-addni dpmac.7 ls-addni dpmac.8 ls-addni dpmac.9 ls-addni dpmac.10 ''; kernel.sysctl = { "net.ipv4.conf.all.forwarding" = true; "net.ipv6.conf.all.accept_ra" = 0; "net.ipv6.conf.all.autoconf" = 0; "net.ipv6.conf.all.use_tempaddr" = 0; }; }; age.secrets = { wgNibylandiaScylla.file = ../../secrets/wg/nibylandia_scylla.age; wgDN42Scylla.file = ../../secrets/wg/dn42_w1kl4s_scylla.age; ddnsKeyKea = { file = ../../secrets/lan/nibylandia-ddns-kea.age; mode = "444"; }; ddnsKeyBind = { file = ../../secrets/lan/nibylandia-ddns-bind.age; mode = "400"; owner = "named"; group = "named"; }; }; networking.hostName = "scylla"; networking.wireless.enable = false; time.timeZone = "Europe/Warsaw"; systemd.network.enable = true; networking.useNetworkd = true; networking.useDHCP = false; networking.interfaces = { eth0 = { useDHCP = true; macAddress = "50:7b:9d:b5:fa:e8"; }; lan = { ipv4.addresses = [{ address = "192.168.24.1"; prefixLength = 24; }]; }; eth1 = { ipv4.addresses = [{ address = "192.168.20.1"; prefixLength = 24; }]; }; }; networking.nameservers = [ "192.168.20.1" ]; networking.vlans = { lan = { id = 10; interface = "eth1"; }; }; networking.wireguard.interfaces = { wg-nibylandia = { ips = [ "10.255.255.2/24" ]; privateKeyFile = config.age.secrets.wgNibylandiaScylla.path; listenPort = 51315; allowedIPsAsRoutes = true; peers = [{ publicKey = "xwTYtejNZCtOyPMNcZVlsBIGYae6aUQczh7UwujLxXg="; allowedIPs = [ "10.255.255.0/24" ]; endpoint = "zorigami.is-a.cat:51315"; persistentKeepalive = 15; }]; }; dn42_w1kl4s_1 = { ips = [ "fd25:af2d:1f51:255::1/64" "fe80::255:acab/64" ]; privateKeyFile = config.age.secrets.wgDN42Scylla.path; listenPort = 51516; allowedIPsAsRoutes = false; peers = [{ publicKey = "zNP632K1qrezFIl8NQK1tR3XEdYHat/YgzdCXnFIWDE="; allowedIPs = [ "0.0.0.0/0" "::/0" ]; endpoint = "193.31.26.15:53137"; }]; postSetup = '' ${pkgs.iproute}/bin/ip addr add dev dn42_w1kl4s_1 172.20.148.161/32 peer 172.23.193.2/32 ''; }; }; networking.firewall.enable = true; networking.firewall.logRefusedConnections = false; networking.nat = { enable = true; externalInterface = "eth0"; internalInterfaces = [ "lan" "eth1" "virbr1" "virbr2" ]; forwardPorts = [ { loopbackIPs = [ "185.102.189.133" ]; destination = "192.168.101.2:22"; sourcePort = 11520; proto = "tcp"; } # sdomi's vm { loopbackIPs = [ "185.102.189.133" ]; destination = "192.168.20.31:22"; sourcePort = 23; proto = "tcp"; } { loopbackIPs = [ "185.102.189.133" ]; destination = "192.168.20.32:22"; sourcePort = 32; proto = "tcp"; } { destination = "192.168.20.31"; sourcePort = 2582; proto = "tcp"; } { destination = "192.168.20.31"; sourcePort = "51411:51423"; proto = "tcp"; } { loopbackIPs = [ "185.102.189.133" ]; destination = "192.168.20.31:80"; sourcePort = 80; proto = "tcp"; } { loopbackIPs = [ "185.102.189.133" ]; destination = "192.168.20.31:443"; sourcePort = 443; proto = "tcp"; } { loopbackIPs = [ "185.102.189.133" ]; destination = "192.168.20.31:2005"; sourcePort = 2005; proto = "tcp"; } { destination = "192.168.20.31"; sourcePort = "51411:51423"; proto = "udp"; } { loopbackIPs = [ "185.102.189.133" ]; destination = "192.168.20.31:80"; sourcePort = 80; proto = "udp"; } { loopbackIPs = [ "185.102.189.133" ]; destination = "192.168.20.31:443"; sourcePort = 443; proto = "udp"; } { loopbackIPs = [ "185.102.189.133" ]; destination = "192.168.20.31:2005"; sourcePort = 2005; proto = "udp"; } ]; }; networking.firewall.allowedTCPPorts = [ 179 # bgp 53 5201 6443 # k3s ]; networking.firewall.allowedUDPPorts = [ 179 # bgp 53 51315 51516 # dn42-w1kl4s ]; networking.firewall.interfaces."eth1".allowedTCPPorts = [ 8123 ]; networking.firewall.interfaces."lan".allowedTCPPorts = [ 8123 ]; systemd.network.wait-online.extraArgs = [ "--any" ]; services.k3s = { enable = false; role = "server"; }; services.kea = { dhcp4 = { enable = true; settings = { interfaces-config = { interfaces = [ "lan/192.168.24.1" "eth1/192.168.20.1" ]; }; lease-database = { name = "/var/lib/kea/dhcp4.leases"; persist = true; type = "memfile"; }; rebind-timer = 2000; renew-timer = 1000; valid-lifetime = 4000; dhcp-ddns = { enable-updates = true; ncr-protocol = "UDP"; ncr-format = "JSON"; server-ip = "127.0.0.1"; server-port = 53001; }; ddns-send-updates = true; ddns-replace-client-name = "when-not-present"; ddns-update-on-renew = true; ddns-override-client-update = true; ddns-override-no-update = true; subnet4 = [ { subnet = "192.168.24.0/24"; pools = [{ pool = "192.168.24.40 - 192.168.24.240"; }]; reservations-out-of-pool = true; reservations-in-subnet = true; ddns-qualifying-suffix = "nibylandia.lan."; option-data = [ { name = "routers"; data = "192.168.24.1"; } { name = "domain-name-servers"; data = "192.168.24.1"; } ]; reservations = [{ hw-address = "34:15:13:b6:2a:e7"; hostname = "yamaha"; ip-address = "192.168.24.11"; }]; } { subnet = "192.168.20.0/24"; pools = [{ pool = "192.168.20.40 - 192.168.20.240"; }]; reservations-out-of-pool = true; reservations-in-subnet = true; ddns-qualifying-suffix = "nibylandia.lan."; option-data = [ { name = "routers"; data = "192.168.20.1"; } { name = "domain-name-servers"; data = "192.168.20.1"; } ]; reservations = [ { hw-address = "00:02:c9:53:9a:c2"; hostname = "stereolith"; ip-address = "192.168.20.31"; } { hw-address = "00:30:93:12:0f:bf"; hostname = "microlith"; ip-address = "192.168.20.32"; } ]; } ]; }; }; dhcp-ddns = { enable = true; settings = { dns-server-timeout = 100; ip-address = "127.0.0.1"; ncr-format = "JSON"; ncr-protocol = "UDP"; forward-ddns = { ddns-domains = [{ key-name = "bind-key-2021-12-27"; dns-servers = [{ ip-address = "192.168.20.1"; }]; name = "nibylandia.lan."; }]; }; reverse-ddns = { ddns-domains = [ { key-name = "bind-key-2021-12-27"; dns-servers = [{ ip-address = "192.168.20.1"; }]; name = "20.168.192.in-addr.arpa."; } { key-name = "bind-key-2021-12-27"; dns-servers = [{ ip-address = "192.168.20.1"; }]; name = "24.168.192.in-addr.arpa."; } ]; }; tsig-keys = [{ name = "bind-key-2021-12-27"; algorithm = "HMAC-SHA512"; secret = "__keaInclude ${config.age.secrets.ddnsKeyKea.path}"; }]; }; }; }; services.bind = { enable = true; listenOn = [ "192.168.20.1" "192.168.24.1" ]; forwarders = [ "8.8.8.8" "1.1.1.1" "8.8.4.4" "1.0.0.1" ]; cacheNetworks = [ "192.168.20.0/24" "192.168.24.0/24" ]; zones = { "nibylandia.lan" = { master = true; file = "/var/lib/bind/nibylandia.lan.zone"; extraConfig = '' allow-update { key "bind-key-2021-12-27"; }; ''; }; "20.168.192.in-addr.arpa" = { master = true; file = "/var/lib/bind/20.168.192.in-addr.arpa.zone"; extraConfig = '' allow-update { key "bind-key-2021-12-27"; }; ''; }; "24.168.192.in-addr.arpa" = { master = true; file = "/var/lib/bind/24.168.192.in-addr.arpa.zone"; extraConfig = '' allow-update { key "bind-key-2021-12-27"; }; ''; }; }; extraConfig = '' key "bind-key-2021-12-27" { algorithm hmac-sha512; include "${config.age.secrets.ddnsKeyBind.path}"; }; ''; extraOptions = '' dnssec-validation no; ''; }; services.bird2 = { enable = true; checkConfig = false; config = '' define OWNAS = 4242423137; define OWNIP = 172.20.148.161; define OWNIPv6 = fd25:af2d:1f51:255::1; define OWNNET = 172.20.148.160/27; define OWNNETv6 = fdc0:b038:c31e::/48; define OWNNETSET = [ 172.20.148.160/27+ ]; define OWNNETSETv6 = [ fdc0:b038:c31e::/48+ ]; router id OWNIP; protocol device { scan time 10; } /* * Utility functions */ function is_self_net() { return net ~ OWNNETSET; } function is_self_net_v6() { return net ~ OWNNETSETv6; } function is_valid_network() { return net ~ [ 172.20.0.0/14{21,29}, # dn42 172.20.0.0/24{28,32}, # dn42 Anycast 172.21.0.0/24{28,32}, # dn42 Anycast 172.22.0.0/24{28,32}, # dn42 Anycast 172.23.0.0/24{28,32}, # dn42 Anycast 172.31.0.0/16+, # ChaosVPN 10.100.0.0/14+, # ChaosVPN 10.127.0.0/16{16,32}, # neonetwork 10.0.0.0/8{15,24} # Freifunk.net ]; } roa4 table dn42_roa; roa6 table dn42_roa_v6; protocol static { roa4 { table dn42_roa; }; include "/etc/bird/roa_dn42.conf"; }; protocol static { roa6 { table dn42_roa_v6; }; include "/etc/bird/roa_dn42_v6.conf"; }; function is_valid_network_v6() { return net ~ [ fd00::/8{44,64} # ULA address space as per RFC 4193 ]; } protocol kernel { scan time 20; ipv6 { import none; export filter { if source = RTS_STATIC then reject; krt_prefsrc = OWNIPv6; accept; }; }; }; protocol kernel { scan time 20; ipv4 { import none; export filter { if source = RTS_STATIC then reject; krt_prefsrc = OWNIP; accept; }; }; } protocol static { route OWNNET reject; ipv4 { import all; export none; }; } protocol static { route OWNNETv6 reject; ipv6 { import all; export none; }; } template bgp dnpeers { local as OWNAS; path metric 1; ipv4 { import filter { if is_valid_network() && !is_self_net() then { if (roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID) then { print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last; reject; } else accept; } else reject; }; export filter { if is_valid_network() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; }; import limit 1000 action block; }; ipv6 { import filter { if is_valid_network_v6() && !is_self_net_v6() then { if (roa_check(dn42_roa_v6, net, bgp_path.last) != ROA_VALID) then { print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last; reject; } else accept; } else reject; }; export filter { if is_valid_network_v6() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; }; import limit 1000 action block; }; } include "/etc/bird/peers/*"; ''; }; security.polkit.enable = true; virtualisation.libvirtd.enable = true; services.avahi = { enable = true; reflector = true; allowInterfaces = [ "lan" "eth1" ]; }; nixpkgs.config.allowUnfree = true; nixpkgs.overlays = [ (self: super: { restool = self.callPackage ./pkgs/restool { }; }) ]; environment.systemPackages = with pkgs; [ pv libarchive lshw zip file tcpdump lsof restool ethtool pciutils usbutils dig dstat wget bind nmap iperf config.boot.kernelPackages.perf ]; programs = { mtr.enable = true; mosh.enable = true; neovim = { enable = true; defaultEditor = true; viAlias = true; vimAlias = true; }; zsh = { enable = true; enableBashCompletion = true; autosuggestions.enable = true; syntaxHighlighting.enable = true; }; command-not-found.enable = false; }; nix = { package = pkgs.nixUnstable; extraOptions = '' experimental-features = nix-command flakes ''; }; users.users.root.openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGfIRe1nH6vwjQTjqHNnkKAdr1VYqGEeQnqInmf3A6UN ar@khas" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO6rEwERSm/Fj4KO4SxFIo0BUvi9YNyf8PSL1FteMcMt arachnist@monolith" ]; services.openssh.enable = true; system.stateVersion = "22.05"; }