{ config, pkgs, lib, ... }: { imports = [./hardware-configuration.nix]; ### Lix Package Manager ### nixpkgs.overlays = [ (final: prev: { inherit (prev.lixPackageSets.stable) nixpkgs-review nix-eval-jobs nix-fast-build colmena ; }) ]; nix.package = pkgs.lixPackageSets.stable.lix; ### Network Configuration ### networking.hostName = "prg-lan-gateway"; networking.domain = "prg.dtu.dk"; networking.useDHCP = false; networking.useNetworkd = true; # Set MAC addresses to match DTU documentation systemd.network.links."10-wan" = { matchConfig. OriginalName = "eth*"; matchConfig.Type = "ether"; linkConfig = { Name = "ens18"; MACAddress = "2a:99:d6:03:dd:92"; # Hardcoded MAC, ensuring that DTU's sysadmin sees it is still the same WakeOnLan = "off"; }; }; # Discuss removing/changing them? systemd.network.links."20-lan1" = { matchConfig.OriginalName = "eth*"; matchConfig.Type = "ether"; linkConfig = { Name = "ens19"; MACAddress = "0e:27:6a:11:a0:77"; }; }; systemd.network.links."30-lan2" = { matchConfig.OriginalName = "eth*"; matchConfig.Type = "ether"; linkConfig = { Name = "ens20"; MACAddress = "42:d7:85:15:e1:ff"; }; }; # WAN Interface (ens18) systemd.network.networks."10-wan" = { matchConfig.Name = "ens18"; address = ["130.225.91.242/27"]; gateway = ["130.225.91.225"]; networkConfig = { IPv6AcceptRA = false; DHCP = "no"; }; linkConfig = { RequiredForOnline = "routable"; MTUBytes = "1500"; }; }; # LAN Interface 1 (ens19) - Dual IP systemd.network.networks."20-lan1" = { matchConfig.Name = "ens19"; address = [ "10.123.123.1/24" "192.168.0.1/24" ]; networkConfig = { IPv6AcceptRA = false; DHCP = "no"; ConfigureWithoutCarrier = true; }; }; # LAN Interface 2 (ens20) systemd.network.networks."30-lan2" = { matchConfig.Name = "ens20"; address = ["10.255.255.1/24"]; networkConfig = { IPv6AcceptRA = false; DHCP = "no"; ConfigureWithoutCarrier = true; }; }; # DNS Configuration services.resolved = { enable = true; dnssec = "false"; domains = ["prg.dtu.dk"]; fallbackDns = ["1.1.1.1" "8.8.8.8" "130.225.89.2"]; extraConfig = '' DNSStubListener=no ''; }; # Kernel parameters for gateway/security boot.kernel.sysctl = { # IP forwarding (gateway) "net.ipv4.ip_forward" = 1; # Reverse Path Filtering "net.ipv4.conf.all.rp_filter" = 1; "net.ipv4.conf.default.rp_filter" = 1; # SYN flood "net.ipv4.tcp_syncookies" = 1; "net.ipv4.tcp_syn_retries" = 5; # ICMP redirects / sending redirects "net.ipv4.conf.all.accept_redirects" = 0; "net.ipv4.conf.default.accept_redirects" = 0; "net.ipv4.conf.all.send_redirects" = 0; "net.ipv4.conf.default.send_redirects" = 0; "net.ipv4.conf.all.secure_redirects" = 0; # Source route / routing protections "net.ipv4.conf.all.accept_source_route" = 0; "net.ipv4.conf.default.accept_source_route" = 0; # Log suspicious packets "net.ipv4.conf.all.log_martians" = 1; "net.ipv4.conf.default.log_martians" = 1; # ICMP hygiene "net.ipv4.icmp_echo_ignore_broadcasts" = 1; "net.ipv4.icmp_ignore_bogus_error_responses" = 1; # Performance "net.ipv4.tcp_window_scaling" = 1; # Disable IPv6 if desired "net.ipv6.conf.all.disable_ipv6" = 1; "net.ipv6.conf.default.disable_ipv6" = 1; # Additional hardening knobs "kernel.kptr_restrict" = 1; # hide kernel pointers in /proc "kernel.dmesg_restrict" = 1; # restrict dmesg "kernel.yama.ptrace_scope" = 1; # restrict ptrace "fs.protected_hardlinks" = 1; "fs.protected_symlinks" = 1; }; # NAT Configuration networking.nat = { enable = true; externalInterface = "ens18"; internalInterfaces = ["ens19" "ens20"]; forwardPorts = []; # Empty - no port forwarding }; # Firewall Configuration networking.firewall = { enable = true; # Trusted LAN interfaces (all ports open) trustedInterfaces = ["ens19" "ens20"]; # Interface-specific rules (keep permitted ports on LAN) interfaces = { ens19.allowedTCPPorts = [22 53]; ens19.allowedUDPPorts = [53 67 123]; ens20.allowedTCPPorts = [22 53]; ens20.allowedUDPPorts = [53 67 123]; }; # Tightened iptables rules using conntrack, drop INVALID, rate-limit ICMP and logging. extraCommands = '' # Default policies iptables -P INPUT DROP iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT # Drop invalid packets early iptables -A INPUT -m conntrack --ctstate INVALID -j DROP # Allow loopback iptables -A INPUT -i lo -j ACCEPT # Established/related iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Rate-limit ICMP (allow limited pings) iptables -A INPUT -p icmp -m conntrack --ctstate NEW -m limit --limit 1/second --limit-burst 5 -j ACCEPT # Block new connections from WAN interface iptables -A INPUT -i ens18 -m conntrack --ctstate NEW -j DROP # Log dropped packets (rate-limited) iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-dropped: " --log-level 7 ''; extraStopCommands = '' iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT ''; }; # Hosts file networking.extraHosts = '' 130.225.91.242 prg-lan-gateway.prg.dtu.dk prg-lan-gateway ''; # Time synchronization time.timeZone = "Europe/Copenhagen"; services.chrony = { enable = true; servers = ["time.cloudflare.com"]; extraConfig = '' makestep 1.0 3 rtcsync ''; }; # Locale settings i18n.defaultLocale = "en_US.UTF-8"; i18n.extraLocaleSettings = { LC_ADDRESS = "da_DK.UTF-8"; LC_IDENTIFICATION = "da_DK.UTF-8"; LC_MEASUREMENT = "da_DK.UTF-8"; LC_MONETARY = "da_DK.UTF-8"; LC_NAME = "da_DK.UTF-8"; LC_NUMERIC = "da_DK. UTF-8"; LC_PAPER = "da_DK.UTF-8"; LC_TELEPHONE = "da_DK.UTF-8"; LC_TIME = "en_DK.UTF-8"; }; # Console keymap # Change it back to Danish? console.keyMap = "us"; # User configuration - users.users.admin = { isNormalUser = true; description = "Gateway Administrator"; extraGroups = ["wheel" "networkmanager" "systemd-journal"]; openssh.authorizedKeys.keys = [ # Christine's Hardware Key - Copy and change to the desired hardware keys "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3pjIXlpg7H9h1RrmdxbIRnDIdQvf/EZKI9PG2/rY7D openpgp:0x8BCD4992" ]; }; # Passwordless sudo for wheel group security.sudo.wheelNeedsPassword = false; # Hardware U2F support - Passwordless sudo with hardware key security.pam.u2f = { enable = true; settings = { authfile = "/etc/u2f_keys"; cue = true; pinverification = 0; # No PIN verification userpresence = 1; # Require user presence (touch) }; }; # SSH Agent authentication security.pam.enableSSHAgentAuth = true; # System packages environment.systemPackages = with pkgs; [ # Network tools wget curl dig tcpdump ethtool iptables nftables iproute2 bridge-utils netcat-gnu traceroute mtr # Monitoring btop htop iotop bandwhich # Editors micro vim helix # System info fastfetch lshw pciutils usbutils ]; # OpenSSH services.openssh = { enable = true; settings = { PermitRootLogin = "no"; PasswordAuthentication = false; KbdInteractiveAuthentication = false; X11Forwarding = false; # Additional hardening MaxAuthTries = 3; LoginGraceTime = "20s"; }; extraConfig = '' AllowUsers admin ''; openFirewall = false; # Manually configured in firewall section }; # Tailscale VPN - We need to discuss about this long term services.tailscale = { enable = true; useRoutingFeatures = "server"; }; # Automatic upgrades system.autoUpgrade = { enable = true; # Set to true for automatic updates dates = "daily"; allowReboot = false; }; # Nix garbage collection nix.gc = { automatic = true; dates = "weekly"; options = "--delete-older-than 30d"; }; # Nix settings nix.settings = { experimental-features = ["nix-command" "flakes"]; auto-optimise-store = true; trusted-users = ["root" "@wheel"]; }; # Allow unfree packages nixpkgs.config.allowUnfree = true; # Boot configuration TO BE CHANGED ACCORDING TO INSTALL VERSION boot.loader = { systemd-boot.enable = true; efi.canTouchEfiVariables = true; timeout = 3; }; # Kernel optimization boot.kernelParams = [ "quiet" "splash" ]; # Enable zram swap zramSwap = { enable = true; memoryPercent = 50; }; # Protect /tmp as a tmpfs with nosuid/nodev/noexec fileSystems."/tmp" = { device = "tmpfs"; fsType = "tmpfs"; options = ["mode=1777" "nosuid" "nodev" "noexec"]; }; # System state version system.stateVersion = "XX.XX"; }