Skip to content

Kernel Hardening

The server kernel is hardened at three levels: blacklisted modules to reduce attack surface, boot parameters to enforce security policies, and sysctl tunables to restrict runtime behaviour.

Source: server/modules/kernel.nix

Blacklisted Kernel Modules

30+ modules are blacklisted to eliminate unnecessary attack surface. None of these are needed on a headless homelab server.

Obscure Networking Protocols

These are legacy or rarely-used protocols that have historically been sources of vulnerabilities:

ModuleProtocol
dccpDatagram Congestion Control Protocol
sctpStream Control Transmission Protocol
rdsReliable Datagram Sockets
tipcTransparent Inter-process Communication
n-hdlcHDLC line discipline
ax25Amateur radio protocol
netromAmateur radio NET/ROM
x25ITU-T X.25
roseAmateur radio ROSE
decnetDECnet
econetAcorn Econet
af_802154IEEE 802.15.4 (Zigbee)
ipxInternetwork Packet Exchange
appletalkAppleTalk
psnapSubNetwork Access Protocol
p8023802.3 Ethernet framing
p8022802.2 LLC
canController Area Network
atmAsynchronous Transfer Mode

Filesystems

Rarely-used filesystem drivers that expand the kernel's parsing surface:

ModuleFilesystem
cramfsCompressed ROM filesystem
freevxfsVeritas VxFS
jffs2Journalling Flash File System
hfsApple HFS
hfsplusApple HFS+
udfUniversal Disk Format
squashfsSquashFS compressed filesystem
cifsSMB/CIFS network filesystem
nfs, nfsv3, nfsv4Network File System
ksmbdIn-kernel SMB3 server
gfs2Global File System 2

Other

ModuleReason
vividVirtual video test driver; has caused privilege escalation CVEs
bluetooth, btusbNo Bluetooth hardware on the server

Boot Parameters

These are passed via kernelParams and enforce security at the earliest possible stage:

nix
kernelParams = [
  "debugfs=off"
  "disable_ipv6=1"
  "hibernate=no"
  "init_on_alloc=1"
  "init_on_free=1"
  "lockdown=confidentiality"
  "module.sig_enforce=1"
  "oops=panic"
  "page_alloc.shuffle=1"
  "pti=on"
  "randomize_kstack_offset=on"
  "slab_nomerge"
  "vsyscall=none"

  "panic=1"
  "boot.panic_on_fail"
];
ParameterEffect
debugfs=offDisables the debug filesystem entirely, removing a common information leak vector
disable_ipv6=1Disables IPv6 at the kernel level (not needed on this LAN)
hibernate=noPrevents hibernation, which could leak memory contents to disk
init_on_alloc=1Zero-fills memory on allocation, preventing use-after-free data leaks
init_on_free=1Zero-fills memory on deallocation, same rationale
lockdown=confidentialityPrevents reading confidential kernel data; blocks /dev/mem, kprobes, raw I/O
module.sig_enforce=1Only allows loading of signed kernel modules
oops=panicKernel oops triggers a panic instead of continuing in a potentially compromised state
page_alloc.shuffle=1Randomises page allocator freelists, making heap exploitation harder
pti=onForces Page Table Isolation (Meltdown mitigation) regardless of CPU flags
randomize_kstack_offset=onRandomises kernel stack offset on each syscall
slab_nomergePrevents merging of SLAB caches, isolating different allocation types
vsyscall=noneDisables the legacy vsyscall page (fixed-address mapping exploitable for ROP)
panic=1Auto-reboot 1 second after a kernel panic (headless server can't be manually recovered)
boot.panic_on_failPanic if any critical boot service fails

Display and Power

nix
"vga=0x317"     # VESA framebuffer mode
"nomodeset"     # No kernel modesetting (headless)
"intel_pstate=active"          # Intel P-state CPU frequency driver
"rcutree.enable_rcu_lazy=1"    # Lazy RCU callbacks for power saving

Sysctl: Kernel Protections

nix
"kernel.dmesg_restrict" = 1;
"kernel.kexec_load_disabled" = 1;
"kernel.kptr_restrict" = 2;
"kernel.printk" = "3 3 3 3";
"kernel.sysrq" = 0;
"kernel.unprivileged_bpf_disabled" = 1;
"kernel.perf_event_paranoid" = 3;
"kernel.yama.ptrace_scope" = 2;
SysctlValueEffect
dmesg_restrict1Only CAP_SYSLOG can read kernel ring buffer
kexec_load_disabled1Prevents loading a new kernel for kexec (blocks rootkit persistence)
kptr_restrict2Hides kernel pointers from all users, including root
printk3 3 3 3Suppresses all but error-level kernel messages
sysrq0Disables all SysRq key combinations
unprivileged_bpf_disabled1Restricts eBPF to CAP_BPF (blocks container/sandbox escapes via BPF)
perf_event_paranoid3Restricts all perf events to CAP_PERFMON
yama.ptrace_scope2Only CAP_SYS_PTRACE can ptrace any process

Commented Out

kernel.modules_disabled = 1 is commented out. Enabling it would prevent all module loading after boot, but breaks NixOS container startup which needs to load modules. Similarly, kernel.unprivileged_userns_clone = 0 is commented out because it breaks many programs.

Sysctl: Terminal and Filesystem

nix
# Terminal
"dev.tty.ldisc_autoload" = 0;
"dev.tty.legacy_tiocsti" = 1;

# Filesystem
"fs.suid_dumpable" = 0;
"fs.protected_fifos" = 2;
"fs.protected_regular" = 2;
"fs.protected_symlinks" = 1;
"fs.protected_hardlinks" = 1;
SysctlValueEffect
ldisc_autoload0Disables automatic loading of TTY line disciplines (attack surface reduction)
legacy_tiocsti1Disables TIOCSTI ioctl injection (prevents terminal injection attacks in containers)
suid_dumpable0Prevents core dumps of SUID binaries (could leak privileged memory)
protected_fifos2Prevents following FIFOs in world-writable sticky directories
protected_regular2Prevents creating regular files in world-writable sticky directories
protected_symlinks1Prevents following symlinks in world-writable sticky directories
protected_hardlinks1Prevents creating hardlinks to files you don't own

Sysctl: Legacy Interface

nix
"abi.vsyscall32" = 1;

Controls the 32-bit vsyscall interface. Set to 1 (emulated) rather than 0 because some legacy binaries may still need it in containers.

Sysctl: Virtual Memory

nix
"vm.mmap_rnd_bits" = 32;
"vm.mmap_rnd_compat_bits" = 16;

Maximises ASLR entropy on 64-bit systems. mmap_rnd_bits = 32 provides 32 bits of randomness for mmap base addresses (maximum on x86_64), making brute-force ASLR bypass significantly harder.

See also Network Hardening for the full network sysctl breakdown.