SSH Cheatsheet
Hardening the Server
Use this SSH reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
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