俺、サービス売って家買うんだ

Swift, Kotlin, Vue.js, 統計, GCP / このペースで作ってればいつか2-3億で売れるのがポっと出来るんじゃなかろうか

ngx_http_proxy_connect_module を使って forward proxy で SSL 通信を利用可能にする

f:id:ie-kau:20190911214620p:plain

前提

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とは?

具体的に何をやってくれるかというと

  1. クライアントがHTTPメソッド(※:後述)プロキシと目的のサーバーに対してTCPのコネクションをはるように要求する
  2. プロキシが目的のサーバーとクライアントの代わりにコネクションをはる
  3. 後続の通信は1,2ではられたコネクションの上で行われる(つまりTCPより上はTSLだろう上位のプロトコルであれば何でもいい)

  4. CONNECTメッドとは?

    • 上記、でいう1のときに投げられるHTTPメソッド
    • このリクエストについているFQDNを利用してプロキシは名前解決及びTCPコネクションの作成を行う
    • RFCで仕様化されている

※参考

ngx_http_proxy_connect_module

でnginxでこれをやろうと思うと、モジュールが必要になってくるので以下を利用する。

github.com

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を使うぞ!

github.com

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"),})