まったり技術ブログ

主にWebエンジニア向けのセキュリティブログ。たまに開発も

HTTPS通信をNginxでフォワードプロキシ

f:id:motikan2010:20200318151440p:plain:w600

はじめに

 Nginxでは「proxy_pass」ディレクティブを指定することでフォワードプロキシとして動作させることが可能です。

 しかし、モジュール等を追加していない素のNginxの場合、HTTPS通信をフォワードプロキシすることはできません

f:id:motikan2010:20200318153058p:plain:w500

 試しにNginxプロキシ経由でHTTPSのサイトにアクセスしたら以下のようにエラーとなりました。

$ curl -Lv https://github.com/ -x 127.0.0.1:3128
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 3128 (#0)
* Establish HTTP proxy tunnel to github.com:443
> CONNECT github.com:443 HTTP/1.1
> Host: github.com:443
> User-Agent: curl/7.54.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 400 Bad Request
< Server: nginx/1.16.1
< Date: Wed, 18 Mar 2020 05:24:05 GMT
< Content-Type: text/html
< Content-Length: 157
< Connection: close
<
* Received HTTP code 400 from proxy after CONNECT
* Closing connection 0
curl: (56) Received HTTP code 400 from proxy after CONNECT

HTTPS通信をプロキシする「ngx_http_proxy_connect_module」モジュール

 「ngx_http_proxy_connect_module」モジュールを利用することでHTTPSサイトへのサクセスをプロキシ経由で行うことができます。

github.com

↓ このモジュールの説明

This module provides support for the CONNECT method request. This method is mainly used to tunnel SSL requests through proxy servers.

環境構築

Nginx と モジュール の ダウンロード & インストール

 configure時に--add-module=../ngx_http_proxy_connect_moduleオプションを指定することで、Nginxにngx_http_proxy_connectモジュールを組み込むことができます。

# 作業用ディレクトリを作成
$ mkdir work && cd work

# Nginxの取得
$ wget http://nginx.org/download/nginx-1.16.1.tar.gz
$ tar zxvf nginx-1.16.1.tar.gz
$ rm -f nginx-1.16.1.tar.gz

# ngx_http_proxy_connect_moduleの取得(現時点の最新版は「0.0.1」)
$ git clone https://github.com/chobits/ngx_http_proxy_connect_module.git -b v0.0.1

# 作業用ディレクトリの内容は以下のようになっています
$ ls
nginx-1.16.1/
ngx_http_proxy_connect_module/

# Nginxに対してのパッチ適用 と Nginxのインストール
$ cd nginx-1.16.1
$ patch -p1 < ../ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_101504.patch
$ ./configure --prefix=/path/to/nginx --add-module=../ngx_http_proxy_connect_module
$ make && make install

Nginx の 設定 & 起動

# Nginxのディレクトリに移動
$ cd /path/to/nginx

# 設定を以下のように修正します
$ vim conf/nginx.conf
---------------------------------------------
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

     server {
         listen                         3128;

         # dns resolver used by forward proxying
         resolver                       8.8.8.8;

         # forward proxy for CONNECT request
         proxy_connect;
         proxy_connect_allow            443 563;
         proxy_connect_connect_timeout  10s;
         proxy_connect_read_timeout     10s;
         proxy_connect_send_timeout     10s;

         # forward proxy for non-CONNECT request
         location / {
             proxy_pass $scheme://$http_host$request_uri;
             proxy_set_header Host $host;
         }
     }
}
---------------------------------------------

# Nginxの起動
$ ./sbin/nginx

動作確認

$ curl -Lv https://github.com/ -x 127.0.0.1:3128
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 3128 (#0)
* Establish HTTP proxy tunnel to github.com:443
> CONNECT github.com:443 HTTP/1.1

< HTTP/1.1 200 Connection Established
< Proxy-agent: nginx

> GET / HTTP/1.1
> Host: github.com
> User-Agent: curl/7.54.0

< HTTP/1.1 200 OK
< date: Tue, 17 Mar 2020 09:25:15 GMT

ダイナミック(動的)モジュール

 ngx_http_proxy_connect_moduleは動的モジュールとして.soファイルを作成することが可能です。

 しかし導入の際にNginxに対してパッチを適用する必要があるため、すでにインストールされているNginxにこのモジュールを導入することはできなさそうです。

 ダイナミックモジュールが動作しない件については、いくつかISSUEがあるようでした。
そんな感じでダイナミックモジュールとして組み込むことは厳しそう。

参考

更新履歴

  • 2020年3月18日 新規作成