简体   繁体   中英

WebSocket/Apache Error AH01991: SSL input filter read failed

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:

  • Apache/2.4.51 (Fedora)
  • Chrome Version 103.0.5060.53

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM