Linux Server Hardening: Complete Guide

Introduction

Linux server hardening is the critical process of securing a Linux system by reducing its attack surface and implementing multiple layers of security controls. In today's threat landscape, where cyberattacks are increasingly sophisticated and automated, a properly hardened server can mean the difference between business continuity and catastrophic data breaches.

This comprehensive guide provides system administrators, DevOps engineers, and security professionals with a systematic approach to hardening Linux servers. Whether you're managing a single VPS or an enterprise infrastructure, implementing these security measures will significantly reduce your risk exposure and ensure compliance with industry security standards.

Server hardening isn't a one-time task but an ongoing process that requires regular assessment, updates, and adaptation to emerging threats. This guide follows defense-in-depth principles, implementing multiple security layers so that if one control fails, others remain in place to protect your systems.

Understanding the Threat Landscape

Common Attack Vectors

Modern Linux servers face numerous threats from multiple sources:

Brute Force Attacks: Automated bots continuously scan the internet attempting to gain SSH access through password guessing. These attacks can generate thousands of login attempts per day against exposed servers.

Vulnerability Exploitation: Unpatched software vulnerabilities remain one of the primary attack vectors. Attackers actively scan for systems running outdated software with known exploits.

Privilege Escalation: Once attackers gain limited access, they attempt to exploit misconfigurations or kernel vulnerabilities to obtain root privileges.

Malware and Rootkits: Advanced persistent threats deploy sophisticated malware designed to maintain long-term access while evading detection.

DDoS Attacks: Distributed denial-of-service attacks can overwhelm server resources, making services unavailable to legitimate users.

Supply Chain Attacks: Compromised software packages or dependencies can introduce vulnerabilities directly into your infrastructure.

Risk Assessment

Before implementing hardening measures, understand your specific risk profile:

  • Data Sensitivity: What type of data does your server process or store?
  • Compliance Requirements: What regulatory frameworks apply to your operations?
  • Service Availability: What is the acceptable downtime threshold?
  • Resource Constraints: What security tools can your server performance support?
  • Attack Surface: What services are exposed to the internet?

Pre-Hardening Preparation

System Inventory

Document your current server configuration before making changes:

# System information
hostnamectl
uname -a
cat /etc/os-release

# Network configuration
ip addr show
ip route show
ss -tuln

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

Backup Critical Configuration

Always backup configuration files before modification:

# Create backup directory
sudo mkdir -p /root/config-backup-$(date +%Y%m%d)

# Backup critical files
sudo cp -r /etc/ssh /root/config-backup-$(date +%Y%m%d)/
sudo cp -r /etc/sysctl.conf /root/config-backup-$(date +%Y%m%d)/
sudo cp -r /etc/security /root/config-backup-$(date +%Y%m%d)/

Operating System Hardening

Minimal Installation

Start with a minimal OS installation containing only essential packages:

# Ubuntu/Debian - Remove unnecessary packages
sudo apt-get autoremove
sudo apt-get purge $(dpkg -l | grep '^rc' | awk '{print $2}')

# CentOS/Rocky Linux - List installed packages
sudo dnf list installed
sudo dnf remove package-name

System Updates and Patch Management

Maintaining current security patches is critical:

# Ubuntu/Debian
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get dist-upgrade -y

# Enable automatic security updates
sudo apt-get install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

Configure automatic updates on CentOS/Rocky:

# CentOS/Rocky Linux
sudo dnf update -y
sudo dnf install dnf-automatic
sudo systemctl enable --now dnf-automatic.timer

Edit /etc/dnf/automatic.conf:

[commands]
upgrade_type = security
apply_updates = yes

Kernel Hardening with Sysctl

Kernel parameters provide powerful security controls:

Edit /etc/sysctl.conf or create /etc/sysctl.d/99-hardening.conf:

# IP Forwarding
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# Syn flood protection
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_max_syn_backlog = 4096

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

# Ignore send redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Disable source packet routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# Reverse path filtering
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Log martian packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# Ignore ICMP ping requests
net.ipv4.icmp_echo_ignore_all = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Ignore bogus ICMP errors
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Enable TCP/IP stack hardening
kernel.randomize_va_space = 2
kernel.exec-shield = 1
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1

# Restrict kernel pointers in /proc
kernel.kptr_restrict = 2

Apply changes:

sudo sysctl -p
sudo sysctl --system

User Account Security

Disable Root Login

Never allow direct root login via SSH:

Edit /etc/ssh/sshd_config:

PermitRootLogin no

Strong Password Policies

Configure password complexity requirements:

Edit /etc/security/pwquality.conf:

# Password minimum length
minlen = 14

# Require complexity
dcredit = -1    # At least one digit
ucredit = -1    # At least one uppercase
lcredit = -1    # At least one lowercase
ocredit = -1    # At least one special character

# Reject passwords with username
usercheck = 1

# Maximum consecutive characters
maxrepeat = 3

Password Aging

Enforce password expiration policies:

Edit /etc/login.defs:

PASS_MAX_DAYS   90
PASS_MIN_DAYS   1
PASS_WARN_AGE   7

Apply to existing users:

sudo chage -M 90 -m 1 -W 7 username

Account Lockout

Prevent brute force attacks with account lockouts:

Edit /etc/security/faillock.conf:

# Lock account after 5 failed attempts
deny = 5

# Unlock time (seconds)
unlock_time = 900

# Root account also subject to lockout
even_deny_root

SSH Hardening

Key-Based Authentication

Disable password authentication entirely:

# Generate SSH key on client
ssh-keygen -t ed25519 -a 100

# Copy to server
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

Configure SSH daemon (/etc/ssh/sshd_config):

# Authentication
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes

# Root login
PermitRootLogin no

# Protocol
Protocol 2

# Key types
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

# Ciphers and algorithms
KexAlgorithms curve25519-sha256,[email protected]
Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr
MACs [email protected],[email protected],hmac-sha2-512,hmac-sha2-256

# Connection settings
ClientAliveInterval 300
ClientAliveCountMax 2
MaxAuthTries 3
MaxSessions 2
LoginGraceTime 60

# Limit users
AllowUsers deployuser adminuser

Change Default SSH Port

Reduce automated attacks by changing the default port:

# Edit SSH config
Port 2222

# Update firewall
sudo ufw allow 2222/tcp
sudo ufw delete allow 22/tcp

# Restart SSH
sudo systemctl restart sshd

Firewall Configuration

UFW (Ubuntu/Debian)

Implement a strict firewall policy:

# Install UFW
sudo apt-get install ufw

# Default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow SSH (custom port)
sudo ufw allow 2222/tcp

# Allow HTTP/HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Rate limit SSH
sudo ufw limit 2222/tcp

# Enable firewall
sudo ufw enable

# Check status
sudo ufw status verbose

Firewalld (CentOS/Rocky)

# Install firewalld
sudo dnf install firewalld
sudo systemctl enable --now firewalld

# Set default zone
sudo firewall-cmd --set-default-zone=public

# Configure services
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https

# Custom SSH port
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --permanent --remove-service=ssh

# Rich rules for rate limiting
sudo firewall-cmd --permanent --add-rich-rule='rule service name=ssh limit value=10/m accept'

# Reload
sudo firewall-cmd --reload

Mandatory Access Control

SELinux Configuration

For Red Hat-based systems:

# Check SELinux status
sestatus

# Set enforcing mode
sudo setenforce 1

# Make permanent
sudo sed -i 's/SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config

Manage SELinux contexts:

# Relabel filesystem
sudo touch /.autorelabel
sudo reboot

# Check file contexts
ls -Z /path/to/file

# Restore default context
sudo restorecon -Rv /path/to/directory

AppArmor Configuration

For Debian-based systems:

# Install AppArmor
sudo apt-get install apparmor apparmor-utils

# Check status
sudo aa-status

