Introduction
SSH (Secure Shell) is a cryptographic network protocol for operating network services securely over an unsecured network. Its most common use is remote command-line access to servers, but SSH also provides secure file transfer, port forwarding, X11 forwarding, and the ability to tunnel arbitrary TCP connections. SSH operates on port 22 by default and uses a client-server architecture.
SSH replaced insecure legacy protocols -- Telnet, rlogin, and rsh -- that transmitted all data, including passwords, in plaintext. Before SSH, anyone with access to the network path between a system administrator and a server could read every command, every password, and every piece of data exchanged. SSH encrypts the entire session, making eavesdropping computationally infeasible.
Today, SSH is one of the most widely deployed security protocols in the world. It is the primary method for managing Linux/Unix servers, networking equipment, cloud instances, and containers. Virtually every Linux server, cloud platform, and DevOps pipeline relies on SSH for secure access and automation.
"I wrote the first version of SSH in spring 1995 because a password-sniffing attack at my university made me lose my temper. Someone had installed a sniffer that was capturing passwords from the network." -- Tatu Ylonen, inventor of SSH
History and Evolution
SSH was created by Finnish researcher Tatu Ylonen in 1995 at the Helsinki University of Technology, directly in response to a network sniffing attack that compromised thousands of passwords on the university network. The first version (SSH-1) was released as free software and quickly gained adoption.
| Year | Event | Significance |
|---|---|---|
| 1995 | SSH-1 released by Tatu Ylonen | First version; replaced Telnet and rlogin |
| 1995 | SSH Communications Security founded | Ylonen commercializes SSH |
| 1999 | OpenSSH 1.0 released | Free, open-source implementation (forked from SSH 1.2.12) |
| 2006 | SSH-2 standardized (RFC 4251-4254) | Complete protocol redesign; current standard |
| 2014 | Ed25519 support in OpenSSH 6.5 | Modern elliptic curve keys become default recommendation |
| 2020 | OpenSSH disables ssh-rsa by default | SHA-1 signatures deprecated for host/user keys |
| 2023 | OpenSSH 9.5 adds post-quantum key exchange | Hybrid X25519+ML-KEM for quantum resistance |
OpenSSH, maintained by the OpenBSD project, is by far the most widely used SSH implementation. It is included by default in virtually every Linux distribution, macOS, and (since 2018) Windows 10. OpenSSH's security track record is exceptional, with very few critical vulnerabilities in over two decades.
How SSH Works
An SSH connection involves three major phases: key exchange, server authentication, and user authentication. All subsequent communication is encrypted.
Key Exchange
The first phase establishes a shared secret between the client and server without transmitting the secret over the network. SSH-2 uses Diffie-Hellman or Elliptic Curve Diffie-Hellman for key exchange.
Connection establishment:
- Client connects to port 22; both sides exchange protocol version strings
- Both sides exchange SSH_MSG_KEXINIT messages listing supported algorithms for key exchange, host key, encryption, MAC, and compression
- They agree on algorithms (client preference order takes priority)
- Key exchange proceeds using the agreed algorithm (e.g.,
curve25519-sha256) - Both sides derive session keys from the shared secret: separate keys for encryption and integrity in each direction
- Encrypted communication begins
Modern OpenSSH defaults to curve25519-sha256 for key exchange, which uses the X25519 Diffie-Hellman function. This provides excellent security with high performance. OpenSSH 9.5+ also supports sntrup761x25519-sha512, a hybrid post-quantum key exchange combining the classical X25519 with the lattice-based NTRU Prime algorithm.
Host Key Verification
During key exchange, the server proves its identity by signing the exchange hash with its host key. The client verifies this signature against its local database of known host keys (typically ~/.ssh/known_hosts).
On first connection, the client displays the server's host key fingerprint and asks the user to verify it -- the familiar "The authenticity of host cannot be established" message. This is the Trust On First Use (TOFU) model. Once accepted, the key is stored and future connections are verified automatically. If the key changes, SSH warns of a possible man-in-the-middle attack.
Alternatives to TOFU include SSHFP DNS records (RFC 4255), which publish host key fingerprints in DNS secured by DNSSEC, and SSH Certificate Authority infrastructure, where a trusted CA signs host keys and clients trust the CA rather than individual keys.
Encryption and Integrity
After key exchange, all data is encrypted. SSH-2 supports several cipher and MAC combinations:
| Algorithm | Type | Status | Notes |
|---|---|---|---|
chacha20-poly1305@openssh.com | AEAD cipher | Recommended (default) | Fast on systems without AES hardware; designed by Daniel Bernstein |
aes256-gcm@openssh.com | AEAD cipher | Recommended | Fast with AES-NI hardware acceleration |
aes128-gcm@openssh.com | AEAD cipher | Recommended | AES-128 with GCM mode |
aes256-ctr | Cipher + separate MAC | Acceptable | Requires separate MAC (e.g., hmac-sha2-256-etm) |
aes128-cbc | CBC cipher | Deprecated | Vulnerable to plaintext recovery attacks |
3des-cbc | CBC cipher | Deprecated | Slow, small block size (64-bit) |
AEAD (Authenticated Encryption with Associated Data) ciphers like ChaCha20-Poly1305 and AES-GCM combine encryption and integrity verification in a single operation, eliminating entire classes of attacks that were possible when encryption and MAC were separate.
Authentication Methods
After the encrypted channel is established, the user must authenticate. SSH supports several methods:
Public Key Authentication (recommended): The user generates a key pair and places the public key on the server (in ~/.ssh/authorized_keys). During authentication, the client proves possession of the private key without transmitting it. The server sends a challenge, the client signs it with the private key, and the server verifies the signature with the stored public key. This is the most secure and widely used method.
Password Authentication: The user sends their password over the encrypted channel. While the password is encrypted in transit, this method is vulnerable to brute-force attacks and phishing. Most hardened servers disable password authentication entirely.
Keyboard-Interactive: A flexible challenge-response mechanism that supports multi-step authentication. Often used for PAM (Pluggable Authentication Modules) integration, two-factor authentication, and one-time password systems.
Certificate-Based Authentication: OpenSSH supports its own certificate format (distinct from X.509). A trusted Certificate Authority signs user keys, and the server trusts the CA rather than individual public keys. This eliminates the need to distribute and manage authorized_keys files across thousands of servers -- a significant operational advantage at scale.
GSSAPI/Kerberos: In enterprise environments with Kerberos infrastructure, SSH can authenticate using Kerberos tickets. The user obtains a TGT from the KDC and uses it to authenticate to SSH servers without additional credentials.
"If you are still using password authentication for SSH, you are doing it wrong. Public key authentication is not just more secure -- it is also more convenient once properly configured." -- Daniel Stenberg, author of curl
Key Types: Ed25519 vs RSA
SSH supports several key algorithms. The choice of key type affects security, performance, and compatibility:
| Key Type | Algorithm | Key Size | Security Level | Performance | Recommendation |
|---|---|---|---|---|---|
ed25519 | EdDSA (Curve25519) | 256 bits (fixed) | ~128 bits | Very fast signing and verification | Recommended default |
ecdsa | ECDSA (P-256/P-384/P-521) | 256/384/521 bits | 128/192/256 bits | Fast | Acceptable (P-256 preferred) |
rsa | RSA | 2048-4096 bits | 112-140 bits | Slow key generation; fast verification | Legacy; use 4096-bit minimum |
dsa | DSA | 1024 bits (fixed) | 80 bits | Slow | Deprecated; disabled in modern OpenSSH |
Ed25519 is the recommended key type for modern SSH deployments. Designed by Daniel Bernstein, it offers several advantages over RSA:
- Fixed, small key size: 256 bits provides ~128-bit security (equivalent to RSA-3072). The entire public key is 68 characters in base64.
- Speed: Signing is significantly faster than RSA. Key generation is nearly instant.
- Security: Resistant to side-channel attacks by design. No known weak keys or parameters to choose incorrectly.
- Deterministic signatures: Ed25519 does not require a random number generator during signing, eliminating the class of vulnerabilities caused by bad RNG (which has compromised ECDSA implementations).
Generating an Ed25519 key:
ssh-keygen -t ed25519 -C "user@example.com"
RSA keys should only be used when compatibility with older systems is required. If RSA must be used, generate a 4096-bit key: ssh-keygen -t rsa -b 4096.
Port Forwarding and Tunneling
One of SSH's most powerful features is its ability to create encrypted tunnels for arbitrary TCP traffic. This is commonly used to secure insecure protocols, access services behind firewalls, or create ad-hoc VPN-like connections.
Local Port Forwarding (-L): Forwards a local port through the SSH connection to a destination accessible from the SSH server. Traffic to localhost:local_port is encrypted through the SSH tunnel and delivered to destination:remote_port.
ssh -L 8080:internal-server:80 user@gateway.example.com
This forwards local port 8080 through the SSH connection to internal-server:80, which is accessible from the gateway server but not directly from the client.
Remote Port Forwarding (-R): Makes a local service accessible through the SSH server. The SSH server listens on a port and forwards traffic back through the SSH connection to the client.
ssh -R 9090:localhost:3000 user@public-server.example.com
This makes the client's local service on port 3000 accessible via public-server:9090. Useful for exposing development servers or services behind NAT.
Dynamic Port Forwarding (-D): Creates a SOCKS proxy on the local machine. All traffic routed through the SOCKS proxy is encrypted through the SSH tunnel and exits from the SSH server.
ssh -D 1080 user@server.example.com
This creates a SOCKS5 proxy on localhost:1080. Configure applications or the browser to use this proxy to tunnel all traffic through the SSH server -- effectively a lightweight VPN.
SSH Tunneling with ProxyJump (-J): Jump through one or more intermediate hosts to reach a destination:
ssh -J jumphost1,jumphost2 user@final-destination
File Transfer: SCP and SFTP
SSH provides two mechanisms for secure file transfer:
SCP (Secure Copy Protocol): A simple file transfer tool that uses the SSH connection to copy files. SCP is being deprecated in favor of SFTP due to protocol limitations and security issues with its remote file name handling. OpenSSH's scp command now uses SFTP internally by default (since OpenSSH 9.0).
SFTP (SSH File Transfer Protocol): A more capable file transfer protocol that runs over SSH. SFTP supports directory listings, file renaming, permissions changes, resume of interrupted transfers, and random access to file contents. It is the recommended method for file transfer over SSH.
| Feature | SCP | SFTP |
|---|---|---|
| Resume interrupted transfers | No | Yes |
| Directory listings | No | Yes |
| File permissions/attributes | Limited | Full support |
| Random file access | No | Yes |
| Firewall-friendly | Yes (single connection) | Yes (single connection) |
| Status | Deprecated | Recommended |
Configuration Hardening
A properly hardened SSH configuration significantly reduces the attack surface. Key settings for /etc/ssh/sshd_config:
- Disable password authentication:
PasswordAuthentication no-- forces public key authentication - Disable root login:
PermitRootLogin no(orprohibit-passwordfor key-only root access) - Restrict users:
AllowUsers admin deployerorAllowGroups ssh-users - Change default port:
Port 2222-- reduces automated scanning noise (not a security measure by itself) - Limit authentication attempts:
MaxAuthTries 3 - Set idle timeout:
ClientAliveInterval 300andClientAliveCountMax 2 - Disable X11 forwarding:
X11Forwarding no(unless needed) - Disable agent forwarding:
AllowAgentForwarding no(unless needed) - Use strong algorithms only: Specify explicit
KexAlgorithms,Ciphers, andMACslists - Enable logging:
LogLevel VERBOSEfor audit trail
Recommended algorithm configuration:
KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com
Additionally, deploy fail2ban or sshguard to automatically ban IP addresses after repeated failed authentication attempts.
Common Attacks and Defenses
Brute Force Attacks: Automated tools attempt thousands of username/password combinations per minute. Defense: disable password authentication, use fail2ban, and implement rate limiting.
Man-in-the-Middle: An attacker intercepts the initial connection and presents their own host key. If the user accepts the unknown key without verification, the attacker can decrypt, read, and modify all traffic. Defense: verify host key fingerprints out-of-band, use SSHFP DNS records, or deploy SSH certificate authorities.
Key Theft: An attacker who gains access to a user's private key can impersonate them. Defense: protect private keys with strong passphrases, use SSH agent with confirmation (ssh-add -c), store keys in hardware tokens (FIDO2/U2F), and implement key rotation policies.
Agent Forwarding Abuse: When agent forwarding is enabled (-A), a compromised intermediate server can use the forwarded agent to authenticate as the user to other servers. Defense: use ProxyJump instead of agent forwarding, or restrict agent forwarding to specific hosts.
SSH Credential Harvesting: Attackers install modified SSH clients or use LD_PRELOAD hooks to capture credentials on compromised systems. Defense: verify SSH binary integrity, use immutable system configurations, and monitor for unauthorized modifications.
For related topics, see HTTPS (TLS-based security for web traffic), asymmetric encryption (the mathematical foundation of SSH keys), and two-factor authentication (which can be integrated with SSH).
References
- Ylonen, T., & Lonvick, C. (2006). RFC 4251: The Secure Shell (SSH) Protocol Architecture. IETF.
- Ylonen, T., & Lonvick, C. (2006). RFC 4252: The Secure Shell (SSH) Authentication Protocol. IETF.
- Ylonen, T., & Lonvick, C. (2006). RFC 4253: The Secure Shell (SSH) Transport Layer Protocol. IETF.
- Ylonen, T., & Lonvick, C. (2006). RFC 4254: The Secure Shell (SSH) Connection Protocol. IETF.
- Bernstein, D. J., et al. (2012). "High-speed high-security signatures." Journal of Cryptographic Engineering, 2(2), 77-89.
- OpenSSH. (2024). "OpenSSH Release Notes." openssh.com.
- Barrett, D., Silverman, R., & Byrnes, R. (2005). SSH, The Secure Shell: The Definitive Guide. 2nd Edition. O'Reilly Media.
- Ylonen, T. (1996). "SSH -- Secure Login Connections over the Internet." USENIX Security Symposium 1996.
- Stebila, D., & Green, J. (2009). RFC 5656: Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer. IETF.
- NIST. (2020). SP 800-57 Part 1 Rev. 5: Recommendation for Key Management. NIST.