I'm trying to use Apache's mod_proxy_wstunnel
to proxy data between a client website and a back end WebSocket server, but it seems like Apache is resetting the socket.
My server/client code is very simple at the moment:
Client JS:
var socket = new WebSocket("wss://local-test.mysite.com/wss/", "basic-protocol");
socket.onopen = function(e) {
console.log('open: ', e);
};
socket.onerror = function(e) {
console.log('error: ', e);
};
socket.onmessage = function(e) {
console.log('message: ', e);
};
socket.onclose = function(e) {
console.log('close: ', e);
};
The server code (C++) is a little more complex, but essentially it does the following (some struct
details left out for briefness):
int server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(server, ...); // binds to port 4433
listen(server, 1024);
int client = accept(server, ...);
char buff[4096];
long r = recv(client, buffer, sizeof(buffer), 0);
This bit works, as once my JS loads up and creates the WebSocket
, my server gets the following HTTP data:
GET /wss/ HTTP/1.1
Host: localhost:4433
Pragma: no-cache
Cache-Control: no-cache
User-Agent: { user agent string }
Origin: https://local-test.mysite.com
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: { cookie data here }
Sec-WebSocket-Key: {base64 key}
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: basic-protocol
X-Forwarded-For: 192.168.11.1
X-Forwarded-Host: local-test.mysite.com
X-Forwarded-Server: local-test.mysite.com
Connection: Upgrade
Upgrade: websocket
Which I then parse out the Sec-WebSocket-Key
, append the "magic string" ( "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
), get the SHA1 hash, base64 encode that, and then send along the following response back:
HTTP/1.1 101 Switching Protocols\r\n
Connection: Upgrade\r\n
Upgrade: websocket\r\n
Sec-WebSocket-Accept: {hashed response key}\r\n
Sec-WebSocket-Protocol: basic-protocol\r\n\r\n
My server then goes back to recv
to wait for the next bit of data (which I'd send from a button in the DOM), but immediately errors out with a ECONNRESET
error while the JS websocket closes with error code 1006 (abnormal termination), and my Apache log reports the following:
[ssl:info] (70014)End of file found: [client 192.168.11.1:54673] AH01991: SSL input filter read failed.
I'm not sure if I've got my Apache config set correctly to proxy data or if it's my server response code, but here's my Apache config (for the relevant virtual host):
Listen local-test.mysite.com:80
Listen local-test.mysite.com:443
<VirtualHost local-test.mysite.com:80>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,QSA]
</VirtualHost>
<VirtualHost local-test.mysite.com:443>
ServerAdmin admin@mysite
DocumentRoot "/Code/source/dev/web"
ErrorLog /var/log/httpd/web/error.log
CustomLog /var/log/httpd/web/access.log common
ServerName local-test.mysite.com
ServerAlias local-test
SSLEngine on
SSLOptions +StrictRequire
SSLCertificateFile /etc/httpd/ssl/mysite.crt
SSLCertificateKeyFile /etc/httpd/ssl/mysite.key
<Directory /Code/source/dev/web>
RewriteEngine On
RewriteBase /
RewriteRule ^/index\.php$ - [L,NC]
RewriteCond %{REQUEST_URI} !\.(png|jpg|gif|jpeg|bmp|svg|ico)$
RewriteCond %{REQUEST_URI} !\.(css|js|map|ttf|woff|woff2|eot)$
RewriteRule . index.php [L]
</Directory>
# Websocket config
SSLProxyEngine on
ProxyPreserveHost On
ProxyRequests Off
ProxyPass /wss ws://localhost:4433 keepalive=On enablereuse=On connectiontimeout=1800
ProxyPassReverse /wss ws://localhost:4433
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:4433%{REQUEST_URI} [P,L]
</VirtualHost>
I've tried all sorts of variations for the ProxyPass
and Rewrite
rules, to no avail.
My environment:
As it turns out, it was actually my server reply and not my Apache config:
First, my base64 encoded string was of the "stringized" SHA1 hash instead of the binary version (eg b1feae...
instead of 0xb1 0xfe 0xae ...
), and secondly I wasn't explicitly returning the Sec-WebSocket-Protocol
in certain instances (to which FireFox didn't seem to care about in some of my tests while Chrome did and would close the connection [as it should]).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.