I recently audited a production environment for a logistics firm based in Bengaluru and discovered over 45,000 failed SSH login attempts logged within a 72-hour window. The majority of these attempts originated from automated botnets targeting default configurations on port 22. This is not an isolated incident; it is the baseline reality for any internet-facing server in the Indian IP space. Relying on simple password authentication is no longer a viable strategy when faced with sophisticated credential stuffing and the recent discovery of critical vulnerabilities like CVE-2024-6387 (regreSSHion).
What is Security Hardening? An Overview of System Defense
Security hardening is the process of eliminating as many security risks as possible by reducing the system's vulnerability surface. When I approach a new server deployment, I treat every default setting as a potential liability. Hardening is not a one-time setup but a continuous state of configuration management designed to ensure that the system only performs its intended function and nothing more.
Defining the Concept of Attack Surface Reduction
Attack surface reduction involves identifying and disabling unnecessary services, ports, and protocols. In the context of a Linux server, this means:
- Removing unused packages like
telnet-serverorrsh. - Closing all network ports except those strictly required for the application.
- Restricting administrative access to specific IP ranges or VPN tunnels.
- Implementing strict filesystem permissions to prevent lateral movement.
The Role of Hardening in Modern Cybersecurity
Hardening acts as the first line of defense in a layered security model (Defense in Depth). Even if an attacker discovers a zero-day vulnerability in a specific application, a hardened OS environment can prevent them from escalating privileges or gaining persistence. We focus on "least privilege" principles, ensuring that even the sshd process runs with the minimum necessary permissions until authentication is successful.
Proactive vs. Reactive Security Measures
Reactive security involves responding to an incident after a breach has occurred—analyzing logs, rotating compromised keys, and restoring backups. Proactive security, which is where hardening sits, aims to prevent the breach entirely. By implementing Multi-Factor Authentication (MFA) and adopting secure SSH access for teams today, we prevent the credential-stuffing attack that would have occurred tomorrow.
What is SSH Hardening and Why is it Critical?
The Secure Shell (SSH) protocol is the de facto standard for remote server administration. Because it provides high-level access (often root or sudo-capable users), it is the primary target for attackers. Default configurations on many distributions are optimized for "ease of use" rather than "maximum security," leaving doors open for exploitation.
Understanding the Secure Shell (SSH) Protocol
SSH provides a secure, encrypted channel over an insecure network. It uses a client-server architecture where the SSH client initiates a connection to the SSH server (sshd). The protocol handles key exchange, encryption negotiation, and authentication. While the OpenSSH security model is robust, the authentication mechanism is often the weakest link.
Common Vulnerabilities in Default SSH Configurations
Out-of-the-box SSH setups often suffer from several critical flaws:
- PermitRootLogin: Many systems allow direct root login, giving attackers a known username to target.
- PasswordAuthentication: Enabling passwords allows for brute-force attacks.
- Weak Ciphers: Support for legacy ciphers like 3DES or RC4 can lead to man-in-the-middle attacks.
- Long Timeouts: Idle sessions that remain open indefinitely increase the window for session hijacking.
The Impact of Unauthorized Server Access
In the Indian context, unauthorized access to a server can lead to severe legal and financial consequences. Under the Digital Personal Data Protection (DPDP) Act 2023, organizations are mandated to implement "reasonable security safeguards" to protect personal data. A breach resulting from a lack of MFA on administrative interfaces can be interpreted as a failure of these safeguards, potentially leading to penalties reaching up to ₹250 crore. Beyond legalities, a compromised SSH gateway often serves as a launchpad for ransomware deployment within internal corporate networks.
Essential SSH Security Hardening Best Practices
Before implementing advanced Zero-Trust features, we must establish a baseline of security. I follow a strict checklist for every new node added to our infrastructure.
Disabling Root Login via SSH
Allowing root login is an unnecessary risk. Instead, we use a standard user account with sudo privileges. This creates an audit trail, as we can see which specific user performed an administrative action. To disable root login, edit /etc/ssh/sshd_config:
# Check current statusgrep "PermitRootLogin" /etc/ssh/sshd_config
Modify the configuration
sudo sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
Implementing SSH Key-Based Authentication
I strictly enforce Ed25519 keys for all users. RSA is legacy; Ed25519 offers better security with shorter key lengths and faster performance. When generating keys, I always use a high iteration count for the KDF (Key Derivation Function) to protect against offline brute-force attacks on the private key file.
# Generate a high-security Ed25519 key
ssh-keygen -t ed25519 -a 100 -C "admin@internal-gateway"
After generating the key, I transfer the public key to the server using ssh-copy-id. I never manually paste keys into authorized_keys to avoid permission errors (the file must be 600 and the .ssh directory 700).
Disabling Password-Based Authentication
Once key-based access is verified, I disable passwords entirely. This effectively kills all automated brute-force attempts. Even if an attacker has your password from a different data breach, they cannot gain access without your physical private key.
# In /etc/ssh/sshd_config
PasswordAuthentication no ChallengeResponseAuthentication no UsePAM yes
Changing the Default SSH Port (Port 22)
While this is "security by obscurity," it is highly effective at reducing log noise. Most automated scanners only target port 22. By moving SSH to a non-standard port (e.g., 2222 or 49152), you eliminate 99% of the "script kiddie" traffic, making it easier to spot targeted attacks in your logs.
# Change port to 2222sudo sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config
Remember to update your firewall!
sudo ufw allow 2222/tcp sudo ufw delete allow 22/tcp
Advanced SSH Security Configurations for Maximum Protection
A true Zero-Trust gateway requires more than just keys. We need to implement granular access controls and secondary verification layers.
Restricting Access with AllowUsers and DenyUsers
I never leave SSH access open to every account on the system. By using the AllowUsers directive, I create a whitelist. If a user is not on this list, they cannot log in, even if they have a valid key.
# Only allow specific admins
echo "AllowUsers sysadmin-rahul secops-priya" | sudo tee -a /etc/ssh/sshd_config
Configuring Idle Timeout Intervals to Prevent Session Hijacking
An unattended terminal is a security vulnerability. I configure the server to automatically terminate sessions that have been idle for more than 5 minutes. This is handled by ClientAliveInterval and ClientAliveCountMax.
# Terminate after 300 seconds of inactivity
ClientAliveInterval 300 ClientAliveCountMax 0
Enabling Two-Factor Authentication (2FA) for SSH
This is the cornerstone of our Zero-Trust gateway. We use the Google Authenticator PAM module to enforce a Time-based One-Time Password (TOTP). This ensures that even if a private key is stolen, the attacker still needs the physical mobile device of the administrator.
Step 1: Install the PAM Module
sudo apt update
sudo apt install libpam-google-authenticator -y
Step 2: Initialize TOTP for the User
Run the following command as the user who will be logging in. I use specific flags to enforce rate-limiting and prevent re-use of the same token.
google-authenticator -t -d -f -r 3 -R 30 -w 3
This command generates a QR code. Scan this into your authenticator app (Google Authenticator, Authy, or Bitwarden). It also provides emergency scratch codes—save these in a secure vault like a physical safe or an encrypted manager.
Step 3: Configure PAM
Edit /etc/pam.d/sshd. I place the authenticator requirement at the top to ensure it is evaluated correctly.
# Add this to the top of /etc/pam.d/sshd
auth required pam_google_authenticator.so nullok auth [success=done default=ignore] pam_unix.so obscure sha512
Step 4: Enforce Multi-Factor in SSHD
We need to tell SSH to require both the public key and the interactive keyboard (TOTP) prompt. This is a critical step that many tutorials miss.
# /etc/ssh/sshd_config
KbdInteractiveAuthentication yes UsePAM yes AuthenticationMethods publickey,keyboard-interactive
Limiting Maximum Authentication Attempts
To thwart sophisticated brute-force tools that try multiple keys in a single connection, I set MaxAuthTries to a low number. If a user fails three times, the connection is dropped and logged.
MaxAuthTries 3
Automating SSH Defense and Monitoring
Manual monitoring is impossible at scale. I rely on automated tools to detect and block malicious patterns in real-time.
Using Fail2Ban to Prevent Brute Force Attacks
Fail2Ban scans log files and bans IPs that show malicious signs, such as too many password failures. For a hardened gateway, it acts as a secondary safety net. I configure it to use iptables or nftables to drop traffic at the kernel level.
# Basic Fail2Ban jail for SSH
[sshd] enabled = true port = 2222 logpath = %(sshd_log)s backend = %(sshd_backend)s maxretry = 3 bantime = 1h findtime = 10m
Auditing SSH Logs for Suspicious Activity
I use journalctl to monitor login patterns. In an Indian enterprise environment, I look for logins outside of standard IST working hours or from unexpected geographic locations (e.g., a sudden login from an Eastern European IP for a Mumbai-based admin).
# Check for failed login attempts in the last hourjournalctl -u ssh --since "1 hour ago" | grep "Failed password"
Monitor successful logins in real-time
tail -f /var/log/auth.log | grep "Accepted"
Keeping OpenSSH Updated and Patched
Recent vulnerabilities like CVE-2024-6387 (regreSSHion) showed that even if your configuration is perfect, the code itself can have flaws. This specific CVE allowed unauthenticated remote code execution as root due to a signal handler race condition. I maintain a strict patching schedule, often using automated tools like unattended-upgrades specifically for security repositories.
# Check OpenSSH versionssh -V
Force update on Debian/Ubuntu
sudo apt update && sudo apt install --only-upgrade openssh-server
The XZ Utils Backdoor (CVE-2024-3094)
This was a sophisticated supply-chain attack targeting the sshd daemon via liblzma. It highlighted why we must monitor not just our code, but our dependencies. I now use tools like lynis to perform regular security audits of the entire system stack to catch anomalies in linked libraries.
Building a Robust SSH Security Strategy
A hardened SSH gateway is the "front door" to your infrastructure. If this door is weak, the rest of your internal security measures—firewalls, VLANs, and encryption at rest—can be bypassed. By moving to a Zero-Trust model where every connection requires both a cryptographic key and a time-sensitive token, we significantly raise the cost of an attack.
Summary of SSH Hardening Steps
| Security Control | Action Taken | Risk Mitigated |
|---|---|---|
| Root Login | PermitRootLogin no |
Targeted root brute-force |
| Authentication Type | Ed25519 Keys Only | Credential stuffing |
| Secondary Auth | Google Authenticator (TOTP) | Stolen private key exploitation |
| Port Configuration | Move to non-standard port | Automated botnet scanning |
| Access Control | AllowUsers whitelist |
Unauthorized account access |
The Importance of Regular Security Audits
Configurations drift over time. An admin might temporarily enable password auth for a vendor and forget to disable it. I recommend a monthly automated audit using the following command to check for configuration regressions:
# Test configuration for syntax errors before reloadingsudo sshd -t
Run a security scan with Lynis
sudo lynis audit system --tests-from-group ssh
In the evolving threat landscape of 2024, "good enough" security is an invitation for disaster. By implementing MFA and following the hardening steps outlined above, you ensure that your infrastructure remains resilient against both automated scripts and targeted intrusions. The next step in this journey is implementing a SSH Certificate Authority (CA) to eliminate the need for authorized_keys management entirely across large-scale fleets.
# Next Command: Investigate SSH CA setup
ssh-keygen -f user_ca -b 4096
