As the title suggests, I'm trying to get Apache and Socket.io (node.js) to play nicely, especially on SSL. Currently, the client app at https://www.example.com uses Socket.io over SSL to connect to the server at [SSL protocol]://socket.example.com/socket.io/?query_stuff*. The connection to wss:// always fails, so Socket.io degrades to https://, which works fine. But I would like to take advantage of the websocket protocol and not rely on polling over http(s).
Linux & Apache
Server version: Apache/2.4.7 (Ubuntu)
Relevant mods: mod_proxy, mod_proxy_http, mod_proxy_wstunnel, mod_rewrite, mod_ssl
Iptables: I have opened ports 80, 443, and 9000.
VirtualHost:
I created a virtualhost on *:443 called socket.example.com. It's intended purpose is to reverse proxy [wss,https]://socket.example.com/ to point to the socket.io server running at http://localhost:9000/. Here it is, with extraneous bits removed:
<VirtualHost *:443>
ServerName socket.example.com
DocumentRoot /var/www/example/socket.io/
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) wss://localhost:9000/$1 [P,L]
## I have also tried the following RewriteRules: ##
# RewriteRule /(.*) http://localhost:9000/$1 [P,L]
# RewriteRule /(.*) http://localhost:9000/socket.io/$1 [P,L]
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/keys/0001_key-certbot.pem
SSLCACertificateFile /etc/letsencrypt/ca-bundle.pem
SSLProxyEngine On
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full
ProxyPass / http://localhost:9000/
ProxyPassReverse / http://localhost:9000/
</VirtualHost>
Success using PHP websockets over SSL
Before switching to node.js for my websocket server, I used the above Apache VirtualHost to successfully route wss://socket.example.com/ws_daemon.php to ws://localhost:9000/ws_daemon.php. In this scenario I 1. removed the rewrite rules and 2. changed the ProxyPass settings to:
ProxyPass / ws://localhost:9000/
ProxyPassReverse / ws://localhost:9000/
But the same logic does not seem to carry over to socket.io.
At this point I've run out of ideas. Any help would be greatly appreciated!