SSH Cheatsheet
Hardening the Server
Use this SSH reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Configuration File
All settings go in /etc/ssh/sshd_config. After every change:
# Test config syntax before reloading sudo sshd -t # Reload (keep existing sessions alive) sudo systemctl reload sshd # Full restart (drops existing sessions) sudo systemctl restart sshd
Essential Hardening Settings
# /etc/ssh/sshd_config # Disable password auth — key-only PasswordAuthentication no ChallengeResponseAuthentication no KbdInteractiveAuthentication no # OpenSSH 8.7+ # Disable root login PermitRootLogin no # (or: PermitRootLogin prohibit-password — allows root with key only) # Disable empty passwords PermitEmptyPasswords no # Move off port 22 (reduces noise, not real security) Port 2222 # Restrict to specific users or groups AllowUsers alice bob AllowGroups sshusers # Limit authentication attempts MaxAuthTries 3 MaxSessions 5 MaxStartups 10:30:60 # start:rate:max half-open connections # Set an auth timeout LoginGraceTime 30 # seconds before unauthenticated connection dropped # Disable X11 and agent forwarding if not needed X11Forwarding no AllowAgentForwarding no AllowTcpForwarding no # Disable tunneled plaintext passwords in PAM UsePAM yes # keep yes; the above PasswordAuthentication no is what locks it # Banner (shown before auth — legal notice) Banner /etc/ssh/banner.txt # Log level LogLevel VERBOSE # or INFO; avoid QUIET in prod
Restrict to Modern Algorithms
# /etc/ssh/sshd_config — strong crypto only (OpenSSH 8.x+) KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
Run
ssh -Q kex,ssh -Q cipher,ssh -Q macto see what your client supports.
Host-Based Access Control
/etc/ssh/sshd_config Match blocks
# Allow password auth only from the internal network Match Address 10.0.0.0/8 PasswordAuthentication yes # Lock down a specific user further Match User deploy ForceCommand /usr/local/bin/deploy.sh PermitTTY no AllowTcpForwarding no
/etc/hosts.allow and /etc/hosts.deny (TCP Wrappers)
# /etc/hosts.allow sshd: 192.168.1.0/24 # /etc/hosts.deny sshd: ALL
Fail2ban (Rate-Limit Brute Force)
apt install fail2ban # Debian/Ubuntu # /etc/fail2ban/jail.local [sshd] enabled = true port = 2222 # match your Port directive maxretry = 5 bantime = 3600 findtime = 600
sudo systemctl enable --now fail2ban sudo fail2ban-client status sshd # check bans sudo fail2ban-client set sshd unbanip 1.2.3.4
Firewall (ufw / iptables)
# ufw — allow SSH on custom port, deny others ufw allow 2222/tcp ufw enable # iptables — rate-limit SSH connections iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
Two-Factor Authentication (TOTP)
# Install apt install libpam-google-authenticator # Run per user google-authenticator # /etc/pam.d/sshd — add at the top auth required pam_google_authenticator.so # /etc/ssh/sshd_config KbdInteractiveAuthentication yes AuthenticationMethods publickey,keyboard-interactive
Key Rotation Checklist
- Generate a new key pair (
ssh-keygen -t ed25519) - Add new public key to
authorized_keys - Test login with the new key
- Remove the old key from
authorized_keys - Delete or archive the old private key
Audit: Who Can Log In
# Check authorized keys for all users find /home -name authorized_keys -exec echo "=== {} ===" \; -exec cat {} \; cat /root/.ssh/authorized_keys 2>/dev/null # Check active SSH sessions who ss -tnp | grep :22 last | head -20 # Recent auth failures grep "Failed password\|Invalid user" /var/log/auth.log | tail -20 journalctl -u sshd --since "1 hour ago" | grep -i fail