ネットワーク●●●○○

HTTPS

HTTPS ・ えいちてぃーてぃーぴーえす

TLSで暗号化したHTTP。盗聴・改ざん・なりすましを防ぐが、守るのは通信の経路だけ。

✦ 30秒で試す — 航海鍵マークのサイトでも、パスワードが読まれる場所がある記録を見た管理者に、読み取れるものは?予想してみる

概要

HTTPS は、HTTP の通信を TLS という暗号化の層で包んだものです。新しいプロトコルが発明されたわけではなく、「いつもの HTTP を、暗号化されたトンネルの中に通す」という組み合わせです。ブラウザのアドレスバーの鍵マークは、サーバの証明書を検証して「通信相手が本物の shop.example である」ことを確かめ、トンネルができた印です。

HTTPS が防ぐのは3つです。途中で読まれること(盗聴)、途中で書き換えられること(改ざん)、偽のサーバにつながされること(なりすまし)。パスワードやカード番号はもちろん、Cookie に載せたセッション ID のように「盗まれたらアカウントを乗っ取られる」情報も、この層に守られています。

逆に、HTTPS が守らないものもあります。「どのサイトと通信しているか」は経路から見えますし、サーバに届いたあとのデータや、サイトそのものの作りの弱さは守備範囲の外です。現在の Web では HTTPS は前提で、ブラウザは素の HTTP のサイトに「保護されていない通信」と表示し、位置情報やカメラ、Service Worker など新しい機能の多くは HTTPS でしか使えません。

なぜ生まれたか

素の HTTP は平文で流れます。通信はいくつものネットワーク機器を経由して届くので、経路のどこか、たとえば同じカフェの Wi-Fi でパケットを覗けば、パスワードも Cookie も読めてしまいます。1990年代半ば、Web で買い物を成り立たせたかった Netscape 社にとって、これは致命的でした。カード番号が丸見えのサイトで買い物をする人はいません。

そこで Netscape が作ったのが SSL(のちの TLS)で、これを HTTP と組み合わせた HTTPS が1995年ごろに登場しました。ただし長いあいだ、証明書は有料で設定も面倒だったので、「ログインと決済のページだけ HTTPS」という使い方が普通でした。

転機は2010年代です。公衆 Wi-Fi が広まり、2010年には同じ Wi-Fi にいる人の Cookie を盗んでログイン状態を乗っ取るツール(Firesheep)が公開されて、ログイン後のページも含めた全ページの暗号化が必要だと広く知られました。2013年のスノーデン事件で大規模な通信の監視が明るみに出たことも後押しになりました。決定打は、2015年末に始まった Let’s Encrypt です。証明書を無料・自動で発行する認証局の登場で、費用と手間の言い訳が消え、HTTPS は Web 全体の標準になりました。

詳細

HTTP を TLS で包み、TCP に載せる

HTTPS の通信は「まず暗号化のトンネルを作り、その中でいつもの HTTP を話す」という二段構えです。TCP/IP の接続を張ったあと、TLS のハンドシェイクでサーバの証明書を検証して鍵を決め、そこから先の HTTP のリクエストとレスポンスはすべて暗号化されて流れます。HTTP 自体は何も変わっておらず、メソッドもステータスコードもヘッダも同じです。暗号化の仕事は TLS の層がまるごと引き受けるので、Web アプリのコードは暗号をほとんど意識せずに済みます。

包み方を外側から順に見ると、経路の途中から何が見えて何が見えないかが分かります。いちばん外側の IP のヘッダには、宛先の IPアドレスが書かれています。次の TCP のヘッダにはポート番号(HTTPS なら 443)があります。その内側が TLS で、ここから先の HTTP の中身、つまりメソッド・パス・ヘッダ・Cookie・ボディが暗号化されます。

IP宛先 IP アドレス 203.0.113.10 … 見えるTCP宛先ポート 443 … 見えるTLSハンドシェイクの SNI に shop.example … 見える(ECH なら隠せる)HTTPPOST /login ・ Cookie: sid=… ・ password=…暗号化されて、経路からは読めないDNS の問い合わせ(shop.example の IP は?)も、DoH などで暗号化しなければ平文で流れる通信の量と時刻も隠れない。HTTPS が隠すのは「何を」であって「どこと」ではない
HTTPS の包み方と、経路の途中から見えるもの。暗号化されるのは HTTP の中身で、宛先の IP アドレスと、ハンドシェイクで送るドメイン名(SNI)は外から見える

接続が確立するまでを時間の順に並べると、次のようになります(TLS 1.3 の場合)。ドメイン名が経路に出るのは、DNS の問い合わせと、TLS の最初のあいさつ ClientHello に入る SNI(Server Name Indication。1つの IP で複数のサイトを運用するサーバに、どのサイトの証明書を出すべきか伝える欄)の2か所です。

サーバDNSリゾルバブラウザサーバDNSリゾルバブラウザ証明書を検証するshop.example の IP アドレスは?203.0.113.10TCP の接続を張るClientHello・SNI は shop.exampleServerHello・ここから暗号化・証明書・FinishedFinished暗号化された POST /login暗号化された 200 OK

DNS の問い合わせは、DoH(DNS over HTTPS)などで暗号化できます。SNI を隠すのが ECH(Encrypted Client Hello)で、ClientHello の中身をまるごとサーバの公開鍵で暗号化し、外側には CDN などが共通に使う名前だけを見せます。2023年ごろから主要ブラウザと一部の CDN で使われ始めました。それでも宛先の IP アドレスと、通信の量・時刻は隠せません。

