やりたかったこと
- 社外への AJAX 通信が必要だった
 - 先方の開発サーバで CORS (*) が設定されており、https://example.com/ の URL でブラウザからアクセスすることが必要
- ブラウザの仕様として、Access-Control-Allow-Origin などのヘッダにより、リクエスト元の URL が限定されている
 
 - 開発しているアプリケーションサーバはいつも localhost:3000 で HTTP をリッスンしているが、外部に AJAX リクエストのテストもやりたい
 - あまり特別な設定ファイルなどは面倒なのでやだ
 
予備知識
- HTTPS を終端した上で、HTTP として 3000番ポートに転送したい
 - この処理を実現するソフトウェアは総称して、TLS Termination Proxy という
 - TLS Termination Proxy の代表例として 
Apache HTTP Server、Nginx、Pound、hitchなどがある 
今回での手法について
- 前提としていつもローカルの PC で開発している
 - Pound は設定ファイルが必要でちょっと面倒。
 - hitch も良い候補だが、英語も含めてドキュメントが足りない
 - 今回はソケットを扱うときの swiss army knife である socat を利用
 
サーバ証明書の準備
下記の手順でサーバ証明書を準備しておく。
$ openssl genrsa -out server.key 1024 # RSA 秘密鍵の生成
$ openssl req -new -key server.key -x509 -days 3653 -out server.crt # サーバ証明書の生成。いろいろ聞かれるので答える
$ cat server.key server.crt > server.pem # 秘密鍵とサーバ証明書を連結して1つのファイルにする
$ openssl dhparam -rand - 2048 >> server.pem # DH パラメータを追記(これをしないと後でうまくいかなかった)
socat を TLS Termination Proxy として動作させる
socat とは
- 
netcatを進化させたもの - さまざまなチャネル間を双方向にリレーできる
 - 標準入出力、フォークしたプロセスへのパイプ、UDP、TCP、SCTP、ユニックスドメインソケットなどを扱える
 - 踏み台、プロキシとかに仕込むと結構いろいろ便利なことができる
 - libev などは使っておらず、スケーラビリティは低い
 
コマンド例
$ sudo socat -vv openssl-listen:443,reuseaddr,fork,verify=0,cert=server.pem TCP4:localhost:3000 
- 443 番ポートをリッスンするには 
sudoが必要 - 
openssl-listen:443と指定すると SSL ソケットを終端して次の処理を行える - 
forkがあると繰り返し、プロキシ処理ができる。(逆につけないと1回のリクエストにだけ処理を行う) - 
verify=0を指定すると、クライアント証明書を確認しない。 - 転送先はローカルホスト 
127.0.0.1の 3000番ポート。 
動作確認
wget で動作確認する
$ wget -d https://localhost/ --no-check-certificate -O -
- 作ったばかりの適当な証明書なので、 
--no-check-certificateをつけないと怒られる 
example.com でアクセスする
あとは、単純に /etc/hosts を編集すると完成
/etc/hosts
127.0.0.1   example.com
$ wget -d https://example.com/ --no-check-certificate -O -
まとめ
- HTTPS を終端した上で、HTTP として転送するには TLS Termination Proxy が必要
 - 
NginxやPoundなどでもできるが、設定ファイルが必要で、ちと面倒 - socat はさまざまなチャネルをリレーしたいときの swiss army knife
 - 
socatで HTTPS を終端し、うしろのアプリケーションサーバに転送できる - HAPPY HACKING!