SSHとは ― 接続の流れと公開鍵認証
SSHとは、
SSHとは、暗号化して遠隔操作するプロトコル
SSH(Secure Shell)は、離れたコンピュータをネットワーク越しに安全に操作するためのプロトコルです。サーバはTCPの22番で待ち受け、通信の暗号化・サーバの確認・利用者の確認の3つを接続のたびに行います。
SSHは、3つの部分を積み重ねた構成です。1つ目は暗号化とサーバの確認、2つ目は利用者の確認を受け持ち、3つ目は端末の操作や転送を運びます。
同じ遠隔操作のプロトコルであるTELNETとの違いは、暗号化の有無です。TELNETとのポート番号の比較は、FTP・TELNET・NTPの記事にあります。以下では、接続の流れと暗号の鍵の仕組みを図で説明します。
SSHの仕組み:接続の流れを6段階で見る
SSHの接続は、6段階で進みます。段階ごとに、通信の暗号化・サーバの確認・利用者の確認がどう変わるかを、次の図で確かめられます。
クライアントが、サーバのTCP 22番へ接続します。つながると、双方がSSHのバージョンとソフトウェア名を文字列で送ります。この文字列は SSH-2.0 で始まります。ここまでの通信は、暗号化されていません。
お互いが、使える方式の一覧を送ります。鍵の作り方、サーバの署名の種類、暗号化の方式、改ざんを検知する方式などです。暗号化の方式は、クライアントの一覧の先頭から順に探し、サーバの一覧にもある最初のものに決まります。共通のものがなければ、接続は切れます。
クライアントとサーバは、計算に使う値を1つずつ送り合います。受け取った値と、自分だけが知る数から、両方が同じ共通の秘密を計算します。共通の秘密そのものは、通信路を流れません。RFC 4253は、この鍵交換の方式として、Diffie-Hellman鍵交換を定めています。サーバは返事に、自分のホスト鍵と、ホスト鍵の秘密鍵で作った署名を添えます。
クライアントは、届いたホスト鍵が目的のサーバのものかを、手元の記録と照合して確かめます。記録のない初めてのサーバなら、鍵の指紋が表示され、続けてよいかを聞かれます。署名も検証できたら、双方が「ここから新しい鍵を使う」という合図を送ります。以降の通信は暗号化されます。
ここからは、暗号化された通信の中です。クライアントは、利用者の確認を始めたいと伝えます。サーバが使える認証方法を知らせ、クライアントはその中から選んで試します。パスワードも、公開鍵認証の署名も、暗号化された通信の中で送られます。
認証が通ると、次のサービスが始まります。クライアントはチャネルを開き、シェル(コマンドを受け付けるプログラム)の起動を依頼します。ここから先が、利用者が見る遠隔操作の画面です。入力した文字も、結果の表示も、暗号化されて流れます。
ステップ3の共通の秘密からは、通信を暗号化する鍵と、改ざんを検知する鍵が作られます。通信の暗号化には、共通鍵暗号方式を使います。公開鍵暗号方式は、共通の秘密を作る鍵交換と、サーバと利用者の確認に使います。この分担は、HTTPSにも共通する考え方です。
ステップ4で暗号化が始まる前の通信は、平文です。ただし、ステップ3で流れるのは計算用の値とホスト鍵と署名で、共通の秘密そのものは流れません。
サーバがTCPの22番で待ち受けているかは、netstat・ss・digの記事の方法で確かめられます。
ホスト鍵と known_hosts:初めての接続で何を確かめるか
ホスト鍵は、サーバが自分を証明するために持つ鍵のペアです。サーバは秘密鍵を自分だけで持ち、公開鍵をクライアントに渡します。サーバはステップ3で秘密鍵で署名を作り、クライアントは公開鍵でその署名が正しいことを確かめます。
ただし、署名が正しいだけでは、その公開鍵が目的のサーバのものかどうかは分かりません。偽のサーバも、自分の鍵のペアで署名を作れるからです。そのためクライアントは、目的のサーバの公開鍵を、あらかじめ知っている必要があります。
RFC 4251は、その方法を2つ挙げています。1つは、クライアントの手元に、ホスト名と公開鍵の対応表を持つ方法です。もう1つは、信頼できる認証局がその対応を保証する方法です。
OpenSSHの標準的な使い方は前者で、対応表は利用者のホームディレクトリの ~/.ssh/known_hosts に保存されます。初めて接続するサーバは、この表に載っていません。
$ ssh user@example.com
このサーバの鍵が手元の記録にないので、本物かどうか確かめられないという意味です。括弧の中は、入力した名前と、接続先のIPアドレスです。
サーバが示した公開鍵の指紋です。ED25519は鍵の種類で、SHA256は指紋の計算に使った方式です。サーバの管理者から別の手段で受け取った指紋と同じなら、本物と判断できます。
続けてよいかの質問です。yesと答えると、この鍵が known_hosts に記録され、2回目からは自動で照合されます。noと答えると、接続をやめます。
yesと答えた結果、記録が追加されました。Warningと付いていますが、異常を知らせる表示ではありません。
行をクリックすると、その行の意味が開きます。
指紋は、公開鍵から計算した短い文字列です。表示の細部は、OpenSSHのバージョンで少し違います。
この時点で、通信はすでに暗号化されています。ただ、相手が本物かどうかは、yesと答える人の判断にかかっています。RFC 4251によると、この確認を省いた場合、盗聴は防げますが、通信の途中に入り込んで双方になりすます中間者攻撃には弱くなります。
ホスト鍵が変わったときの警告
OpenSSHは、記録と違う鍵を示されると「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」と警告し、既定の設定では接続を中止します。
原因には、中間者攻撃の場合と、サーバのホスト鍵が正当に変わっただけの場合があります。警告の文面は、システム管理者への連絡を求めています。鍵が正当に変わったと確かめられたら、known_hosts の古い記録を直してから接続し直します。
パスワード認証と公開鍵認証の違い
サーバが利用者を確認する方法には、パスワード認証と公開鍵認証があります。RFC 4252では、公開鍵認証はすべての実装が対応しなければならない方法で、パスワード認証は対応が望ましい方法とされています。
パスワード認証は、パスワードをサーバに送る
パスワード認証では、クライアントがパスワードをサーバに送ります。暗号化された通信の中で送るので途中では読まれませんが、パスワードそのものがサーバに届きます。
サーバが乗っ取られていると、そこでパスワードが読み取られます。RFC 4251も、パスワード認証はサーバの安全を前提にしていると指摘しています。
公開鍵認証は、秘密鍵で作った署名を送る
公開鍵認証では、利用者があらかじめ鍵のペアを作り、公開鍵だけをサーバに登録します。OpenSSHでは、サーバ側の ~/.ssh/authorized_keys に公開鍵を1行ずつ書きます。秘密鍵は、利用者の手元に残します。
ログインのとき、クライアントは秘密鍵で署名を作って送り、サーバは登録された公開鍵で署名を検証します。秘密鍵を持っていることが、そのまま本人の証明になります。
署名の対象には、ステップ3でできた、この接続だけのセッション識別子が含まれます。秘密鍵は暗号化して保存することが多く、署名を作るときに利用者がパスフレーズを入力します。秘密鍵のファイルを盗まれると持ち主になりすまされるので、取り扱いに注意が必要です。
| 比べる | パスワード認証 | 公開鍵認証 |
|---|---|---|
| サーバへ送るもの | パスワードそのもの | 秘密鍵で作った署名 |
| サーバが持つもの | パスワードを確かめる情報 | 公開鍵だけ |
| サーバが乗っ取られたとき | パスワードが読み取られる | 公開鍵しかなく、秘密鍵は読み取られない |
| 利用者の手元にあるもの | 覚えたパスワード | 秘密鍵のファイル |
公開鍵認証は、サーバの安全性を前提にしません。サーバが乗っ取られても、読み取れるのは公開鍵だけです。暗号化はどちらの認証でも使われるので、違いはサーバに何が届くかです。
ホスト鍵と利用者の鍵は、確かめる向きが逆
SSHには、役割の違う鍵のペアが2組あります。どちらも公開鍵と秘密鍵の組ですが、確かめる向きが逆です。
| 比べる | ホスト鍵 | 利用者の |
|---|---|---|
| 鍵のペアを持つのは | サーバ | 利用者(クライアント側) |
| 確かめるのは | クライアントが、サーバを | サーバが、利用者を |
| 確かめる段階 | ステップ4(暗号化を始める前) | ステップ5(ユーザー認証) |
| 公開鍵の置き場所(OpenSSH) | クライアントの known_hosts | サーバの authorized_keys |
ホスト鍵は、クライアントが「この相手は本物のサーバか」を確かめるための鍵です。利用者の鍵は、サーバが「この人は登録された利用者か」を確かめるための鍵です。2組とも、通信を暗号化する鍵とは別のものです。暗号化の鍵は、ステップ3の共通の秘密から作られます。
1本の接続で運べるもの:ポートフォワーディングとSFTP
SSHの1本の接続には、チャネルという論理的な通信路をいくつも束ねられます。端末の操作も、転送された通信も、それぞれ別のチャネルとして1本の接続を共有します。
ポートフォワーディング:別の通信をSSHの中に通す
ポートフォワーディングは、片側のポートに届いた通信を、SSHの暗号化された接続に乗せて、反対側から別の宛先へ渡す機能です。手元のポートを入口にする場合は、-L で指定します。自分のPCのターミナルで次のように入力すると、PCの8080番がサーバの80番につながります。
$ ssh -L 8080:localhost:80 user@203.0.113.50 # 自分のPCの8080番に届いた通信が、SSHの接続の中を通ってサーバへ運ばれます。 # サーバは、その通信を自分自身(localhost)の80番へ渡します。
ブラウザで localhost:8080 を開くと、203.0.113.50 のサーバの80番にあるWebページが、暗号化された通信で届きます。Web以外の通信でも、仕組みは同じです。転送される通信は、SSHの接続の中を通る間、暗号化されます。外から直接入れない内部のサーバへ接続するときの使い方は、踏み台サーバの記事で説明しています。
この名前は、ルータで設定するポート開放の別名と同じですが、中身は別のものです。ポート開放はルータの変換テーブルの設定で、SSHのポートフォワーディングはSSHの接続を使う機能です。
RFC 4251は、この転送がファイアウォールに検知されずに通り抜ける通信にもなりうると注意し、管理者が転送を制御できる仕組みを実装に求めています。ファイアウォールが通す通信を絞っていても、許可されたSSHの通信の中に別の通信が隠れることがあるためです。
SFTP:SSHの上でファイルを運ぶ
SFTPは、SSHの暗号化された接続の上でファイルを転送するプロトコルです。OpenSSHのsftpは、すべての操作をSSHの通信路の上で行います。FTPとの違いは、FTP・TELNET・NTPの記事で比べています。
Ansibleのような自動化ツールも、SSHなどの既存の接続手段で機器を操作します。この使われ方は、ネットワーク自動化の記事で説明しています。
練習問題(全6問)
正解:秘密鍵で
公開鍵認証では、
正解:サーバの
サーバは、
正解:サーバの
OpenSSHは、
正解:サーバが
known_hosts の
正解:サーバには
パスワード認証では、
正解:自分の
-L は、
選んでから「採点する」を押すと、解説つきで答え合わせができます。
参考にした資料
- RFC 4251 The Secure Shell (SSH) Protocol Architecture:全体の構成、ホスト鍵の信頼モデル
- RFC 4252 The Secure Shell (SSH) Authentication Protocol:パスワード認証と公開鍵認証
- RFC 4253 The Secure Shell (SSH) Transport Layer Protocol:22番、方式の合意、鍵交換
- RFC 4254 The Secure Shell (SSH) Connection Protocol:チャネルとポートの転送
- OpenSSH ssh(1) マニュアル:known_hosts、authorized_keys、-L
- OpenSSH sftp(1) マニュアル:SFTPとSSHの関係
- OpenSSH sshconnect.c:初回接続の確認文と警告の文面
関連記事
おすすめの本 PR
ネットワークを初めて学ぶ人向けの入門書です。
![『[改訂新版]3分間ネットワーク基礎講座』の表紙](https://m.media-amazon.com/images/P/4774143731.09.MZZZZZZZ.jpg)
