thelinuxvault guide

How to Harden Your Linux System: A Step-by-Step Tutorial

Linux is renowned for its security, but no operating system is inherently "unbreakable." Default configurations often prioritize usability over security, leaving systems vulnerable to attacks like unauthorized access, malware, or data breaches. **System hardening** is the process of securing a Linux system by reducing its attack surface, enforcing strict access controls, and mitigating known vulnerabilities. Whether you’re running a personal laptop, a home server, or a production environment, hardening your Linux system is critical to protecting sensitive data and ensuring uptime. In this tutorial, we’ll walk through a comprehensive, step-by-step guide to hardening your Linux system, covering everything from user accounts to network security and beyond.

Table of Contents

  1. Pre-Hardening Preparation

  2. User Account & Privilege Management

  3. Secure Authentication

  4. Network Security

  5. File System Security

  6. Service Hardening

  7. System Monitoring & Logging

  8. Post-Hardening Testing

  9. Conclusion

  10. References

Pre-Hardening Preparation

Before making changes, lay the groundwork to avoid data loss and ensure you can revert if something breaks.

Backup Your System

Always back up critical data and configurations before modifying system settings. Use tools like rsync, Timeshift (GUI), or tar for backups:

# Example: Backup /home and /etc to an external drive (replace /mnt/backup with your drive path)  
sudo rsync -av /home /etc /mnt/backup  

For system-wide snapshots (Linux Mint/Ubuntu), use Timeshift:

sudo apt install timeshift  
sudo timeshift --create --comments "Pre-hardening backup" --yes  

Update Your System

Outdated software is a common attack vector. Update all packages to their latest security patches:

Debian/Ubuntu:

sudo apt update && sudo apt upgrade -y  
sudo apt autoremove -y  # Remove unused dependencies  

RHEL/CentOS:

sudo dnf update -y  
sudo dnf autoremove -y  

Document Current Configuration

Record your system’s baseline state to compare later. Note:

  • Installed packages: dpkg -l (Debian) or rpm -qa (RHEL).
  • Running services: systemctl list-unit-files --type=service --state=enabled.
  • Open ports: ss -tuln or netstat -tuln.
  • User accounts: cat /etc/passwd | grep -v nologin.

User Account & Privilege Management

Weak user account practices (e.g., default passwords, unrestricted root access) are low-hanging fruit for attackers.

Disable Root Login

Never log in directly as root. Instead, use sudo for administrative tasks. Disable root login via password:

sudo passwd -l root  # Locks the root account  

Verify: sudo passwd -S root (should show “L” for locked).

Enforce Strong Password Policies

Use pam_pwquality to enforce password complexity (length, special characters, etc.).

Install pam_pwquality:

# Debian/Ubuntu  
sudo apt install libpam-pwquality  

# RHEL/CentOS  
sudo dnf install pam_pwquality  

Edit /etc/security/pwquality.conf (or /etc/pam.d/common-password on Debian) to set rules:

minlen = 12          # Minimum password length  
dcredit = -1         # At least 1 digit  
ucredit = -1         # At least 1 uppercase  
lcredit = -1         # At least 1 lowercase  
ocredit = -1         # At least 1 special character  
retry = 3            # Max retries before failure  

Test with sudo passwd <username> to ensure policies are enforced.

Restrict Sudo Access

Limit sudo privileges to trusted users. Edit the sudoers file with visudo (safer than editing directly):

sudo visudo  

Add/modify users/groups:

# Allow "alice" to run all commands with sudo (restrict if possible)  
alice ALL=(ALL:ALL) ALL  

# Allow "developers" group to run only /usr/bin/git and /usr/bin/docker  
%developers ALL=(ALL:ALL) /usr/bin/git, /usr/bin/docker  

Avoid NOPASSWD (no password for sudo) unless absolutely necessary.

Remove/Disable Unused Accounts

Delete dormant or unnecessary accounts to reduce attack surface:

# List all user accounts  
cut -d: -f1 /etc/passwd  

# Delete an account (and home directory)  
sudo userdel -r old_user  

# Lock an account (instead of deleting)  
sudo usermod -L unused_user  

Secure Authentication

SSH is the primary way to access Linux servers—harden it to prevent brute-force attacks.

Harden SSH Configuration

Edit /etc/ssh/sshd_config (backup first: sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak):

Port 2222                  # Change default SSH port (reduce automated scans)  
Protocol 2                 # Use SSHv2 (disable SSHv1)  
PermitRootLogin no         # Block direct root login  
PasswordAuthentication no  # Disable password login (use keys instead)  
ChallengeResponseAuthentication no  
AllowUsers alice bob       # Allow only specific users (whitelist)  
AllowGroups ssh-users      # Or whitelist a group  
DenyUsers *                # Deny all others (if using AllowUsers)  
MaxAuthTries 3             # Limit login attempts  
LoginGraceTime 30s         # Auto-disconnect after 30s of inactivity  
X11Forwarding no           # Disable X11 forwarding (if unused)  
LogLevel VERBOSE           # Log detailed SSH activity  

