ソフトウェアエンジニア現役続行

雑多なことを綴ります

HTTPSプロキシの仕組み

例えば、以下のようなネットワークを考えます。


┌──────────┐       ┌─────────┐       ┌───────────┐
│ クライアントPC │ <───> │ プロキシサーバ │ <───> │ HTTPSサーバ  │
└──────────┘       └─────────┘       └───────────┘
  192.168.1.40            192.168.1.2            https_server.jp(1.1.1.1)

HTTPSサーバはインターネット上にあり、プロキシサーバとHTTPSサーバの間にはルータがあるものとします。


プロキシサーバ経由でHTTPSの通信を行う場合は、以下のようなリクエストを発行し、プロキシサーバに接続先のHTTPSサーバから公開鍵と証明書を転送するように、指示を行います。

CONNECT server_name:443 HTTP/1.0


このリクエストの結果として、プロキシサーバはボディー部分に、サーバの証明書と公開鍵を設定しクライアントに転送します。クライアントは、この情報を用いてリクエストに必要な情報を暗号化して送信を行います。


つまり、HTTPSの場合は、プロキシサーバはルータのようにパケットの転送だけを行います。


HTTPSプロキシは上記のようにして実現していたのですね。


てっきり僕は、プロキシサーバとHTTPSサーバ間で鍵を交換して暗号化通信を行い、クライアントとプロキシサーバでは別の鍵を交換して暗号化通信をしているのだと思っていました。なので、クライアントはHTTPSサーバの証明書の正当性を検証することが出来ないのだと思っていました。


確かめるために、簡単にsquidでプロキシサーバを立ててみました。


Red Hat系のLinuxならsquidのインストールは簡単です。yumでインストールできます。

[root@localhost java]# yum install squid

次に設定ファイルsquid.confを編集します。yumでインストールした場合は、絶対パスは/etc/squid/squid.confです。手を加えるのは以下の2点のみです。

acl our_network src 192.168.1.0/24  # out_networkというネットワーク名を定義しています
http_access allow our_network     # out_networkからのアクセスを許可します

設定ファイルsquid.confの編集が終わったら、squidを起動(または再起動)します。


クライアントPCのブラウザにプロキシサーバの設定をして、まずはHTTPアクセスをしてみて、プロキシサーバのログを見てみます。ログは/var/log/squid/squid.logに出力されます。

1235470602.889 79 192.168.1.40 TCP_MISS/200 8132 GET http://img0.gmodules.com/ig/f/vcbK_2Vv3S8/intl/ALL_jp/logo.png - DIRECT/66.249.89.104 image/png

google.com(66.249.89.104)のトップページのイメージロゴをブラウザに表示させたときのログが出ています。確かにプロキシサーバによってリクエストが代行されていることが分かります。

次にHTTPSアクセスをしてみて、ログを見てみます。

1235471049.377 64 192.168.1.40 TCP_MISS/200 2113 CONNECT https_server.jp:443 - DIRECT/1.1.1.1 -

プロキシサーバはパケットの転送を行っていますが、コネクションの中身は見ることが出来ません。


なるほど、だからプロキシサーバでは、
・HTTPセッションはコンテンツフィルタリングが可能
HTTPSセッションはコンテンツフィルタリングが不可能(ただしURLフィルタリングは可能)
なのですね。