10 Proven SSH Hardening Techniques to Stop Bruteforce Attacks

This guide shares ten battle‑tested methods for hardening SSH, from changing the default port and disabling root login to using key authentication, fail2ban, IP whitelisting, two‑factor authentication, bastion hosts, and automated monitoring, helping you build a multilayered defense against brute‑force attacks.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
10 Proven SSH Hardening Techniques to Stop Bruteforce Attacks

Introduction

At 3 a.m. a server’s CPU spiked to 100 % and the /var/log/secure file grew to several gigabytes filled with failed SSH login attempts, revealing a brute‑force attack. Statistics show that over 80 % of server compromises start with SSH password‑guessing, with millions of automated scripts scanning port 22 daily. This article presents ten practical SSH hardening methods that have protected hundreds of servers from intrusion for three years.

SSH Brute‑Force Threat Analysis

Typical attacks exhaust a server with 3 000–8 000 login attempts per day, often from foreign IPs (≈70 %). Peak activity occurs between 02:00–04:00 a.m. Once a password is cracked, malware can be installed within 12 minutes. Attack trends include distributed botnets, smart dictionaries, low‑frequency “time‑gap” attacks, and 0‑day exploits.

10 SSH Hardening Methods

Method 1: Change the Default SSH Port

Changing the port reduces automated scans by >95 %.

# Edit /etc/ssh/sshd_config
Port 23456  # original: Port 22
semanage port -a -t ssh_port_t -p tcp 23456
firewall-cmd --permanent --add-port=23456/tcp
firewall-cmd --reload
systemctl restart sshd
# Test
ssh -p 23456 user@server_ip

Notes: Verify the new port is free ( netstat -tulnp | grep 23456) and keep a backup session.

Method 2: Disable Direct Root Login

# /etc/ssh/sshd_config
PermitRootLogin no
systemctl restart sshd

Create regular admin accounts and use sudo su - for privilege escalation.

Method 3: Use SSH Key Authentication

# Generate key pair
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_server
# Copy public key to server
ssh-copy-id -i ~/.ssh/id_ed25519_server.pub -p 23456 user@server_ip
# Server side
vim /etc/ssh/sshd_config
PubkeyAuthentication yes
PasswordAuthentication no
systemctl restart sshd

Prefer Ed25519 keys; rotate every 3–6 months.

Method 4: Install Fail2Ban

# Install
yum install -y epel-release fail2ban fail2ban-systemd
# Create jail
cat > /etc/fail2ban/jail.d/sshd.local <<EOF
[sshd]
enabled = true
port = 23456
filter = sshd
logpath = /var/log/secure
maxretry = 3
findtime = 600
bantime = 3600
ignoreip = 127.0.0.1/8 192.168.1.0/24
EOF
systemctl enable fail2ban
systemctl start fail2ban

Configure aggressive rules with incremental ban times if needed.

Method 5: IP Whitelisting

# /etc/ssh/sshd_config
AllowUsers [email protected].* [email protected]/24
# Or using TCP wrappers
# /etc/hosts.allow
sshd: 192.168.1.0/24
sshd: 203.0.113.0/24
# /etc/hosts.deny
sshd: ALL

Method 6: Two‑Factor Authentication (2FA)

# Install Google Authenticator
yum install -y google-authenticator qrencode
# Configure for user
google-authenticator
# PAM configuration
auth required pam_google_authenticator.so
# SSH config
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
systemctl restart sshd

Method 7: Limit Concurrent Connections

# /etc/ssh/sshd_config
MaxStartups 3:50:10   # start:rate:full
MaxSessions 3
MaxAuthTries 3
LoginGraceTime 30

Method 8: Session Timeout

# /etc/ssh/sshd_config
ClientAliveInterval 300
ClientAliveCountMax 2
# Shell timeout
echo "export TMOUT=900" >> /etc/profile.d/timeout.sh
chmod +x /etc/profile.d/timeout.sh

Method 9: Log Monitoring & Alerts

# rsyslog configuration
:programname, isequal, "sshd" /var/log/ssh.log
& stop
*.* @@logserver.company.com:514
# Simple alert script (ssh_monitor.sh)
#!/bin/bash
LOG_FILE="/var/log/secure"
ALERT_EMAIL="[email protected]"
WEBHOOK_URL="https://hooks.slack.com/services/xxx"
# ... (parses failures, sends email/slack, auto‑bans IP)

