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:
| Module | Protocol |
|---|---|
dccp | Datagram Congestion Control Protocol |
sctp | Stream Control Transmission Protocol |
rds | Reliable Datagram Sockets |
tipc | Transparent Inter-process Communication |
n-hdlc | HDLC line discipline |
ax25 | Amateur radio protocol |
netrom | Amateur radio NET/ROM |
x25 | ITU-T X.25 |
rose | Amateur radio ROSE |
decnet | DECnet |
econet | Acorn Econet |
af_802154 | IEEE 802.15.4 (Zigbee) |
ipx | Internetwork Packet Exchange |
appletalk | AppleTalk |
psnap | SubNetwork Access Protocol |
p8023 | 802.3 Ethernet framing |
p8022 | 802.2 LLC |
can | Controller Area Network |
atm | Asynchronous Transfer Mode |
Filesystems
Rarely-used filesystem drivers that expand the kernel's parsing surface:
| Module | Filesystem |
|---|---|
cramfs | Compressed ROM filesystem |
freevxfs | Veritas VxFS |
jffs2 | Journalling Flash File System |
hfs | Apple HFS |
hfsplus | Apple HFS+ |
udf | Universal Disk Format |
squashfs | SquashFS compressed filesystem |
cifs | SMB/CIFS network filesystem |
nfs, nfsv3, nfsv4 | Network File System |
ksmbd | In-kernel SMB3 server |
gfs2 | Global File System 2 |
Other
| Module | Reason |
|---|---|
vivid | Virtual video test driver; has caused privilege escalation CVEs |
bluetooth, btusb | No Bluetooth hardware on the server |
Boot Parameters
These are passed via kernelParams and enforce security at the earliest possible stage:
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"
];| Parameter | Effect |
|---|---|
debugfs=off | Disables the debug filesystem entirely, removing a common information leak vector |
disable_ipv6=1 | Disables IPv6 at the kernel level (not needed on this LAN) |
hibernate=no | Prevents hibernation, which could leak memory contents to disk |
init_on_alloc=1 | Zero-fills memory on allocation, preventing use-after-free data leaks |
init_on_free=1 | Zero-fills memory on deallocation, same rationale |
lockdown=confidentiality | Prevents reading confidential kernel data; blocks /dev/mem, kprobes, raw I/O |
module.sig_enforce=1 | Only allows loading of signed kernel modules |
oops=panic | Kernel oops triggers a panic instead of continuing in a potentially compromised state |
page_alloc.shuffle=1 | Randomises page allocator freelists, making heap exploitation harder |
pti=on | Forces Page Table Isolation (Meltdown mitigation) regardless of CPU flags |
randomize_kstack_offset=on | Randomises kernel stack offset on each syscall |
slab_nomerge | Prevents merging of SLAB caches, isolating different allocation types |
vsyscall=none | Disables the legacy vsyscall page (fixed-address mapping exploitable for ROP) |
panic=1 | Auto-reboot 1 second after a kernel panic (headless server can't be manually recovered) |
boot.panic_on_fail | Panic if any critical boot service fails |
Display and Power
"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 savingSysctl: Kernel Protections
"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;| Sysctl | Value | Effect |
|---|---|---|
dmesg_restrict | 1 | Only CAP_SYSLOG can read kernel ring buffer |
kexec_load_disabled | 1 | Prevents loading a new kernel for kexec (blocks rootkit persistence) |
kptr_restrict | 2 | Hides kernel pointers from all users, including root |
printk | 3 3 3 3 | Suppresses all but error-level kernel messages |
sysrq | 0 | Disables all SysRq key combinations |
unprivileged_bpf_disabled | 1 | Restricts eBPF to CAP_BPF (blocks container/sandbox escapes via BPF) |
perf_event_paranoid | 3 | Restricts all perf events to CAP_PERFMON |
yama.ptrace_scope | 2 | Only 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
# 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;| Sysctl | Value | Effect |
|---|---|---|
ldisc_autoload | 0 | Disables automatic loading of TTY line disciplines (attack surface reduction) |
legacy_tiocsti | 1 | Disables TIOCSTI ioctl injection (prevents terminal injection attacks in containers) |
suid_dumpable | 0 | Prevents core dumps of SUID binaries (could leak privileged memory) |
protected_fifos | 2 | Prevents following FIFOs in world-writable sticky directories |
protected_regular | 2 | Prevents creating regular files in world-writable sticky directories |
protected_symlinks | 1 | Prevents following symlinks in world-writable sticky directories |
protected_hardlinks | 1 | Prevents creating hardlinks to files you don't own |
Sysctl: Legacy Interface
"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
"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.