The history of SSH, from telnet to OpenSSH
A 1995 password sniffing attack in Helsinki produced SSH. Here is the verified timeline from telnet and rlogin to OpenSSH and post-quantum defaults.
Where the history of SSH begins
The history of SSH begins with stolen passwords. Before 1995, logging in to a remote Unix machine meant telnet or rlogin, and both sent your password across the network as readable text. Anyone who could watch the wire could read it, and by the early 1990s people were doing exactly that, at scale.
SSH was one person's answer to that problem, written in 1995 and given away. The protocol has been rebuilt once since then, and the program almost everyone runs today is a fork of a fork. The dates below matter, because every step was a response to a specific failure.
What telnet and rlogin actually sent
Telnet is defined in RFC 854, published in May 1983 by Jon Postel and Joyce Reynolds. It describes a terminal session carried over TCP, and it contains no encryption of any kind. Every byte you type, your password included, travels as plain bytes that any device on the path can read.
rlogin came out of Berkeley Unix and was written up later, in RFC 1282 (BSD Rlogin, B. Kantor, December 1991). It added something worse than a readable password: host-based trust. A server could be told to accept logins from a named host with no password at all. The RFC carries a section called "A Cautionary Tale" that says "Bypassing password authentication from trusted hosts opens ALL the systems so configured when just one is compromised." It also notes that the trust is keyed on hostnames, so a DNS (domain name system) compromise or a spoofed address defeats it.
Both designs suited the network they were born on. Early Ethernet was a shared medium: every machine on a segment received every frame and was expected to ignore the frames not addressed to it. A machine that stopped ignoring them, which is what promiscuous mode means, saw everybody else's traffic. Add a university handing shell accounts to thousands of students, and one compromised account became a password collector for a whole department.
The 1994 advisory that came with no fix
On 3 February 1994 CERT published advisory CA-94:01, "Ongoing Network Monitoring Attacks". It reported that intruders had captured access information for tens of thousands of systems across the internet. The tool they used put the network interface into promiscuous mode and recorded the beginning of every new telnet, rlogin and FTP session, which is the part that carries the username and the password.
CERT advised sites to change the password on every network-accessed account. Read that against the protocols and the trap is clear: the new password crosses the same wire in clear text the first time it is used. No fix existed inside telnet or rlogin, because neither protocol had anywhere to put one.
Why a sniffing attack in Helsinki produced SSH
In 1995 the network at Helsinki University of Technology was hit by a password sniffing attack of the kind CERT had described. Tatu Ylönen, a researcher there, wrote a replacement and released it as freeware in July 1995. He called it Secure Shell.
Two design decisions carried it. The session was encrypted, so a listener on the segment learned nothing useful. And the server proved its identity with a key, so the client could tell whether it had reached the right machine, which is the hole that rlogin's hostname trust left open.
It also spread because the commands matched the ones people already typed. ssh stood in for rsh and rlogin, scp stood in for rcp. Switching cost a habit, not a workflow. By the end of 1995 the user base had reached roughly 20,000 users in fifty countries. That December, Ylönen founded SSH Communications Security to develop and sell the software.
From a free release to a commercial product
As SSH became a business, the licence on the source changed. Later releases carried terms that limited what other people could do with the code, and the last release anyone could freely reuse was ssh 1.2.12. Nothing about that is improper. It simply meant the version of SSH the rest of the world could build on stopped moving, while development continued somewhere that world could not follow. Licences decide which code survives, a pattern worth reading about in how open source licensing shaped modern infrastructure.
Why OpenBSD forked OpenSSH in 1999
Early in 1999 Björn Grönvall went back to that last free release and started fixing bugs in it. His version was called OSSH, and it spoke only the SSH 1.3 protocol.
The OpenBSD project picked up OSSH and rebuilt it. By the project's own account, Theo de Raadt, Niels Provos, Markus Friedl, Bob Beck, Aaron Campbell and Dug Song did the work of cleaning, auditing and extending the code. The result was OpenSSH 1.2.2, and it shipped with OpenBSD 2.6 on 1 December 1999.
Why did a fork by one small operating system project end up on nearly every machine? Because of what OpenBSD needed from it. OpenBSD ships an audited base system that is meant to be safe in its default configuration, so encrypted remote login had to live in that base system, under a licence with no restrictions attached. Audited code under an unrestricted licence is precisely what every other operating system vendor also wanted. Damien Miller, Philip Hands and others started a portable branch almost immediately, which is where the p in a version like 10.5p1 comes from. OpenBSD develops the clean version, and the portable branch adds the glue for everything else. The way Unix split into the systems we run today is why that glue is needed at all.
Support for the second protocol version followed. OpenSSH 2.0 shipped with OpenBSD 2.7 on 15 June 2000.
Why SSH-2 is a new protocol and not a version bump
SSH-1 protected the integrity of the encrypted stream with CRC-32, a checksum designed to catch transmission errors rather than to resist an attacker. In 1998 Ariel Futoransky and Emiliano Kargieman of CORE SDI showed what that costs. With CBC or CFB cipher modes and a CRC-32 check, an attacker who knows as little as 16 bytes of the plaintext can insert chosen ciphertext that the receiver accepts as genuine, which means running commands on the server.
The flaw lived in the protocol, so it could not be corrected without breaking compatibility. Implementations shipped a detector instead, code in a file called deattack.c that tried to recognise the attack as it happened. In February 2001 the detector was found to contain an integer overflow of its own, CVE-2001-0144, giving remote code execution against servers and clients that carried the patch. A design that cannot be repaired collects patches, and the patches bring their own bugs.
SSH-2 was worked out in an IETF working group named secsh and published as RFCs in January 2006: the architecture in RFC 4251, the transport layer in RFC 4253, user authentication in RFC 4252, the connection layer in RFC 4254. The split into layers is the important part, because each layer can then be replaced on its own. Most of the rest of this history is that replacement happening.
Two changes stand out. Integrity moved from CRC-32 to an HMAC (hash-based message authentication code) keyed with a shared secret, so an attacker who cannot compute the MAC cannot forge a packet. And key agreement moved to Diffie-Hellman. In SSH-1 the client chose the session key and sent it encrypted under the server's RSA keys, so anyone who later obtained those private keys could decrypt a recorded session. Diffie-Hellman derives a fresh secret per session that is never transmitted, so recording traffic now and stealing the host key later yields nothing. That property is called forward secrecy.
SSH-2 shares no wire compatibility with SSH-1. That is why the number changed rather than the decimal.
Why SSH-1 was removed instead of repaired
Removal took three OpenSSH releases. Version 7.0, on 11 August 2015, disabled protocol 1 by default at compile time. Version 7.4, on 19 December 2016, removed server support for it. Version 7.6, on 3 October 2017, deleted the client side as well, along with its configuration options and documentation.
Keeping it as an option for old equipment would have been the friendlier choice, and the CRC-32 detector explains why that choice was refused. The overflow was reachable only because protocol 1 code was compiled in, and it sat in a path most administrators believed was dormant on their systems. Code that ships can be reached. Code that was deleted cannot.
Why your first SSH connection warns about the host key
Encryption tells you the traffic is private. It does not tell you who is at the other end. If an attacker sits in the path and answers in place of your server, you get a perfectly encrypted session with the attacker, which is a machine-in-the-middle attack. SSH answers that with a host key: the server proves it holds the private half of a key pair, and the client checks that key against what it recorded last time. If you want the mechanics of the connection itself, see what happens when you open an SSH connection.
On the first connection there is no last time, so the client has nothing to compare and has to ask you:
The authenticity of host 'vps.example.com (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:BQ0Qs2jVXhH2lPZ2rM0aQ0mQ8f9pQ0m3nH0oQ1bYqkE.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?Answering yes stores that key in ~/.ssh/known_hosts. Every later connection compares against the stored value, and a mismatch produces the loudest message the program has:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!The honest reading of that first prompt is that the protocol is admitting its one weak moment. Trust on first use means the first connection is only as safe as the network you made it on. You can close that gap. Read the fingerprint from your provider's console or the server's build log before you connect. Publish it in DNS as an SSHFP record (RFC 4255), which is worth doing only if you have DNSSEC. Or sign host keys with your own certificate authority (CA), so clients trust the CA and not each individual key. In practice most people accept the prompt without checking, which is worth being honest about.
How public keys pushed passwords aside
Public key authentication was there from the early SSH releases, and it still took years to become the normal habit. The mechanism is asymmetric: the client proves it holds a private key by signing a challenge, and the private key never leaves the client. A password does the opposite. Even though SSH carries it inside the encrypted channel, the server receives the actual secret, so a compromised or hostile server ends up holding something it can reuse against you elsewhere.
The second reason is arithmetic. Any server with port 22 open on a public address receives automated login attempts around the clock, and a password is a guessable string. A key is not guessable in any practical sense. Setting PasswordAuthentication no ends that whole category of attack, which is why it appears on every hardening checklist. Generating and rotating keys is covered in SSH key management basics, and the server side settings in hardening SSH on a VPS.
Why the SSH algorithm list keeps changing
A layered protocol lets algorithms retire without a new protocol. OpenSSH has used that freedom steadily, and the release dates show the pace.
Ed25519 arrived in OpenSSH 6.5 on 30 January 2014, alongside the chacha20-poly1305 cipher and a private key format protected by bcrypt. Ed25519 signatures derive their per-signature nonce deterministically, so a weak random number generator at signing time cannot leak the private key. That is exactly how DSA and ECDSA private keys have been recovered in real incidents.
DSA went the other way. OpenSSH 7.0 disabled ssh-dss host and user keys at run time in 2015, because the algorithm is limited to a 160-bit private key and to SHA-1. Version 9.8, on 1 July 2024, disabled DSA at compile time. Version 10.0, on 9 April 2025, removed it, in the project's words "completing the deprecation process that began in 2015". Ten years from disabled to deleted.
RSA did not disappear, but its old signature format did. OpenSSH 8.8, on 26 September 2021, stopped accepting RSA signatures made with SHA-1 by default. The release notes state the reason plainly: SHA-1 is cryptographically broken, and chosen-prefix collisions were achievable for under USD 50,000. If you have ever met sign_and_send_pubkey: no mutual signature supported while connecting to an old server, that is this change. Your key is fine. The signature algorithm the other end asked for is not.
The same process now runs for key exchange, this time ahead of the threat. Traffic captured today can be stored and decrypted years later by whoever first owns a capable quantum computer, so key agreement had to change before such a machine exists. OpenSSH 9.0, on 8 April 2022, made a hybrid key exchange the default: sntrup761x25519-sha512@openssh.com pairs a post-quantum algorithm with the X25519 exchange, so the result is no weaker than the classical part if the new algorithm disappoints. OpenSSH 9.9, on 19 September 2024, added mlkem768x25519-sha256, built on ML-KEM (module lattice key encapsulation mechanism), standardised by NIST in 2024. OpenSSH 10.0 made that the default for key agreement, and the project's post-quantum page explains the reasoning. OpenSSH 10.1, on 6 October 2025, began warning when the other end cannot do it:
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded.That warning is on by default and is controlled by the WarnWeakCrypto option in ssh_config. What it means in practice, and what to do about a server that triggers it, is covered in the post-quantum SSH key exchange defaults.
What this history means for the server in front of you
The command you type has barely changed since 1995. Nearly everything underneath it has been replaced: the integrity check, the key exchange, the signature algorithms, the code base itself. That was possible only because each replacement ended in a deliberate removal, and each removal broke something for somebody.
So your SSH security is decided mostly by your version. The defaults carry the decisions about which algorithms are offered, which are refused and which warnings you see. An old server keeps offering whatever its release still permitted, and it will keep negotiating down to meet an old client. As of August 2026 the current release is OpenSSH 10.5, published on 11 August 2026. The distance between that and the version on a machine nobody has touched in three years is the size of the problem. Checking it belongs in the first ten minutes on a new VPS.
FAQ
Who created SSH, and why?
Tatu Ylönen, a researcher at Helsinki University of Technology, wrote SSH in 1995 after a password sniffing attack on the university network. The remote login tools of the time, telnet and rlogin, sent passwords across the network as readable text, so anyone monitoring a shared segment collected credentials as they went past. He released the program as freeware in July 1995. By the end of that year it had roughly 20,000 users in fifty countries, and in December 1995 he founded SSH Communications Security.
What is the difference between SSH-1 and SSH-2?
They are different protocols with no wire compatibility. SSH-1 was a single monolithic protocol that used CRC-32 for integrity and had the client send a session key encrypted under the server's RSA keys. SSH-2 splits the work into a transport layer, an authentication layer and a connection layer (RFCs 4251 to 4254, January 2006), uses an HMAC for integrity, and derives session keys with Diffie-Hellman, so recorded traffic stays private even if the host key is stolen afterwards. SSH-1 left OpenSSH in stages, ending with version 7.6 in October 2017.
Why did OpenSSH replace the original SSH implementation?
Development of the original moved into a commercial product with a restrictive licence, and the last freely reusable release was ssh 1.2.12. Early in 1999 Björn Grönvall revived that release as OSSH, and the OpenBSD team forked OSSH into OpenSSH, which shipped with OpenBSD 2.6 on 1 December 1999. OpenBSD needed audited code under an unrestricted licence for its base system, and those two properties are what let every other operating system ship the same implementation through the portable branch.
Why does SSH ask about the host key the first time I connect?
Because the client has never seen that server before and has nothing to compare its key against. Encryption alone cannot separate an honest server from a machine sitting in the middle of the path, so SSH identifies servers by key and records what it saw in ~/.ssh/known_hosts. The first connection is the one moment with no stored value to check, which is why the client asks you instead. Compare the fingerprint against one you got from the provider console or the server itself, and treat any later REMOTE HOST IDENTIFICATION HAS CHANGED message as a real event until you can explain it.
Why do older SSH keys stop working after an upgrade?
Because OpenSSH retires algorithms on a published schedule. DSA (ssh-dss) keys were disabled by default in OpenSSH 7.0 in 2015 and removed outright in OpenSSH 10.0 on 9 April 2025. RSA keys still work, but signatures made with SHA-1 were disabled by default in OpenSSH 8.8 in September 2021, which appears as sign_and_send_pubkey: no mutual signature supported when you reach an old server. An Ed25519 key, available since OpenSSH 6.5 in January 2014, avoids both problems.