SSH認証が複雑に見えるのは、目的の違う3つのフェーズが順番に並んでいるから。分けて見れば怖くない。カギは「クライアントとサーバーが、逆向きに確かめ合う」という一点です。
SSHは接続してからログインが確定するまで、次の3段階を必ずこの順で通ります。①と③で「疑う向き」が逆なのが最大のポイント。①ではクライアントがサーバーを疑い、③ではサーバーがあなたを疑う。お互いを確かめ合うわけです。
つなぐ相手は本物のサーバー? 偽物にすり替えられていない?
確認する側 → クライアント誰にも読めない暗号トンネルを先に作る。まだ本人確認はしない。
両者で共通鍵を作るログインしていいのはあなた? 許可された人か?
確認する側 → サーバー順番も意味があります。②で暗号トンネルを先に作るから、③のパスワードや署名が平文で流れません。「まだ認証は終わっていない」と本が念押しするのはこの理由です。
初学者が必ずつまずくのがこの2ファイル。名前も置き場所も役割も“逆”です。ここに色をつけて覚えると、後の図が全部つながります。
この先、known_hosts は必ずクライアント色、authorized_keys は必ずサーバー色で出てきます。色で役割を思い出せるようにしてあります。
回線の途中で偽サーバーにすり替えられていないかを確認します。判断材料は、クライアント手元の known_hosts です。
「記録が無い」ときに出るのが、初めての接続で必ず見るこの警告です。公開鍵そのものは長いので、ハッシュ(フィンガープリント)だけを見せて「この相手、信じる?」と聞いてきます。
$ ssh mowree@192.168.56.109 The authenticity of host '192.168.56.109' can't be established. ED25519 key fingerprint is SHA256:9x8s...Kf2a. Are you sure you want to continue connecting (yes/no)? yes # yes と答えると、この公開鍵が known_hosts に保存される # → 次回からは一致するので、黙って繋がる
一度保存した鍵と違う鍵が飛んできたら「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」という強い警告が出ます。これが中間者攻撃(なりすまし)に気づくための仕組みです。安易に鍵を消して繋ぎ直すのは危険。
サーバーが本物だと分かったので、次は盗聴対策。回線は誰でも覗ける前提なので、クライアントとサーバーだけが知る共通鍵を、盗聴されても漏れない方法で共有します。
これに使うのが Diffie–Hellman鍵共有。「やりとりを全部見ていても、共通鍵そのものは計算できない」という数学の性質を使います。ここで作るセッションID(この接続だけの使い捨ての値)が、あとで③でも登場するので覚えておいてください。
この時点でも、まだ「あなたが誰か」は一切確認していません。できたのは暗号トンネルだけ。本人確認は次の③でようやく始まります。
パスワード認証もありますが、SSHの主役は公開鍵認証。使う道具はデジタル署名です。まず前提から。
ssh-keygen で自分のPCに鍵ペアを作ります。
この公開鍵 vk を、ログインしたいサーバーの authorized_keys に事前登録しておきます。「この鍵の持ち主は入れてよい」という名簿に一行加えるイメージです。
「ユーザー名・自分の公開鍵・セッションID」をまとめたデータに、秘密鍵 sk で署名 σ を作る(Sign)。
元データと署名 σ をセットにしてサーバーへ送信する。
送られた公開鍵が authorized_keys に載っているか確認。載っていなければ即NG。
その公開鍵 vk で署名 σ を検証(Ver)。出力が 1(正しい) なら認証OK、ログイン許可。
サーバーが見ているのは「公開鍵を知っているか」ではなく「その公開鍵に対応する秘密鍵で署名を作れるか」です。署名は秘密鍵がないと作れない。攻撃者は公開鍵を持っていても秘密鍵を持っていないので、正しい署名を作れず Ver が 0 を返して弾かれます。ここが公開鍵暗号の非対称性の肝です。
もし毎回同じデータに署名していたら、攻撃者が過去に流れた署名を盗んで使い回す(リプレイ攻撃)ことができてしまいます。②で作った使い捨てのセッションIDを署名対象に含めるので、盗んだ署名は次の接続では通用しません。
※本の図の「データはセッションIDを含んでいません」は“送信するデータ本体”の話。“署名対象”には入っている、という区別です。
「秘密鍵のパスフレーズ」と「サーバーのパスワード認証」は別物です。パスフレーズは、手元の秘密鍵ファイルを復号するためのもの。ネットワークには流れません。
パスフレーズ無しで鍵を作ると、その鍵ファイルはそのまま使えてしまいます(=ファイルを盗まれた瞬間アウト)。だからパスフレーズは付けておくのが安全です。
authorized_keys は「この公開鍵の持ち主はログインを許す」という名簿でした。ということは——
攻撃者が何らかの手段でサーバーの ~/.ssh/authorized_keys に自分の公開鍵を書き込めれば、自分の秘密鍵で正規ユーザーとしてSSHログインできてしまう。前に見た LFI や書き込み可能な脆弱性から authorized_keys に一行追記する——これはCTFでも実戦でも定番の手口です。
だから防御側は、authorized_keys の書き込み権限と見覚えのない公開鍵エントリを監視します。侵害ホストを調べるとき、.ssh/authorized_keys に知らない鍵が増えていないかは、.bashrc の改ざん確認と並ぶ定番チェックポイントです。
known_hosts でサーバーを確認。初回の「本当に繋ぐ?」がこれ。authorized_keys + 署名検証であなたを確認。秘密鍵を持つ本人しか署名を作れない。known_hosts=クライアントがサーバーを疑う / authorized_keys=サーバーがユーザーを疑う。ここが腹落ちすれば図が全部つながる。authorized_keys に公開鍵を書ければ侵入できる。書き込み経路(LFIなど)と鍵の監視が要。