Comprehensive Guide to Ubuntu Server Hardening

Dhairya PatelDhairya Patel
8 min read

What is Server Hardening?

Server hardening is a comprehensive security strategy that involves reducing a server's vulnerability surface and strengthening its defenses against potential cyber attacks. It's like fortifying a castle – you're building multiple layers of security to protect your valuable assets.

Key aspects of server hardening include:

  1. Attack Surface Reduction: Removing or disabling unnecessary services, ports, and software that could be exploited by attackers.

  2. Access Control: Implementing strict authentication and authorization mechanisms to ensure only legitimate users can access the system.

  3. System Hardening: Configuring system parameters, file permissions, and kernel settings to enhance security.

  4. Network Security: Implementing firewalls, intrusion detection systems, and network access controls.

  5. Monitoring and Logging: Setting up comprehensive logging and monitoring systems to detect and respond to security incidents.

Why is server hardening important?

  • Protects against common cyber attacks (brute force, DDoS, etc.)

  • Helps meet compliance requirements (PCI-DSS, HIPAA, etc.)

  • Reduces the risk of data breaches

  • Maintains system integrity and availability

  • Protects customer data and business reputation

Introduction

This guide provides detailed steps to harden an Ubuntu server deployed on AWS, making it more resilient against common security threats. Each section includes not just commands but detailed explanations of why we're implementing specific measures and how they contribute to overall security.

Prerequisites

  • An AWS account with necessary permissions

  • A newly created Ubuntu server instance

  • Basic understanding of Linux commands

  • SSH access to your server

1. Initial Server Setup and Access Control

1.1 Update System Packages

First and foremost, update all system packages to their latest versions:

# Update package index
sudo apt update

# Upgrade installed packages
sudo apt upgrade -y

# Perform distribution upgrade (includes kernel updates)
sudo apt dist-upgrade -y

# Remove unnecessary packages
sudo apt autoremove

Command Explanation:

  • apt update: Updates the package index files from repositories, ensuring we know about the latest available versions

  • apt upgrade: Installs newer versions of installed packages while respecting dependencies

  • apt dist-upgrade: Similar to upgrade but handles changing dependencies intelligently and can remove obsolete packages

  • apt autoremove: Removes packages that were installed as dependencies but are no longer needed

Why This Matters: Outdated software often contains known vulnerabilities that attackers can exploit. Regular updates are your first line of defense against security threats. Many major security breaches have occurred due to unpatched systems.

1.2 Configure SSH Security

SSH (Secure Shell) is your primary access point to the server. As it's often the only public-facing service, securing it properly is crucial for overall server security.

  1. Create SSH key pair (on your local machine):
# Generate a strong SSH key (Ed25519 is recommended for modern systems)
ssh-keygen -t ed25519 -a 100 -C "your_email@example.com"

# Copy the public key to server
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server-ip
  1. Edit SSH configuration:
sudo nano /etc/ssh/sshd_config
  1. Implement these security measures:
# Disable root login - prevents direct root access
PermitRootLogin no

# Use SSH Protocol 2 (more secure than Protocol 1)
Protocol 2

# Disable password authentication (use keys only)
PasswordAuthentication no

# Use only SSH key-based authentication
PubkeyAuthentication yes

# Change default port (reduces automated attacks)
Port 2222

# Limit login attempts
MaxAuthTries 3

# Set idle timeout interval (in seconds)
ClientAliveInterval 300
ClientAliveCountMax 2

# Restrict SSH access to specific users
AllowUsers your_username

# Disable empty passwords
PermitEmptyPasswords no

# Disable X11 forwarding if not needed
X11Forwarding no

# Use strong ciphers only
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

# Limit SSH version displayed
DebianBanner no
  1. Restart SSH service:
sudo systemctl restart sshd

Security Measures Explained:

  • Changing Default Port: While security through obscurity isn't perfect, moving SSH from port 22 reduces automated scanning attacks

  • Key-based Authentication: Much stronger than passwords, virtually impossible to brute force

  • Login Restrictions: Limiting attempts and timeouts helps prevent brute force attacks

  • Strong Ciphers: Using modern encryption algorithms ensures secure communication

  • User Restrictions: Limiting SSH access to specific users reduces attack surface

Important Note: When changing the SSH port:

  1. Update your AWS security group to allow the new port

  2. Keep your current SSH session open and test the new configuration in a new session before logging out

  3. Update any automation tools or scripts that use SSH

2. Firewall Configuration

2.1 Configure UFW (Uncomplicated Firewall)

# Install UFW if not present
sudo apt install ufw

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

# Allow SSH (use your custom port if changed)
sudo ufw allow 2222/tcp

# Enable UFW
sudo ufw enable

# Check status
sudo ufw status verbose

2.2 AWS Security Group Configuration

  1. Allow only necessary ports in your AWS Security Group

  2. Limit SSH access to specific IP ranges

  3. Remove default 'Allow All' rules

3. System Hardening

3.1 Configure System Security Parameters

Edit /etc/sysctl.conf:

# Network security
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.default.rp_filter=1
net.ipv4.icmp_echo_ignore_broadcasts=1
net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.default.accept_redirects=0
net.ipv4.conf.all.secure_redirects=0
net.ipv4.conf.default.secure_redirects=0
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.default.accept_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.default.send_redirects=0
net.ipv4.icmp_ignore_bogus_error_responses=1

# Disable IPv6 if not needed
net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6=1

Apply changes:

sudo sysctl -p

3.2 Secure User Authentication

  1. Configure password policies in /etc/login.defs:
