Skip to content
System Administration

Linux Hardening Checklist: What innerwarden harden Checks and Why

10 min read

Why hardening matters

Most breaches do not start with a zero-day. They start with a misconfiguration: a default password left in place, a firewall rule that exposes a database, SSH wide open to password brute-force. Verizon's annual breach report consistently shows that misconfigurations and credential attacks account for the majority of incidents.

Hardening is the process of reducing your attack surface by fixing these misconfigurations before an attacker finds them. The problem is that hardening checklists are long, easy to forget, and drift over time as packages get updated and new services are installed. That is why innerwarden harden exists: it checks every item programmatically, scores your system, and tells you exactly what to fix.

SSH hardening

SSH is the most attacked service on any Linux server. Botnets continuously scan the internet for port 22 and attempt credential stuffing with leaked password lists. Inner Warden checks four critical SSH settings:

  • PasswordAuthentication no forces key-based auth, making brute-force impossible.
  • PermitRootLogin no prevents direct root login, requiring attackers to escalate after initial access.
  • MaxAuthTries 3 limits authentication attempts per connection, slowing automated attacks.
  • Non-default port moving SSH off port 22 eliminates noise from automated scanners (not security by itself, but reduces log volume by 90%+).
/etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin no
MaxAuthTries 3
Port 2222
Apply changes
sudo systemctl restart sshd

Firewall configuration

A firewall that is installed but not enabled does nothing. Inner Warden checks that UFW (or iptables/nftables) is active and that the default policy denies incoming traffic. It also scans for exposed database ports (MySQL on 3306, Redis on 6379, and MongoDB on 27017) bound to 0.0.0.0 instead of 127.0.0.1. Exposed databases are the single fastest way to lose data.

Enable UFW with default deny
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp    # SSH on custom port
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Check for exposed databases
# These should return nothing or show 127.0.0.1 only
ss -tlnp | grep ':3306'   # MySQL
ss -tlnp | grep ':6379'   # Redis
ss -tlnp | grep ':27017'  # MongoDB

Kernel parameters

The Linux kernel has several security-relevant parameters that are not always set to their safest values by default. Inner Warden checks five critical sysctl settings:

  • ASLR (randomize_va_space=2) randomizes memory layout to make buffer overflow exploits unreliable. Value 2 is full randomization including the heap.
  • SYN cookies (tcp_syncookies=1) protects against SYN flood denial-of-service attacks by not allocating resources until the handshake completes.
  • IP forwarding disabled (ip_forward=0) prevents the server from routing traffic between networks. Should be 0 unless the machine is explicitly a router.
  • ICMP redirects disabled prevents attackers from redirecting traffic by sending crafted ICMP packets.
  • Source routing disabled prevents packets from specifying their own route through the network, which can bypass firewall rules.
/etc/sysctl.d/99-hardening.conf
# ASLR: full randomization
kernel.randomize_va_space = 2

# SYN flood protection
net.ipv4.tcp_syncookies = 1

# Disable IP forwarding
net.ipv4.ip_forward = 0

# Disable ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0

# Disable source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
Apply without reboot
sudo sysctl --system

File permissions

Misconfigured file permissions are a silent escalation path. Inner Warden checks three things: world-writable files in /etc (any user can modify system configuration), unexpected SUID binaries (any user can run them as root), and /etc/shadow permissions (password hashes must be readable only by root).

Find world-writable files in /etc
find /etc -type f -perm -o+w 2>/dev/null
# This should return nothing on a hardened system
Audit SUID binaries
find / -perm -4000 -type f 2>/dev/null
# Review each binary. Remove SUID from anything unnecessary
# Common legitimate SUID: /usr/bin/sudo, /usr/bin/passwd, /usr/bin/ping
Fix /etc/shadow permissions
sudo chmod 640 /etc/shadow
sudo chown root:shadow /etc/shadow
ls -la /etc/shadow
# Expected: -rw-r----- 1 root shadow

Automatic security updates

Known vulnerabilities get patched in hours. But if you do not apply the patch, you are running a system with a public exploit. Inner Warden checks whether unattended-upgrades is installed and configured to apply security updates automatically. This is the single highest-impact hardening step for servers that are not actively managed daily.

Install and enable unattended-upgrades
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades
Verify it is active
cat /etc/apt/apt.conf.d/20auto-upgrades
# Should contain:
# APT::Periodic::Update-Package-Lists "1";
# APT::Periodic::Unattended-Upgrade "1";

Docker security

Docker introduces its own attack surface. A privileged container has full access to the host kernel. It is root on the host in every meaningful way. Inner Warden checks for two critical Docker misconfigurations:

  • No privileged containers containers running with --privileged can escape to the host, mount the host filesystem, and load kernel modules. There is almost never a legitimate reason for this in production.
  • Docker socket permissions (660) the Docker socket at /var/run/docker.sock grants full control over all containers and the host. If it is world-readable (666), any user on the system can escalate to root.
Check for privileged containers
docker ps --quiet | xargs docker inspect \
  --format '{{.Name}} privileged={{.HostConfig.Privileged}}' \
  | grep 'privileged=true'
# This should return nothing
Fix Docker socket permissions
sudo chmod 660 /var/run/docker.sock
ls -la /var/run/docker.sock
# Expected: srw-rw---- 1 root docker

The hardening score

After checking every item, innerwarden harden calculates a score from 0 to 100. The score starts at 100 and deducts points based on the severity of each failed check:

Critical issue (e.g., PasswordAuthentication yes)-15 points
High issue (e.g., firewall disabled)-10 points
Medium issue (e.g., SSH on default port)-5 points
Low issue (e.g., unattended-upgrades not installed)-3 points

A score of 80+ means your system follows best practices. Below 60 means there are critical gaps that an attacker could exploit with minimal effort. The score is designed to give you an instant read on your security posture, and to track improvement over time as you fix each issue.

Running the hardening advisor

Run the hardening check with a single command. The default output shows a summary with your score and any failed checks. Use --verbose to see every check including the ones that passed.

Quick scan
innerwarden harden
Verbose output
innerwarden harden --verbose
Example output
$ innerwarden harden

  Hardening Score: 72 / 100

  CRITICAL
  x  SSH PasswordAuthentication is enabled          (-15)
  x  Firewall is not active                         (-10)

  HIGH
  x  /etc/shadow is world-readable                  (-10)

  MEDIUM
  !  SSH is running on default port 22              ( -5)

  LOW
  ~  unattended-upgrades is not installed            ( -3)

  PASSED (12 checks)
  ✓  PermitRootLogin is disabled
  ✓  MaxAuthTries is set to 3
  ✓  ASLR is enabled (randomize_va_space=2)
  ✓  SYN cookies are enabled
  ✓  IP forwarding is disabled
  ✓  ICMP redirects are disabled
  ✓  Source routing is disabled
  ✓  No world-writable files in /etc
  ✓  No unexpected SUID binaries
  ✓  No privileged Docker containers
  ✓  Docker socket permissions are 660
  ✓  No exposed database ports

  Run 'innerwarden harden --verbose' for full details.

Fix the issues from the top down: critical first, then high, then medium. Each fix raises your score. Run the check again after applying changes to verify.