Cloud VPS

How to Secure and Harden a Linux Cloud VPS: UFW, Fail2ban & SSH Hardening Checklist

How to Secure and Harden a Linux Cloud VPS: UFW, Fail2ban & SSH Hardening Checklist - CpanelFree Guide
Written by Blog

The Reality of Public Internet Scanners & Automated Attack Bots

The moment you launch a fresh Linux VPS and assign it a public IPv4 address, automated malicious botnets and vulnerability scanners begin probing your server within minutes. These automated crawlers execute tens of thousands of dictionary attacks against default SSH port 22, scan for open database ports (3306, 5432), probe for unpatched Redis instances (6379), and search for exposed web panel login portals.

Leaving a production server with default root passwords or unrestricted firewall policies is an invitation to malware compromise, ransomware extortion, and botnet recruitment. By implementing a layered defense strategy comprising unprivileged sudo users, ed25519 SSH cryptographic keys, a strict UFW firewall, and automated Fail2ban intrusion prevention, you eliminate 99.9% of automated cyber threats.

In this enterprise hardening guide, we will step through locking down a fresh Ubuntu 24.04/22.04 LTS server from scratch.

Step 1: Creating a Dedicated Sudo User and Disabling Root Login

Direct login as the root superuser should always be disabled. Create a dedicated administrative user account with granular sudo privileges:

# Create a new administrative user
adduser devadmin

# Add user to sudo group
usermod -aG sudo devadmin

# Copy SSH authorized keys from root to new user
mkdir -p /home/devadmin/.ssh
cp /root/.ssh/authorized_keys /home/devadmin/.ssh/
chown -R devadmin:devadmin /home/devadmin/.ssh
chmod 700 /home/devadmin/.ssh
chmod 600 /home/devadmin/.ssh/authorized_keys

Step 2: Cryptographic SSH Hardening (Disabling Password Authentication)

Password authentication allows brute-force dictionary bots to hammer your server continuously. Enforce cryptographic public key authentication only by editing /etc/ssh/sshd_config:

# Custom SSH Port (Optional but reduces automated bot noise by 95%)
Port 2222

# Permit root login restrictions
PermitRootLogin no

# Enforce public key authentication only
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no

# Disconnect idle sessions after 10 minutes
ClientAliveInterval 300
ClientAliveCountMax 2

# Disable X11 forwarding
X11Forwarding no

Test the SSH configuration before restarting the service:

# Verify syntax for errors
sudo sshd -t

# Restart SSH daemon safely
sudo systemctl restart ssh

Step 3: Configuring UFW (Uncomplicated Firewall)

Enforce a strict default-deny inbound network policy. Allow only essential web traffic (HTTP 80, HTTPS 443) and your designated SSH port:

# Set default firewall rules
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow SSH on your configured port (e.g. 2222 or 22)
sudo ufw allow 2222/tcp comment 'SSH Port'

# Allow standard web server traffic
sudo ufw allow 80/tcp comment 'HTTP Web'
sudo ufw allow 443/tcp comment 'HTTPS SSL Web'

# Enable firewall
sudo ufw enable

# Verify active status
sudo ufw status verbose

Step 4: Installing and Configuring Fail2ban Intrusion Prevention

Fail2ban dynamically monitors server authentication log files (such as /var/log/auth.log or Nginx access logs). When an IP address fails authentication multiple times within a short window, Fail2ban automatically modifies firewall rules to ban the offending IP address for a configurable duration.

# Install Fail2ban daemon
sudo apt install -y fail2ban

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

Edit /etc/fail2ban/jail.local to configure aggressive ban times:

[DEFAULT]
# Ban IP for 24 hours after repeated offenses
bantime = 86400

# Look back window of 10 minutes
findtime = 600

# Maximum failed attempts before banning
maxretry = 4

# Ignore local loopback
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
port = 2222
logpath = %(sshd_log)s
backend = systemd

Restart Fail2ban and verify active jail status:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Step 5: Enabling Automated Unattended Security Patches

Ensure that critical Linux kernel and package CVE vulnerabilities are patched automatically without requiring manual intervention:

# Install unattended upgrades package
sudo apt install -y unattended-upgrades

# Enable automated security patching
sudo dpkg-reconfigure -plow unattended-upgrades

VPS Security Hardening Checklist Summary

Hardening Step Security Impact Verification Command
Dedicated Sudo User Eliminates direct root exploits whoami && groups
Ed25519 SSH Keys Only Stops dictionary brute-force attacks ssh -o PubkeyAuthentication=no user@ip
UFW Firewall (Deny Inbound) Blocks unauthorized port scanning sudo ufw status verbose
Fail2ban Auto-Banning Dynamically blacklists abusive botnets sudo fail2ban-client status

Configuring Granular Fail2ban Jails for Nginx & Bad Bots

In addition to SSH protection, you can configure Fail2ban to block web vulnerability scanners and DDoS scrapers that attempt SQL injection or probe for non-existent admin URLs (e.g., /wp-login.php on non-WordPress sites or /phpmyadmin). Edit /etc/fail2ban/jail.local:

[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log

[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 3
findtime = 300
bantime = 86400

[nginx-limit-req]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
findtime = 600
bantime = 7200

Auditing Active Listening Network Ports with ss and lsof

Perform regular network port audits to ensure no unexpected processes are listening on public interfaces:

# Check all listening TCP/UDP sockets with process names
sudo ss -tulpn

# Inspect open file handles for network sockets
sudo lsof -i -P -n | grep LISTEN

Automated Security Alerting via Telegram / Discord Webhooks

Configure Fail2ban action scripts to post real-time alerts whenever a malicious IP address is banned:

# Test ban action notification
sudo fail2ban-client set sshd banip 198.51.100.1
sudo fail2ban-client status sshd

Deploy on Fortress-Grade CpanelFree Cloud Infrastructure

Protect your mission-critical applications with enterprise DDoS mitigation, automated firewall management, and 100% free hosting and VPS options.

Deploy Free Secure Hosting →

Deploy Fast, Reliable Web Hosting on CpanelFree

Get genuine cPanel control, unmetered NVMe SSD storage, and free AutoSSL at $0 cost forever.

Claim Free Hosting Account

About the author

Blog

DevOps architect and Linux sysadmin specializing in server hardening, OpenLiteSpeed performance optimization, and free cloud hosting infrastructure.

Leave a Comment