How to Configure SSH Security on a Debian System

How to Configure SSH Security on a Debian System

This guide explains the principles, reasoning, and layered approach to securing SSH on modern Debian (Debian 13 “Trixie” in 2026). The focus is on understanding why each control matters, the threat model it addresses, and realistic trade-offs — rather than just a checklist of settings.

SSH remains the #1 exposed service on internet-facing Linux servers in 2026. Most compromises still come from automated brute-force, credential stuffing, weak key management, or unrestricted root login. Debian’s default OpenSSH configuration is already reasonably sane (Protocol 2 only, modern ciphers, KbdInteractiveAuthentication no), but it is not production-hardened for public exposure.

1. Threat Model & Layered Defense Strategy

Effective SSH security follows defense-in-depth:

Layer Primary Threat Mitigated Priority (2026) Effectiveness vs Effort
Key-based auth only Brute-force, password reuse Critical Very high
Disable root login Direct root compromise (single point failure) Critical Very high
Fail2Ban / rate limiting Automated scanning & brute-force High High
Non-standard port Reduces automated bot noise (obscurity) Medium Medium
Restrict users/groups Limit blast radius if key is stolen High High
Idle timeout & keepalive Forgotten sessions, hijacking Medium Medium
Modern crypto + logging Weak algorithms, post-compromise visibility Medium Medium
MFA / PAM modules Stolen key + password High (if exposed) High (added friction)
nftables / firewall Block unauthorized source IPs High High

Core principle: Make password auth impossible → force asymmetric crypto → add behavioral protection → restrict who/what can connect.

2. Foundational Steps (Do These First)

  1. Use a non-root sudo user All remote access should happen through a regular user with sudo privileges. Direct root login over SSH is almost never justified in 2026.

  2. Generate strong Ed25519 keys (preferred over RSA-4096) Ed25519 offers better security, smaller keys, and faster performance. On your client machine:

    Reasoning: Ed25519 is side-channel resistant, uses modern elliptic curve, and is the de-facto standard in 2026.

  3. Copy the public key to the server (before disabling passwords!)

    Test this connection works perfectly before proceeding.

3. Hardening /etc/ssh/sshd_config (Recommended Production Settings)

Edit /etc/ssh/sshd_config (or better: use drop-in files in /etc/ssh/sshd_config.d/ for cleaner management).

Essential changes (2026 best practices):

  • Authentication
    • PermitRootLogin no → Eliminates the single biggest privilege target.
    • PasswordAuthentication no → After keys are confirmed working — blocks all password attempts.
    • PubkeyAuthentication yes (usually already default)
    • KbdInteractiveAuthentication no (Debian default in Trixie)
    • PermitEmptyPasswords no
  • Access Control
    • AllowUsers admin@trusted.ip.address (strongest — IP restrict) or AllowGroups sudo wheel → Explicitly list who can log in.
    • MaxAuthTries 3 or 4 → Limits guessing attempts per connection.
  • Session Management
    • ClientAliveInterval 300ClientAliveCountMax 0 → Disconnects idle clients after ~5 minutes.
    • LoginGraceTime 30 → Shortens grace period for slow authenticators.
  • Port & Listening
    • Port 2222 (or any high port >1024) → Reduces log noise from bots scanning port 22 (security by obscurity — not a real control, but useful noise reduction).
  • Crypto (usually already good in Debian 13)
    • Prefer defaults unless you have very specific compliance needs.

    • Optional explicit list (if paranoid):

      Reasoning: Debian/OpenSSH in Trixie already disables weak ciphers (3DES, Blowfish, etc.) and prefers curve25519-sha256/chacha20-poly1305.

4. Apply & Test Safely

Always follow this sequence:

  1. Backup original config: cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
  2. Edit config (prefer drop-in file: /etc/ssh/sshd_config.d/50-hardening.conf)
  3. Test syntax: sshd -t
  4. Open a second terminal/session and test new connection with keys
  5. Reload: systemctl reload ssh (or sshd service)
  6. If locked out → use console access (VPS panel, KVM, physical) to revert

5. Behavioral Protection: Fail2Ban (Strongly Recommended)

Install and enable:

Bash
apt install fail2ban
systemctl enable --now fail2ban

Default [sshd] jail is usually sufficient. It bans IPs after 3–5 failed attempts (configurable in /etc/fail2ban/jail.local).

Why it still matters in 2026: Even with password auth off, bots attempt old exploits or probe for weak keys. Fail2Ban reduces noise and blocks scanners.

6. Firewall Layer (nftables – Debian Default)

Ensure SSH port is explicitly allowed:

  • Input chain policy drop
  • Accept established/related
  • Accept tcp dport <your-ssh-port> (e.g. 2222)
  • Optional: rate limit new connections per IP

7. Optional Advanced Layers (Pick According to Exposure)

  • MFA with Google Authenticator (PAM) → extra factor after key
  • Certificate-based auth → centralized key management (enterprise)
  • Restrict ciphers/MACs/KexAlgorithms → only if auditing tools demand it
  • Log monitoring → send auth logs to central SIEM or use log2ram + alerts

8. Realistic 2026 Checklist Summary

  1. Non-root user with sudo → all access through this account
  2. Ed25519 keys → copy public key, test login
  3. PasswordAuthentication no + PermitRootLogin no
  4. Restrict via AllowUsers/AllowGroups
  5. Fail2Ban enabled
  6. nftables allows only necessary port
  7. Idle timeout configured
  8. Test from second session → reload → verify logs

Bottom line: In 2026, key-only + no root + Fail2Ban + firewall stops ~99% of SSH attacks on Debian servers. The remaining risk is almost always stolen private keys or compromised client machines — protect your laptop and use strong key passphrases.

Configure deliberately, test ruthlessly, monitor logs regularly. SSH security is not a one-time task — it is ongoing hygiene.

Fast • Reliable • Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!