As of version 1.4, nginx is capable of forwarding WebSocket requests, so it can be used as a reverse proxy for HTTP, HTTPS, WS and WSS.
Example Backends
- WebSocket server, running on ws://ws1.example.com:10080
- HTTP server (for fallback), running on http://ws1.example.com:10080
This is a typical scenario given by Engine.IO, which provides a WebSocket server with HTTP fallback.
Goal
- WebSocket Proxy: forwards ws|http://ws.example.com to ws|http://ws1.example.com:10080 (WebSocket and HTTP requests)
- WSS SSL Endpoint: forwards wss|https://ws.example.com to ws|http://ws1.example.com:10080
- Path Rewriting: forwards wss|https://ws.example.com/services/myservice to ws|http://ws1.example.com:10080
- Load Balancing and Sticky Sessions: like 3., but forwards to three wsX servers, with one client always being forwarded to the same server
1. WebSocket Proxy
Simple forwarding of unencrypted HTTP and WebSocket to a different host:
server {
listen 80;
server_name ws.example.com;
location / {
access_log off;
proxy_pass http://ws.example.com:10080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support (nginx 1.4)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
2. WebSocketSecure SSL Endpoint
The proxy is also an SSL endpoint for WSS and HTTPS connections. So the clients can use wss:// connections (e.g. from pages served via HTTPS) which work better with broken proxy servers, etc.
server {
listen 443;
server_name ws.example.com;
ssl on;
ssl_certificate ws.example.com.bundle.crt;
ssl_certificate_key ws.example.com.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
# like above
}
}
3. WSS Proxy with Path Rewriting
Like above, but HTTPS and WSS endpoints are not “/” but “/services/myservice/”. So something like wss://api.example.com/services/myservice can be done.
server {
# like above
location /services/myservice {
access_log off;
proxy_pass http://ws1.example.com:10080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support (nginx 1.4)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Path rewriting
rewrite /services/myservice/(.*) /$1 break;
proxy_redirect off;
}
}
4. Load Balancing
Like 3., but there are three WS backends (ws1, ws2, ws3). Each client must always be forwarded to the same backend (e.g. when using HTTPS requests).
upstream webpush {
ip_hash;
server ws1.example.com:10080;
server ws2.example.com:10080;
server ws3.example.com:10080;
}
server {
# like above
location /services/myservice {
proxy_pass http://webpush;
# the rest, like above
}
Issues
- Old WebSocket versions (hixie-76) are not supported by nginx (this is no issue, because even mobile clients implement hybi-10/RFC 6455 now)
- Not tested with Engine.IO’s FlashSocket fallback module
- Not tested how nginx performs with > 30.000 connections