SSHの歴史:telnetからOpenSSH、耐量子暗号まで
1995年、ヘルシンキでのパスワード盗聴攻撃を機にSSHが誕生しました。telnetとrloginからOpenSSH、耐量子暗号のデフォルトまで、検証済みの沿革を追います。
SSH の歴史の始まり
SSH の歴史は、盗まれたパスワードから始まります。1995 年以前、リモートの Unix マシンにログインするには telnet または rlogin を使っていました。どちらもパスワードを読み取り可能なテキストとしてネットワーク上に送信していました。ネットワーク通信を監視できる者は誰でもパスワードを読めました。1990 年代初頭までには、実際に大規模な盗聴が行われていました。
SSH は、この問題に対する 1 人の回答として、1995 年に作成され、無償で公開されました。その後、プロトコルは 1 度再構築されています。現在、ほとんどの人が実行しているプログラムは、フォークからさらにフォークされたものです。以下の日付が重要なのは、各段階が特定の障害への対応だったためです。
telnet と rlogin が実際に送信していたもの
Telnet は、Jon Postel と Joyce Reynolds が 1983 年 5 月に公開した RFC 854 で定義されています。TCP 経由で端末セッションを運ぶ方式で、暗号化は一切ありません。入力したすべてのバイトは、パスワードを含め、経路上のどのデバイスからも読み取れる平文のまま送信されます。
rlogin は Berkeley Unix から生まれ、後に RFC 1282(BSD Rlogin、B. Kantor、1991 年 12 月)で文書化されました。読み取れるパスワードよりも危険な仕組みとして、ホストベースの信頼を導入しました。サーバーに名前付きホストからのログインを、パスワードなしで受け入れるよう指定できました。この RFC には「A Cautionary Tale」というセクションがあり、「信頼されたホストからのパスワード認証を回避すると、1 台が侵害された時点で、そのように構成されたすべてのシステムが危険にさらされる」と記載されています。また、この信頼がホスト名を基準にするため、DNS(domain name system)の侵害や偽装アドレスによって無効化されることも説明しています。
どちらの設計も、生まれた当時のネットワークには適していました。初期の Ethernet は共有メディアでした。セグメント上のすべてのマシンがすべてのフレームを受信し、自分宛てでないフレームを無視する設計でした。無視をやめたマシン、つまり promiscuous mode のマシンは、他のすべての通信を確認できました。さらに、大学が数千人の学生に shell アカウントを提供している環境では、1 つのアカウントが侵害されるだけで、学部全体のパスワード収集に使われる可能性がありました。
修正プログラムが提供されなかった1994年の勧告
1994年2月3日、CERTは勧告CA-94:01「継続的なネットワーク監視攻撃」を公開しました。この勧告では、侵入者がインターネット上の数万台のシステムからアクセス情報を取得したと報告されています。侵入者が使用したツールはネットワークインターフェイスをプロミスキャスモードに設定し、新しく開始されるすべてのtelnet、rlogin、FTPセッションの先頭部分を記録しました。そこにはユーザー名とパスワードが含まれます。
CERTは、ネットワーク経由でアクセスするすべてのアカウントのパスワードを変更するよう各サイトに勧告しました。しかし、各プロトコルの仕様に照らすと、問題は明らかです。新しいパスワードを初めて使用したときも、同じ回線を通って平文で送信されます。telnetにもrloginにも修正方法はありませんでした。どちらのプロトコルにも、その情報を安全に格納する場所がなかったためです。
Helsinki での盗聴攻撃から SSH が生まれた理由
1995 年、Helsinki University of Technology のネットワークが、CERT が説明していた種類のパスワード盗聴攻撃を受けました。同大学の研究者だった Tatu Ylönen は代替ソフトウェアを作成し、1995 年 7 月に freeware として公開しました。彼はそれを Secure Shell と名付けました。
このソフトウェアを支えた設計上の決定は 2 つあります。セッションを暗号化したため、ネットワークセグメント上で通信を監視しても有用な情報は得られませんでした。また、サーバーが cryptographic key で自身の正当性を証明したため、クライアントは正しいマシンに接続しているか確認できました。これは、rlogin がホスト名による信頼に任せていた弱点を解消するものでした。
さらに、利用者がすでに入力していたコマンドと同じ形式だったため、普及しました。ssh は rsh と rlogin の代わりになり、scp は rcp の代わりになりました。切り替えに必要だったのは作業手順の変更ではなく、習慣の変更だけでした。1995 年末までに、ユーザーベースは 50 か国でおよそ 20,000 ユーザーに達しました。同年 12 月、Ylönen はソフトウェアの開発と販売を目的として SSH Communications Security を設立しました。
フリーリリースから商用製品へ
SSH がビジネスとして成長すると、ソースコードのライセンスが変更されました。その後のリリースには、他者によるコードの利用を制限する条項が含まれ、誰でも自由に再利用できた最後のリリースは ssh 1.2.12 でした。これは不適切なことではありません。単に、世界中の利用者が基盤として利用できる SSH のバージョンの更新が止まり、その一方で開発は利用者が追随できない場所で続いたということです。どのコードが存続するかはライセンスによって決まります。このパターンについては、オープンソースライセンスが現代のインフラストラクチャを形作った経緯で詳しく確認できます。
OpenBSDが1999年にOpenSSHをフォークした理由
1999年初頭、Björn Grönvallは最後の無償リリースに戻り、バグ修正を始めました。彼のバージョンはOSSHと呼ばれ、SSH 1.3プロトコルだけを使用していました。
OpenBSDプロジェクトはOSSHを引き継ぎ、再構築しました。プロジェクト自身の説明によると、Theo de Raadt、Niels Provos、Markus Friedl、Bob Beck、Aaron Campbell、Dug Songがコードの整理、監査、拡張を行いました。その成果がOpenSSH 1.2.2であり、1999年12月1日にOpenBSD 2.6とともにリリースされました。
なぜ、1つの小規模なOSプロジェクトによるフォークが、ほぼすべてのマシンで使われるようになったのでしょうか。OpenBSDが必要としていたものを満たしていたからです。OpenBSDは、デフォルト設定で安全に動作することを目指した、監査済みのベースシステムを提供しています。そのため、暗号化されたリモートログイン機能も、そのベースシステムに含める必要があり、制限のないライセンスで提供されなければなりませんでした。制限のないライセンスで提供される監査済みコードは、他のすべてのOSベンダーも必要としていたものです。Damien Miller、Philip Handsらは、ほぼすぐにportableブランチを開始しました。バージョンの10.5p1に含まれるpは、ここに由来します。OpenBSDはクリーンなバージョンを開発し、portableブランチはその他の環境に対応するための接着コードを追加します。現在使われているシステムへUnixが分岐していった経緯があるため、この接着コードが必要になります。
2番目のプロトコルバージョンへの対応も続きました。OpenSSH 2.0は、2000年6月15日にOpenBSD 2.7とともにリリースされました。
SSH-2 はバージョンアップではなく新しいプロトコルである理由
SSH-1 は、暗号化ストリームの完全性を CRC-32 で保護していました。CRC-32 は、攻撃者への耐性ではなく、伝送エラーの検出を目的としたチェックサムです。1998 年、CORE SDI の Ariel Futoransky と Emiliano Kargieman は、この設計の問題を実証しました。CBC または CFB の暗号モードと CRC-32 検査を使用している場合、攻撃者は平文を 16 バイト程度しか知らなくても、受信側が正規のデータとして受け入れる選択暗号文を挿入できます。これにより、サーバー上でコマンドを実行できます。
この欠陥はプロトコル自体に存在したため、互換性を壊さずに修正することはできませんでした。そこで実装側は検出機能を追加しました。これは deattack.c というファイルに含まれるコードで、攻撃の発生中にそれを認識しようとするものでした。しかし 2001 年 2 月、この検出機能自体に整数オーバーフロー CVE-2001-0144 があることが判明しました。この欠陥により、パッチを適用したサーバーやクライアントに対してリモートコード実行が可能でした。修復できない設計にはパッチが積み重なり、そのパッチ自体が新たなバグを持ち込みます。
SSH-2 は secsh という IETF ワーキンググループで策定され、2006 年 1 月に RFC として公開されました。アーキテクチャは RFC 4251、トランスポート層は RFC 4253、ユーザー認証は RFC 4252、接続層は RFC 4254 で定義されています。重要なのは層に分割されたことです。これにより、各層を個別に置き換えられます。この後の歴史の大部分は、その置き換えが進んだ過程です。
特に重要な変更は 2 つあります。完全性の保護が CRC-32 から、共有秘密鍵を使用する HMAC(ハッシュベースのメッセージ認証コード)に移行しました。そのため、MAC を計算できない攻撃者はパケットを偽造できません。また、鍵共有方式が Diffie-Hellman に移行しました。SSH-1 では、クライアントがセッション鍵を選び、サーバーの RSA 鍵で暗号化して送信していました。そのため、後からサーバーの秘密鍵を入手した攻撃者は、記録済みのセッションを復号できました。Diffie-Hellman は、送信されることのない新しい秘密値をセッションごとに導出します。そのため、通信を記録しておき、後からホスト鍵を盗んでも何も得られません。この性質を前方秘匿性と呼びます。
SSH-2 は SSH-1 とワイヤーレベルの互換性を共有していません。これが、番号を小数点以下のバージョンとして変更するのではなく、番号自体を変更した理由です。
SSH-1 が修正ではなく削除された理由
削除には 3 つの OpenSSH リリースを要しました。Version 7.0 では、2015 年 8 月 11 日に、コンパイル時のデフォルト設定で protocol 1 を無効化しました。Version 7.4 では、2016 年 12 月 19 日に、protocol 1 のサーバーサポートを削除しました。Version 7.6 では、2017 年 10 月 3 日に、設定オプションとドキュメントも含めてクライアント側を削除しました。
古い機器向けの選択肢として残すほうが利用者には親切でした。しかし、CRC-32 検出器が、その選択が拒否された理由を示しています。オーバーフローが到達可能だったのは、protocol 1 のコードがコンパイルに含まれていたからです。また、そのコードは、多くの管理者が自分のシステムでは休止していると考えていた経路にありました。リリースされたコードには到達される可能性があります。削除されたコードには到達できません。
最初の SSH 接続でホストキーに関する警告が表示される理由
暗号化により、通信が非公開であることは保証されます。しかし、接続先が誰であるかは保証されません。攻撃者が通信経路に入り込み、サーバーの代わりに応答すると、攻撃者との通信が完全に暗号化されたセッションが確立されます。これは中間者攻撃です。SSH はホストキーでこの問題に対処します。サーバーはキーペアの秘密鍵を保持していることを証明し、クライアントはそのキーを前回記録した値と照合します。接続自体の仕組みについては、SSH 接続を開始すると何が起きるかを参照してください。
初回接続には前回の接続がないため、クライアントは比較対象を持っていません。そのため、次のように確認を求めます。
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])?yes と答えると、そのキーが ~/.ssh/known_hosts に保存されます。以後の接続では保存された値と照合され、不一致があると、プログラムは次の最も強い警告を表示します。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!この最初の確認メッセージを正直に解釈すると、プロトコル自身が、最初の接続に弱点があることを認めています。初回使用時の信頼では、最初の接続の安全性は、その接続に使用したネットワークの安全性に依存します。この弱点は解消できます。接続前に、プロバイダーのコンソールまたはサーバーのビルドログでフィンガープリントを確認してください。フィンガープリントを DNS に SSHFP レコード(RFC 4255)として公開する方法もありますが、DNSSEC を使用している場合に限って有効です。また、自分で運用する認証局(CA)でホストキーに署名し、クライアントが個々のキーではなく CA を信頼する構成にもできます。実際には、確認せずにこのメッセージを受け入れる人がほとんどです。この点は正直に認識しておくべきです。
公開鍵がパスワードに取って代わった理由
公開鍵認証は初期の SSH リリースから存在していましたが、一般的な運用になるまでには何年もかかりました。この仕組みは非対称です。クライアントはチャレンジに署名して秘密鍵を保持していることを証明し、秘密鍵がクライアントの外へ出ることはありません。一方、パスワードは逆の動作になります。SSH はパスワードを暗号化されたチャネル内で送信しますが、サーバーは実際の Secret を受け取ります。そのため、侵害されたサーバーや悪意のあるサーバーに、他の環境で再利用できる情報を保持されることになります。
2 つ目の理由は、総当たり攻撃の容易さです。公開アドレスで 22 番ポートを開いているサーバーには、常時、自動化されたログイン試行が届きます。パスワードは推測可能な文字列です。鍵は、現実的な意味で推測できません。PasswordAuthentication no を設定すると、この種類の攻撃を完全に防げるため、あらゆる hardening checklist に記載されています。ただし、鍵に問題が起きたときに以前は救済策となっていた fallback もなくなります。そのため、接続できなくなる前に、すべて Permission denied (publickey) と報告される複数の障害を見分ける方法を学んでください。パスワードを使わない運用では、鍵の数も増えます。十数個の鍵を保持する agent は、サーバーが試行回数の上限に達して接続を切断するまで、各鍵を順番に提示します。これが、正しい鍵が読み込まれていてもログインが Too many authentication failures で失敗する理由です。鍵の生成とローテーションについては SSH 鍵管理の基本で、サーバー側の設定については VPS の SSH を hardening する方法で説明します。
SSH のアルゴリズム一覧が変わり続ける理由
階層化されたプロトコルでは、新しいプロトコルを作成しなくてもアルゴリズムを廃止できます。OpenSSH はこの自由を継続的に活用しており、リリース日からその進み方が分かります。
Ed25519 は、chacha20-poly1305 cipher と bcrypt で保護された private key format とともに、2014 年 1 月 30 日に OpenSSH 6.5 で導入されました。Ed25519 の署名では、署名ごとの nonce が決定論的に生成されます。そのため、署名時の乱数生成器が弱くても private key が漏えいしません。実際のインシデントでは、DSA と ECDSA の private key がまさにこの方法で復元されています。
DSA は反対の経過をたどりました。OpenSSH 7.0 は 2015 年に、実行時に ssh-dss host key と user key を無効化しました。このアルゴリズムは 160-bit の private key と SHA-1 に制限されているためです。2024 年 7 月 1 日の Version 9.8 では、コンパイル時に DSA を無効化しました。2025 年 4 月 9 日の Version 10.0 では削除されました。プロジェクトの言葉では、「2015 年に始まった非推奨化プロセスを完了」したことになります。無効化から削除まで 10 年かかりました。
RSA 自体は消えませんでしたが、古い署名形式は消えました。2021 年 9 月 26 日の OpenSSH 8.8 では、SHA-1 で作成された RSA 署名をデフォルトで受け付けなくなりました。リリースノートには理由が明確に記載されています。SHA-1 は暗号学的に破られており、chosen-prefix collision は 50,000 USD 未満で実現可能でした。古いサーバーへの接続時に sign_and_send_pubkey: no mutual signature supported を見たことがあるなら、それがこの変更です。key に問題はありません。相手側が要求した署名アルゴリズムに問題があります。
同じプロセスは現在、脅威に先行して key exchange にも適用されています。現在取得された network traffic は保存され、将来、十分な性能を持つ quantum computer を最初に所有した者によって復号される可能性があります。そのため、そのようなマシンが存在する前に key agreement を変更する必要がありました。2022 年 4 月 8 日の OpenSSH 9.0 では、hybrid key exchange がデフォルトになりました。sntrup761x25519-sha512@openssh.com は post-quantum algorithm と X25519 exchange を組み合わせます。新しいアルゴリズムに問題があっても、結果が classical part より弱くならない構成です。2024 年 9 月 19 日の OpenSSH 9.9 では、2024 年に NIST が標準化した ML-KEM(module lattice key encapsulation mechanism)を基盤とする mlkem768x25519-sha256 が追加されました。OpenSSH 10.0 では、key agreement のデフォルトがこれに変更されました。プロジェクトの post-quantum ページで、その理由を説明しています。2025 年 10 月 6 日の OpenSSH 10.1 では、相手側がこれを使用できない場合に警告を表示するようになりました。
** 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.この警告はデフォルトで有効で、ssh_config の WarnWeakCrypto option で制御します。実際に何を意味するのか、また、この警告を発生させるサーバーにどう対処するのかは、post-quantum SSH key exchange のデフォルト設定で説明します。
目の前のサーバーにとって、この歴史が意味すること
入力するコマンドは、1995 年以降ほとんど変わっていません。その下で動くものは、ほぼすべて置き換えられています。完全性チェック、鍵交換、署名アルゴリズム、そしてコードベース自体も対象です。これが可能だったのは、各置き換えが意図的な削除で終わり、その削除によって誰かの環境で何かが動かなくなったからです。
そのため、SSH のセキュリティは主にバージョンで決まります。デフォルト設定には、提供するアルゴリズム、拒否するアルゴリズム、表示する警告に関する判断が組み込まれています。古いサーバーは、そのリリースでまだ許可されているアルゴリズムを提供し続け、古いクライアントに合わせるために、より古い方式へネゴシエーションを下げ続けます。2026 年 8 月時点の最新リリースは OpenSSH 10.5 で、2026 年 8 月 11 日に公開されました。これと、3 年間誰も触れていないマシンにインストールされたバージョンとの差が、問題の規模を示します。確認は新しい VPS で最初の 10 分に行う作業に含めるべきです。
FAQ
SSHを作成したのは誰で、なぜですか?
Helsinki University of Technologyの研究者だったTatu Ylönenは、大学のネットワークでパスワードの盗聴攻撃が発生した後、1995年にSSHを作成しました。当時のリモートログインツールであるtelnetとrloginは、パスワードを読めるテキストとしてネットワーク上に送信していました。そのため、共有セグメントを監視している人物は、通過する認証情報を収集できました。彼は1995年7月にこのプログラムをfreewareとして公開しました。同年末までに、50か国でおよそ20,000人が利用するようになり、1995年12月にはSSH Communications Securityを設立しました。
SSH-1とSSH-2の違いは何ですか?
両者は異なるプロトコルであり、wire互換性はありません。SSH-1は単一のモノリシックなプロトコルで、完全性の検証にCRC-32を使用し、クライアントがサーバーのRSA keysで暗号化したsession keyを送信していました。SSH-2は処理をtransport layer、authentication layer、connection layerに分割しています(RFCs 4251から4254、2006年1月)。完全性の検証にはHMACを使用し、Diffie-Hellmanでsession keysを導出します。そのため、後からhost keyが盗まれても、記録されたnetwork trafficの内容は保護されます。SSH-1はOpenSSHから段階的に廃止され、2017年10月のversion 7.6で終了しました。
OpenSSHが元のSSH実装に取って代わったのはなぜですか?
元の実装の開発は、制限の厳しいlicenseを持つcommercial productへ移行し、自由に再利用できる最後のreleaseはssh 1.2.12でした。1999年初頭、Björn GrönvallがこのreleaseをOSSHとして復活させ、OpenBSD teamがOSSHをforkしてOpenSSHを作成しました。OpenSSHは1999年12月1日にOpenBSD 2.6とともにreleaseされました。OpenBSDには、base systemで使用できる、監査済みで制限のないlicenseのcodeが必要でした。この2つの条件があったため、他のすべてのoperating systemもportable branchを通じて同じ実装をreleaseできました。
初めて接続するときにSSHがhost keyについて確認するのはなぜですか?
クライアントはそのserverを以前に認識したことがなく、keyと比較する対象がないためです。暗号化だけでは、正規のserverと通信経路の途中に存在するmachineを区別できません。そのためSSHはkeyでserverを識別し、確認した内容を~/.ssh/known_hostsに記録します。最初の接続では、照合できる保存済みの値がないため、クライアントが代わりに確認を求めます。fingerprintをprovider consoleまたはserver自体から取得した値と比較してください。その後にREMOTE HOST IDENTIFICATION HAS CHANGEDというmessageが表示された場合は、理由を説明できるまで実際の事象として扱ってください。
upgrade後に古いSSH keysが使えなくなるのはなぜですか?
OpenSSHが公開されたscheduleに従ってalgorithmsを廃止するためです。DSA(ssh-dss)keysは、2015年のOpenSSH 7.0でdefaultで無効になり、2025年4月9日のOpenSSH 10.0で完全に削除されました。RSA keysは引き続き使用できます。ただし、SHA-1で作成したsignaturesは、2021年9月のOpenSSH 8.8でdefaultで無効になりました。古いserverに接続すると、これはsign_and_send_pubkey: no mutual signature supportedとして表示されます。2014年1月のOpenSSH 6.5以降で利用できるEd25519 keyを使えば、両方の問題を回避できます。