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
その他の条件:
- 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は、単なる思い付きですので適当なポートをどうぞ。
--------------------------------------------------------------------------------
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を切り替えて接続先を制御することにより接続単位のロードバランシングを実現できます。
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 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のインストールで設定されていましたので特に必要ありません。