SSH
Secure Shell ・ えすえすえいち
暗号化された安全な遠隔操作チャネル。サーバ運用とGit操作の足回り。
概要
SSH(Secure Shell)は、ネットワーク越しに別のコンピュータを安全に操作するためのプロトコルです。ssh user@example.com と打てば、暗号化された通信路の先に相手マシンのシェルが開き、目の前の端末を操作するのと同じようにコマンドを実行できます。サーバにログインして設定を変える、ログを調べる、ファイルを転送する — サーバ運用の日常作業のほぼすべてがSSHの上で行われています。
SSHの守備範囲は遠隔シェルにとどまりません。ファイル転送のscp/SFTP、Gitのpush/pullの通信路、後述するポートフォワーディングによる任意の通信の中継など、「認証済みの暗号化チャネル」を土台とした多目的トンネルとして使われています。GitHubに公開鍵を登録する、デプロイ先サーバに鍵でログインする、といった操作は開発者の通過儀礼と言ってよいでしょう。
標準ではTCPの22番ポートで待ち受けます。インターネットに露出した22番ポートには世界中から不正ログイン試行が絶え間なく届くため、SSHの設定はサーバセキュリティの最初の関門でもあります。
なぜ生まれたか
SSH以前、遠隔操作にはtelnet、ファイル転送にはFTP、UNIX間の遠隔実行にはrsh/rloginが使われていました。これらに共通する致命的な問題は、パスワードを含むすべての通信が平文で流れることです。同じネットワークにいる誰かがパケットを覗けば、ログインパスワードがそのまま読めてしまいます。牧歌的な学術ネットワークの時代には許容されていたこの前提は、インターネットの商用化とともに崩壊しました。
決定打は1995年、フィンランドのヘルシンキ工科大学で起きたパスワード盗聴事件です。大学のネットワークに仕掛けられたスニファ(盗聴プログラム)で大量のパスワードが盗まれたことを受け、同大学のTatu Ylönenが「telnetとrshをそのまま置き換えられる、暗号化された遠隔操作ツール」としてSSHを開発・公開しました。既存の操作感を変えずに通信だけを安全にしたSSHは爆発的に普及し、のちにプロトコルを再設計したSSH-2がIETFで標準化され、フリー実装のOpenSSHが事実上の標準となって現在に至ります。telnetによるサーバ管理は、今日では「やってはいけないこと」の代名詞です。
詳細
二段構えの暗号 — ホスト認証とユーザ認証
SSHの接続は二段構えです。まず接続直後に鍵交換を行って通信路全体を暗号化し、そのなかでサーバの正体確認(ホスト認証)とユーザの本人確認(ユーザ認証)を行います。TLSと似た構図ですが、TLSが認証局の証明書でサーバを検証するのに対し、SSHは認証局を前提とせず、後述するknown_hostsによる素朴な照合を使う点が対照的です。
ユーザ認証の方式で最も重要なのが公開鍵認証です。パスワード認証がパスワードそのもの(の検証情報)をサーバに送るのに対し、公開鍵認証では秘密の情報が一切ネットワークを流れません。公開鍵暗号の鍵ペアを作り、公開鍵をあらかじめサーバの authorized_keys に登録しておくと、認証は次の流れで進みます。
サーバが送ったチャレンジに対し、対応する秘密鍵の持ち主だけが正しい署名を作れる — これが本人確認の根拠です。秘密鍵は手元のマシンから出ていかないため、通信を盗聴されても、悪意あるサーバに接続してしまっても、認証情報は漏れません。総当たり攻撃も事実上不可能なため、実務ではパスワード認証を無効化して公開鍵認証のみに絞るのが定石です。秘密鍵自体はパスフレーズで暗号化して保管し、ssh-agentに一度だけ読み込ませて使い回すのが典型的な運用です。
known_hosts — 相手は本物か
初めてのサーバに接続すると「このホストの真正性は確認できません。続行しますか?」と聞かれます。これはホスト認証の仕組みで、サーバが名乗ったホスト鍵の指紋を利用者が確認し、承認すると known_hosts ファイルに記録される流れです。次回以降は記録と自動照合され、もし鍵が変わっていれば大きな警告が出ます。これはサーバの再構築で鍵が変わっただけのこともありますが、偽サーバに誘導する中間者攻撃の兆候かもしれません。「いつものWARNINGだから」と known_hosts の該当行を機械的に消すのは、SSHの安全性の片翼を自ら外す行為です。最初の接続(Trust On First Use と呼ばれる割り切り)だけは検証が利用者任せになる、というのがこのモデルの弱点で、厳格な組織では指紋の事前配布や認証局方式(SSH証明書)で補います。
ポートフォワーディング — 暗号化チャネルの転用
SSHの応用範囲を大きく広げているのがポートフォワーディングです。確立済みのSSH接続をトンネルとして、別の通信を相手側へ運ぶ機能で、いわば1本のSSHを簡易VPNとして使う仕組みです。
代表はローカルフォワーディングです。たとえば ssh -L 15432:db.internal:5432 bastion と実行すると、手元の15432番ポートへの接続が、踏み台サーバbastion経由で社内のデータベースサーバの5432番へ転送されます。ファイアウォールの内側にあるDBに、手元のツールから localhost:15432 としてつなげるわけです。逆向きのリモートフォワーディング(-R)は、サーバ側のポートへの接続を手元へ引き込むもので、開発中のWebアプリを一時的に外部へ公開するといった用途に使われます。踏み台を経由して目的のサーバへ直接つなぐ ProxyJump(多段SSH)も、クラウド時代のサーバ運用では日常の道具です。
運用の落とし穴
SSHは強力なぶん、雑に扱うと事故の温床になります。定番の失敗は、パスフレーズなしの秘密鍵をリポジトリやチャットにうっかり置いてしまうこと、退職者や不要になった公開鍵が authorized_keys に残り続けること、そしてrootでの直接ログインを許可したままにすることです。秘密鍵は「サーバへの入館証そのもの」であり、漏えい時は即座に該当公開鍵を全サーバから撤去する必要があります。誰の鍵がどこに登録されているかの棚卸しは、地味ですが最小権限を保つうえで欠かせない運用です。近年はこの鍵管理の負担を減らすため、有効期限付きのSSH証明書を短時間だけ発行する方式や、IdPでの認証と連動させるアクセス基盤への移行も進んでいます。それでもなお、1台のサーバと1人のエンジニアを最短距離でつなぐ道具として、SSHはインフラ作業の共通言語であり続けています。
