Academy

Module 1 Β· Linux Hardening Fundamentals πŸ”’

Manish Garg
Manish Garg Associate CISSP Β· RingSafe
April 19, 2026
4 min read

You get root on a fresh Linux server. Now what? Default installs β€” whether Ubuntu, RHEL, Amazon Linux β€” are not hardened out of the box. This module is your opinionated checklist: the baseline controls every production Linux server should have before it sees traffic.

The hardening stack

  1. Network β€” firewall, SSH, services
  2. Users & authentication β€” sudo, SSH keys, lockouts
  3. Filesystem β€” permissions, mounts, SELinux / AppArmor
  4. Logging & audit β€” journald, auditd
  5. Updates β€” unattended security patches
  6. Kernel β€” sysctl tunings, module blacklists

1. Firewall baseline (ufw / firewalld)

# Ubuntu / Debian β€” ufw
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp     # SSH (restrict source IP if possible)
ufw allow 80,443/tcp # web
ufw enable

# RHEL / CentOS / Amazon Linux β€” firewalld
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --remove-service=cockpit
firewall-cmd --reload

Default-deny inbound is non-negotiable. Allow only what’s needed, scoped to source IPs where possible.

2. SSH hardening

Edit /etc/ssh/sshd_config:

Port 22                        # consider non-default
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
UsePAM yes
X11Forwarding no
AllowUsers deploy admin        # whitelist specific users
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
AllowTcpForwarding no
PermitEmptyPasswords no
Protocol 2

Then systemctl reload sshd. Use fail2ban for brute-force protection, but disabling password auth eliminates most brute-force value anyway.

3. Users and sudo

  • Disable root login over SSH (above); require SSH key + sudo
  • Create individual user accounts β€” don’t share the deploy account
  • Use visudo to edit /etc/sudoers; prefer /etc/sudoers.d/* drop-ins
  • Require password for sudo escalation (NOPASSWD for convenience = audit finding)
  • Timeout sudo cache: Defaults timestamp_timeout=5
  • Log sudo commands to /var/log/auth.log (default)

4. Automatic security updates

# Debian / Ubuntu
apt install unattended-upgrades
dpkg-reconfigure --priority=low unattended-upgrades

# RHEL / CentOS
dnf install dnf-automatic
systemctl enable --now dnf-automatic.timer

5. Filesystem permissions + mount hardening

Add restrictive mount options in /etc/fstab:

# /tmp β€” nodev, nosuid, noexec (prevents malware execution from /tmp)
tmpfs /tmp tmpfs defaults,nodev,nosuid,noexec 0 0

# /var/tmp, /dev/shm β€” same pattern
tmpfs /dev/shm tmpfs defaults,nodev,nosuid,noexec 0 0

Run find / -perm -4000 2>/dev/null to inventory setuid binaries. Remove any that shouldn’t be setuid (e.g. /usr/bin/pkexec has had multiple CVEs).

6. SELinux / AppArmor

Mandatory Access Control prevents compromised services from accessing resources they’re not supposed to:

  • SELinux (RHEL/CentOS/Amazon Linux/Fedora) β€” keep in Enforcing mode. getenforce should return Enforcing.
  • AppArmor (Ubuntu/Debian/SUSE) β€” aa-status should show multiple enforced profiles.
  • Never disable MAC to “make things work” β€” investigate the denial and write a policy exception instead

7. Logging and audit

# Install auditd
apt install auditd       # Debian / Ubuntu
dnf install audit        # RHEL

# Add critical audit rules (/etc/audit/rules.d/security.rules)
-w /etc/passwd -p wa -k passwd_changes
-w /etc/shadow -p wa -k shadow_changes
-w /var/log -p rwa -k log_changes
-a always,exit -F arch=b64 -S execve -F uid=0 -k root_commands
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid!=0 -k escalation

service auditd restart

# Ship logs offsite β€” rsyslog to SIEM
# Local logs can be tampered with; ship immediately

8. Kernel sysctl hardening

# /etc/sysctl.d/99-security.conf
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.yama.ptrace_scope = 2
kernel.randomize_va_space = 2
net.ipv4.conf.all.rp_filter = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.log_martians = 1
fs.suid_dumpable = 0

# Apply
sysctl --system

9. Disable unused services

systemctl list-unit-files --type=service --state=enabled β€” disable anything not required. Common wins: cups (printing), avahi-daemon, rpcbind, bluetooth on servers.

10. File integrity monitoring

  • AIDE or Tripwire β€” baseline system file hashes; alert on changes
  • Run daily via cron, send report to sec team
  • Tune to expected changes (logs, /tmp, /var/run) to reduce noise

CIS Benchmarks

The Center for Internet Security publishes detailed hardening benchmarks for every major Linux distro. Run Lynis for automated scoring, or use CIS-provided hardening scripts. Aim for 80%+ CIS compliance as a minimum production baseline.

Quick reference summary

  • Default-deny firewall, SSH with key-only auth, no root SSH
  • Individual user accounts + sudo with password + command logging
  • Automatic security updates (unattended-upgrades / dnf-automatic)
  • Harden /tmp, /var/tmp, /dev/shm mount options (nodev,nosuid,noexec)
  • Keep SELinux / AppArmor in Enforcing mode
  • auditd with rules for passwd, shadow, privilege escalation
  • Sysctl: restrict dmesg, randomise ASLR, drop source-routed packets
  • Disable unused services; run Lynis + CIS Benchmark annually
  • Ship logs off-host to a SIEM β€” local logs can be tampered
🧠
Check your understanding

Module Quiz Β· 20 questions

Pass with 70%+ to mark this module complete. Unlimited retries. Each question shows an explanation.