Skip to content

Linux Security -- Hardening, Firewalls, SELinux & AppArmor

DodaTech Updated 2026-06-22 6 min read

In this tutorial, you'll learn about Linux Security. We cover key concepts, practical examples, and best practices.

Linux security hardening is the process of reducing attack surface by disabling unnecessary services, enforcing access controls, configuring firewalls, and using mandatory access control systems like SELinux or AppArmor.

What You'll Learn

You will learn to harden a Linux server using CIS benchmarks, configure nftables firewall rules, set up SELinux policies, enable auditd logging, and automate security checks with OpenSCAP.

Why It Matters

Over 60% of web servers run Linux. A single unpatched service or misconfigured permission has caused breaches at Equifax, Capital One, and SolarWinds. Proper hardening blocks the majority of common attack vectors.

Real-World Use

A fintech startup reduces its PCI DSS compliance scope by hardening all production Ubuntu servers with CIS Level 2 benchmarks, enforced through Ansible playbooks that run weekly audits.

User Account Security

Before hardening SSH, ensure your user accounts follow security best practices. Every human user should have an individual account with sudo access logged via sudoers configuration.

# Create a user with a home directory and sudo access
useradd -m -s /bin/bash deploy
passwd deploy
usermod -aG sudo deploy

# Configure sudo logging
echo 'Defaults logfile=/var/log/sudo.log' >> /etc/sudoers
echo 'Defaults log_input, log_output' >> /etc/sudoers

Expected behavior: All sudo commands are logged to /var/log/sudo.log with input and output recorded for audit purposes.

SSH Hardening

SSH is the most common attack vector on Linux servers. Secure it immediately.

# /etc/ssh/sshd_config
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers deploy jenkins
Protocol 2

Expected behavior: SSH listens on port 2222, root login is disabled, only key-based auth is allowed, and idle sessions disconnect after 10 minutes.

Firewall with nftables

nftables is the modern replacement for iptables with better performance and syntax.

#!/usr/sbin/nft -f

table inet filter {
  chain input {
    type filter hook input priority 0; policy drop;

    ct state established,related accept
    ct state invalid drop

    iif lo accept
    ip protocol icmp accept

    tcp dport { 2222, 80, 443 } accept
    udp dport 51820 accept
  }

  chain forward {
    type filter hook forward priority 0; policy drop
  }

  chain output {
    type filter hook output priority 0; policy accept
  }
}

Expected behavior: All inbound traffic is dropped except SSH on 2222, HTTP/HTTPS, and WireGuard on 51820. Loopback and established connections are allowed.

SELinux Configuration

SELinux enforces mandatory access controls beyond standard Unix permissions.

# Check current mode
getenforce
# Expected: Enforcing

# Set a custom policy for a web application
semanage fcontext -a -t httpd_sys_content_t "/var/www/app(/.*)?"
restorecon -Rv /var/www/app

# List and fix file context mismatches
restorecon -Rv /etc/nginx

Expected behavior: The web application runs with confined httpd context. Any file outside the labeled context is denied access.

AppArmor Profile Example

# /etc/apparmor.d/usr.sbin.nginx
#include <tunables/global>

/usr/sbin/nginx {
  #include <abstractions/base>
  #include <abstractions/nameservice>

  /etc/nginx/** r,
  /var/log/nginx/* w,
  /var/www/** r,
  /run/nginx.pid rw,

  network tcp,
  network inet stream,
}

Expected behavior: Nginx can only read its config files and web root, write to logs, and bind to network sockets. Any file access outside these paths is denied and logged.

Kernel Hardening with sysctl

Several kernel parameters reduce attack surface when properly configured.

# /etc/sysctl.d/99-security.conf
# Disable IP forwarding (unless needed)
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# Prevent source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# Enable reverse path filtering
net.ipv4.conf.all.rp_filter = 1

# Ignore ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# Disable magic SysRq
kernel.sysrq = 0

# Restrict kernel pointer access
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1

Expected behavior: Source routing and ICMP redirects are disabled, preventing man-in-the-middle attacks at the network layer. Kernel pointers are hidden from unprivileged users, making exploitation harder.

Auditd Configuration

# /etc/audit/rules.d/hardening.rules
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/ssh/sshd_config -p wa -k sshd
-w /var/log/auth.log -p wa -k auth
-a always,exit -F arch=b64 -S execve -k process_creation

Expected behavior: Every change to critical files and every process execution is logged to /var/log/audit/audit.log.

Automated Patch Management

Keeping software updated is the most effective single security control.

# Configure unattended security updates
cat <<EOF > /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Allowed-Origins {
  "\${distro_id}:\${distro_codename}-security";
  "\${distro_id}ESMApps:\${distro_codename}-apps-security";
  "\${distro_id}ESM:\${distro_codename}-infra-security";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
EOF

# Enable automatic updates
dpkg-reconfigure --priority=low unattended-upgrades

Expected behavior: Security patches are downloaded and installed automatically each night. No reboot is triggered automatically, preventing service disruption.

CIS Benchmark Automation with OpenSCAP

# Install and run
apt install libopenscap8 scap-security-guide
oscap xccdf eval \
  --profile xccdf_org.ssgproject.content_profile_cis_level2_server \
  --results scan-results.xml \
  --report scan-report.html \
  /usr/share/xml/scap/ssg/content/ssg-ubuntu2204-ds.xml

Expected output: An HTML report showing passing and failing controls against the CIS Level 2 benchmark.

Common Errors

  1. Locking yourself out of SSH -- Changed SSH config without keeping a second session open. The new config has a syntax error or port mismatch. Always test with sshd -t before restarting, and keep a root shell open until you verify you can reconnect.

  2. AppArmor profile blocks legitimate application -- Default deny profile is too restrictive. Check /var/log/syslog for apparmor="DENIED" messages and add the necessary paths to the profile.

  3. nftables rules don't persist after reboot -- The ruleset was loaded with nft -f but not saved. Use nft list ruleset > /etc/nftables.conf and enable the nftables service.

  4. SELinux boolean misconfiguration -- A service needs a capability disabled by default but the admin sets setenforce 0 instead of enabling the correct boolean. Use getsebool -a and setsebool -P to adjust specific booleans.

  5. Auditd fills the disk -- Too many audit rules generate gigabytes of logs. Set reasonable max_log_file and num_logs in /etc/audit/auditd.conf, and rotate logs with logrotate.

Practice Questions

  1. What is the difference between SELinux and AppArmor? SELinux uses a labeled security model with type enforcement on all system objects, while AppArmor uses path-based profiles confined to individual programs. SELinux is more granular but harder to configure.

  2. Why disable root SSH login? Root has unlimited privileges. If an attacker cracks the root password, they own the system. Use sudo for administrative tasks and log in as a regular user.

  3. What does ct state invalid drop do in nftables? It drops packets with invalid connection tracking state, blocking many spoofing and injection attacks that manipulate TCP state.

  4. How does auditd help detect breaches? It logs all file changes, process executions, and authentication events, giving incident responders a tamper-proof timeline of attacker activity.

  5. Challenge: Write an Ansible playbook that applies the CIS Level 1 SSH hardening rules across 50 Ubuntu servers, generates a compliance report, and emails it to the security team.

Mini Project

Harden a fresh Ubuntu 22.04 VPS by applying SSH key-only auth, configuring nftables with a default-deny policy, enabling auditd with identity monitoring rules, and running OpenSCAP to verify compliance. Generate the HTML report and fix any failing controls until you reach 90%+ compliance.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro