thelinuxvault guide

10 Essential Linux Security Hardening Techniques

Linux is renowned for its robust security, but no operating system is immune to threats. Whether you’re running a personal server, a enterprise-grade infrastructure, or a IoT device, **security hardening**—the process of securing a system by reducing its attack surface and strengthening its defenses—is critical. This blog outlines 10 essential Linux security hardening techniques to protect against common vulnerabilities, brute-force attacks, and unauthorized access. By implementing these steps, you’ll significantly enhance your system’s resilience against cyber threats.

Table of Contents

  1. Regular System Updates and Patching
  2. Enforce Strong Password Policies
  3. Secure SSH Access
  4. Implement File and Directory Permissions
  5. Configure a Host-Based Firewall
  6. Limit User Privileges with sudo
  7. Disable Unnecessary Services and Daemons
  8. Use Security-Enhanced Linux (SELinux) or AppArmor
  9. Enable Log Monitoring and Auditing
  10. Regularly Backup Critical Data
  11. Conclusion
  12. References

1. Regular System Updates and Patching

Why It Matters

Outdated software is one of the most common entry points for attackers. Vulnerabilities in the Linux kernel, libraries, or applications are frequently discovered and patched by developers. Failing to update leaves your system exposed to known exploits.

Implementation Steps

  • Update Package Repositories and Install Patches:
    Use your distribution’s package manager to update and upgrade software.

    • Debian/Ubuntu:

      sudo apt update && sudo apt upgrade -y  
      sudo apt dist-upgrade -y  # For kernel updates  
    • RHEL/CentOS/Rocky Linux:

      sudo dnf update -y  
      sudo dnf upgrade -y  
  • Enable Automatic Updates:
    Reduce human error by automating updates.

    • Debian/Ubuntu: Install unattended-upgrades:

      sudo apt install unattended-upgrades  
      sudo dpkg-reconfigure -plow unattended-upgrades  # Enable automatic updates  
    • RHEL/CentOS: Use dnf-automatic:

      sudo dnf install dnf-automatic  
      sudo systemctl enable --now dnf-automatic.timer  
  • Reboot After Kernel Updates:
    Kernel patches require a reboot to take effect. Use sudo reboot when safe.

2. Enforce Strong Password Policies

Why It Matters

Weak passwords are a primary target for brute-force attacks. Enforcing complexity, expiration, and history policies reduces this risk.

Implementation Steps

  • Use PAM (Pluggable Authentication Modules):
    Linux uses PAM to manage authentication. Configure password rules in /etc/pam.d/common-password (Debian/Ubuntu) or /etc/pam.d/system-auth (RHEL).

    • Install pam_pwquality (enforces complexity):

      sudo apt install libpam-pwquality  # Debian/Ubuntu  
      sudo dnf install pam-pwquality     # RHEL  
    • Edit PAM Configuration:
      Add/modify these lines in the PAM password file:

      password    requisite     pam_pwquality.so retry=3 minlen=12 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 enforce_for_root  
      • minlen=12: Minimum password length (12 characters).
      • ucredit=-1: Require at least 1 uppercase letter.
      • lcredit=-1: Require at least 1 lowercase letter.
      • dcredit=-1: Require at least 1 digit.
      • ocredit=-1: Require at least 1 special character.
      • enforce_for_root: Apply rules to the root user.
  • Set Password Expiration:
    Use chage to enforce password expiration for users:

    sudo chage -M 90 -m 7 -W 14 <username>  # Max 90 days, min 7 days, warn 14 days before expiry  
    • Apply Globally: Edit /etc/login.defs to set system-wide defaults:
      PASS_MAX_DAYS   90  
      PASS_MIN_DAYS   7  
      PASS_WARN_AGE   14  

3. Secure SSH Access

Why It Matters

SSH (Secure Shell) is the primary method for remote Linux administration. Misconfigured SSH is a top attack vector.

Implementation Steps

  • Disable Password Authentication:
    Use SSH keys instead of passwords, which are more secure.

    1. Generate an SSH key pair on your local machine:

      ssh-keygen -t ed25519  # Use Ed25519 (more secure than RSA)  
    2. Copy the public key to the server:

      ssh-copy-id <username>@<server-ip>  
    3. Disable password auth in /etc/ssh/sshd_config:

      PasswordAuthentication no  
      ChallengeResponseAuthentication no  
  • Restrict Root Login:
    Prevent direct root login via SSH:

    PermitRootLogin no  # In /etc/ssh/sshd_config  
  • Change the Default SSH Port:
    Reduce automated scans by changing from port 22 to a non-standard port (e.g., 2222):

    Port 2222  # In /etc/ssh/sshd_config  
  • Limit User Access:
    Allow only specific users/groups to SSH in:

    AllowUsers alice [email protected]/24  # Allow alice (any IP) and bob (only from 192.168.1.0/24)  
    AllowGroups ssh-users  # Allow only members of "ssh-users" group  
  • Block Brute-Force Attacks:
    Install fail2ban to ban IPs after repeated failed login attempts:

    sudo apt install fail2ban  # Debian/Ubuntu  
    sudo dnf install fail2ban  # RHEL  
    sudo systemctl enable --now fail2ban  

    Configure rules in /etc/fail2ban/jail.local:

    [sshd]  
    enabled = true  
    port = 2222  # Match your SSH port  
    filter = sshd  
    logpath = /var/log/auth.log  
    maxretry = 3  # Ban after 3 failed attempts  
    bantime = 86400  # Ban for 24 hours (86400 seconds)  

