🤔

SSHの基本を理解したい(シーケンス図付き)

に公開

1. 初回 SSH 接続時の流れ (秘密鍵のパスフレーズ入力あり)

このシナリオでは、ユーザーが初めて特定のサーバーに SSH 接続を試みるか、あるいは SSH エージェントにまだ該当の秘密鍵がロードされていない状況を想定します。秘密鍵はパスフレーズで保護されているものとします。

登場人物

  • User: 操作を行うユーザー
  • SSH_Client: ユーザーが操作する SSH クライアント(例: sshコマンド)
  • SSH_Agent: SSH エージェントプロセス(秘密鍵をメモリに保持)
  • SSH_Server: 接続先の SSH サーバー

初回接続時の流れのポイント解説:

  1. ユーザーが SSH クライアントを通じて接続を開始します。
  2. 基本的な TCP 接続と SSH プロトコルの初期設定が行われます。サーバーは自身のホスト鍵を提示し、クライアントは(必要であればユーザーに確認の上)それを検証します。この際、初回接続であればクライアントとユーザー間でホスト鍵のフィンガープリント確認と承認のやり取りが発生します。
  3. 認証段階に入ると、SSH クライアントはまず SSH エージェントに適切な秘密鍵がロードされているか問い合わせることがあります。
  4. このシナリオではエージェントに鍵がないため、クライアントはディスク上の秘密鍵ファイル(例: ~/.ssh/id_rsa)を使用しようとします。
  5. 秘密鍵がパスフレーズで保護されているため、ユーザーにパスフレーズの入力が求められます。
  6. パスフレーズが正しければ秘密鍵が復号され、クライアントはその公開鍵部分をサーバーに提示します。
  7. サーバーは提示された公開鍵が、予めサーバー上のユーザーの ~/.ssh/authorized_keys ファイルに登録されているか確認します。
  8. 登録されていれば、サーバーはチャレンジ(ランダムなデータ)をクライアントに送ります。
  9. クライアントは復号した秘密鍵でチャレンジに署名し、サーバーに返送します。
  10. サーバーが署名を検証し、正当であれば認証成功となり、SSH セッションが開始されます。
  11. 接続成功後、ユーザーは次回以降の接続のために、使用した秘密鍵を ssh-add コマンドで SSH エージェントに追加することが推奨されます。この際、再度パスフレーズの入力が求められることがあります(エージェントが秘密鍵を復号してメモリに保持するため)。

【補足】複数の鍵ペアが存在する場合の鍵選択について

もしクライアント側に複数の秘密鍵が存在する場合(例: server1_key, server2_key, server3_key など)、SSH クライアントは以下の優先順位でどの鍵を使用するかを決定しようとします。

  1. コマンドラインオプションでの指定: ssh -i ~/.ssh/server3_key user@server のように -i オプションで秘密鍵ファイルが明示的に指定されていれば、その鍵が試されます。
  2. SSH クライアント設定ファイル (~/.ssh/config): ~/.ssh/config ファイル内で、接続先ホストに対応する IdentityFile ディレクティブで鍵が指定されていれば、その鍵が試されます。
    Host server3
        IdentityFile ~/.ssh/server3_key
    
  3. SSH エージェントにロードされた鍵: SSH エージェントに鍵がロードされている場合、クライアントはエージェントに問い合わせます。サーバー側から利用可能な公開鍵が提示された後、サーバーが受け入れ可能な公開鍵(対象サーバーの authorized_keys に登録されているもの)を指定し、クライアントはその公開鍵に対応する秘密鍵をエージェントに要求して署名処理を行います。
  4. デフォルトの秘密鍵ファイル: 上記いずれにも該当しない場合、クライアントは ~/.ssh/id_rsa, ~/.ssh/id_ed25519 などのデフォルトのパスにある秘密鍵を順番に試します。クライアントはこれらの鍵の公開鍵部分をサーバーに提示し、サーバーが受け入れ可能なものがあれば認証プロセスが進みます。

これらのステップを経て、適切な鍵ペアが選択され、認証処理が行われます。


2. 2 回目以降の SSH 接続時の流れ (SSH エージェント利用、パスフレーズ入力なし)

このシナリオでは、SSH エージェントが起動しており、前回の接続後などに対象の秘密鍵が既にエージェントにロード(ssh-add済みでパスフレーズも入力済み)されている状況を想定します。

登場人物

  • User: 操作を行うユーザー
  • SSH_Client: ユーザーが操作する SSH クライアント(例: sshコマンド)
  • SSH_Agent: SSH エージェントプロセス(秘密鍵をメモリに保持)
  • SSH_Server: 接続先の SSH サーバー

2 回目以降の接続時の流れのポイント解説:

  1. ユーザーが SSH クライアントを通じて接続を開始します(初回と同様)。
  2. TCP 接続と SSH プロトコルの初期設定も同様に行われます。サーバーホスト鍵は通常 known_hosts ファイルにより検証されます。
  3. 認証段階で、SSH クライアントは SSH エージェントに適切な秘密鍵がロードされているか問い合わせます。
  4. 今回は SSH エージェントが該当の秘密鍵を(復号された状態で)メモリに保持しているため、「鍵あり、署名準備 OK」とクライアントに応答します。この時点でユーザーによるパスフレーズ入力は不要です。
  5. クライアントは、エージェントが使用できる公開鍵をサーバーに提示します。
  6. サーバーは提示された公開鍵が ~/.ssh/authorized_keys に登録されているか確認します。
  7. 登録されていれば、サーバーはチャレンジ(ランダムなデータ)をクライアントに送ります。
  8. クライアントは受け取ったチャレンジの署名を SSH エージェントに依頼します。
  9. SSH エージェントはメモリ上の秘密鍵を使ってチャレンジに署名し、結果をクライアントに返します。
  10. クライアントはその署名済みチャレンジをサーバーに送ります。
  11. サーバーが署名を検証し、正当であれば認証成功となり、SSH セッションが開始されます。

まとめ

本記事では、SSH 公開鍵認証における「初回接続時(パスフレーズ入力あり)」と「SSH エージェント利用時(パスフレーズ入力なし)」という 2 つの主要なシーケンスについて、Mermaid で記述した図とポイント解説を通じて、その詳細な流れを自分なりの理解のために書いてみました!!

これらのシーケンスを段階的に追うことで、普段何気なく利用しているsshコマンドの裏側で、クライアント、サーバー、そして SSH エージェントがどのように連携し、セキュアな通信路を確立しているのか、その具体的なイメージを掴んでいただけたのではないでしょうか。特に、パスフレーズ入力の有無の理由や、SSH エージェントが果たす役割の重要性について、自分なりの理解が深まったことと思います!🫠

自分の中では、複数の公開鍵と秘密鍵の組み合わせがローカルマシンに存在する時の流れが把握できてとても良かったと思ってます。✨

この記事が、皆さんの SSH に対する理解を一段深めるための一助となれば幸いです。🫨

参考資料

Discussion