LinuxXXIX · Linux Security Hardeningsysctl
Kernel hardening with sysctl - the runtime network and security parameters
What you'll learn
- Apply a production sysctl hardening baseline
- Distinguish security-relevant from performance-relevant sysctls
- Persist sysctl settings across reboots
- Recognise when sysctl changes break applications
- Decide between kexec hardening and kdump crash capture, which are mutually exclusive
Prerequisites
Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09
sysctl is the runtime parameter interface to the kernel. Many security-relevant settings are exposed as sysctls: ASLR, IP forwarding, ICMP redirects, kernel pointer restrictions. This lesson covers a production hardening baseline.
Read sysctls
sysctl net.ipv4.ip_forward
sysctl -a | grep -E 'kernel.randomize|net.ipv4.conf'
A hardening baseline
/etc/sysctl.d/99-hardening.conf:
# Kernel hardening
kernel.randomize_va_space = 2 # full ASLR
kernel.kptr_restrict = 2 # hide kernel pointers
kernel.dmesg_restrict = 1 # restrict dmesg to CAP_SYSLOG
#kernel.kexec_load_disabled = 1 # disable kexec - ALSO DISABLES KDUMP, see below
kernel.sysrq = 0 # disable magic sysrq
kernel.unprivileged_bpf_disabled = 1 # disable unprivileged BPF
kernel.unprivileged_userns_clone = 0 # disable user namespaces for unprivileged
net.core.bpf_jit_harden = 2 # harden BPF JIT
# Network hardening
net.ipv4.ip_forward = 0 # no forwarding unless router
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
Apply:
sudo sysctl -p /etc/sysctl.d/99-hardening.conf
What each setting does
| Setting | Effect |
|---|---|
kernel.randomize_va_space = 2 | Full ASLR (defeats memory-based exploits) |
kernel.kptr_restrict = 2 | Hide kernel pointers in /proc/kallsyms |
kernel.dmesg_restrict = 1 | Only CAP_SYSLOG holders can read dmesg |
kernel.kexec_load_disabled = 1 | Block kexec_load(), so root cannot boot an arbitrary kernel. Also disables kdump. Commented out in the baseline above — enable it per host role, not by default |
kernel.unprivileged_bpf_disabled = 1 | Block unprivileged BPF programs |
kernel.unprivileged_userns_clone = 0 | Block unprivileged user namespaces (containers) |
net.ipv4.ip_forward = 0 | No forwarding; set to 1 only on routers |
net.ipv4.conf.*.accept_redirects = 0 | Reject ICMP redirects |
net.ipv4.conf.*.accept_source_route = 0 | Reject source-routed packets |
net.ipv4.conf.*.log_martians = 1 | Log packets with impossible addresses |
net.ipv4.icmp_echo_ignore_broadcasts = 1 | Ignore broadcast pings (smurf attack) |
net.ipv4.tcp_syncookies = 1 | SYN flood protection |
net.ipv4.conf.*.rp_filter = 1 | Reverse-path filter (anti-spoofing) |
Test before persisting
A wrong sysctl can break networking:
ip_forward = 0on a router: routing breaks.accept_redirects = 0on a segment with two routers where the hosts hold only a default route: traffic for the second router’s networks keeps hairpinning through the default gateway instead of being redirected. The symptom is a latency and bandwidth penalty, not a loss of connectivity — and the fix is a specific route (or a correct default), never accepting unauthenticated ICMP from anything on the wire. Leave this at 0.rp_filter = 1strict mode breaks asymmetric routing. Where return paths genuinely differ,2(loose mode) keeps a spoofing check without requiring symmetry. This is the baseline setting most likely to break an existing host: every multi-homed machine built with the policy-routing recipes inlinux-policy-routingandlinux-multiple-routing-tablesrelies on paths that strict mode discards, and the drops are silent. Note that the kernel usesmax(conf.all.rp_filter, conf.<iface>.rp_filter), so exempting one interface means loweringconf.alltoo. Count the damage withnstat -az TcpExtIPReversePathFilter.
Test with sysctl -w (not -p) so the change is not
persistent:
sudo sysctl -w kernel.kptr_restrict=2
Verify the application or service still works. If it does, persist in the configuration file.
Persist via configuration files
Place files in /etc/sysctl.d/ (named with a numeric
prefix; loaded in lexical order):
sudo nano /etc/sysctl.d/99-hardening.conf
sudo sysctl -p /etc/sysctl.d/99-hardening.conf
To make settings survive reboot, the file must end in
.conf and be in /etc/sysctl.d/, /run/sysctl.d/, or
/usr/local/lib/sysctl.d/.
Verify
sudo sysctl -p /etc/sysctl.d/99-hardening.conf
sudo sysctl kernel.randomize_va_space
sudo sysctl net.ipv4.tcp_syncookies
Common pitfalls
net.ipv4.ip_forward = 0on a Docker host: containers need forwarding. Most container runtimes set this automatically, but check.net.ipv6.conf.*.disable_ipv6 = 1with IPv6 enabled services: services fail to bind. Verify withip -6 addr.fs.protected_hardlinks = 1with old applications: some old applications fail. Verify.kernel.yama.ptrace_scope = 3with debugging tools: gdb and strace stop working for non-root processes.kernel.kexec_load_disabled = 1on a host you need crash dumps from: kdump cannot load its capture kernel, so a panic produces no vmcore. Check withcat /sys/kernel/kexec_crash_loaded—1means armed,0means no dump. The flag is one-way until reboot.
Knowledge check
Knowledge check · 4 questions
Q1. What does kernel.randomize_va_space = 2 enable?
Q2. net.ipv4.ip_forward = 0 is correct for a Linux host used as a router.
Q3. Which of the following are valid sysctl hardening settings? Select all that apply.
Q4. You roll this hardening baseline out fleet-wide with kernel.kexec_load_disabled = 1 uncommented. Three weeks later a database host panics nightly and the kernel team asks for a vmcore. /var/crash is empty and kdump.service is enabled and active. Why is there no dump?
Passing score: 75%. Answers are checked in this browser.