Implementing JSON-LD Schema Markup on Custom Blogger Templates for Rich Snippets
Linux VPS Security Hardening Guide: SSH, Firewall, and Access Control
Written by a senior cybersecurity engineer specializing in cloud infrastructure defense and incident response.
Default Linux VPS configurations are a recurring root cause in incident response engagements: Password-based SSH authentication open to the entire internet remains one of the most common initial access vectors observed across ransomware post-mortems and honeypot telemetry alike. Automated scanners typically attempt credential access within minutes of a new instance going live. A rigorous hardening baseline covering SSH, the host firewall, and audit logging closes this specific class of intrusion before it starts. This guide walks through that baseline the way I configure it on every production VPS I stand up.
SSH Hardening: Eliminating the Most Exploited Attack Surface
The SSH daemon is the primary administrative interface for any Linux VPS and the most aggressively scanned service on the public internet. Relying on password authentication for SSH runs counter to NIST SP 800-53 Rev 5 Control AC-17 (Remote Access), which calls for strong authentication on remote administrative channels. When auditing a new cloud environment, /etc/ssh/sshd_config is the first file I inspect. Password-based access maps directly to MITRE ATT&CK T1110.001 (Password Guessing), giving automated botnets a trivial path to initial access.
Eradicating Password Authentication
Disable password authentication entirely and enforce Ed25519 public-key cryptography. Ed25519 offers strong security guarantees with better performance than legacy RSA keys of comparable strength. Also disable direct root login: it bypasses individual accountability and violates least-privilege principles, since every administrative action should be traceable to a named account via sudo.
# /etc/ssh/sshd_config modifications
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
AuthenticationMethods publickey
MaxAuthTries 3
LoginGraceTime 30
Restricting MaxAuthTries and LoginGraceTime degrading the efficiency of brute-force tools, which rely on high-volume, rapid-fire connection attempts. Limiting attempts and grace time raises the attacker's operational cost.
Add Multi-Factor Authentication
Key-based auth alone does not protect against a stolen private key. Layering TOTP-based MFA on top of public-key authentication, for example via libpam-google-authenticator, closes that gap and is increasingly expected in compliance frameworks that reference NIST SP 800-63B.
Actionable takeaway: Disable SSH password authentication, enforce Ed25519 key-based access, disable direct root login, restrict authentication attempts, and add MFA as a second factor.
Perimeter Defense: Host-Based Network Segmentation
A host-based firewall is your final checkpoint against unauthorized network traffic. Cloud-provider security groups filter traffic externally, but the internal VPS firewall protects the host even if that external layer is misconfigured. This is consistent with ISO/IEC 27001:2022 Annex A.8.20 (Network Security). UFW (Uncomplicated Firewall) is a reliable choice on Ubuntu and Debian systems for its straightforward syntax and stateful packet inspection.
The Deny-by-Default Paradigm
The most important firewall rule is to deny all inbound traffic by default and open only the ports a service actually needs. For a standard web server, that means TCP 443 (HTTPS) and TCP 80 (HTTP). SSH (TCP 22) should be restricted to specific, trusted IP addresses whenever possible.
# Reset and configure UFW baseline
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 443/tcp
sudo ufw allow 80/tcp
# Restrict SSH to a specific trusted IP range
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp
sudo ufw enable
Note: If your administrative IPs are dynamic and static IP restriction is not feasible, use rate limiting instead of the IP-based allow rule above, not in addition to it, to avoid conflicting rules on the same port:
sudo ufw limit 22/tcp
Kernel-Level Network Hardening
UFW controls what traffic reaches your services; sysctl settings control how the kernel's network stack behaves under attack. At minimum, disable IP forwarding on non-router hosts, enable SYN flood protection, and disable ICMP redirects:
# /etc/sysctl.d/99-hardening.conf
net.ipv4.ip_forward = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.rp_filter = 1
Actionable takeaway: Configure the host firewall to deny all inbound traffic by default, explicitly allow only required ports, restrict SSH to known IPs or rate-limit it, and apply kernel-level network hardening via sysctl.
Intrusion Prevention and Kernel-Level Audit Logging
Access control and firewalls keep most threats out, but once an attacker breaches the perimeter, logging and auditing become your primary detection mechanism. Attackers routinely attempt to cover their tracks, which maps to MITRE ATT&CK T1070.002 (Clear Linux or Mac System Logs). Storing logs only on the VPS itself is a critical failure point: an attacker with root access can delete or alter local log files.
Automated Brute-Force Mitigation
Deploy Fail2ban on every public-facing VPS. It monitors authentication logs and dynamically updates firewall rules to block IPs exhibiting malicious behavior, providing an automated, active defense layer against credential stuffing.
# /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
Granular Auditing with auditd
Standard logging often misses the nuances of privilege escalation. Deploy the Linux Audit Daemon (auditd) to track system calls and file access at the kernel level. Configuring rules to monitor sudo execution and changes to critical configuration files creates a high-fidelity alerting mechanism, supporting NIST SP 800-53 Rev 5 Control AU-6 (Audit Record Review, Analysis, and Reporting).
# /etc/audit/rules.d/audit.rules
# Monitor sudoers file modifications
-w /etc/sudoers -p wa -k sudo_changes
-w /etc/sudoers.d/ -p wa -k sudo_changes
# Monitor user and group modifications
-w /etc/passwd -p wa -k identity_changes
-w /etc/group -p wa -k identity_changes
# Monitor execution of privileged commands
-a always,exit -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged_exec
Configure rsyslog to forward audit logs in real time to a remote, centralized SIEM. This preserves forensic evidence even if the VPS itself is destroyed or wiped by an attacker.
Mandatory Access Control
Firewalls and SSH hardening control access to the host; AppArmor (default on Ubuntu) or SELinux (default on RHEL/CentOS) constrain what a compromised process can do once it is running. Confirm AppArmor is active and enforcing on Ubuntu with:
sudo aa-status
Keep the Attack Surface Patched
None of the above matters if the system runs unpatched software with known CVEs. Enable automatic security updates:
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
Actionable takeaway: Deploy Fail2ban to block brute-force attempts, configure auditd to track privilege escalation, forward logs to a remote SIEM, enforce AppArmor or SELinux, and enable automatic security patching.
Vulnerability-to-Mitigation Mapping
The table below maps common default VPS weaknesses to the specific hardening controls that neutralize them.
| Default VPS Vulnerability | Associated Attack Vector | Hardening Mitigation Control | Framework Reference |
|---|---|---|---|
| Password-based SSH authentication enabled | Brute-force and credential stuffing | Enforce Ed25519 key-based authentication + MFA | NIST SP 800-53 Rev 5 (AC-17) |
| Direct root login permitted | Privilege escalation, untracked admin actions | Disable root login; enforce sudo with individual accounts | ISO 27001:2022 (A.8.2) |
| Permissive inbound firewall rules | Unauthorized service access, lateral movement | Implement deny-by-default UFW policies | ISO 27001:2022 (A.8.20) |
| Local-only log storage | Anti-forensics, log tampering post-compromise | Forward logs to a remote, immutable SIEM | NIST SP 800-53 Rev 5 (AU-9) |
| Unpatched packages / no MAC enforcement | Known-CVE exploitation, post-exploit lateral movement | Automatic updates + AppArmor/SELinux enforcement | NIST SP 800-53 Rev 5 (SI-2, AC-6) |

Join the conversation