nginx で SSL リバースプロキシを構築
最近あまりネタがないのでが、このままだとまた何週間も投稿なしになりそうなので、以前やった nginx による SSL リバースプロキシの構築方法を備忘録的に書いてみます。開発目的で GAE の dev_appserver.py を SSL 化するために使っただけですが、パッケージシステム等を使わずにソースからビルドし、一般ユーザー権限でインストールする方法にしています。ごく基本的な内容ですが、参考にしていただければ幸いです。
nginx とは
nginx は Tornado などと同様の非同期イベントドリブンモデルを採用した HTTP サーバーです。 BSD に似たライセンスのオープンソースソフトウェアとして公開されています。プロセス・スレッドモデルを採用した Apache などよりも多数のコネクションを効率よく処理できるため、多くの高負荷サイトで採用されています。現在 Apache, IIS に次いで世界で三番目に多く使われている Web サーバーだそうです。
その高速性を生かして高速なリバースプロキシやロードバランサとして使えるほか、 FastCGI のサポートや gzip, XSLT, 画像リサイズ等のフィルタ、IMAP/POP3 プロキシなど、数多くの機能が実装されています。
また、これだけ高機能なわりには設定もシンプルで、今回のような用途にも簡単に使えるのも嬉しいところですね。
インストール
今回もシステムレベルへのインストールはせず、独立した適当なディレクトリ(ここでは ~/nginx と仮定します)にインストールします。 nginx が依存するライブラリは zlib, PCRE, OpenSSL の 3 つ。 Mac OS X Lion の場合 zlib と OpenSSL は入っていますが、 PCRE ライブラリはないので、そちらも ~/nginx 以下にビルド & インストールします。
PCRE のインストール
まずは依存ライブラリである PCRE のインストールです。こちらも configure の --prefix オプションでルートを~/nginx に指定しています。
cd ~/nginx curl -O ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.30.tar.gz tar zxvf pcre-8.30.tar.gz cd pcre-8.30 ./configure --prefix=/Users/ユーザー名/nginx make && make install
nginx のインストール
次は nginx のインストールです。 PCRE と同様に ~/nginx をルートに指定し、さらに --with-pcre オプションで PCRE のソースパッケージの場所を指定します。今回は SSL リバースプロキシの構築が目的なので、 http_ssl モジュールも有効にしています。
cd ~/nginx curl -O http://nginx.org/download/nginx-1.2.0.tar.gz tar zxvf nginx-1.2.0.tar.gz cd nginx-1.2.0 ./configure --prefix=/Users/ユーザー名/nginx \ --with-pcre=/Users/ユーザー名/nginx/pcre-8.30 \ --with-http_ssl_module make && make install
以上でインストールは終了です。
SSL リバースプロキシの設定
~/nginx/conf/nginx.conf に設定ファイルのテンプレートが作成されるので、それをもとに SSL リバースプロキシとして動作するように設定していきましょう。
nginx の設定ファイルの構造
設定ファイルを変更する前に、その概要を理解しておきましょう。一般的に nginx.conf は以下のような構造になっています。
# コアモジュールの設定 events { # Eventsモジュールの設定 } http { # すべてのドメインに共通の設定 server { listen 80; server_name www.example.com; # www.example.com全体の設定 location / { # / 以下の URL の設定 } location /foo { # /foo 以下の URL の設定 } } server { listen 80; server_name www2.example.com; # www2.example.comの設定 } }
nginx.conf はブロック(ブロック名 { 〜 } という構造)によって階層化されており、下位のブロックは上位のブロックの設定を継承・上書きします。ブロックの外側には nginx 全体で共通の設定(主に CoreModule のもの)、 events ブロックにはローレベルの通信処理を担う EventsModule の設定、 http ブロックには HTTP サーバーに関わる HttpCoreModule, HttpIndexModule など多くのモジュールの設定を記述します。上記の例では省略していますが、 IMAP/POP3 プロキシを設定する mail ブロックもあります。
http ブロックはさらに http, server, location というブロックに階層化されています。 http ブロックの直下にはすべてのドメインで共通の設定を記述し、さらにドメイン(バージャルホスト)ごとに server ブロックを作ります。同様に、各 server ブロックの直下にはそのドメインで共通の設定を記述し、パスごとの設定は location ブロックを作る、というようになっています。
注意すべきは、それぞれの location ブロックは独立しており、上位のパスが指定された location ブロックの設定を引き継がないという点です。上記の例で言えば、 /foo 以下のパスに適用されるのは location /foo ブロックの設定のみで、 location / ブロックの設定は適用されません。このあたりは Apache と違うところです。
以上をふまえて、 SSL リバースプロキシの設定を記述します。各設定項目の解説は省きますので、 リファレンス を参照してください。
非 SSL HTTP サーバーの設定
今回の目的は SSL リバースプロキシですが、念のため SSL なしのリバースプロキシも設定しておきましょう。 localhost:80 の設定がすでに存在するはずなので、その location / ブロックを以下の内容に書き換えます。
location / { proxy_pass http://localhost:8080/; proxy_redirect default; }
基本的にはこれだけでリバースプロキシとして動作します。ただ、 X-Forwarded-For などのヘッダが設定されないので、後ほど http ブロックに設定を追加します。
SSL HTTP サーバーの設定
コメントアウトされてはいますが、 SSL の設定もすでに含まれているので、そのコメントを外して、 location / ブロックの内容を非 SSL と同じ内容に変更しておきます。そして、 ssl_certificate と ssl_certificate_key にそれぞれ証明書と秘密鍵のファイルを指定すれば OK です。
ssl_certificate /path/to/ssl.crt ssl_certificate_key /path/to/ssl.key
これで SSL のリバースプロキシも動作するようになります。
リバースプロキシの設定
すでに一応リバースプロキシとして動作するようになっていますが、一般的なリバースプロキシが追加する X-Forwarded-For などの HTTP ヘッダが出力されません。その設定を行うため、 http ブロックの直下に以下の項目を追加します。
proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
これで、適切な HTTP ヘッダが出力されるようになります。
設定ファイル
参考までに、今回使った設定ファイルを掲載しておきます。テンプレートにあったコメントなどは削除してありますので、ご了承ください。
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { proxy_pass http://localhost:8080/; proxy_redirect default; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { listen 443; server_name localhost; ssl on; ssl_certificate /Users/ito/lib/ssl/ssl.crt; ssl_certificate_key /Users/ito/lib/ssl/ssl.key; ssl_session_timeout 5m; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { proxy_pass http://localhost:8080/; proxy_redirect default; } } proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
nginx の起動
nginx の実行ファイルは ~/nginx/sbin/nginx としてインストールされているはずなので、これを単に実行すれば nginx が起動します。ただし、今回は 80, 443 番ポートを使うので、 sudo で実行する必要があります。
sudo ~/nginx/sbin/nginx
これでリバースプロキシが動作し、 http://localhost/ と https://localhost/ が http://localhost:8080/ に転送されるようになりました。 Web ブラウザで表示して、確認してみてください。
nginx の終了は、 -s オプションでできます。
sudo ~/nginx/sbin/nginx -s stop
だいぶ手抜きではありますが、以上で nginx による SSL リバースプロキシが構築できました。 nginx は軽量でモダンな機能を多数搭載しているので、なかなか使いでがありそうです。 Tornado との相性もよさそうなので、今後も活用していきたいと思っています。
詳しくはこちらの記事をどうぞ!
この記事にコメントする