the_prg_server_configuratio.../nix-system-configs/nixos-gateway.nix

387 lines
9.1 KiB
Nix

{
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";
}