Table of Contents
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) orrpm -qa(RHEL). - Running services:
systemctl list-unit-files --type=service --state=enabled. - Open ports:
ss -tulnornetstat -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
- “Do you want authentication tokens to be time-based?” →
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 auditFix 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
- Ubuntu Server Security Guide
- SSH Hardening Guide
- UFW Firewall Documentation
- AIDE Official Documentation
- Lynis Security Scanner
- NIST Special Publication 800-171 (Security for Non-Federal Systems)