目次
1.接続開始(TCP接続)
クライアントからサーバへ接続します。
- プロトコル:TCP
- ポート:通常 22番
例
ssh user@server
この時点では、まだ平文です
2.バージョン交換
接続直後、お互いにSSHのバージョンを交換します。
例:SSH-2.0-OpenSSH_8.9
- SSH1 / SSH2の判定
- 通常はSSH2が使われる
この時点では、まだ平文です
3.鍵交換(Key Exchange)
クライアントとサーバで以下を決めます。
- 暗号方式(AESなど)
- ハッシュ方式
- 鍵交換アルゴリズム(Diffie-Hellman など)
そして共通鍵(セッション鍵)を生成します。
処理の流れ
- クライアントとサーバの交渉(ネゴシエーション)で鍵交換アルゴリズムを決める
- クライアントとサーバが、その鍵交換アルゴリズムで共有秘密(K)を生成する
- その共有秘密からクライアントとサーバがセッション鍵を生成する(鍵派生)
この鍵は通信ごとに毎回変わる使い捨てです。
※鍵交換は、公開鍵認証ではありません。
鍵交換が完了した瞬間から暗号化に切り替わります。
4.サーバ認証(Host Key確認)
※厳密には鍵交換が完了してからサーバ認証という別ステップではなく鍵交換の一部です。
サーバが本物かどうかを確認します。
仕組み
- サーバはホスト鍵を持っている
- クライアントは過去に接続したホスト鍵を保存している
保存場所:~/.ssh/known_hosts
チェック内容
- 初回:登録するか聞かれる
- 2回目以降:一致するか確認
一致しない場合、なりすまし(MITM攻撃)対策で以下のメッセージが表示されます。
| WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! |
5.ユーザ認証
ログインできるかを確認します。
主な方式:
パスワード認証
user + password
公開鍵認証(推奨)
仕組み
- クライアント:秘密鍵を持ちます。
- サーバ:公開鍵を持ちます(authorized_keys)。
流れ
| 1.サーバ → クライアントにチャレンジ送信 | サーバはランダムなデータを生成して送ります。 challenge = ランダムなバイト列(例:0x3F A2 ...) |
| 2.クライアントは秘密鍵で署名します。 | 署名 = Sign(チャレンジ, 秘密鍵) |
| 3.サーバは公開鍵で検証します。 | Verify(チャレンジ, 署名, 公開鍵) |
→ OKであれば、ログイン許可します。
失敗の場合
| エラー | 原因 |
|---|---|
| Permission denied (publickey) | 公開鍵と秘密鍵が不一致 |
| no supported authentication methods | サーバ側で公開鍵認証が無効になっている クライアントが対応する認証方式を持っていない |
| bad permissions | 鍵ファイルの権限 |
6.セッション開始
認証成功後、
- シェルが起動(bashなど)
- コマンド実行可能
- scp / sftp も同じ仕組み
7.通信の暗号化
以降の通信はすべて暗号化されます。
- コマンド
- 出力結果
- ファイル転送
→盗聴されても読めない
実務でよくあるトラブルとの対応関係
| エラー | 原因 |
|---|---|
| Host key verification failed | known_hosts不一致 |
| Connection timed out | SG / FW / ポート閉塞 |
| Permission denied (publickey) | 鍵不一致 or 権限不備 |
| REMOTE HOST IDENTIFICATION HAS CHANGED | サーバ鍵変更 or 攻撃の可能性 |
関連の記事
