このページの目次

SSH プロトコル

SSH は単なる「暗号化された telnet」ではない——トランスポート層(鍵交換+暗号化)、認証層(公開鍵/パスワード/証明書)、接続層(ポートフォワーディング/X11/SFTP のマルチプレクシング)の 3 層が分離されている。ポートフォワーディングにより、SSH は「スイスアーミーナイフ」のような存在となる。

概要

SSH(Secure Shell, 1995/2006)は Unix/Linux システム管理の中核ツールである。プロトコルは 3 層に分かれている:Transport Layer は鍵交換と暗号化を行い、User Authentication Layer は身份認証(公開鍵/パスワード/TOTP)を行い、Connection Layer は単一の TCP 接続上で shell/port forwarding/SFTP などのチャネルをマルチプレクシングする。SSH のポートフォワーディング(-L/-R)は簡易 VPN として機能し、暗号化トンネルを通じてリモートポートをローカルにマッピングできる。SSH 2.0 は SSH 1.x の重大なセキュリティ問題を修正したものであり、現代において唯一安全なバージョンである。

3 層アーキテクチャ

Connection Protocol (RFC 4254):  channels (shell, exec, forward, SFTP)
User Authentication (RFC 4252):  password, publickey, keyboard-interactive
Transport Layer (RFC 4253):      key exchange, encryption, server auth
TCP

Transport Layer: 鍵交換 (curve25519-sha256)

SSH 鍵交換の5ステップ (curve25519-sha256) ① 接続確立とアルゴリズム合意 ② DH 鍵交換 ③ 鍵導出とホスト認証 バージョン交換 C ↔ S で SSH-2.0-OpenSSH_9.6 を交換 アルゴリズム合意 (KEXINIT) 候補リスト: kex / host_key 暗号化アルゴリズム / MAC アルゴリズム C → S: KEX_ECDH_INIT 一時公開鍵 Q_C を送信 S → C: KEX_ECDH_REPLY K_S (サーバー公開鍵) + Q_S (一時公開鍵) H に対する署名で秘密鍵の所持を証明 共有秘密鍵の計算 shared secret → H = session_id IV / 暗号化鍵 / MAC 鍵 (双方向) を導出 クライアントによる K_S の検証 初回接続: 指紋を確認 known_hosts に書き込み/照合 検証順序が重要である:署名によりまずサーバーが K_S 秘密鍵を所持していることを証明し、known_hosts の照合で中間者攻撃を防ぐ。 初回接続の信頼は TOFU (Trust On First Use) に依存する——これは SSH において自動化検証が唯一不可能な箇所である。

User Authentication

方法 (順序で試行):
  1. publickey: クライアント: sign(session_id + request + publickey, privatekey)
     サーバー: verify → SSH_MSG_USERAUTH_SUCCESS
  2. keyboard-interactive: TOTP または challenge-response
  3. password: 暗号化チャネル内で送信 (安全)

Connection Layer: チャネルマルチプレクシング

各チャネルは独立:
  SSH_MSG_CHANNEL_OPEN: type="session" → channel 0
  SSH_MSG_CHANNEL_OPEN: type="direct-tcpip" → channel 1 (ポートフォワーディング)

チャネルタイプ:
  session:         shell, exec, subsystem (SFTP)
  direct-tcpip:    ローカルポートフォワーディング (-L)
  forwarded-tcpip: リモートポートフォワーディング (-R)

ポートフォワーディング

ローカル (-L 8080:internal:80): SSH クライアントが :8080 でリッスン → トンネル → SSH サーバーが internal:80 に接続
リモート (-R 3000:localhost:22): SSH サーバーが :3000 でリッスン → トンネル → SSH クライアントが localhost:22 に接続

参考

  • RFC: 4251-4254, 5656, 8731
  • ソースコード⁠: OpenSSH (sshconnect2.c for auth, channels.c for channels)

Keywords: SSH, transport, kex, publickey, channel, port forwarding, SFTP, known_hosts