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.

YearEventSignificance
1995SSH-1 released by Tatu YlonenFirst version; replaced Telnet and rlogin
1995SSH Communications Security foundedYlonen commercializes SSH
1999OpenSSH 1.0 releasedFree, open-source implementation (forked from SSH 1.2.12)
2006SSH-2 standardized (RFC 4251-4254)Complete protocol redesign; current standard
2014Ed25519 support in OpenSSH 6.5Modern elliptic curve keys become default recommendation
2020OpenSSH disables ssh-rsa by defaultSHA-1 signatures deprecated for host/user keys
2023OpenSSH 9.5 adds post-quantum key exchangeHybrid 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:

  1. Client connects to port 22; both sides exchange protocol version strings
  2. Both sides exchange SSH_MSG_KEXINIT messages listing supported algorithms for key exchange, host key, encryption, MAC, and compression
  3. They agree on algorithms (client preference order takes priority)
  4. Key exchange proceeds using the agreed algorithm (e.g., curve25519-sha256)
  5. Both sides derive session keys from the shared secret: separate keys for encryption and integrity in each direction
  6. 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:

AlgorithmTypeStatusNotes
chacha20-poly1305@openssh.comAEAD cipherRecommended (default)Fast on systems without AES hardware; designed by Daniel Bernstein
aes256-gcm@openssh.comAEAD cipherRecommendedFast with AES-NI hardware acceleration
aes128-gcm@openssh.comAEAD cipherRecommendedAES-128 with GCM mode
aes256-ctrCipher + separate MACAcceptableRequires separate MAC (e.g., hmac-sha2-256-etm)
aes128-cbcCBC cipherDeprecatedVulnerable to plaintext recovery attacks
3des-cbcCBC cipherDeprecatedSlow, 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 TypeAlgorithmKey SizeSecurity LevelPerformanceRecommendation
ed25519EdDSA (Curve25519)256 bits (fixed)~128 bitsVery fast signing and verificationRecommended default
ecdsaECDSA (P-256/P-384/P-521)256/384/521 bits128/192/256 bitsFastAcceptable (P-256 preferred)
rsaRSA2048-4096 bits112-140 bitsSlow key generation; fast verificationLegacy; use 4096-bit minimum
dsaDSA1024 bits (fixed)80 bitsSlowDeprecated; 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.

FeatureSCPSFTP
Resume interrupted transfersNoYes
Directory listingsNoYes
File permissions/attributesLimitedFull support
Random file accessNoYes
Firewall-friendlyYes (single connection)Yes (single connection)
StatusDeprecatedRecommended

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 (or prohibit-password for key-only root access)
  • Restrict users:AllowUsers admin deployer or AllowGroups 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 300 and ClientAliveCountMax 2
  • Disable X11 forwarding:X11Forwarding no (unless needed)
  • Disable agent forwarding:AllowAgentForwarding no (unless needed)
  • Use strong algorithms only: Specify explicit KexAlgorithms, Ciphers, and MACs lists
  • Enable logging:LogLevel VERBOSE for 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.