下の部品で確かめてください。「盗聴者」をつかんで経路のどこかに置くと、ブラウザがログインのリクエストを送り、盗聴者の手元に写しが届きます。方式を切り替えたり、置く場所を変えたりすると、メモに並ぶ項目が変わります。

⚡ 体験: 盗聴者を経路に置いて、HTTPS が隠すものを確かめる
方式
サーバ側のネットワークインターネットの経路 — 平文のまま流れる内側は平文ブラウザカフェの Wi-FiプロバイダTLS 終端アプリサーバ盗聴者のメモ宛先 IP…ドメイン名…パス…Cookie…ボディ…量と時刻…盗聴者

左下の「盗聴者」をつかんで、経路のどこか(カフェの Wi-Fi・プロバイダ・TLS 終端の内側)に置いてください。置くと、ブラウザがログインのリクエストを送ります。

証明書 — 相手が本物であることの保証

暗号化だけでは足りません。偽のサーバと「安全に」暗号化通信をしてしまっては意味がないからです。なりすましを防ぐ要がサーバ証明書です。証明書は「この公開鍵暗号の公開鍵は shop.example のものである」ことを認証局(CA)が署名して保証した電子文書で、ブラウザは署名を、自分があらかじめ信頼しているルート CA までたどって検証します。この信頼の連鎖の仕組みは TLS の記事で詳しく扱います。

証明書には有効期限があり、期限切れは「ある日突然サイトが全部エラーになる」定番の障害です。Let’s Encrypt などを使って自動で更新するのが常識になっています。発行できる証明書の最長の有効期間も短くなり続けていて(2026年3月から200日、2029年には47日まで段階的に短縮)、手作業での更新はますます現実的でなくなっています。

どこで TLS を終えるか

アプリケーションサーバ自身で TLS を処理することは実は少なく、多くの構成では前段のリバースプロキシやロードバランサ、CDN が TLS を終わらせます(TLS 終端)。インターネットの区間は HTTPS で守り、サーバ側のネットワークの中は平文の HTTP で中継する、という形です。部品で見たとおり、終端の内側を覗ける者には HTTPS でも全部見えます。内側も守りたいときは、プロキシとアプリの間にも TLS を張ったり、お互いに証明書を見せ合う mTLS を使ったりします。

TLS 終端の構成では、アプリからは「自分は HTTP で受けている」ように見えます。元が HTTPS だったことは、プロキシが付ける X-Forwarded-Proto ヘッダで伝えます。これを見ずに「HTTP で来たから HTTPS へリダイレクトする」と実装すると、リダイレクトが無限に続く典型的な事故になります。

HTTPS を前提にした防御と、守らないもの

HTTPS の効果を確実にする仕組みもあります。HSTS(HTTP Strict Transport Security)は、「このサイトには今後 HTTPS でしか接続しないこと」をブラウザに覚えさせるレスポンスヘッダです。一度 HSTS を受け取ったブラウザは、利用者が http:// と打っても、リンクが http:// でも、最初から HTTPS で接続します。これで、平文の最初のリクエストを途中で横取りして偽のページを見せる攻撃(SSL ストリッピング)を2回目以降は防げます。ただし、HSTS はそのヘッダを一度受け取るまで効かないので、初めての訪問には隙が残ります。この隙を塞ぐのが HSTS プリロードリストで、ブラウザに最初から組み込まれた「HTTPS でしか接続しないドメインの一覧」に登録しておくと、初回から HTTPS で接続されます。

Cookie の Secure 属性は「HTTPS のときしか送らない」という指定で、セッション ID が平文で漏れるのを防ぎます。

そして、HTTPS は万能ではありません。守るのは通信の経路で、XSS や SQLインジェクションのようなアプリ自体の脆弱性には効きません。証明書が保証するのも「そのドメインの持ち主と通信している」ことだけです。フィッシング用の偽サイトも正規の証明書を簡単に取れるので、鍵マークは「安全なサイト」の印ではなく「そのドメインと暗号化された通信をしている」印にすぎません。

試問

ブラウザからカフェの Wi-Fi・プロバイダ・サーバ側の入口の「TLS 終端」を経て、アプリサーバへログインのリクエストが届く経路です。「盗聴者」をつかんで経路のどこかに置くと写しを取り、見えたものがメモに並びます。方式は HTTP・HTTPS・HTTPS+ECH(ドメイン名まで隠す)から選べます。

✦ 命題挑戦中

方式を「HTTPS+ECH」にしたまま、盗聴者のメモにパスワードを写させよ

  • 方式は「HTTPS+ECH」(中身もドメイン名も隠す設定)
  • その方式のまま、盗聴者のメモにパスワード(ボディ)が写っている
⚡ 体験: 暗号化したまま、パスワードを盗み見る
方式
サーバ側のネットワークインターネットの経路 — 平文のまま流れるブラウザカフェの Wi-FiプロバイダTLS 終端アプリサーバ盗聴者のメモ宛先 IP…ドメイン名…パス…Cookie…ボディ…量と時刻…盗聴者

左下の「盗聴者」をつかんで、経路のどこか(カフェの Wi-Fi・プロバイダ・TLS 終端の内側)に置いてください。置くと、ブラウザがログインのリクエストを送ります。