nginx(1.4.3)のproxyでWebとWebSocketのポート共有。SSL対応

user-pic
0
nginx(1.4.3)のproxyでWebとWebSocketのポート共有させてみました。
以下、同時に試した項目です。
  • WebSocketのproxy(ws://~) → OK
  • WebSocketのproxy(wss://~) → OK
  • Webのproxy(http://~) → OK
  • Webのproxy(https://~) → OK
  • マルチドメイン(ただし、SSLは1ドメインのみ) → OK

【動作確認ブラウザ】
  • Chrome 30.0 → OK
  • Safari (iOS6.1) → OK
  • Safari 6.0.5 → OK
  • Mozilla Firefox 24.0 → OK
  • IE 8.0  → NG
  • IE 10.0 → OK

nginx-websocket1.png

その他の条件:
  • Webサーバ(Apache)とWebSocketサーバの前にnginxを配置、同一ドメインに対する接続をWebサーバとWebSocketサーバへ振り分ける。
  • WebSocketのポートはWebと同じポートを使用し、振り分けはパス/ws/の場合にWebSocketサーバとする。
  • SSLはnginxで処理しWebサーバとWebSocketサーバへはhttpおよびwsで接続する。

【ファイアウォール → nginx → web/websocketサーバのURL】

  • SSLなし
    http://domain:80/ → http://domain:8080/ → http://127.0.0.1:80/
    ws://domain:80/ws/ → ws://domain:8080/ws/ → ws://127.0.0.1:8000/ws/

  • SSLあり
    https://domain:443/ → https://domain:443/ → http://127.0.0.1:80/
    wss://domain:443/ws/ → wss://domain:443/ws/ → ws://127.0.0.1:8000/ws/

Apacheの設定変更なしとするためファイアウォールで80から8080へポート転送し、nginxで8080を受けるようにしています。nginxで80を受けてApacheへ8080で渡すもよいでしょう。
WebSocketサーバのポート8000は、単なる思い付きですので適当なポートをどうぞ。


/etc/nginx/nginx.confの設定

--------------------------------------------------------------------------------
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    keepalive_timeout  65;
    gzip  on;

    include /etc/nginx/conf.d/*.conf;

}
--------------------------------------------------------------------------------


/etc/nginx/conf.d/proxy.confの設定

--------------------------------------------------------------------------------
# ヘッダの設定                                                                  
proxy_redirect                          off;
proxy_set_header Host                   $host;
proxy_set_header X-Real-IP              $remote_addr;
proxy_set_header X-Forwarded-Proto      $scheme;
proxy_set_header X-Forwarded-Host       $host;
proxy_set_header X-Forwarded-Server     $host;
proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;

# タイムアウトの設定                                                            
proxy_connect_timeout 60;
proxy_read_timeout    90;
proxy_send_timeout    60;

# バッファサイズの設定                                                          
proxy_buffering  on;
proxy_buffer_size       8k;
proxy_buffers           100 8k;

# キャッシュの設定                                                              
proxy_cache_path      /var/cache/nginx/domain.co.jp levels=1:2 keys_zone=cache_domain.co.jp:15m inactive=7d max_size=1000m;
proxy_temp_path       /var/cache/nginx/temp;

proxy_cache_valid     200 2h;
proxy_cache_valid     302 2h;
proxy_cache_valid     301 4h;
proxy_cache_valid     any 1m;

    upstream any_web {
        ip_hash;
        server 127.0.0.1:80;
#       server 192.168.0.1:80 weight=5;
#       server 192.168.0.2:80 weight=5;
    }

    upstream any_websocket {
        ip_hash;
        server 127.0.0.1:8000;
#       server 192.168.0.1:8000;
    }

    server {
        listen       8080;
        server_name  host.domain1 host.domain2 host.domain3;

        location /ws/ {
            proxy_pass http://any_websocket;

            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }

        location / {
            proxy_pass http://any_web;
            proxy_redirect default;
        }
    }

    server {
        listen       443;
        server_name  host.domain1;

        ssl on;
        ssl_certificate      /etc/pki/tls/certs/server.crt;
        ssl_certificate_key  /etc/pki/tls/certs/server.key;

        location /ws/ {
            proxy_pass http://any_websocket;
            proxy_redirect http:// https://;

            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }

        location / {
            proxy_pass http://any_web;
            proxy_redirect http:// https://;
        }
    }
--------------------------------------------------------------------------------

これでWebとWebSocket共存しマルチドメインも動作できました。
SSLは、マルチドメインでもどれか一つのドメインのみ対応しています。


設定(#コメント部分)を少し変えれば、下図の小規模冗長構成にしてWebサーバのロードバランシングに対応できるようになります。
WebSocketについては、ステートフルのためWebサーバのようにリクエスト単位のロードバランシングはできませんが、負荷をみながらパス(上記/ws/部分)またはportを切り替えて接続先を制御することにより接続単位のロードバランシングを実現できます。

nginx-websocket2.png

Mailサーバをnginxでproxyするのも良いですが、今回はWebとWebSocketにフォーカスしています。


【環境】



nginxのインストール(CentOS 6.3)


  • リポジトリを追加
# vi /etc/yum.repos.d/nginx.repo
------------------------------------------------------
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
------------------------------------------------------

  • YUMで「nginx」をインストール
yum install nginx-1.4.3-1.el6.ngx.x86_64



SSL証明書(自己証明書)の作成

cd /etc/pki/tls/certs
make server.key
openssl rsa -in server.key -out server.key

make server.csr
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]: ←指定なし
Organization Name (eg, company) [Default Company Ltd]: ←指定なし
Organizational Unit Name (eg, section) []: ←指定なし
Common Name (eg, your name or your server's hostname) []:host.domain1
Email Address []:postmaster@host.domain1

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: ←指定なし
An optional company name []: ←指定なし

これで
  /etc/pki/tls/certs/server.crt
  /etc/pki/tls/certs/server.key
が作成されます。


nginx起動


service nginx start
で起動されます。

自動起動は、nginxのインストールで設定されていましたので特に必要ありません。

トラックバック(0)

トラックバックURL: http://web.sfc.keio.ac.jp/~kj/mt4/mt-tb.cgi/46

コメントする

このブログ記事について

このページは、madpapaが2013年10月20日 01:05に書いたブログ記事です。

ひとつ前のブログ記事は「電子カルテ、マイカルテに関するリンク集」です。

次のブログ記事は「nginx経由apacheでクライアントのIPアドレスを取得する」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。