Restart SSH to apply changes:

sudo systemctl restart sshd  

Use SSH Keys Instead of Passwords

SSH keys are more secure than passwords. Generate a key pair on your local machine:

ssh-keygen -t ed25519 -C "[email protected]"  # Ed25519 is more secure than RSA  

Press Enter to save to ~/.ssh/id_ed25519 and set a passphrase (optional but recommended).

Copy the public key to the server:

ssh-copy-id -p 2222 alice@your-server-ip  # Replace 2222 with your SSH port  

Test login:

ssh -p 2222 alice@your-server-ip  # Should log in without a password (if passphrase is not set)  

Enable Two-Factor Authentication (2FA)

Add an extra layer with 2FA using Google Authenticator.

Install the PAM module:

# Debian/Ubuntu  
sudo apt install libpam-google-authenticator  

# RHEL/CentOS  
sudo dnf install google-authenticator  

Run google-authenticator as the user (e.g., alice) to generate a QR code:

google-authenticator  
  • Scan the QR code with the Google Authenticator app (iOS/Android).
  • Save the emergency scratch codes (store offline!).
  • Answer prompts:
    • “Do you want authentication tokens to be time-based?” → y
    • “Update the .google_authenticator file?” → y
    • “Disallow multiple uses?” → y
    • “Increase the window?” → n (strict time sync)
    • “Enable rate-limiting?” → y

Edit /etc/pam.d/sshd to enable 2FA for SSH:

# Add at the top  
auth required pam_google_authenticator.so  

Edit /etc/ssh/sshd_config to require both key and 2FA:

AuthenticationMethods publickey,password publickey,keyboard-interactive  # Or "publickey,keyboard-interactive"  

Restart SSH:

sudo systemctl restart sshd  

Test login—you’ll need both your SSH key and the 2FA code.

Network Security

Control network traffic and block unauthorized access.

Configure a Firewall

Use ufw (Uncomplicated Firewall) for simplicity, or iptables for advanced rules.

Enable UFW and set default policies:

sudo ufw default deny incoming   # Block all unsolicited incoming traffic  
sudo ufw default allow outgoing  # Allow all outgoing traffic  
sudo ufw allow 2222/tcp          # Allow SSH (replace with your port)  
sudo ufw allow 80/tcp            # Allow HTTP (if running a web server)  
sudo ufw allow 443/tcp           # Allow HTTPS (if running a web server)  
sudo ufw enable                  # Start UFW on boot  
sudo ufw status verbose          # Verify rules  

For logging, enable UFW logging:

sudo ufw logging medium  

Disable Unused Network Services

Stop and disable services that listen on the network (e.g., FTP, Telnet, CUPS):

# List enabled services  
systemctl list-unit-files --type=service --state=enabled  

# Stop and disable a service (e.g., Telnet)  
sudo systemctl stop telnet.socket  
sudo systemctl disable telnet.socket  

Check for open ports with ss (replace ss with netstat if preferred):

ss -tuln  # t: TCP, u: UDP, l: listening, n: numeric ports  

Restrict Network Protocols

Disable unused protocols like IPv6 (if not needed) to reduce attack surface.

Edit /etc/sysctl.conf or /etc/sysctl.d/99-custom.conf:

# Disable IPv6  
net.ipv6.conf.all.disable_ipv6 = 1  
net.ipv6.conf.default.disable_ipv6 = 1  

# Apply changes  
sudo sysctl -p  

File System Security

Protect files from unauthorized access, tampering, or execution.

Set Strict File Permissions

Use chmod and chown to restrict access to sensitive files:

# Restrict /etc/passwd and /etc/shadow  
sudo chmod 644 /etc/passwd  
sudo chmod 000 /etc/shadow  # Only root can read/write  

