Short version: Keys only, no root login, narrow who can connect, and log enough to investigate. Do not hardcode ciphers; modern OpenSSH defaults are already strong—your job is policy and hygiene.
1) Access policy
# /etc/ssh/sshd_config — additive baseline
Protocol 2
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
UsePAM yes
LoginGraceTime 30
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowGroups sshusers # create/manage this group
# Optionally narrow by user or CIDR:
# Match Address 203.0.113.0/24
# AllowUsers kevin opsuser
2) Keys & strong identities
- Prefer
ed25519
or FIDO2 (security keys) for admins. ~/.ssh/authorized_keys
can restrict a key:from="1.2.3.4/32",no-agent-forwarding,no-pty
.
3) Hardening options (optional, tested first)
LogLevel VERBOSE # record key fingerprint on auth
PermitEmptyPasswords no
AllowTcpForwarding no
X11Forwarding no
AllowAgentForwarding no
# Banner /etc/issue.net # if your legal requires it
4) Testing & rollout
sudo sshd -t # syntax check
sshd -T -C user=kevin,host=server,addr=203.0.113.5 | less
sudo systemctl reload ssh || sudo systemctl reload sshd
Keep an emergency session open while reloading. Confirm new log entries and allowed users behave as intended.
5) Hygiene & review
- Ship
auth.log
/secure
to your SIEM; alarm on bursts. - Rotate admin keys quarterly; remove dormant accounts (>90 days).
- Use a bastion or SSM Session Manager; do not expose 22/TCP broadly.