Linux Server Hardening

Secure your Linux servers against attacks

Linux server security
By FixTheVuln Team Peer-reviewed security content Sources: CISA, NVD, OWASP

Key Takeaways

  • Disable root SSH login and use key-based authentication instead of passwords
  • Configure firewall rules (iptables/ufw) to allow only necessary ports
  • Keep the system updated with automatic security patches enabled
  • Remove unnecessary services and packages to reduce attack surface
  • Set proper file permissions — never use 777 on production files
Why Linux Hardening Matters: Default Linux installations prioritize ease of use over security. Hardening reduces the attack surface by disabling unnecessary services, enforcing strong authentication, and implementing defense-in-depth.

System Updates

1. Keep System Updated

Debian/Ubuntu

# Update package lists and upgrade sudo apt update && sudo apt upgrade -y # Enable automatic security updates sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades # Configure automatic updates sudo nano /etc/apt/apt.conf.d/50unattended-upgrades # Uncomment: "${distro_id}:${distro_codename}-security";

RHEL/CentOS/Rocky/Alma

# Update all packages sudo dnf update -y # RHEL 8+/Rocky/Alma sudo yum update -y # RHEL 7/CentOS 7 # Enable automatic updates sudo dnf install dnf-automatic sudo systemctl enable --now dnf-automatic.timer # Configure automatic updates sudo nano /etc/dnf/automatic.conf # Set: apply_updates = yes

SSH Hardening

2. Secure SSH Configuration

Edit SSH Config (/etc/ssh/sshd_config)

# /etc/ssh/sshd_config - Security hardened configuration # Change default port (security through obscurity - optional) Port 2222 # Disable root login PermitRootLogin no # Disable password authentication (use keys only) PasswordAuthentication no PubkeyAuthentication yes # Disable empty passwords PermitEmptyPasswords no # Limit login attempts MaxAuthTries 3 # Set login grace time LoginGraceTime 60 # Disable X11 forwarding X11Forwarding no # Disable TCP forwarding (unless needed) AllowTcpForwarding no # Use strong ciphers only Ciphers [email protected],[email protected],[email protected] MACs [email protected],[email protected] KexAlgorithms [email protected],diffie-hellman-group16-sha512 # Limit users who can SSH AllowUsers admin deploy # Or use groups AllowGroups sshusers # Set idle timeout (5 minutes) ClientAliveInterval 300 ClientAliveCountMax 0 # Disable unused authentication methods ChallengeResponseAuthentication no KerberosAuthentication no GSSAPIAuthentication no # Enable logging LogLevel VERBOSE

Apply Changes

# Test configuration before restart sudo sshd -t # Restart SSH service sudo systemctl restart sshd # IMPORTANT: Keep current session open and test new connection first!

SSH Key Setup

# Generate SSH key pair (on client machine) ssh-keygen -t ed25519 -C "[email protected]" # Or RSA 4096 if ed25519 not supported ssh-keygen -t rsa -b 4096 -C "[email protected]" # Copy public key to server ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server # Or manually add to server cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys chmod 700 ~/.ssh

Firewall Configuration

3. Configure Firewall

UFW (Uncomplicated Firewall) - Ubuntu/Debian

# Install UFW sudo apt install ufw # Set default policies sudo ufw default deny incoming sudo ufw default allow outgoing # Allow SSH (BEFORE enabling!) sudo ufw allow 22/tcp # Or custom port sudo ufw allow 2222/tcp # Allow common services sudo ufw allow 80/tcp # HTTP sudo ufw allow 443/tcp # HTTPS # Allow from specific IP only sudo ufw allow from 192.168.1.100 to any port 22 # Enable firewall sudo ufw enable # Check status sudo ufw status verbose # View rules numbered (for deletion) sudo ufw status numbered # Delete a rule sudo ufw delete 3

firewalld - RHEL/CentOS/Rocky

