HTTPS・TLS
HTTPS・TLSとは
HTTPSは、[[HTTP]] を TLS(Transport Layer Security) で暗号化した通信方式です。URLが https:// で始まり、ブラウザに鍵マークが表示されます。現代のWebでは事実上の必須要件です。
何を守っているのか
| 脅威 | TLSによる防御 |
|---|---|
| 盗聴 | 通信内容を暗号化し、途中で覗かれても読めない |
| 改ざん | 内容が書き換えられたら検知できる |
| なりすまし | サーバー証明書で「本物のサイト」であることを証明 |
接続が始まるまでに起きていること
https:// のページを開くと、画面が出るより前に短いやり取りが済んでいます。これを TLSハンドシェイク と呼びます。
- TCPで接続する([[TCP/IP]] の3ウェイハンドシェイク)
- サーバーがサーバー証明書を提示する
- ブラウザが証明書を検証する — 信頼できる認証局までたどれるか、アクセスしたドメイン名と一致するか、有効期間内か
- 双方が計算をやり取りして、この接続でだけ使う共通鍵を作る
- 以降のHTTPのやり取りを、その共通鍵で暗号化する
要は4番目です。共通鍵そのものは回線に流れず、双方が手元の計算で同じ鍵にたどり着きます。だから全パケットを記録されていても、後から中身を復号することはできません。現行の TLS 1.3 ではこのハンドシェイクの往復が1回に減り、「HTTPSにすると遅くなる」という心配はほぼ過去のものになりました。
暗号化されないもの
HTTPSにしても隠れないものがあります。暗号化されるのはHTTPの中身 — URLのパス、ヘッダー、Cookie、ボディ — であって、接続先のIPアドレスとホスト名は経路上の機器から見えます。通信の量やタイミングも隠せません。実際に [[パケットキャプチャ]] で覗くと、「誰がいつどのサイトへ接続したか」までは分かるのに中身だけ読めない、という状態が観察できます。「HTTPSなら何を見ていたかまで秘密になる」は誤解です。
初学者向けポイント
- サーバー証明書 = 認証局(CA)が発行する「このドメインの持ち主は本物」という証明書。Let's Encrypt で無料取得できる
- 鍵交換には公開鍵暗号、通信本体には高速な共通鍵暗号、とハイブリッドで使い分けている
- パスワードや [[認証と認可]] のトークンを送る通信は、HTTPSでなければ危険にさらされる
開発者が気をつけること
- ローカル開発以外は常にHTTPS。フォームやAPIも例外なし(初回アクセスが平文で飛ぶ穴は [[セキュリティヘッダー(CSP・HSTS)]] のHSTSで塞ぐ)
- 証明書の有効期限切れは定番の障害。自動更新を仕組み化する
- 「httpsだから安全なサイト」ではない。通信路が安全なだけで、サイト自体の信頼性は別問題
つまずきやすい失敗
- 混在コンテンツ — HTTPSのページから
http://のスクリプトやCSSを読み込むと、ブラウザがその読み込みをブロックします(画像などはHTTPSへ読み替えられるか警告扱いになります)。「HTTPSにした途端に画面が崩れた」の定番原因です。移行時は埋め込みタグやコードに直書きされたURLまで洗い出します - リダイレクトループ — プロキシでTLSを終端し、内部は平文でアプリに渡す構成では、アプリから見た通信は「HTTP」です。ここでアプリが「HTTPだからHTTPSへリダイレクトしよう」と判断すると、永遠に往復し続けます。プロキシが付ける
X-Forwarded-Protoヘッダーを見て判定するよう設定します - 期限切れ — 無料証明書の代表である Let's Encrypt は有効期間が90日と短く、手動更新の運用はいずれ必ず破綻します。自動更新と期限監視をセットで組みます
- 時計のずれ — 証明書の有効期間は時刻で判定されるため、サーバーの時計が大きく狂うと正しい証明書でも「期限切れ」と判定されます([[NTPと時刻同期]])
HTTPSの次に読む地図
HTTPSはWebのほぼ全域に触れるため、隣接する話題が広く散らばっています。目的別に4つの入口を用意しました。
仕組みをもう一段掘る — 「なぜ盗聴されないのか」を理解したいなら、[[暗号化の基礎]] で共通鍵・公開鍵・ハッシュの役割分担を押さえ、[[電子署名とハッシュ]] で改ざん検知と本人性の証明を見て、[[電子証明書とPKI]] で証明書チェーンと認証局へ進むのが最短です。この3本は、上のハンドシェイクの手順にそのまま対応しています。
自分のサイトをHTTPSにする — 証明書を置く場所は、多くの場合アプリ本体ではありません。[[リバースプロキシ]] や [[Nginx]] でTLSを終端して内部は平文にする構成が定番で、静的ファイルが主役なら [[CDN]] のエッジで終端する形もあります。公開そのものの手順は [[ホスティングとレンタルサーバー]] にまとまっています。なお中継者はサーバー側だけでなく利用者側にも立ちます — 会社支給のPCに独自の証明書が入っているのは、[[プロキシサーバー]] が通信内容を検査しているためです。
HTTPSだけでは足りない防御を足す — 通信路が安全でも、アプリ自身の穴は塞げません。最初の1回の平文アクセスを消すHSTSは [[セキュリティヘッダー(CSP・HSTS)]] に、XSSやCSRFといったアプリ側の脆弱性は [[Webセキュリティ]] にあります。ログイン周りでトークンを扱うなら [[OAuth・OIDC]] も併せて読むと、仕様のあちこちに「HTTPS必須」と書かれている理由が腹落ちします。
同じTLSが働いている別の場所 — TLSはWeb専用の技術ではありません。[[HTTP/2とHTTP/3]] のQUICには暗号化が最初から組み込まれ、[[VPN]] のSSL-VPNは同じTLSでトンネルを張り、[[メールの仕組み(SMTP・POP3・IMAP)]] のSTARTTLSも同じ技術です。ブラウザ側では [[PWA]] がHTTPS配信を動作条件にしています。
関連技術とのつながり
- [[HTTP]] — 暗号化される対象のプロトコル
- [[TCP/IP]] — TLSはTCPとHTTPの間の層で動く
- [[認証と認可]] — トークンやCookieを安全に運ぶ前提がHTTPS
Q: TLSハンドシェイクで作られる「この接続でだけ使う共通鍵」について、本文の説明として正しいのはどれ?
- [x] 共通鍵そのものは回線に流れず、双方が手元の計算で同じ鍵にたどり着く
- [ ] サーバーが生成した共通鍵をそのまま平文で送り、ブラウザが受け取る
- [ ] 認証局が接続ごとに共通鍵を発行してブラウザへ配布する
解説: 鍵自体が流れないため、通信をすべて記録されていても後から復号できません。公開鍵暗号は鍵交換に、共通鍵暗号は通信本体に使われます。
Q: HTTPSで通信していても経路上の機器から見えてしまうものはどれ?
- [ ] リクエストのボディに入れた入力内容
- [ ] Cookieに保存されたセッションID
- [x] 接続先のIPアドレスとホスト名
解説: 暗号化されるのはHTTPの中身です。宛先や通信量・タイミングといったメタ情報は隠せません。
Q: プロキシでTLSを終端し内部は平文でアプリへ渡す構成で、リダイレクトループが起きる原因はどれ?
- [ ] 証明書の有効期間が90日と短いため
- [x] アプリが自分に届いた平文のHTTPだけを見て、HTTPSへリダイレクトし続けるため
- [ ] 混在コンテンツをブラウザがブロックするため
解説: プロキシが付ける `X-Forwarded-Proto` ヘッダーを見て判定するよう設定すれば解消します。