httpsのアクセスをnginxでプロキシしてnode.jsに渡す

httpsアクセスを前面に立てたnginxで受け取って、node.jsに渡すというのをやってみました。
かなり面倒そうだなーと思っていたのですが、それほどでもなかったです。
環境:OS X 10.8.2 / node.js 0.8.17 / nginx 1.3.12

証明書の作成

httpsサーバを実行してみたよ - 四角革命前夜を参考にそれっぽく作ります。

$ head -c 20 /dev/random > seed.data
$ openssl genrsa -rand seed.data -des3 1024 > secret-key.pem
$ openssl req -new -key secret-key.pem -out csr.pem
$ openssl x509 -in csr.pem -out server.cert -req -signkey secret-key.pem
$ openssl rsa -in secret-key.pem -out secret-key-nopass.pem

どのファイルがなんなのかとか全然わかってません。

nginxのインストール

まずはnginxをインストールします。

$ curl -O http://nginx.org/download/nginx-1.3.12.tar.gz
$ tar xvfz nginx-1.3.12.tar.gz
$ cd nginx-1.3.12/
$ ./configure --prefix=$HOME/Work/nginx/bin --with-http_ssl_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --without-http_rewrite_module
$ make
$ make install

こんな感じでインストールしました。httpsを扱うのでそのモジュールを入れているのと、メール関連のモジュールを外しているのと、PCREを入れるのが面倒だったという理由でrewriteモジュールも外してあります。

nginxの設定ファイルを記述する

次にnginxにプロキシしてもらうため設定ファイルを書きます。

$ cd $HOME/Work/nginx/bin/conf
$ cp nginx.conf{,.bak}
$ vim nginx.conf
nginx.conf
worker_processes  1;

events {
    worker_connections  1024;
}

http {
  server {
    listen 8080;
    server_name localhost;

    ssl on;
    ssl_certificate (パス)/server.cert;
    ssl_certificate_key (パス)/secret-key-nopass.pem;

    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Real-IP $remote_addr;

    location /aaa {
      proxy_pass https://localhost:3000;
    }

    location /bbb {
      proxy_pass https://localhost:3001;
    }
  }
}

鍵の設定は何度か試したらエラーが出なかったのでこれで。

プロキシされるnode.jsのスクリプトを書く

nginxから渡されたアクセスを処理するnode.jsのスクリプトを書きます。
2つ書きますが大してかわりません。

index.js
#!/usr/bin/env node

var fs = require('fs'),
    https = require('https'),
    server;

server = https.createServer({
  key: fs.readFileSync('./secret-key-nopass.pem'),
  cert: fs.readFileSync('./server.cert')
}, function(req, res) {
  res.writeHead(200);
  res.end('/aaa');
}).listen(3000, function() {
  console.log('server running port at 3000');
});
index2.js
#!/usr/bin/env node

var fs = require('fs'),
    https = require('https'),
    server;

server = https.createServer({
  key: fs.readFileSync('./secret-key-nopass.pem'),
  cert: fs.readFileSync('./server.cert')
}, function(req, res) {
  res.writeHead(200);
  res.end('/bbb');
}).listen(3001, function() {
  console.log('server running port at 3001');
});

nginxとnode.jsを起動させる

あとは起動させてアクセスするだけ!

$ ./nginx
$ node index.js &
$ node index2.js &

これでFirefoxからhttps://localhost:8080/aaaとhttps://localhost:8080/bbbにアクセスするとそれぞれの出力が表示されます。


nginxのことをまだまだ全然知らないので、少しでも慣れるように使っていくか、node-http-proxyでプロキシを書いてしまうか……