# Start and enable firewalld sudo systemctl enable --now firewalld # Check status sudo firewall-cmd --state # List all rules sudo firewall-cmd --list-all # Add services sudo firewall-cmd --permanent --add-service=ssh sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https # Add custom port sudo firewall-cmd --permanent --add-port=2222/tcp # Remove service sudo firewall-cmd --permanent --remove-service=ssh # Allow from specific IP sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept' # Reload to apply changes sudo firewall-cmd --reload

iptables (Advanced)

# Flush existing rules sudo iptables -F # Set default policies sudo iptables -P INPUT DROP sudo iptables -P FORWARD DROP sudo iptables -P OUTPUT ACCEPT # Allow loopback sudo iptables -A INPUT -i lo -j ACCEPT # Allow established connections sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Allow SSH sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT # Allow HTTP/HTTPS sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT # Rate limit SSH connections (prevent brute force) sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 -j DROP # Save rules sudo iptables-save | sudo tee /etc/iptables/rules.v4 # Install persistence sudo apt install iptables-persistent

User Management

4. Secure User Accounts

Create Non-Root Admin User

# Create user sudo useradd -m -s /bin/bash admin # Set strong password sudo passwd admin # Add to sudo group sudo usermod -aG sudo admin # Debian/Ubuntu sudo usermod -aG wheel admin # RHEL/CentOS # Lock root account (after confirming sudo works!) sudo passwd -l root

Password Policy (/etc/login.defs)

# /etc/login.defs PASS_MAX_DAYS 90 # Maximum days password valid PASS_MIN_DAYS 7 # Minimum days between changes PASS_MIN_LEN 12 # Minimum password length PASS_WARN_AGE 14 # Warning days before expiry # Apply to existing user sudo chage -M 90 -m 7 -W 14 username

PAM Password Requirements

# Install password quality checking sudo apt install libpam-pwquality # Configure /etc/security/pwquality.conf minlen = 12 minclass = 3 maxrepeat = 3 maxclassrepeat = 4 lcredit = -1 ucredit = -1 dcredit = -1 ocredit = -1 dictcheck = 1

Audit User Accounts

# List all users with login shells cat /etc/passwd | grep -v nologin | grep -v false # List users with UID 0 (root privileges) awk -F: '($3 == "0") {print}' /etc/passwd # Find users with empty passwords sudo awk -F: '($2 == "") {print $1}' /etc/shadow # List users in sudo/wheel group getent group sudo getent group wheel # Check for unauthorized SSH keys find /home -name "authorized_keys" -exec ls -la {} \;

File Permissions

5. Secure File Permissions

Critical File Permissions

# Secure SSH files chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chmod 600 ~/.ssh/id_* chmod 644 ~/.ssh/id_*.pub chmod 644 ~/.ssh/known_hosts # Secure system files sudo chmod 644 /etc/passwd sudo chmod 000 /etc/shadow sudo chmod 000 /etc/gshadow sudo chmod 644 /etc/group sudo chmod 600 /etc/ssh/sshd_config # Remove world-writable permissions find /home -type f -perm -002 -exec chmod o-w {} \; # Find SUID/SGID files (potential security risk) find / -perm /4000 -type f 2>/dev/null # SUID find / -perm /2000 -type f 2>/dev/null # SGID # Find world-writable files find / -type f -perm -002 2>/dev/null # Find files without owner find / -nouser -o -nogroup 2>/dev/null

Secure /tmp

# Mount /tmp with noexec, nosuid (edit /etc/fstab) tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0 # Remount without reboot sudo mount -o remount /tmp

Disable Unnecessary Services

6. Minimize Attack Surface

List Running Services

# List all running services sudo systemctl list-units --type=service --state=running # List enabled services sudo systemctl list-unit-files --type=service --state=enabled # List listening ports sudo ss -tulpn sudo netstat -tulpn

Disable Unnecessary Services