4. Implement File and Directory Permissions

Why It Matters

Overly permissive files/directories allow unauthorized access to sensitive data (e.g., /etc/passwd, logs). Follow the principle of least privilege.

Implementation Steps

  • Understand Permission Basics:

    • Use ls -l to check permissions (e.g., -rw-r--r-- = user: read/write, group: read, others: read).
    • chmod modifies permissions (e.g., chmod 600 file = user read/write, no access for others).
    • chown changes ownership (e.g., chown alice:alice file).
  • Secure Critical Files:

    • /etc/shadow (password hashes): Should be 0000 (no access for non-root).
    • /etc/sudoers: 0440 (read-only for root and sudo group).
    • User home directories: 700 (only user access).

    Example fixes:

    sudo chmod 0000 /etc/shadow  
    sudo chmod 0440 /etc/sudoers  
    sudo chmod 700 /home/*  
  • Audit World-Writable Files:
    Find and fix files accessible to all users:

    sudo find / -type f -perm -0002 -ls  # World-writable files  
    sudo find / -type d -perm -0002 -ls  # World-writable directories  
  • Disable Setuid/Setgid Risks:
    setuid allows users to run a file with the owner’s privileges (e.g., sudo). Audit and remove unnecessary setuid files:

    sudo find / -perm -4000 -ls  # Setuid files  
    sudo chmod u-s /path/to/unneeded-setuid-file  # Remove setuid  
  • Set Default Umask:
    umask defines default permissions for new files. Set umask 027 in /etc/profile (system-wide) to restrict group/other access:

    echo "umask 027" | sudo tee -a /etc/profile  

5. Configure a Host-Based Firewall

Why It Matters

A firewall blocks unauthorized network traffic. Linux firewalls (e.g., ufw, iptables, firewalld) act as a first line of defense.

Implementation Steps

  • Use ufw (Uncomplicated Firewall) for Simplicity (Debian/Ubuntu):

    • Install and enable:

      sudo apt install ufw  
      sudo ufw default deny incoming  # Deny all inbound traffic  
      sudo ufw default allow outgoing  # Allow all outbound traffic  
    • Allow essential ports (e.g., SSH, HTTP/HTTPS):

      sudo ufw allow 2222/tcp  # SSH (use your custom port)  
      sudo ufw allow 80/tcp    # HTTP (if hosting a web server)  
      sudo ufw allow 443/tcp   # HTTPS  
    • Enable and verify:

      sudo ufw enable  
      sudo ufw status verbose  # Check rules  
  • Use firewalld (RHEL/CentOS):

    • Enable and start:

      sudo systemctl enable --now firewalld  
    • Allow ports:

      sudo firewall-cmd --add-port=2222/tcp --permanent  # SSH  
      sudo firewall-cmd --add-port=443/tcp --permanent   # HTTPS  
      sudo firewall-cmd --reload  # Apply changes  
  • Advanced: Use iptables (Manual Control):
    For granular rules (e.g., block an IP):

    sudo iptables -A INPUT -s 192.168.1.100 -j DROP  # Block IP 192.168.1.100  
    sudo iptables-save | sudo tee /etc/iptables/rules.v4  # Save rules (Debian)  

6. Limit User Privileges with sudo

Why It Matters

Avoid giving users direct root access. sudo grants temporary, controlled privileges, reducing the risk of accidental or malicious damage.

Implementation Steps

  • Edit the sudoers File Safely:
    Always use visudo to edit /etc/sudoers (prevents syntax errors):

    sudo visudo  
  • Restrict sudo Access:

    • Allow specific commands instead of full root access:

      alice ALL=(ALL) /usr/bin/apt, /usr/bin/systemctl restart apache2  # Alice can run apt and restart Apache  
    • Disable passwordless sudo (remove NOPASSWD: unless necessary).

    • Set password timeout (e.g., 5 minutes):

      Defaults timestamp_timeout=5  
  • Audit sudo Usage:
    sudo logs actions to /var/log/auth.log (Debian) or /var/log/secure (RHEL). Monitor with:

    sudo grep sudo /var/log/auth.log  

7. Disable Unnecessary Services and Daemons

Why It Matters

Every running service opens a potential attack vector. Disable unused services to reduce your attack surface.

Implementation Steps

  • List Running Services:

    sudo systemctl list-unit-files --type=service --state=enabled  # Enabled services  
    sudo ss -tulpn  # Open ports and associated services  
  • Disable Insecure Services:
    Remove legacy services like telnet, ftp, or rsh (use ssh/sftp instead):

    sudo systemctl disable --now telnet.service  
    sudo apt purge telnet-server  # Uninstall completely  
  • Stop and Mask Unneeded Services:
    Use systemctl to disable and prevent restarting:

    sudo systemctl stop cups.service  # Stop printing service (if unused)  
    sudo systemctl disable cups.service  # Disable on boot  
    sudo systemctl mask cups.service  # Prevent accidental start  
  • Verify Open Ports:
    After cleanup, confirm only essential ports are open:

    sudo ss -tulpn  # Should show only SSH (2222), HTTP (80), etc.  

8. Use Security-Enhanced Linux (SELinux) or AppArmor

Why It Matters

SELinux (Red Hat) and AppArmor (Debian/Ubuntu) enforce mandatory access control (MAC), restricting processes to predefined actions (e.g., a web server can’t read /etc/shadow).

Implementation Steps

  • SELinux (RHEL/CentOS):

    • Check status: sestatus (should be Enforcing).

    • Enable if disabled:

      sudo setenforce 1  # Temporary (until reboot)  
      sudo sed -i 's/SELINUX=permissive/SELINUX=enforcing/' /etc/selinux/config  # Permanent  
    • Troubleshoot with audit2allow:
      If an app breaks, generate policy rules from logs:

      sudo yum install policycoreutils-python-utils  
      sudo audit2allow -a -M myapp-policy  # Create policy module  
      sudo semodule -i myapp-policy.pp  # Load module  
  • AppArmor (Debian/Ubuntu):

    • Check status: sudo aa-status.

    • Enable profiles for critical apps (e.g., apache2, sshd):

      sudo aa-enforce /etc/apparmor.d/usr.sbin.apache2  
      sudo systemctl restart apparmor  
    • Edit profiles to restrict access (e.g., prevent Apache from writing to /tmp):

      sudo nano /etc/apparmor.d/usr.sbin.apache2  

9. Enable Log Monitoring and Auditing

Why It Matters

Logs track system activity, helping detect breaches (e.g., failed logins, file changes). Centralized monitoring ensures you don’t miss critical events.

Implementation Steps

  • Centralize Logs with rsyslog:
    Configure rsyslog to send logs to a central server (optional but recommended for enterprises). Edit /etc/rsyslog.conf:

    *.* @@log-server-ip:514  # Send all logs to log server via UDP  
  • Monitor Key Log Files:

    • /var/log/auth.log (Debian) or /var/log/secure (RHEL): Authentication events (SSH, sudo).
    • /var/log/syslog (Debian) or /var/log/messages (RHEL): System-wide events.
    • /var/log/fail2ban.log: Brute-force attempts blocked by fail2ban.
  • Use auditd for File/Process Auditing:
    Track changes to sensitive files (e.g., /etc/passwd):

    sudo apt install auditd  # Debian/Ubuntu  
    sudo dnf install audit  # RHEL  
    sudo systemctl enable --now auditd  

    Add a watch rule for /etc/passwd:

    sudo auditctl -w /etc/passwd -p wa -k passwd-changes  # Log write/attribute changes  

    Search audit logs:

    sudo ausearch -k passwd-changes  
  • Automate Alerts with logwatch:
    logwatch summarizes logs and emails reports:

    sudo apt install logwatch  # Debian/Ubuntu  
    sudo dnf install logwatch  # RHEL  
    sudo logwatch --mailto [email protected] --output mail  # Send daily reports  

10. Regularly Backup Critical Data

Why It Matters

Even with perfect hardening, data loss can occur (e.g., ransomware, hardware failure). Backups ensure recovery.

Implementation Steps

  • Follow the 3-2-1 Backup Rule:

    • 3 copies of data (original + 2 backups).
    • 2 different media (e.g., local SSD + cloud).
    • 1 copy offsite (e.g., AWS S3, Backblaze).
  • Use rsync for Local Backups:
    Sync files to an external drive:

    rsync -av --delete /home /etc /var/log /mnt/external-drive/backup-$(date +%F)  
  • Encrypt Backups:
    Use borgbackup for encrypted, deduplicated backups:

    sudo apt install borgbackup  
    borg init --encryption=repokey /mnt/external-drive/borg-repo  # Initialize encrypted repo  
    borg create /mnt/external-drive/borg-repo::backup-$(date +%F) /home /etc  # Backup  
  • Test Restores Regularly:
    Verify backups work by restoring a file:

    borg extract /mnt/external-drive/borg-repo::backup-2024-01-01 /home/alice/doc.txt  
  • Automate Backups with cron:
    Schedule daily backups:

    crontab -e  
    # Add: 0 2 * * * /usr/bin/borg create /mnt/external-drive/borg-repo::backup-$(date +\%F) /home /etc  

Conclusion

Linux security hardening is an ongoing process, not a one-time task. By combining these 10 techniques—from patching and strong passwords to firewalls and backups—you’ll significantly reduce your attack surface. Regular audits, monitoring, and updates are key to maintaining a secure system. Remember: security is a journey, not a destination.

References