SSH Hardening and Key Management
Chapter 32: SSH Hardening and Key Management
Section titled “Chapter 32: SSH Hardening and Key Management”Mastering SSH Security for Production Environments
Section titled “Mastering SSH Security for Production Environments”Why This Matters in DevOps/SRE
Section titled “Why This Matters in DevOps/SRE”SSH is the primary access method for servers in production:
SSH for DevOps/SRE+------------------------------------------------------------------+| || Server Access: || +----------------------------------------------------------+ || | All production servers accessed via SSH | || | CI/CD pipelines use SSH for deployments | || | Ansible/Terraform use SSH for connectivity | || | Jump hosts/bastions → Single entry point | || +----------------------------------------------------------+ || || Security Hardening: || +----------------------------------------------------------+ || | Key-based auth only → No passwords | || | Disable root login → Prevent direct root access | || | Use non-standard port → Reduce attack surface | || | Fail2Ban → Block brute force attacks | || +----------------------------------------------------------+ || || Automation: || +----------------------------------------------------------+ || | SSH keys → Deploy keys via Ansible | || | SSH agent → Avoid re-entering passphrases | || | ProxyJump → Bastion host access | || | Config management → Centralized SSH config | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Practical Impact:
- Secure remote access to all production systems
- Enable secure automation without password prompts
- Protect against brute force attacks
- Comply with security policies (key-based auth only)
33.1 Understanding SSH Protocol
Section titled “33.1 Understanding SSH Protocol”SSH Protocol Architecture
Section titled “SSH Protocol Architecture” SSH Protocol Layers+------------------------------------------------------------------+| || SSH Application Layer || +-------------------------------------------------------------+ || | sftp, scp, ssh-add, ssh-keygen, ssh-agent | || +-------------------------------------------------------------+ || | || v || SSH Connection Protocol || +-------------------------------------------------------------+ || | - Channel management | || | - Session multiplexing | || | - X11 forwarding | || | - Agent forwarding | || | - TCP forwarding | || +-------------------------------------------------------------+ || | || v || SSH Authentication Protocol || +-------------------------------------------------------------+ || | - publickey (RSA, ECDSA, Ed25519) | || | - password | || | - keyboard-interactive | || | - hostbased | || +-------------------------------------------------------------+ || | || v || SSH Transport Layer Protocol || +-------------------------------------------------------------+ || | - Server authentication | || | - Key exchange (DH, ECDH) | || | - Encryption (AES, ChaCha20) | || | - MAC (HMAC, Poly1305) | || | - Compression (zlib) | || +-------------------------------------------------------------+ || | || v || TCP/IP Layer || |+------------------------------------------------------------------+SSH Protocol Versions
Section titled “SSH Protocol Versions” SSH Protocol Comparison+------------------------------------------------------------------+| || SSH Version 1 || +----------------------------------------------------------+ || | - Deprecated due to security vulnerabilities | || | - Single encryption tunnel | || | - Vulnerable to man-in-the-middle attacks | || | - No integrity checking for channels | || | - Still exists on some legacy systems | || +----------------------------------------------------------+ || || SSH Version 2 || +----------------------------------------------------------+ || | - Current standard (RFC 4251-4256) | || | - Multiple encryption channels | || | - Strong key exchange algorithms | || | - Better integrity checking (MAC) | || | - Modular design | || | - Extension support | || +----------------------------------------------------------+ || || Key Differences: || +----------------------------------------------------------+ || | Feature | SSHv1 | SSHv2 | || | ---------------|------------|----------------------------| || | Encryption | Single | Multiple channels | || | Key Exchange | Fixed | Modular (diffie-hellman) | || | Integrity | Weak | HMAC | || | Security | Weak | Strong | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+33.2 SSH Hardening Strategies
Section titled “33.2 SSH Hardening Strategies”Comprehensive sshd_config
Section titled “Comprehensive sshd_config”# /etc/ssh/sshd_config - Production Hardened Configuration
# =============================================================================# SSH PROTOCOL SETTINGS# =============================================================================
# Use only SSH Protocol 2 (mandatory for security)Protocol 2
# Listen on specific interfaces (reduce attack surface)ListenAddress 0.0.0.0ListenAddress ::
# =============================================================================# AUTHENTICATION SETTINGS# =============================================================================
# Disable root login (critical security measure)PermitRootLogin no
# Disable empty passwordsPermitEmptyPasswords no
# Disable password authentication (use keys only)PasswordAuthentication noPermitUserEnvironment noChallengeResponseAuthentication no
# Maximum authentication attemptsMaxAuthTries 3MaxSessions 10
# Login grace timeLoginGraceTime 30
# Strict modes - check file permissionsStrictModes yes
# Allow specific users/groups (whitelist approach)AllowUsers admin deployuser automation# AllowGroups sudo developers
# =============================================================================# KEY/BANNER SETTINGS# =============================================================================
# Login bannerBanner /etc/ssh/banner
# Public key authenticationPubkeyAuthentication yes
# AuthorizedKeysFile locationAuthorizedKeysFile .ssh/authorized_keys
# =============================================================================# SESSION SETTINGS# =============================================================================
# Client alive settings (detect disconnected clients)ClientAliveInterval 300ClientAliveCountMax 2
# Session timeout# Idle timeout (set in client)# Add to client config: ServerAliveInterval 300
# =============================================================================# FORWARDING SETTINGS# =============================================================================
# Disable all forwarding (if not needed)# Disable X11 forwarding (security risk)X11Forwarding no
# Disable agent forwardingAllowAgentForwarding no
# Disable TCP forwardingAllowTcpForwarding no
# Disable tunnel forwarding# PermitTunnel no
# =============================================================================# ENCRYPTION AND HASHING# =============================================================================
# Ciphers (order matters - put strongest first)Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
# MAC (Message Authentication Codes)MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256
# Key exchange algorithmsKexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
# =============================================================================# HOSTKEY SETTINGS# =============================================================================
# HostKeys for protocol 2HostKey /etc/ssh/ssh_host_rsa_keyHostKey /etc/ssh/ssh_host_ecdsa_keyHostKey /etc/ssh/ssh_host_ed25519_key
# Use privileged port (security)# HostKey /etc/ssh/ssh_host_key (SSHv1 - disable)
# =============================================================================# SUBSYSTEMS# =============================================================================
Subsystem sftp /usr/lib/ssh/sftp-server -f AUTHPRIV -l INFO
# =============================================================================# ACCESS CONTROL# =============================================================================
# Deny certain users# DenyUsers baduser
# Kerberos optionsKerberosAuthentication noKerberosOrLocalPasswd yesKerberosTicketCleanup yes
# GSSAPI optionsGSSAPIAuthentication noGSSAPICleanupCredentials yes
# =============================================================================# LOGGING# =============================================================================
# Log levelLogLevel VERBOSE
# =============================================================================# ENVIRONMENT# =============================================================================
# Accept environment variables from client (disable for security)AcceptEnv LANG LC_*
# =============================================================================# PAM SETTINGS# =============================================================================
UsePAM yes
# =============================================================================# OTHER SETTINGS# =============================================================================
# Print last login infoPrintLastLog yes
# Print MOTDPrintMotd no
# Handle deprecated options# IgnoreRhosts yes# RhostsRSAAuthentication no# HostbasedAuthentication no
# Allow shared connections# ControlMaster auto# ControlPath /tmp/ssh_mux_%h_%p# ControlPersist 4hSSH Banner
Section titled “SSH Banner”+------------------------------------------------------------------+| || AUTHORIZED ACCESS ONLY || || If you are not authorized to access or use this system, || disconnect immediately. || || All connections are logged and monitored. || Unauthorized access is prohibited and will be prosecuted. || || By using this system, you consent to these terms. || |+------------------------------------------------------------------+33.3 SSH Key Management
Section titled “33.3 SSH Key Management”Understanding SSH Key Types
Section titled “Understanding SSH Key Types” SSH Key Types Comparison+------------------------------------------------------------------+| || RSA (Rivest-Shamir-Adleman) || +----------------------------------------------------------+ || | Key Sizes: 1024, 2048, 3072, 4096 bits | || | Compatibility: Excellent (all SSH clients) | || | Security: Good (2048+ bits recommended) | || | Performance: Slower than Ed25519 | || | Use Case: Legacy systems, compatibility | || +----------------------------------------------------------+ || || ECDSA (Elliptic Curve DSA) || +----------------------------------------------------------+ || | Key Sizes: 256, 384, 521 bits | || | Compatibility: Good (modern clients) | || | Security: Good (depends on curve) | || | Performance: Faster than RSA | || | Use Case: Balanced performance/security | || | Concerns: NIST curves (potential backdoor concerns) | || +----------------------------------------------------------+ || || Ed25519 (Edwards-curve DSA) || +----------------------------------------------------------+ || | Key Size: 256 bits (fixed) | || | Compatibility: Very Good (modern clients) | || | Security: Excellent (modern, well-reviewed) | || | Performance: Fastest | || | Key Size: Smallest (37 bytes public, 64 bytes priv) | || | Use Case: RECOMMENDED for new deployments | || +----------------------------------------------------------+ || || Ed448 (Edwards-curve DSA) || +----------------------------------------------------------+ || | Key Size: 448 bits (fixed) | || | Compatibility: Limited (newer) | || | Security: Highest (largest key) | || | Performance: Very fast | || | Use Case: Maximum security requirements | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Key Generation Best Practices
Section titled “Key Generation Best Practices”# =============================================================================# ED25519 KEY (RECOMMENDED)# =============================================================================
# Generate Ed25519 key with commentssh-keygen -t ed25519 -C "work@company.com - Production"
# Ed25519 with custom filenamessh-keygen -t ed25519 -f ~/.ssh/id_ed25519_production -C "production-server"
# Ed25519 with passphrase (REQUIRED for production)ssh-keygen -t ed25519 -C "production" -a 100# -a rounds: Key derivation function iterations (more = slower but secure)
# =============================================================================# RSA KEY (FOR LEGACY COMPATIBILITY)# =============================================================================
# RSA 4096-bit keyssh-keygen -t rsa -b 4096 -C "legacy@company.com"
# RSA with more KDF rounds (slower but secure)ssh-keygen -t rsa -b 4096 -a 100 -C "production"
# =============================================================================# ED448 KEY (MAXIMUM SECURITY)# =============================================================================
ssh-keygen -t ed448 -C "maximum-security"
# =============================================================================# VIEW KEY DETAILS# =============================================================================
# View public keycat ~/.ssh/id_ed25519.pub
# View key fingerprintssh-keygen -lf ~/.ssh/id_ed25519.pub
# View key fingerprint (MD5 - useful for comparing)ssh-keygen -lf ~/.ssh/id_ed25519.pub -E md5
# View key commentsssh-keygen -y -f ~/.ssh/id_ed25519
# =============================================================================# KEY MANAGEMENT# =============================================================================
# Change passphrasessh-keygen -p -f ~/.ssh/id_ed25519
# Change commentssh-keygen -c -f ~/.ssh/id_ed25519 -C "new-comment"
# Generate public key from private keyssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pubDeploying SSH Keys
Section titled “Deploying SSH Keys”# =============================================================================# METHOD 1: ssh-copy-id (Simplest)# =============================================================================
# Standard copyssh-copy-id user@server
# Copy specific keyssh-copy-id -i ~/.ssh/id_ed25519_production.pub user@server
# =============================================================================# METHOD 2: Manual Copy# =============================================================================
# Create .ssh directory and set permissionsssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh"
# Copy public keycat ~/.ssh/id_ed25519.pub | ssh user@server "cat >> ~/.ssh/authorized_keys"
# Set correct permissionsssh user@server "chmod 600 ~/.ssh/authorized_keys && chmod 700 ~/.ssh"
# =============================================================================# METHOD 3: Using Ansible# =============================================================================
ansible all -m authorized_key -a "user=deploy key={{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
# =============================================================================# METHOD 4: SSH Key Deployment (Restricted)# =============================================================================
# Create restricted authorized_keys# Force specific options per key
# Command restriction (user can only run specific commands)command="/usr/local/bin/deploy.sh",no-pty,no-agent-forwarding,no-X11-forwarding ssh-rsa AAAA... user@host
# From specific IP onlyfrom="192.168.1.100" ssh-rsa AAAA... user@host
# Multiple restrictionsfrom="192.168.1.0/24",command="/usr/bin/git-shell" ssh-rsa AAAA... git@host33.4 SSH Agent Management
Section titled “33.4 SSH Agent Management”SSH Agent Security
Section titled “SSH Agent Security” SSH Agent Architecture+------------------------------------------------------------------+| || SSH Agent: In-memory key manager for SSH authentication || || +----------------------------------------------------------+ || | ssh-agent (runs as background process) | || | +------------------------------------------------------+ | || | | - Holds decrypted private keys in memory | | || | | - Communicates with SSH client via socket | | || | | - Keys never written to disk in decrypted form | | || | +------------------------------------------------------+ | || +----------------------------------------------------------+ || || Security Concerns: || +----------------------------------------------------------+ || | 1. Keys in memory can be extracted (cold boot attack) | || | 2. Agent forwarding exposes keys to remote servers | || | 3. Agent can be hijacked if socket is compromised | || | 4. Lock agent when leaving workstation | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Agent Commands
Section titled “Agent Commands”# =============================================================================# START SSH AGENT# =============================================================================
# Start agent and set environmenteval "$(ssh-agent -s)"
# Or start agent in backgroundssh-agent -s > /tmp/ssh-agent-envsource /tmp/ssh-agent-env
# Check if agent is runningecho $SSH_AUTH_SOCK
# =============================================================================# ADD KEYS TO AGENT# =============================================================================
# Add key with default settingsssh-add
# Add specific keyssh-add ~/.ssh/id_ed25519_production
# Add key with time limit (5 hours)ssh-add -t 18000 ~/.ssh/id_ed25519
# Add with confirmation (macOS)ssh-add -K ~/.ssh/id_ed25519
# =============================================================================# LIST KEYS# =============================================================================
# List all keys in agentssh-add -l
# List with fingerprintsssh-add -l -E md5ssh-add -l -E sha256
# List all (including those not in agent but with keys available)ssh-add -L
# =============================================================================# REMOVE KEYS# =============================================================================
# Remove specific keyssh-add -d ~/.ssh/id_ed25519
# Remove all keysssh-add -D
# Remove keys with timeoutssh-add -t 300 -d ~/.ssh/id_ed25519
# =============================================================================# LOCK/UNLOCK AGENT# =============================================================================
# Lock agent with passwordssh-add -x
# Unlock agentssh-add -X
# =============================================================================# AGENT FORWARDING# =============================================================================
# In SSH config (client)Host remote-server HostName server.example.com ForwardAgent yes
# On command linessh -A user@server
# CAUTION: Agent forwarding allows remote server to use your keys# Only use with trusted servers33.5 SSH Client Configuration
Section titled “33.5 SSH Client Configuration”Client Config Best Practices
Section titled “Client Config Best Practices”# ~/.ssh/config - Production SSH Client Configuration
# =============================================================================# GLOBAL DEFAULTS# =============================================================================
Host * # Security defaults PasswordAuthentication no PubkeyAuthentication yes IdentitiesOnly yes
# Connection settings ServerAliveInterval 60 ServerAliveCountMax 3 TCPKeepAlive yes
# Forwarding ForwardAgent no ForwardX11 no ForwardX11Trusted no
# Security HashKnownHosts yes VerifyHostKeyDNS yes StrictHostKeyChecking ask
# Performance Compression yes ControlMaster auto ControlPath ~/.ssh/sockets/%r@%h-%p ControlPersist 600
# Logging LogLevel ERROR
# =============================================================================# PRODUCTION SERVERS# =============================================================================
Host prod-* User admin Port 22 IdentityFile ~/.ssh/id_ed25519_production ServerAliveInterval 30 ServerAliveCountMax 5
Host prod-web-1 HostName 192.168.1.10 Host prod-web-*
Host prod-web-2 HostName 192.168.1.11 Host prod-web-*
Host prod-db-1 HostName 192.168.1.20 User dbadmin
# =============================================================================# DEVELOPMENT SERVERS# =============================================================================
Host dev-* User developer Port 22 IdentityFile ~/.ssh/id_ed25519_dev StrictHostKeyChecking no
Host dev-server HostName dev.example.com
# =============================================================================# JUMP HOST / BASTION# =============================================================================
Host bastion HostName bastion.example.com User admin Port 22 IdentityFile ~/.ssh/id_ed25519_bastion ForwardAgent yes
Host internal-server HostName 192.168.1.100 User admin ProxyJump bastion
# Alternative using ProxyCommandHost internal-server-alt HostName 192.168.1.100 User admin ProxyCommand ssh -W %h:%p bastion
# =============================================================================# GITHUB / GIT SERVICES# =============================================================================
Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github IdentitiesOnly yes
Host gitlab.com HostName gitlab.com User git IdentityFile ~/.ssh/id_ed25519_gitlab IdentitiesOnly yes
# =============================================================================# SPECIAL CONNECTIONS# =============================================================================
# High latency connectionsHost overseas-server HostName server.example.com Compression yes Cipher aes256-gcm@openssh.com MACs hmac-sha2-512-etm@openssh.com
# =============================================================================# CREATE SOCKET DIRECTORY# =============================================================================
# Run this once:mkdir -p ~/.ssh/socketschmod 700 ~/.ssh/sockets33.6 Fail2Ban Configuration
Section titled “33.6 Fail2Ban Configuration”Fail2Ban Architecture
Section titled “Fail2Ban Architecture” Fail2Ban Architecture+------------------------------------------------------------------+| || +---------------+ || | Log Files | || | (/var/log/) | || +---------------+ || | || v || +---------------+ || | Fail2Ban | || | Server | || +---------------+ || | || +------+------+-------+------+ || | | | | | || v v v v v || +------+------+-------+------+------+ || |Filter|Filter|Filter |Filter |Filter | (Regex patterns) || |sshd |nginx |apache |postfix|mysql | || +------+------+-------+------+------+ || | | | | | || v v v v v || +------+------+-------+------+------+ || |Action|Action|Action |Action |Action | (Ban/Unban actions) || |iptabl|firew |abuse |notify |cloud | || +------+------+-------+------+------+ || |+------------------------------------------------------------------+Comprehensive Fail2Ban Configuration
Section titled “Comprehensive Fail2Ban Configuration”# /etc/fail2ban/jail.local - Production Configuration
[DEFAULT]# Global settingsbantime = 1hfindtime = 10mmaxretry = 5destemail = admin@example.comsender = fail2ban@example.comaction = %(action_mwl)s
# Override action defaultsbanaction = iptables-multiportbanaction_allports = iptables-allports
# =============================================================================# SSH JAIL# =============================================================================
[sshd]enabled = trueport = sshfilter = sshdlogpath = /var/log/auth.logmaxretry = 3bantime = 24hfindtime = 1h
# Using recidive jail for repeat offenders[sshd-ddos]enabled = trueport = sshfilter = sshd-ddoslogpath = /var/log/auth.logmaxretry = 20bantime = 1wfindtime = 1d
# =============================================================================# WEB SERVER JAILS# =============================================================================
[nginx-http-auth]enabled = trueport = http,httpsfilter = nginx-http-authlogpath = /var/log/nginx/error.logmaxretry = 5bantime = 1h
[nginx-noscript]enabled = trueport = http,httpsfilter = nginx-noscriptlogpath = /var/log/nginx/access.logmaxretry = 6bantime = 1h
[nginx-badrequests]enabled = trueport = http,httpsfilter = nginx-badrequestslogpath = /var/log/nginx/access.logmaxretry = 3bantime = 1h
[apache-auth]enabled = trueport = http,httpsfilter = apache-authlogpath = /var/log/apache2/error.logmaxretry = 5
[apache-badbots]enabled = trueport = http,httpsfilter = apache-badbotslogpath = /var/log/apache2/access.logmaxretry = 2
[apache-noscript]enabled = trueport = http,httpsfilter = apache-noscriptlogpath = /var/log/apache2/access.logmaxretry = 6
# =============================================================================# DATABASE JAILS# =============================================================================
[mysqld]enabled = trueport = 3306filter = mysqld-authlogpath = /var/log/mysql/error.logmaxretry = 5bantime = 1h
[postgresql]enabled = trueport = 5432filter = postgresqllogpath = /var/log/postgresql/postgresql.logmaxretry = 5
# =============================================================================# MAIL SERVER JAILS# =============================================================================
[postfix]enabled = trueport = smtp,submission,imapsfilter = postfixlogpath = /var/log/mail.logmaxretry = 5bantime = 1h
[dovecot]enabled = trueport = pop3,pop3s,imap,imapsfilter = dovecotlogpath = /var/log/mail.logmaxretry = 5
# =============================================================================# FTP JAILS# =============================================================================
[vsftpd]enabled = trueport = ftp,ftp-data,ftps,ftps-datafilter = vsftpdlogpath = /var/log/vsftpd.logmaxretry = 5bantime = 1h
# =============================================================================# CUSTOM FILTERS# =============================================================================
# Example: Protect API endpoints[nginx-api]enabled = trueport = http,httpsfilter = nginx-apilogpath = /var/log/nginx/api-access.logmaxretry = 10bantime = 30mfindtime = 1m
# Create /etc/fail2ban/filter.d/nginx-api.conf#[Definition]#failregex = ^<HOST> .* "POST /api/.*" HTTP/1.1" (401|403|500|502|503|504)#ignoreregex =Fail2Ban Management Commands
Section titled “Fail2Ban Management Commands”# =============================================================================# MONITORING# =============================================================================
# Check statussudo fail2ban-client statussudo fail2ban-client status sshd
# View banned IPssudo iptables -L -nsudo fail2ban-client get sshd banned
# View logstail -f /var/log/fail2ban/fail2ban.log
# =============================================================================# BANNING/UNBANNING# =============================================================================
# Ban IP manuallysudo fail2ban-client set sshd banip 192.168.1.100
# Unban IPsudo fail2ban-client set sshd unbanip 192.168.1.100
# Unban allsudo fail2ban-client unban --all
# =============================================================================# TESTING FILTERS# =============================================================================
# Test regex against logfail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
# Test with custom logecho "Failed password for invalid user admin from 192.168.1.100" | \ fail2ban-regex /dev/stdin /etc/fail2ban/filter.d/sshd.conf33.7 Exam Tips
Section titled “33.7 Exam Tips”- SSH Protocol: Always use SSHv2 (Protocol 2)
- Key Types: Ed25519 is recommended (fastest, most secure)
- Passphrases: Always use passphrases for production keys
- Root Login: Always disable PermitRootLogin in production
- Password Auth: Disable PasswordAuthentication in production
- Port: Change default port 22 (security through obscurity)
- Fail2Ban: Configure for SSH and web services
- Key Deployment: Use authorized_keys with restrictions
- Agent Forwarding: Use carefully, only with trusted servers
- Client Config: Use ~/.ssh/config for organization
Common Mistakes & Anti-Patterns
Section titled “Common Mistakes & Anti-Patterns”1. Using Password Authentication
Section titled “1. Using Password Authentication”# ❌ WRONG: Enabling password authentication# In /etc/ssh/sshd_config:PasswordAuthentication yesPermitRootLogin yes
# ✅ CORRECT: Key-based auth onlyPasswordAuthentication noPubkeyAuthentication yesPermitRootLogin prohibit-password2. Weak SSH Key Algorithms
Section titled “2. Weak SSH Key Algorithms”# ❌ WRONG: Using weak key typesssh-keygen -t rsa -b 2048 # Too small nowssh-keygen -t dsa # Deprecated!ssh-keygen -t ecdsa -b 256 # Too small
# ✅ CORRECT: Use strong key typesssh-keygen -t ed25519 -a 100 # Recommended!ssh-keygen -t rsa -b 4096 # If Ed25519 not supported3. Not Securing SSH Agent
Section titled “3. Not Securing SSH Agent”# ❌ WRONG: Leaving SSH agent unprotectedssh-add # Adds all keys without passphrase# Keys with empty passphrases are vulnerable
# ✅ CORRECT: Use ssh-agent with passphrasessh-agent bashssh-add # Enter passphrase for each key# Or use keychainsource ~/.keychain/$HOSTNAME-sh4. Ignoring SSH Config Security
Section titled “4. Ignoring SSH Config Security”# ❌ WRONG: Insecure SSH client config# ~/.ssh/config:Host * ServerAliveInterval 0 StrictHostKeyChecking no # Accepts any host key!
# ✅ CORRECT: Secure SSH configHost * ServerAliveInterval 60 StrictHostKeyChecking ask IdentityFile ~/.ssh/id_ed25519 AddKeysToAgent yesInterview Questions
Section titled “Interview Questions”- What is the difference between SSH version 1 and 2?
- How do you harden SSH configuration for production?
- What are the advantages of Ed25519 over RSA keys?
- How does Fail2Ban protect SSH?
- Explain SSH agent forwarding and its security implications
- What is ProxyJump and how is it used?
Summary
Section titled “Summary”In this chapter, you learned:
- ✅ SSH protocol architecture (transport, authentication, connection)
- ✅ Comprehensive sshd_config hardening
- ✅ SSH key types (RSA, ECDSA, Ed25519, Ed448)
- ✅ SSH key generation and deployment
- ✅ SSH agent management and security
- ✅ SSH client configuration best practices
- ✅ Fail2Ban architecture and configuration
- ✅ SSH security best practices for production
Next Chapter
Section titled “Next Chapter”Chapter 33: Intrusion Detection and Fail2Ban
Last Updated: February 2026