# Disable and stop service sudo systemctl disable --now cups # Printing sudo systemctl disable --now avahi-daemon # mDNS sudo systemctl disable --now bluetooth # Bluetooth sudo systemctl disable --now ModemManager # Modem sudo systemctl disable --now rpcbind # NFS (if not used) # Mask service (prevent starting) sudo systemctl mask cups

Remove Unnecessary Packages

# Debian/Ubuntu sudo apt remove --purge telnet rsh-client sudo apt autoremove # RHEL/CentOS sudo dnf remove telnet rsh

Logging & Auditing

7. Enable Comprehensive Logging

Configure auditd

# Install auditd sudo apt install auditd audispd-plugins # Enable and start sudo systemctl enable --now auditd # Add audit rules (/etc/audit/rules.d/audit.rules) # Monitor authentication -w /etc/passwd -p wa -k identity -w /etc/shadow -p wa -k identity -w /etc/group -p wa -k identity -w /etc/gshadow -p wa -k identity # Monitor sudo usage -w /etc/sudoers -p wa -k sudoers -w /etc/sudoers.d/ -p wa -k sudoers # Monitor SSH config -w /etc/ssh/sshd_config -p wa -k sshd # Monitor login/logout -w /var/log/faillog -p wa -k logins -w /var/log/lastlog -p wa -k logins # Reload rules sudo augenrules --load

View Audit Logs

# Search audit logs sudo ausearch -k identity sudo ausearch -k sudoers # Generate report sudo aureport --summary sudo aureport --auth sudo aureport --login

Centralize Logs (rsyslog)

# Send logs to remote server # Add to /etc/rsyslog.conf *.* @syslog-server.example.com:514 # UDP *.* @@syslog-server.example.com:514 # TCP # Restart rsyslog sudo systemctl restart rsyslog

Intrusion Prevention

8. Install Fail2Ban

# Install Fail2Ban sudo apt install fail2ban # Debian/Ubuntu sudo dnf install fail2ban # RHEL/Rocky # Create local config sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local # Edit /etc/fail2ban/jail.local [DEFAULT] bantime = 1h findtime = 10m maxretry = 5 ignoreip = 127.0.0.1/8 ::1 [sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log # Debian # logpath = /var/log/secure # RHEL maxretry = 3 bantime = 24h # Enable and start sudo systemctl enable --now fail2ban # Check status sudo fail2ban-client status sudo fail2ban-client status sshd # Unban an IP sudo fail2ban-client set sshd unbanip 192.168.1.100

Security Checklist

☐ System fully updated with auto-updates enabled
☐ SSH: Root login disabled, key-based auth only
☐ SSH: Running on non-standard port (optional)
☐ Firewall enabled with minimal open ports
☐ Non-root admin user created
☐ Strong password policy enforced
☐ Unnecessary services disabled
☐ File permissions secured
☐ Audit logging enabled (auditd)
☐ Fail2Ban or similar installed
☐ Logs centralized to remote server
☐ Regular security scans scheduled

Important: Always test SSH configuration changes in a separate terminal before closing your current session. Incorrect SSH settings can lock you out permanently!

Related Resources

🪟 Windows Hardening Windows security guide 🐳 Container Security Docker & Kubernetes security 📊 Log Management Logging and SIEM basics

Test Your Knowledge

Linux+ Practice Quiz Security+ Practice Quiz

Latest from the Blog

CompTIA Linux+ Study Guide: How to Pass the XK0-005 Exam CompTIA Server+ Study Guide: Everything You Need to Pass the SK0-00... Microsoft AI-102 Study Guide: Everything You Need to Pass the AI-10...
← Back to Tools

FixTheVuln Store

Get the CompTIA Linux+ Study Planner

Fillable PDF study planners with domain trackers, weekly schedules, and progress tracking. Available in Standard, ADHD-Friendly, Dark Mode, and 4-Format Bundle.

CompTIA Linux+ Planner

60+ certifications available — from $5.99

CyberFolio

Choosing your next cert? Track them all in one place.

Build a shareable cybersecurity portfolio that highlights your certifications, projects, and skills — free.

Build Your Portfolio →