WebSocket(node + socket.io)をstunnel + HAProxyでプロキシする - その3 - stunnelのセットアップ

以下の図のような、stunnelとHAProxyを使ってnode.jsとnginxを1つにまとめる構成のサーバー構築手順をまとめています。

その1ではHAProxyのインストール、その2ではプロキシの設定例についてまとめました。
OSに依存する箇所はUbuntu 10.04を例に説明しています。

今回は、最後にHAProxyの前にstunnelを建ててSSLWebサービスにアクセスできるようにして行きます。

stunnelのインストール (パッケージインストール)

stunnelのインストール手順については、主に以下のブログを参考にしました:
https://www.siamnet.org/Wiki/Ubuntu-SettingUpStunnel

stunnelはaptでインストールできます*1

$ sudo apt-get install stunnel4

/etc/default/stunnel4の「ENABLED」の値を「0」から「1」に変更します。

#ENABLED=0
ENABLED=1

今回はテスト用に自己証明書を用意します。

$ cd /etc/stunnel
$ sudo openssl req -new -out stunnel.pem -keyout stunnel.pem -nodes -x509 -days 365
Generating a 1024 bit RSA private key
...++++++
...........++++++
writing new private key to 'stunnel.pem'
        • -
You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank.
        • -
Country Name (2 letter code) [AU]:JP State or Province Name (full name) [Some-State]:Tokyo Locality Name (eg, city) :Minatoku Organization Name (eg, company) [Internet Widgits Pty Ltd]:co-meeting Inc Organizational Unit Name (eg, section) : Common Name (eg, YOUR name) :Hiroyuki Endoh Email Address :hrendoh@gmail.com $ sudo chmod 600 stunnel.pem

生成した証明書をstunnel.confに指定します。
また、https以外の設定をコメントアウトして、httpsのconnectにHAProxyサーバーのホストとポートを指定します。

$ sudo vi stunnel.conf
...
; Certificate/key is needed in server mode and optional in client mode
;cert = /etc/ssl/certs/stunnel.pem
cert = /etc/stunnel/stunnel.pem
;key = /etc/ssl/certs/stunnel.pem

...

; Service-level configuration

;[pop3s]
;accept  = 995
;connect = 110

;[imaps]
;accept  = 993
;connect = 143

;[ssmtp]
;accept  = 465
;connect = 25

[https]
accept  = 443
connect = 192.168.1.1:80
TIMEOUTclose = 0

サービスを再起動します。

$ sudo service stunnel4 restart
Restarting SSL tunnels: [Started: /etc/stunnel/stunnel.conf] stunnel.

以上で、WebSocketなアプリケーションをプロキシでまとめる構成が出来上がりました。

stunnelのメモリー使用量

ドキュメントのパフォーマンスにも記載されていますが、stunnelを運用する際に気になるのがメモリー使用量です。
ドキュメントによると1接続あたり150Kバイト必要とあります。
WebSocketやロングポーリングを使用する環境では、基本的にはブラウザーとサーバーは繋ぎっぱなしの状態になるため同時接続数x150Kバイトのメモリー消費はかなり厳しい制限になります。

そこで、簡単に測れる範囲で測定してみると、以下の結果になりました。

測定環境
OS: Ubuntu 10.04 Server (64bit)
stunnel: 4.44(ソースをコンパイルしてインストールしました)
ハードウェアは、メモリー1Gバイトを割り当てたPC上のVMWareインスタンスです。

$ ps -ax
...
 1282 ?        Ss     0:00 stunnel /etc/stunnel/stunnel.conf
...

起動時

$ ps v 1282
  PID TTY      STAT   TIME  MAJFL   TRS   DRS   RSS %MEM COMMAND
 1282 ?        Ss     0:00      0     0 27120   824  0.0 stunnel /etc/stunnel/st

1接続

$ ps v 1282
  PID TTY      STAT   TIME  MAJFL   TRS   DRS   RSS %MEM COMMAND
 1282 ?        Ssl    0:00      0     0 27364  1944  0.1 stunnel /etc/stunnel/st

20接続

$ ps v 1282
  PID TTY      STAT   TIME  MAJFL   TRS   DRS   RSS %MEM COMMAND
 2950 ?        Ssl    0:03      0     0 107420 15616  1.5 stunnel /etc/stunnel/s

40接続

 ps v 1282
  PID TTY      STAT   TIME  MAJFL   TRS   DRS   RSS %MEM COMMAND
 2950 ?        Ssl    0:07      0     0 186572 28836  2.8 stunnel /etc/stunnel/s

60接続

  PID TTY      STAT   TIME  MAJFL   TRS   DRS   RSS %MEM COMMAND
 2950 ?        Ssl    0:11      0     0 200652 42068  4.1 stunnel /etc/stunnel/s

大体、1接続あたり700バイト弱という結果になりました。ぜんぜん問題無いレベルですね。
ドキュメントの150000バイトから比べると1/200。測定方法まずいかな。

*1:クライアントIPアドレスを、X-Forwareded-ForヘッダをHAProxyからアプリケーションに送信する場合は、HAPorxyプロジェクトが用意しているパッチをあててソースからインストールする必要があります