# Enable profiles
sudo aa-enforce /etc/apparmor.d/*

# Create custom profile
sudo aa-genprof /usr/bin/application

File System Security

Partition Security with Mount Options

Edit /etc/fstab with secure mount options:

/dev/sda1  /           ext4    defaults,nodev,nosuid,noexec    1 1
/dev/sda2  /home       ext4    defaults,nodev,nosuid           1 2
/dev/sda3  /tmp        ext4    defaults,nodev,nosuid,noexec    1 2
/dev/sda4  /var        ext4    defaults,nodev                  1 2
/dev/sda5  /var/tmp    ext4    defaults,nodev,nosuid,noexec    1 2
tmpfs      /dev/shm    tmpfs   defaults,nodev,nosuid,noexec    0 0

Apply immediately:

sudo mount -o remount /tmp
sudo mount -o remount /var/tmp

File Permission Hardening

Set restrictive default permissions:

# Set umask in /etc/profile and /etc/bash.bashrc
umask 027

# Secure sensitive files
sudo chmod 600 /etc/ssh/sshd_config
sudo chmod 600 /boot/grub/grub.cfg
sudo chmod 644 /etc/passwd
sudo chmod 640 /etc/shadow
sudo chmod 640 /etc/gshadow

Find and fix world-writable files:

# Find world-writable files
sudo find / -xdev -type f -perm -0002 -ls

# Find files without owner
sudo find / -xdev -nouser -o -nogroup

# Find SUID/SGID files
sudo find / -xdev -type f \( -perm -4000 -o -perm -2000 \) -ls

Process and Service Hardening

Disable Unnecessary Services

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

# Disable unnecessary services
sudo systemctl disable cups
sudo systemctl disable avahi-daemon
sudo systemctl disable bluetooth

Restrict Core Dumps

Prevent sensitive data leakage through core dumps:

Edit /etc/security/limits.conf:

* hard core 0

Create /etc/sysctl.d/50-coredump.conf:

kernel.core_pattern = |/bin/false
fs.suid_dumpable = 0

Monitoring and Logging

Centralized Logging

Configure rsyslog for remote logging:

Edit /etc/rsyslog.conf:

# Send logs to remote server
*.* @@logserver.example.com:514

Audit Logging with Auditd

# Install auditd
sudo apt-get install auditd audispd-plugins

# Enable and start
sudo systemctl enable auditd
sudo systemctl start auditd

Configure audit rules in /etc/audit/rules.d/hardening.rules:

# Delete all existing rules
-D

# Buffer size
-b 8192

# Failure mode
-f 1

# Monitor authentication
-w /etc/passwd -p wa -k passwd_changes
-w /etc/group -p wa -k group_changes
-w /etc/shadow -p wa -k shadow_changes
-w /etc/sudoers -p wa -k sudoers_changes

# Monitor login/logout
-w /var/log/lastlog -p wa -k logins
-w /var/run/faillock/ -p wa -k logins

# Monitor network changes
-w /etc/hosts -p wa -k network_changes
-w /etc/network/ -p wa -k network_changes

# Monitor privilege escalation
-w /usr/bin/sudo -p x -k privilege_escalation
-w /usr/bin/su -p x -k privilege_escalation

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

# System calls
-a always,exit -F arch=b64 -S execve -k exec
-a always,exit -F arch=b64 -S connect -k network_connect

Reload rules:

sudo augenrules --load
sudo systemctl restart auditd

Log Retention

Configure log rotation in /etc/logrotate.d/rsyslog:

/var/log/syslog
/var/log/auth.log
{
    rotate 90
    daily
    missingok
    notifempty
    compress
    delaycompress
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate
    endscript
}

Intrusion Detection and Prevention

Fail2Ban Configuration

# Install Fail2Ban
sudo apt-get install fail2ban

# Create local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edit /etc/fail2ban/jail.local:

[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
destemail = [email protected]
sendername = Fail2Ban
action = %(action_mwl)s

[sshd]
enabled = true
port = 2222
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400

AIDE (Advanced Intrusion Detection Environment)

# Install AIDE
sudo apt-get install aide

# Initialize database
sudo aideinit

# Move database
sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# Run checks
sudo aide --check

# Automate with cron
echo "0 3 * * * root /usr/bin/aide --check | mail -s 'AIDE Report' [email protected]" | sudo tee -a /etc/crontab

Incident Response Procedures

Detection and Analysis

When suspicious activity is detected:

# Check active connections
sudo ss -tupn
sudo netstat -tupn

# Review authentication logs
sudo tail -100 /var/log/auth.log
sudo journalctl -u sshd -n 100

# Check for new users
sudo tail /etc/passwd
sudo tail /etc/shadow

# Identify suspicious processes
ps aux | grep -v root
ps aux --sort=-pcpu | head -10

Containment

# Block attacking IP
sudo ufw deny from <attacking-ip>
sudo iptables -I INPUT -s <attacking-ip> -j DROP

# Disable compromised account
sudo usermod -L compromised-user
sudo passwd -l compromised-user

# Kill suspicious processes
sudo kill -9 <pid>

# Disconnect network (if necessary)
sudo ip link set eth0 down

Evidence Collection

# Capture system state
sudo ps aux > /root/incident-$(date +%Y%m%d-%H%M%S)-ps.txt
sudo netstat -tupn > /root/incident-$(date +%Y%m%d-%H%M%S)-netstat.txt
sudo ss -tupn > /root/incident-$(date +%Y%m%d-%H%M%S)-ss.txt

# Copy logs
sudo tar czf /root/incident-$(date +%Y%m%d-%H%M%S)-logs.tar.gz /var/log/

# Memory dump (if installed)
sudo dd if=/dev/mem of=/root/memory-dump-$(date +%Y%m%d-%H%M%S).img

Recovery

# Change all passwords
sudo passwd root
sudo passwd username

# Regenerate SSH host keys
sudo rm /etc/ssh/ssh_host_*
sudo dpkg-reconfigure openssh-server

# Update all packages
sudo apt-get update && sudo apt-get upgrade -y

# Review and close unnecessary ports
sudo ss -tuln

Compliance Considerations

PCI-DSS Requirements

For payment card processing:

  • Strong access control (Requirement 7, 8)
  • Encrypt data transmission (Requirement 4)
  • Maintain audit logs (Requirement 10)
  • Regular security testing (Requirement 11)
  • Vulnerability management (Requirement 6)

HIPAA Compliance

For healthcare data:

  • Implement access controls
  • Audit controls and logging
  • Encryption of ePHI
  • Regular risk assessments

GDPR Requirements

For EU personal data:

  • Data protection by design
  • Pseudonymization and encryption
  • Ability to restore data availability
  • Regular testing of security measures

Implementation Checklist

# Verify compliance controls
- [ ] Multi-factor authentication enabled
- [ ] Full disk encryption configured
- [ ] Audit logging active and monitored
- [ ] Regular vulnerability scans scheduled
- [ ] Incident response plan documented
- [ ] Data retention policies configured
- [ ] Backup and recovery tested
- [ ] Security awareness training completed

Continuous Security Maintenance

Regular Security Audits

Schedule monthly security reviews:

#!/bin/bash
# Security audit script

echo "=== Security Audit $(date) ===" > /root/security-audit.log

# Check for updates
apt-get -s upgrade >> /root/security-audit.log

# List listening ports
echo -e "\n=== Listening Ports ===" >> /root/security-audit.log
ss -tuln >> /root/security-audit.log

# Check failed login attempts
echo -e "\n=== Failed Login Attempts ===" >> /root/security-audit.log
grep "Failed password" /var/log/auth.log | tail -20 >> /root/security-audit.log

# World-writable files
echo -e "\n=== World-Writable Files ===" >> /root/security-audit.log
find / -xdev -type f -perm -0002 >> /root/security-audit.log 2>/dev/null

# SUID files
echo -e "\n=== SUID/SGID Files ===" >> /root/security-audit.log
find / -xdev -type f \( -perm -4000 -o -perm -2000 \) >> /root/security-audit.log 2>/dev/null

Vulnerability Scanning

# Schedule weekly vulnerability scans
0 2 * * 0 /usr/bin/lynis audit system --cronjob > /var/log/lynis/$(date +\%Y\%m\%d).log

Security Update Management

Establish a patch management schedule:

  • Critical security patches: Within 24 hours
  • Important security patches: Within 7 days
  • Normal updates: Monthly maintenance window
  • Test updates in staging before production

Conclusion

Linux server hardening is a comprehensive, ongoing process that requires systematic implementation of security controls across multiple layers. By following this guide, you've established a robust security foundation that addresses:

Prevention: Through strong authentication, firewall rules, and access controls Detection: Via comprehensive logging, monitoring, and intrusion detection systems Response: With documented incident response procedures and evidence collection methods

Remember that security is not a destination but a continuous journey. The threat landscape evolves constantly, requiring regular reassessment of your security posture. Maintain vigilance through:

  • Weekly review of security logs
  • Monthly vulnerability scans
  • Quarterly security audits
  • Annual penetration testing
  • Continuous education on emerging threats

A properly hardened Linux server significantly reduces your attack surface and provides multiple defensive layers. However, hardening must be balanced with operational requirements and usability. Document all changes, maintain backups, and test security configurations regularly.

The investment in comprehensive server hardening pays dividends through reduced security incidents, improved compliance posture, and protection of critical business assets. Start with the fundamentals outlined in this guide, then progressively implement advanced security controls as your security maturity evolves.

Stay informed about new vulnerabilities, follow security mailing lists for your Linux distribution, and participate in the security community to maintain awareness of emerging threats and best practices.