ITの窓辺から

三流IT技術者の日常

HTTPSとCONNECTメソッド

以下の画像はSquidの通信をTcpdumpしたものです。

f:id:ReaLiZeZNSG:20180806223048p:plain

宛先はAppleのどこかのページです。AppleのサイトはHTTPSによるアクセスになっており、TLSで暗号化されています。そのため、宛先URIはサーバ名までしか表示されないですし、この後はTLSのやり取りが始まり、問題なければ暗号化されたHTTPのアプリケーションデータの通信が開始されます。

CONNECTメソッド

クライアントがプロキシ経由でHTTPS通信をする場合、HTTP的には通常CONNECTメソッドを使用します。CONNECTメソッドはHTTP1.1で実装されたメソッドです。CONNECTメソッドを使うとHTTP以外のプロトコルをトンネルするように指示を出すことができます。この場合はプロキシサーバに対してTLS通信をトンネルするように指示を出すことになります。簡単書くと以下の順序で処理が行われる、はずです。

  1. CONNECTメソッドを受け取ったプロキシは宛先URIとHTTPコネクションを張ります。ここでいうコネクションはL4のTCP/UDPとは関係ない言葉です。コネクションが確立できれば当然ながらサーバからはHTTP200の応答があります。これでHTTP以外のプロトコルがトンネルされる準備が整いました。
  2. クライアントからのTLS通信がサーバと行われ、TLSセッションが張られます。
  3. HTTPS (HTTP over TLS)による通信が行われ、アプリケーションデータの転送が行われます。

HTTPS通信をする時はCONNECTメソッドを使う」という表現はいたるところで見ますが実態はこんな感じです。間違っていないのですが、ちゃんと知っておくとプロキシ構成、Webサーバの構成を正しく理解できます。

プロキシ経由のHTTPSの実態はCONNECTメソッドで確立されたHTTPコネクション上を流れるTLS上を流れるHTTPというわけです。HTTPSによる暗号化は最後のHTTPに対してかかります。

4階層モデル

OSI7階層モデルという言葉があります。色々なところで聞く言葉ですが、インターネット(≒HTTP)はOSI7階層モデルに従っていません。4階層で構成されています。といっても元はOSI7階層を集約したものですが。インターネットでは最上位層をアプリケーション層と定義しており、このアプリケーション層にはOSI7階層モデルのL5〜L7が集約されています。つまりTLSによる暗号化とHTTPが一纏めになっており、4階層モデルに照らし合わせるとHTTPSは一つのレイヤのプロトコルと見ることができます。もちろん実際はHTTP over TLSなのですが。

CONNECTメソッドとX-Forwarded-For

HTTPSを使うとHTTPリクエストやHTTPレスポンスが暗号化されます。暗号化されると当然ながらプロキシ等の中継サーバではこれらの中身を盗聴、改ざんは困難になります。念の為ですが、HTTPリクエストにはHTTPリクエストライン、HTTPリクエストヘッダ、HTTPリクエストボディが含まれます。

X-Forwarded-ForはHTTPリクエストヘッダに入ります。HTTPS通信の場合、暗号化されているのでHTTPSリクエストヘッダの改ざんができません(プロキシによるX-Forwarded-Forの挿入はある種の改ざんです)。つまりHTTPSの場合X-Forwarded-Forが使用できないというのは、この意味では間違っていません。

ところが以下の画像を見てみてください。(この記事の冒頭の画像と同じです。)

f:id:ReaLiZeZNSG:20180806231740p:plain

HTTPS通信にも関わらず、X-Forwarded-Forが含まれています。何なら他のヘッダも含まれています。これは何故でしょうか。もうおわかりでしょう。プロキシ経由でのHTTPS通信をするためにCONNECTメソッドを使用しています。HTTPリクエストラインのCONNECTメソッドとそのHTTPリクエストヘッダ自体は暗号化されないため、このように任意のHTTPリクエストヘッダを挿入することができます。このようにHTTPSだからといって必ずしもX-Forwarded-Forが使用できないわけではないのです。

 HTTPSでX-Forwarded-Forは使えない?

そこら中にHTTPSだからX-Forwarded-Forは使用できないと書いてあるのは何故でしょうか。この記事の中でも使用できない例を一つ書きましたが、恐らく多くの記事ではプロキシではなく、Webサーバの手前のリバースプロキシでX-Forwarded-Forを使おうとしているのだと思います。この場合、リバースプロキシでHTTPS通信にX-Forwarded-Forを挿入しようとすると、当然ながら暗号化されているため挿入できません。

しかし前回記事に書いたとおり、クライアントからのHTTPS通信をリバースプロキシで終端することでHTTPSの復号化が可能です。いわゆるSSLオフロード、SSLアクセラレーションと呼ばれる機能です。クライアントのTLS通信の終端先がWebサーバではなくリバースプロキシになる構成です。リバースプロキシで復号化が行われるため、リバースプロキシからWebサーバ向けのHTTP通信にはX-Forwarded-Forを挿入することができます。全てのリバースプロキシでこの機能が使えるわけではないので、環境によって各記事の表記が異なっているのが実態なのでしょう。

realizeznsg.hatenablog.com

 

まだ数回SquidやHTTPに関する記事を続けようと思います。