ngx_http_proxy_connect_module を使って forward proxy で SSL 通信を利用可能にする
前提
SSL通信を nginx を利用してプロキシさせようとすると、暗号化された payload が見れないのでアクセス対象の URL にデータ通信を送る事ができない。
そのために HTTP tunnel という技術を利用することになる。
※ 参考
Nginx as forward proxy for HTTPS - Super User
proxyについて知識整理
- forward proxy
- インターネットにつながる手前にあるプロキシ
- トンネルとかゲートウェイとかよばれる
- 主な用途はIPアドレスを隠すこと
- 名前解決は、こいつとDNSサーバー間でやることがほとんど
- reverse proxy
- 内部ネットワークでアプリケーション・サーバーの手前にあるプロキシ
- 主な用途はロードバランシングや、アクセスコントロール
今回の主眼は forward proxyの方
まずトンネリングとは
ネットワーク技術におけるトンネリングとは、インターネット等のなんらかのネットワークで接続されている、物理的、または、論理的に離れた2点間を、仮想の回線(トンネル)によりあたかも同一点であるかのように扱えるようにすることである。
※ 参考
トンネリング - Wikipedia
HTTP tunnelとは?
具体的に何をやってくれるかというと
- クライアントがHTTPメソッド(※:後述)プロキシと目的のサーバーに対してTCPのコネクションをはるように要求する
- プロキシが目的のサーバーとクライアントの代わりにコネクションをはる
後続の通信は1,2ではられたコネクションの上で行われる(つまりTCPより上はTSLだろう上位のプロトコルであれば何でもいい)
CONNECTメッドとは?
- 上記、でいう1のときに投げられるHTTPメソッド
- このリクエストについているFQDNを利用してプロキシは名前解決及びTCPコネクションの作成を行う
- RFCで仕様化されている
※参考
- HTTP tunnel - Wikipedia
- 【図解】httpプロキシサーバの仕組み(http GET/https CONNECTメソッド)や必要性・役割・メリットデメリット・DNSの名前解決の順序 | SEの道標
ngx_http_proxy_connect_module
でnginxでこれをやろうと思うと、モジュールが必要になってくるので以下を利用する。
nginx.conf
ser www-data; worker_processes auto; daemon off; # Don't run Nginx as daemon, as we run it in Docker we need a foreground process. events {} http { server_names_hash_bucket_size 128; access_log /var/log/nginx_access.log; error_log /var/log/nginx_errors.log; server { listen 80; proxy_connect; proxy_max_temp_file_size 0; resolver 8.8.8.8; proxy_connect_allow 443 563; location / { proxy_pass http://$http_host; proxy_set_header Host $http_host; } } }
8.8.8.8はGoogleのパブリックDNS
構築
便利なDockerを使うぞ!
docker pull reiz/nginx_proxy:latest docker run -it -p 80:80 -v $(pwd)/nginx.conf:/usr/local/nginx/conf/nginx.conf reiz/nginx_proxy:latest
【おまけ】 ruby の open-uri でproxyに繋ぐ例
open("https://hogehoge.com", {:proxy => URI::parse("http://proxy_example.comm"),})
完