# Edit /etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
# Restart SSH service
systemctl restart sshd
Disabling password authentication forces the use of SSH keys, which are more secure and resistant to brute force attacks.
# Edit /etc/ssh/sshd_config
PermitRootLogin no
# Restart SSH service
systemctl restart sshd
Disabling root login prevents direct root access, forcing attackers to compromise a regular user account first and then escalate privileges.
# Install Google Authenticator
apt-get install libpam-google-authenticator
# Edit /etc/pam.d/sshd
auth required pam_google_authenticator.so
# Edit /etc/ssh/sshd_config
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
# Restart SSH service
systemctl restart sshd
# Configure Google Authenticator for each user
google-authenticator
Multi-factor authentication adds an additional layer of security by requiring something you have (SSH key) and something you know (TOTP code).
# Edit /etc/ssh/sshd_config
AllowUsers user1 user2
DenyUsers user3 user4
AllowGroups sshusers admins
DenyGroups guests
# Restart SSH service
systemctl restart sshd
Restricting which users can access SSH limits the attack surface and helps prevent unauthorized access.
# Generate Ed25519 key (recommended)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N "strong_passphrase"
# Generate RSA key (if Ed25519 is not supported)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N "strong_passphrase"
Using strong key types and sizes helps protect against cryptographic attacks and ensures key security.
# Change passphrase for existing key
ssh-keygen -p -f ~/.ssh/id_ed25519
Using strong passphrases helps protect private keys from unauthorized use if they are compromised.
# Start SSH agent
eval $(ssh-agent)
# Add key to agent with timeout (3600 seconds = 1 hour)
ssh-add -t 3600 ~/.ssh/id_ed25519
Using SSH agent with timeouts helps manage passphrases securely while limiting the window of opportunity for attackers.
# Generate new key
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new -N "strong_passphrase"
# Add new key to authorized_keys on remote servers
ssh-copy-id -i ~/.ssh/id_ed25519_new.pub user@remote-server
# Test new key
ssh -i ~/.ssh/id_ed25519_new user@remote-server
# Remove old key from authorized_keys on remote servers
ssh user@remote-server "grep -v 'old-key-content' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.new && mv ~/.ssh/authorized_keys.new ~/.ssh/authorized_keys"
# Replace old key with new key
mv ~/.ssh/id_ed25519_new ~/.ssh/id_ed25519
mv ~/.ssh/id_ed25519_new.pub ~/.ssh/id_ed25519.pub
Implementing key rotation helps limit the impact of key compromise and ensures ongoing key security.
# Generate key on YubiKey
ssh-keygen -t ecdsa-sk -f ~/.ssh/id_ecdsa_sk
# Add key to authorized_keys on remote servers
ssh-copy-id -i ~/.ssh/id_ecdsa_sk.pub user@remote-server
Using hardware security keys helps protect private keys from extraction and provides physical security for authentication.
# ~/.ssh/config example
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
HashKnownHosts yes
IdentitiesOnly yes
AddKeysToAgent yes
AddKeysToAgent 1h
Host production
HostName production.example.com
User admin
Port 2222
IdentityFile ~/.ssh/id_ed25519_production
Host staging
HostName staging.example.com
User developer
Port 2222
IdentityFile ~/.ssh/id_ed25519_staging
ProxyJump bastion
Using SSH config files helps manage connections securely and consistently.
# Generate CA key
ssh-keygen -t ed25519 -f ca_key
# Sign user key
ssh-keygen -s ca_key -I user_id -n user1 -V +52w id_ed25519.pub
# Configure server to trust CA
echo "@cert-authority * $(cat ca_key.pub)" >> /etc/ssh/ssh_known_hosts
# Configure server to accept certificates
echo "TrustedUserCAKeys /etc/ssh/ca_key.pub" >> /etc/ssh/sshd_config
echo "AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u" >> /etc/ssh/sshd_config
# Create authorized principals file
mkdir -p /etc/ssh/auth_principals
echo "user_id" > /etc/ssh/auth_principals/user1
# Restart SSH service
systemctl restart sshd
Using SSH certificates helps manage SSH keys at scale and provides centralized control over authentication.
# SSH through jump host
ssh -J jumphost user@target
# Configure SSH config file
Host target
HostName target.internal
User user
ProxyJump jumphost
Host jumphost
HostName bastion.example.com
User jumpuser
IdentityFile ~/.ssh/id_ed25519_jump
Using jump hosts or bastion servers helps limit direct access to sensitive systems and provides a centralized point for access control and auditing.
# Edit ~/.ssh/authorized_keys
command="rsync --server -logDtpre.iLsfx . /backup",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... backup@example.com
Restricting SSH commands helps limit what users can do with their SSH access, reducing the risk of unauthorized activities.
# Install auditd
apt-get install auditd
# Configure auditd to monitor SSH
cat << EOF > /etc/audit/rules.d/ssh.rules
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/ssh/ssh_config -p wa -k ssh_config
-w /root/.ssh -p wa -k root_ssh
-w /var/log/auth.log -p wa -k auth_log
EOF
# Restart auditd
systemctl restart auditd
Implementing SSH auditing and monitoring helps detect and investigate security incidents by providing detailed information about SSH-related activities.
# Install ssh-audit
git clone https://github.com/jtesta/ssh-audit.git
cd ssh-audit
# Audit SSH server
./ssh-audit.py localhost
# Audit SSH server with policy
./ssh-audit.py -P /path/to/policy.txt localhost
Using SSH audit tools helps identify security issues and compliance gaps in SSH configurations.