# Restrict user home directories (no world access)  
sudo chmod 700 /home/*  

Set umask (default permissions for new files) to 027 (read/write for owner, read for group, none for others) by editing /etc/profile or ~/.bashrc:

umask 027  

Enable File Integrity Monitoring

Detect unauthorized file changes with AIDE (Advanced Intrusion Detection Environment).

Install AIDE:

# Debian/Ubuntu  
sudo apt install aide  

# RHEL/CentOS  
sudo dnf install aide  

Initialize the AIDE database (first run takes time):

sudo aideinit  
sudo cp /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz  # Replace old database  

Run a manual check:

sudo aide --check  

Schedule daily checks with cron (edit sudo crontab -e):

0 3 * * * /usr/bin/aide --check | mail -s "AIDE Integrity Check" [email protected]  

Secure Mount Options

Edit /etc/fstab to add security flags for partitions like /tmp and /var/tmp:

# Example /etc/fstab entry for /tmp  
tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0  

# /var/tmp (persistent, use ext4 with flags)  
/dev/sda5 /var/tmp ext4 defaults,noexec,nosuid,nodev 0 0  

# /home (restrict user files)  
/dev/sda6 /home ext4 defaults,nosuid 0 0  
  • noexec: Prevent execution of binaries.
  • nosuid: Block set-user-ID (SUID) binaries.
  • nodev: Disable device files.

Remount partitions without rebooting:

sudo mount -o remount /tmp  

Encrypt Sensitive Data

Encrypt partitions with LUKS (full disk or specific partitions) or home directories with eCryptfs.

Encrypt home directory (eCryptfs):

sudo apt install ecryptfs-utils  # Debian/Ubuntu  
ecryptfs-migrate-home -u alice   # Encrypt "alice" home dir (log out first!)  

Follow prompts to set a passphrase. Reboot and verify with mount | grep ecryptfs.

Service Hardening

Limit service privileges to minimize damage if compromised.

Run Services as Non-Root Users

Most services (e.g., Nginx, Apache, MySQL) run as non-root by default, but verify and enforce:

Example: Nginx
Check user in /etc/nginx/nginx.conf:

user www-data;  # Non-root user  

Disable Core Dumps

Core dumps (memory snapshots) can leak sensitive data. Disable them in /etc/security/limits.conf:

* hard core 0  
root hard core 0  

Or via sysctl:

sudo sysctl -w fs.suid_dumpable=0  
echo "fs.suid_dumpable=0" | sudo tee -a /etc/sysctl.conf  

Harden Kernel Parameters

Edit /etc/sysctl.conf to enable security-focused kernel settings:

# Block IP spoofing  
net.ipv4.conf.all.rp_filter = 1  
net.ipv4.conf.default.rp_filter = 1  

# Prevent SYN flood attacks  
net.ipv4.tcp_syncookies =1  

# Disable ICMP redirects (used in MITM attacks)  
net.ipv4.conf.all.accept_redirects = 0  
net.ipv6.conf.all.accept_redirects = 0  

# Enable ASLR (Address Space Layout Randomization)  
kernel.randomize_va_space = 2  

Apply changes:

sudo sysctl -p  

System Monitoring & Logging

Monitor activity to detect breaches early.

Centralize Logging

Aggregate logs from multiple systems with rsyslog or tools like Graylog. For a single server, ensure logs are stored securely:

Edit /etc/rsyslog.conf to log critical events to a separate file:

*.emerg :omusrmsg:*  # Send emergencies to all users  
auth,authpriv.* /var/log/auth.log  # Auth logs (SSH, sudo)  

Set log rotation in /etc/logrotate.conf to prevent disk overflow:

/var/log/auth.log {  
    daily  
    rotate 7  # Keep 7 days of logs  
    compress  
    delaycompress  
    missingok  
}  

Enable Auditd for Activity Tracking

Audit system calls and user actions with auditd.

Install and start auditd:

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

Add rules to /etc/audit/rules.d/audit.rules to monitor sensitive files:

# Monitor /etc/passwd and /etc/shadow  
-w /etc/passwd -p wa -k passwd_changes  
-w /etc/shadow -p wa -k shadow_changes  

# Monitor SSH config  
-w /etc/ssh/sshd_config -p wa -k sshd_config  

# Monitor user logins  
-a exit,always -F arch=b64 -S execve -k user_logins  

Restart auditd and search logs with ausearch:

sudo systemctl restart auditd  
sudo ausearch -k passwd_changes  # Search for password changes  

Post-Hardening Testing

Verify your hardening efforts with these tools:

  • Lynis (security audit tool):

    sudo apt install lynis  # Debian/Ubuntu  
    sudo lynis audit system  # Run a full audit  

    Fix issues flagged under “Suggestions” or “Warnings.”

  • Nmap (port scanning):
    From another machine, scan for open ports:

    nmap -p- your-server-ip  # Should only show allowed ports (e.g., 2222)  
  • SSH Test:
    Verify 2FA and key-based login work:

    ssh -p 2222 alice@your-server-ip  # Should prompt for 2FA code  

Conclusion

Linux hardening is an ongoing process, not a one-time task. Regularly update your system, review logs, and re-run audits (e.g., with Lynis) to adapt to new threats. By following these steps, you’ll significantly reduce your system’s attack surface and protect against common vulnerabilities.

References