NginxでHTTPS対応のフォワードプロキシを構築
今回の記事の構成は、以下の通りです。構築方法は、「ハンズオン」に記載しています。
背景
フォワードプロキシとしてNginxの利用を検討しているのですが、HTTPSの通信を行った際に以下のエラーが発生しました。
$ curl --proxy http://localhost:80 https://www.google.com/ curl: (56) Received HTTP code 400 from proxy after CONNECT
調査の結果、NginxをHTTPS対応のフォワードプロキシとして利用する場合、別途パッチを当てる必要があるようです。その対応を行う際に、調べた内容を以下にまとめます。
調査結果
CONNECT
とはなにか
上述のエラーメッセージに含まれるCONNECT
に関して、HTTPのメソッドの1つになります。CONNECT
メソッドを用いると、フォワードプロキシが通信内容を意識せずに、クライアントとサーバ間の中継を行う様になります。具体的な通信の流れは以下を御覧ください。
CONNECT
メソッドを用いたHTTPS通信の流れ
How to Use NGINX as an HTTPS Forward Proxy Server - Alibaba Cloud Communityより
以下の流れで通信が行われます。
(a). クライアントがフォワードプロキシにCONNECT
リクエストを行う。
(b)-(c). フォワードプロキシが目的のサーバへのTCPコネクションを確立する。
(d). フォワードプロキシがクライアントへ200 OK
を返却する。
(e). フォワードプロキシが、クライアントとサーバ間のHTTPS通信をそのまま中継する。
そもそも、なぜCONNECT
メソッドが必要か
HTTPSでは、HTTPの通信内容がSSLによって暗号化されています。その為、フォワードプロキシは通信内容を把握できず、送信先のサーバも知ることができません。
そこで上述の流れの通り、CONNECT
メソッドを用いることで、フォワードプロキシが通信内容を把握できずとも、クライアントとサーバ間の通信が可能になります。
エラー原因
今回のエラーに関して、NginxがCONNECT
メソッドに対応していないことが、発生の原因になります。
ハンズオン
概要
Nginxに以下パッチを適用し、CONNECT
メソッドを使用可能にします。
GitHub - chobits/ngx_http_proxy_connect_module: A forward proxy module for CONNECT request handling
下記の「手順」では、Dockerを用いてCentOSのコンテナ上で、Nginxのソースコードを取得し、該当のパッチを適用し、動作確認を行うまでを記載しています。
手順
Nginxのソースコードを取得
$ docker run -it centos:centos7 /bin/bash // 以降、CentOSのコンテナ内での操作 $ cd /var/tmp $ yum install -y wget $ wget http://nginx.org/download/nginx-1.9.2.tar.gz $ tar -xzvf nginx-1.9.2.tar.gz
パッチを取得し適用
$ yum install -y git $ git clone https://github.com/chobits/ngx_http_proxy_connect_module.git $ yum install -y patch $ cd nginx-1.9.2/ // patchコマンドを発行し、diffファイル(proxy_connect.patch)の内容を元に、ソースコードの書き換えを行う。 $ patch -p1 < /var/tmp/ngx_http_proxy_connect_module/patch/proxy_connect.patch
ソースコードをコンパイルし起動
$ yum install -y gcc pcre pcre-devel openssl openssl-devel gd gd-devel $ ./configure --add-module=/var/tmp/ngx_http_proxy_connect_module $ make && make install $ alias nginx=/usr/local/nginx/sbin/nginx $ nginx
設定ファイルを修正し反映
/usr/local/nginx/conf/nginx.conf
ファイルのserver
コンテキスト内の記載を、以下の通り追記・変更する。
... http { ... server { listen 80; server_name localhost; # ↓追記箇所 resolver 8.8.8.8; # DNSサーバのIPアドレス proxy_connect; # ↑追記箇所 ... location / { # ↓変更箇所(既存の記述は削除) proxy_pass $scheme://$http_host$request_uri; # ↑変更箇所 } ... } } ...
その他の設定に関して、以下URIの「Directive」を御覧ください。
GitHub - chobits/ngx_http_proxy_connect_module: A forward proxy module for CONNECT request handling
設定の反映の為に以下コマンドを発行します。
$ nginx -s reload
動作確認
以下の通り、フォワードプロキシ経由でHTTPS通信を行った際に、結果が無事取得できることが確認できます。
$ curl --proxy http://localhost:80 https://www.google.com <!doctype html><html itemscope=...