How to Hardened SSH: Require Both Key and Password Authentication for Secure Server Access


2 views

SSH offers multiple authentication mechanisms, but most administrators choose between:

  • Password authentication (weakest but simplest)
  • Public key authentication (stronger but single-factor)
  • Multi-factor authentication (strongest configuration)

The ideal approach combines public key authentication with password verification for defense in depth.

Edit your /etc/ssh/sshd_config file with these settings:

# Disable password-only authentication
PasswordAuthentication no

# Enable public key authentication
PubkeyAuthentication yes

# Require both key AND password
AuthenticationMethods publickey,password

After saving, reload SSH with sudo systemctl reload sshd or sudo service ssh reload.

For your DynDNS whitelist idea, create a script (/usr/local/bin/ssh_filter.sh):

#!/bin/bash
ALLOWED_HOSTS=("user1.dyndns.org" "user2.dyndns.org")

resolve_ip() {
  dig +short "$1" | tail -n1
}

CLIENT_IP=${SSH_CONNECTION%% *}
CLIENT_HOST=$(dig +short -x "$CLIENT_IP" | sed 's/\.$//')

for host in "${ALLOWED_HOSTS[@]}"; do
  if [[ "$(resolve_ip "$host")" == "$CLIENT_IP" ]] || [[ "$CLIENT_HOST" == "$host" ]]; then
    exit 0
  fi
done

logger "SSH login attempted from unauthorized host: $CLIENT_IP"
exit 1

Then add to sshd_config:

UsePAM yes
ForceCommand /usr/local/bin/ssh_filter.sh

Consider these supplementary measures:

  • Change default SSH port: Port 2222
  • Limit user access: AllowUsers admin1 admin2
  • Enable fail2ban for brute force protection
  • Set login grace time: LoginGraceTime 60
  • Disable root login: PermitRootLogin no

Always test changes using a secondary session:

ssh -vvv user@yourserver.com -p 2222

Keep another terminal open as root to revert changes if needed:

sudo nano /etc/ssh/sshd_config
sudo systemctl restart sshd

Combining public key authentication with password verification creates a robust two-factor security layer. This approach requires both:

  • Something you have (the private key)
  • Something you know (the password)

Edit your sshd_config file (usually located at /etc/ssh/sshd_config):

# Enable public key authentication
PubkeyAuthentication yes

# Require both key and password
AuthenticationMethods publickey,password

# Additional security settings
PasswordAuthentication yes
PermitEmptyPasswords no
ChallengeResponseAuthentication no

For your DynDNS whitelist idea, combine these approaches:

# In /etc/hosts.allow
sshd: .dyndns.example.com

# Or in sshd_config
Match Host *.dyndns.example.com
    AllowUsers your_username

Consider these additional measures:

# Change default port
Port 2222

# Limit login attempts
MaxAuthTries 3

# Disable root login
PermitRootLogin no

# Implement fail2ban
[ssh]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3

When implementing key-based authentication:

# Generate secure keys
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/server_access

# Restrict key usage in ~/.ssh/authorized_keys
from="*.dyndns.example.com",command="/bin/restricted-shell" ssh-ed25519 AAAAC3Nz...

Remember to restart sshd after configuration changes:

sudo systemctl restart sshd