Method 10: Use a Bastion (Jump) Host

# Deploy JumpServer via Docker
curl -sSL https://github.com/jumpserver/jumpserver/releases/download/v2.28.0/quick_start.sh | bash
cd /opt/jumpserver
./jmsctl.sh start
# Access via http://ip:80 (default admin/admin)

Building a Multi‑Layer Defense

Combine network firewalls, application firewalls (Fail2Ban), strong authentication, least‑privilege authorization, and continuous audit. Example layered diagram:

Internet → [Network Firewall] → [App Firewall] → [Auth Layer] → [Authorization] → [Audit]

Performance and Optimization

Hardening measures add varying overhead. Changing the port adds negligible latency; key authentication adds 5‑10 ms and ~2 MB memory; 2FA adds 2‑3 s latency and ~5 MB memory; Fail2Ban consumes ~50 MB; a bastion adds 100‑200 ms latency and ~200 MB memory. Optimize SSH client config for connection reuse and disable DNS lookups on the server.

# ~/.ssh/config
Host *
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h-%p
    ControlPersist 600
    ServerAliveInterval 60
    Compression yes
# Server side
UseDNS no
GSSAPIAuthentication no
Compression delayed

Automation Practices

Use Ansible to apply hardening across fleets.

# ssh_hardening.yml
---
- name: SSH Security Hardening
  hosts: all
  become: yes
  vars:
    ssh_port: 23456
    allowed_users:
      - sysadmin
      - developer
  tasks:
    - name: Backup ssh config
      copy:
        src: /etc/ssh/sshd_config
        dest: /etc/ssh/sshd_config.bak
        remote_src: yes
    - name: Configure SSH
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: "{{ item.regexp }}"
        line: "{{ item.line }}"
      loop:
        - { regexp: '^#?Port', line: 'Port {{ ssh_port }}' }
        - { regexp: '^#?PermitRootLogin', line: 'PermitRootLogin no' }
        - { regexp: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
        - { regexp: '^#?PubkeyAuthentication', line: 'PubkeyAuthentication yes' }
    - name: Install Fail2Ban
      package:
        name: fail2ban
        state: present
    - name: Configure Fail2Ban
      template:
        src: jail.local.j2
        dest: /etc/fail2ban/jail.local
      notify: restart fail2ban
    - name: Deploy SSH keys
      authorized_key:
        user: "{{ item }}"
        key: "{{ lookup('file', 'keys/{{ item }}.pub') }}"
      loop: "{{ allowed_users }}"
  handlers:
    - name: restart sshd
      systemd:
        name: sshd
        state: restarted
    - name: restart fail2ban
      systemd:
        name: fail2ban
        state: restarted

Troubleshooting & Disaster Recovery

Common issues:

Cannot connect after config change: Use console access, validate syntax with sshd -t, check logs via journalctl -u sshd -n 50, restore backup config.

Forgot custom port: Find listening port with netstat -tlnp | grep sshd or ss -tlnp | grep sshd, inspect /etc/ssh/sshd_config.

Key authentication fails: Ensure correct permissions ( chmod 700 ~/.ssh, chmod 600 ~/.ssh/authorized_keys), enable verbose client logs ( ssh -vvv), review server logs.

Disaster recovery steps include booting into single‑user mode, restoring a default sshd_config, cleaning suspicious files, and rebooting.

Compliance Checklist

Disable SSH protocol 1.

Enforce strong ciphers (AES‑256, SHA‑256).

Use keys ≥2048 bits (RSA) or ≥256 bits (ECDSA).

Lock accounts after 5 failed attempts (30 min).

Enforce password complexity (≥12 characters, mixed case, numbers, symbols).

Session timeout ≤15 min.

Retain audit logs ≥6 months.

Quarterly security assessments.

Conclusion

Implementing these ten SSH hardening techniques can reduce the risk of compromise by over 99 %, but security is an ongoing process. Continuously monitor, audit, and update your defenses to stay ahead of attackers.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

SSHbrute forceHardening
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.