388 lines
9.1 KiB
Nix
388 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";
|
|
}
|