こんにちは!日々のインフラ運用やWeb開発、本当にお疲れ様です。技術メディア主筆の私です。
突然ですが、みなさんは普段何気なく見ているWebサイトの裏側で、どんな「交通整理」が行われているか気になったことはありませんか? 「HTTP/2」といえば、Webの通信を劇的に速くしてくれた現代の主役です。1本の道路(TCPコネクション)の上を、いくつもの荷物を載せたバイクが同時にびゅんびゅん走り抜けるような「マルチプレクシング(多重化)」というすごい仕組みを持っていますよね。
でも、このHTTP/2、実は「鍵をかけずに暗号なしで走る道」も用意されているんです。それが今回お話しする「h2c(HTTP/2 Cleartext)」という仕様です。
「暗号化しないHTTP/2?なんだか速そうだし、ローカルテストなら良さそう!」と思ったそこのあなた。ちょっと待ってください。その便利さの裏側には、インフラエンジニアが冷や汗をかくような「なかなかにスリリングなリスク」が隠されているんです。
今回は、この「h2c」の正体と、なぜ現代のインターネットでは嫌われ者扱い(ブラウザ非対応など)なのかを、身近な例えを交えながら一緒に優しく紐解いていきましょう。一歩ずつ理解していけば全然難しくありませんよ!
—
1. そもそも「h2c」ってなんだろう?(郵便配達のたとえ)
普段、私たちがセキュアなサイトを見るときに使われるのは「HTTPS(暗号化された通信)」ですよね。HTTP/2を使うときも、基本的にはTLS(暗号化の仕組み)とセットで使われます。これを識別子(プロトコル名)で「h2」と呼びます。
これに対して、暗号化の鍵を一切使わず、昔ながらのむき出しの通信(HTTP)のままでHTTP/2のマルチプレクシング機能を使おうというのが「h2c(HTTP/2 Cleartext)」です。
これを現実世界で例えるなら……。
- 通常のHTTPS (h2):
頑丈なカギのかかった「特製のジュラルミンケース」に荷物を入れ、さらに警備員を何人もつけて宛先まで届けるスタイル。
- h2cの通信:
カギの壊れた、中身がスケスケの「透明なプラスチックケース」に荷物を詰め込み、何人もの配達員(ストリーム)が1台の台車に乗って、一気に大量の荷物を街中にばら撒きながら走るスタイル。
どうでしょう? 想像するだけで「中身が丸見えなのに、そんなに一気に運んで大丈夫!?」ってハラハラしちゃいますよね。h2cは、まさにこの「丸見えのまま爆速で走る」状態なんです。
—
2. なぜ暗号化なしの「h2c」なんて存在するの?
「中身が見えるなら、最初から使わなきゃいいのに!」と思いますよね。全くその通りなのですが、実はこのh2c、生まれてきたのにはちゃんとした理由(おもに開発や内部ネットワークの都合)があるんです。
① 開発やデバッグのしやすさ
私たちエンジニアがローカル環境でアプリを作るとき、わざわざオレオレ証明書を発行してHTTPSの設定をするのって、ちょっと面倒くさいですよね。「まずはサクッと通信テストがしたい!」というとき、暗号化なしのプレーンテキストでHTTP/2の動作を確認できるh2cは、手軽で便利なんです。
② マイクロサービス間の「内部通信」の高速化
最近のシステムは、たくさんの小さなアプリ(マイクロサービス)が社内のプライベートなネットワーク内で連携し合っています。
「社内の閉じた安全なネットワークなんだから、わざわざ重たい暗号化(TLSハンドシェイク)の処理を毎回やるのはCPUの無駄遣いじゃね?」ということで、あえて高速でオーバーヘッドの少ないh2cを使ってサービス間通信を最適化したい、という需要が生まれたのです。
—
3. h2cが抱える「致命的なセキュリティリスク」
便利そうなh2cですが、冒頭でもお伝えした通り、実務ではなかなかのじゃじゃ馬、いえ「爆弾」のような存在です。最大の脅威は、もちろん「中間者攻撃(Man-in-the-Middle Attack)」です。
パケットが暗号化されていないため、もし悪意ある攻撃者が社内ネットワークや公衆Wi-Fiの経路に入り込んでいると、流れるデータがすべて丸見えになってしまいます。ID、パスワード、セッションCookie……。HTTP/2は1つのコネクション上で複数のデータを同時にやり取りするため、一度盗聴されると、一度に大量のプライベートな情報がごっそり抜き取られてしまうリスクがあります。
アップグレードの罠(Cleartext Upgrade)
さらに厄介なのが、h2cが使われるまでの「交渉のプロセス」です。
クライアント(ブラウザやアプリ)は、最初は普通のHTTP(HTTP/1.1)でサーバーに話しかけます。そのときに、こんな風に持ちかけます。
> 「ねえ、僕たちHTTP/2(h2c)で話せるんだけど、そっちも対応してる? 対応してたら途中からh2cに切り替えようよ!」(HTTP Upgradeリクエスト)
もしサーバーが「お、いいよ!切り替えよう!」と答えてしまうと、そこから通信がh2cに切り替わります。
しかし、この「最初の挨拶」のやり取りも暗号化されていないため、途中の悪い人が「俺がサーバーのふりをして、偽のh2cに切り替えさせちゃおう」と割って入る隙(ダウングレード攻撃やセッションハイジャックなど)を与えてしまうのです。
—
4. ブラウザのサポート状況は? 実は「使えない」のが現実
ここまで読んで、「自分のブラウザでもh2cを試してみたい!」と思った方もいるかもしれませんが、実は現代の主要なWebブラウザ(Google Chrome、Safari、Firefox、Edgeなど)は、インターネット上の公開サイトに対する「h2c(HTTP Upgrade方式)」のサポートを頑なに拒否(あるいは廃止)しています。
理由はシンプルです。
- 「暗号化されていないウェブ(HTTP)」を根絶し、すべての通信をセキュア(HTTPS)にしたいという強いセキュリティ方針があるため。
- 先ほど説明したようなダウングレード攻撃などのセキュリティリスクをユーザーが踏まないようにするため。
そのため、現在ブラウザでHTTP/2を利用したい場合は、必ずTLS(暗号化)が有効な「h2」を使うことが大前提となっています。
—
5. 実務で触れるなら? Nginxでの設定と検証の作法
「じゃあ、h2cは完全に封印された技術なの?」というと、そうではありません。前述の通り、「信頼できるプライベートネットワーク内のサーバー間通信(リバースプロキシとバックエンドAPサーバーの間など)」では、今でも現役で使われることがあります。
もし実務や検証環境でNginxなどのリバースプロキシを使い、バックエンドのアプリケーションへh2cで繋ぎたい場合の、設定の雰囲気(イメージ)を覗いてみましょう。
server {
listen 80; # 外部からのアクセスは暗号化なしのポート80で受ける(検証用)
location / {
# バックエンドのアプリケーションサーバーへ転送
proxy_pass http://192.168.1.50:8080;
# 重要:HTTP/1.1からHTTP/2 (h2c) へプロトコルをアップグレードするための設定
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;
# クライアントの実際のIPアドレスなどをバックエンドに引き渡す親切設計
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Host $host;
}
}
※注:上記はあくまで「パブリックなインターネット側はHTTPSにして、社内・ローカルのプロキシ〜バックエンド間だけでh2cやHTTP/2の恩恵を受けたい」といった特殊な構成の文脈で用いられるアプローチの一例です。
—
まとめ:安全なスピードの恩恵を受けよう
今回は、HTTP/2の暗号化なしバージョンである「h2c」の仕様と、そこに潜むセキュリティリスクについてお話ししました。
- h2cは、暗号化なしでHTTP/2のマルチプレクシング(多重化)を使える技術。
- 開発の効率化や、閉じた内部ネットワーク(マイクロサービス間)での高速化には便利。
- しかし、通信が丸見えになるため中間者攻撃の危険性が高く、モダンブラウザはウェブ閲覧でのh2cをサポートしていない。
ネットワークインフラの世界は、「速さ」と「安全性」のトレードオフの連続です。「速いからといって何でも暗号なしで動かすのは、鍵をかけずに札束を積んで走るようなもの」と心得ておくと、セキュリティ事故を未然に防ぐ素晴らしいエンジニアになれますよ。
それでは、また次回の深掘り技術解説でお会いしましょう! 安全で快適なネットワークライフを!
コメント