PASS_MAX_DAYS 90
PASS_MIN_DAYS 7
PASS_WARN_AGE 7
  1. Install and configure PAM for password complexity:
sudo apt install libpam-pwquality

Edit /etc/security/pwquality.conf:

minlen = 12
minclass = 4
maxrepeat = 2
enforce_for_root

3.3 File System Security

  1. Set secure mount options in /etc/fstab:
# Add these options to relevant mount points
defaults,noexec,nosuid,nodev
  1. Secure shared memory:
echo "tmpfs /run/shm tmpfs defaults,noexec,nosuid,nodev 0 0" >> /etc/fstab

4. Monitoring and Logging

4.1 Configure Audit System

# Install auditd
sudo apt install auditd

# Configure basic audit rules
cat << EOF | sudo tee /etc/audit/rules.d/audit.rules
# Delete all existing rules
-D

# Set buffer size
-b 8192

# Monitor file system for changes
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k identity

# Monitor network configuration changes
-w /etc/network/ -p wa -k network
-w /etc/sysconfig/ -p wa -k network

# Monitor command execution
-w /usr/bin/ -p wa -k commands
-w /usr/sbin/ -p wa -k commands
EOF

# Restart audit daemon
sudo systemctl restart auditd

4.2 Configure System Logging

  1. Install and configure fail2ban:
sudo apt install fail2ban
  1. Create custom jail configuration:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edit /etc/fail2ban/jail.local:

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

5. Advanced Security Measures

5.1 Install and Configure Rootkit Detection

# Install rkhunter
sudo apt install rkhunter

# Update rkhunter database
sudo rkhunter --update

# Perform initial system scan
sudo rkhunter --check

5.2 Configure Automatic Security Updates

# Install unattended-upgrades
sudo apt install unattended-upgrades

# Configure automatic updates
sudo dpkg-reconfigure unattended-upgrades

5.3 Remove Unnecessary Services and Packages

# List all running services
systemctl list-units --type=service

# Disable unnecessary services
sudo systemctl disable <service_name>
sudo systemctl stop <service_name>

# Remove unnecessary packages
sudo apt purge telnet rsh-client rsh-server xinetd nis yp-tools tftpd atftpd tftpd-hpa telnetd rsh-server

# Remove unnecessary ports and services
sudo apt purge openssh-server vsftpd apache2 samba

# Only reinstall services you actually need
sudo apt install openssh-server

# Remove unnecessary compilers if not needed
sudo apt purge gcc g++ make automake

Why Remove Services:

  • Each running service is a potential attack vector

  • Unnecessary services consume system resources

  • Reduces complexity in security auditing

  • Minimizes potential vulnerabilities

5.4 Implement Port Knocking

Port knocking adds an additional layer of security by requiring a specific sequence of connection attempts before opening a port:

  1. Install port knocking service:
sudo apt install knockd
  1. Configure knockd (/etc/knockd.conf):
[options]
    UseSyslog
    LogFile = /var/log/knockd.log

[openSSH]
    sequence    = 7000,8000,9000
    seq_timeout = 5
    command     = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 2222 -j ACCEPT
    tcpflags    = syn

[closeSSH]
    sequence    = 9000,8000,7000
    seq_timeout = 5
    command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 2222 -j ACCEPT
    tcpflags    = syn

5.5 Secure Shared Memory

# Add to /etc/fstab
none /run/shm tmpfs rw,noexec,nosuid,nodev 0 0

# Remount all
sudo mount -a

5.6 Implement File Integrity Monitoring

Install and configure AIDE (Advanced Intrusion Detection Environment):

# Install AIDE
sudo apt install aide

# Initialize AIDE database
sudo aideinit

# Move the new database to the proper location
sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# Configure daily checks
echo '0 5 * * * root /usr/bin/aide --check' | sudo tee -a /etc/crontab

6. Regular Maintenance and Monitoring

6.1 Implement Regular Security Checks

Create a maintenance schedule for:

  • System updates

  • Log review

  • User account audit

  • Security scan with tools like rkhunter

  • Firewall rule review

  • SSL certificate renewal (if applicable)

6.2 Document Changes

Maintain a changelog of:

  • System modifications

  • Security updates

  • Configuration changes

  • Incident responses

Best Practices and Tips

  1. Principle of Least Privilege

    • Grant minimal necessary permissions

    • Regularly review and revoke unnecessary access

    • Use sudo instead of root

  2. Regular Backups

    • Implement automated backups

    • Test backup restoration regularly

    • Store backups in separate secure location

  3. Monitoring and Alerts

    • Set up monitoring for system resources

    • Configure alerts for suspicious activities

    • Regularly review security logs

  4. Documentation

    • Maintain detailed documentation of configurations

    • Keep recovery procedures updated

    • Document incident response plans

Conclusion

Server hardening is an ongoing process rather than a one-time task. Regular reviews and updates of security measures are essential to maintain a robust security posture. While this guide covers fundamental hardening steps, security requirements may vary based on specific use cases and compliance needs.

Remember to:

  • Regularly test security measures

  • Keep systems and packages updated

  • Monitor security advisories

  • Maintain proper documentation

  • Conduct regular security audits

Additional Resources

  • AWS Security Best Practices Documentation

  • Ubuntu Security Guide

  • CIS Benchmarks for Ubuntu Linux

  • NIST Security Guidelines

0
Subscribe to my newsletter

Read articles from Dhairya Patel directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dhairya Patel
Dhairya Patel

A DevOps Engineer with 2 year of experience as infrastructure support (AWS, Linux, Azure), DevOps (Build, CICD & Release Management)