Edited at

socket.io ~2.0 にリバースプロキシを通す方法

More than 1 year has passed since last update.


構成

127.0.0.1:3000 で socket.io v2系 のサーバーが LISTEN していると仮定。


Apache 2.4.27

必要なモジュールは以下の通り。

* mod_proxy

* mod_rewrite

* mod_proxy_wstunnel

バックエンドへの通信は http://, ws:// で行い、TLSはリバースプロキシで落とす。

# ......

# 必ず VirtualHost の中に記述すること
<VirtualHost _default_:443>
# ......
# リライトを有効化
RewriteEngine on
# パスが /socket.io/ で始まり、クエリに transport=websocket が含まれているとき、
RewriteCond "%{REQUEST_URI}" "^/socket.io/" [NC]
RewriteCond "%{QUERY_STRING}" "transport=websocket" [NC]
# パスを保持したまま WebSocket プロトコルでローカルホストにプロキシを通す。
RewriteRule "/(.*)" "ws://127.0.0.1:3000/$1" [P,L]
# もちろんフォワードプロキシは無効化
ProxyRequests off
# それ以外のリクエストのうち /socket.io/ で始まるものは、localhost に通す。
ProxyPass "/socket.io/" "http://127.0.0.1:3000/socket.io/"
ProxyPassReverse "/socket.io/" "http://127.0.0.1:3000/socket.io/"
# ......
</VirtualHost>
# ......


補足

transport=websocket がクエリに含まれているとき、

socket.io は WebSocket へのプロトコルアップグレードを要求している。

従って、この時だけ WebSocket のプロトコルとして転送する。

それ以外のときは、フォールバックの可能性等もあるため http で転送。

Qiita にこれ以外の設定もあるが、フォールバックしか動いていない可能性が高いので要注意。


Nginx 1.13.3

詳細な情報は以下にあるため、そちらを参照すると良い。

https://www.nginx.com/blog/nginx-nodejs-websockets-socketio/

Apacheの場合と違って、ほとんど何も考えずに流してあげれば動いてくれる。

# Upstream の設定。

# 流したい先をここに記述する。
upstream websocket {
server localhost:3000;
}
# ......
server {
# ......
location /socket.io/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # どのプロトコルにアップグレードするかを残す
proxy_set_header Connection "upgrade"; # とりあえずプロトコルをアップグレードすることにする
}
# ......
}


動作確認法

Chrome の Developer Tools などを活用して確認できる。

1. Network のタブを選択

2. 種類は All or WS

3. Type が websocket になっているものを選択

4. Frames のタブを選択

以上の手順で、実際に送られている WebSocket のフレームを確認することが出来る。

image.png