繁体   English   中英

WebSocket/Apache 错误 AH01991:SSL 输入过滤器读取失败

[英]WebSocket/Apache Error AH01991: SSL input filter read failed

我正在尝试使用 Apache 的mod_proxy_wstunnel在客户端网站和后端 WebSocket 服务器之间代理数据,但似乎 Apache 正在重置套接字。

我的服务器/客户端代码目前非常简单:

客户端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);
};

服务器代码 (C++) 稍微复杂一些,但本质上它执行以下操作(为简洁起见,省略了一些struct细节):

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);

这一点有效,因为一旦我的 JS 加载并创建了WebSocket ,我的服务器就会获得以下 HTTP 数据:

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

然后我解析出Sec-WebSocket-Key ,附加“魔术字符串”( "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ),获取 SHA1 哈希,base64 对其进行编码,然后将以下响应发送回:

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

然后,我的服务器返回recv以等待下一位数据(我将从 DOM 中的按钮发送),但当 JS websocket 以错误代码 1006(异常终止)关闭时,立即出错并出现ECONNRESET错误,并且我的 Apache 日志报告以下内容:

[ssl:info] (70014)End of file found: [client 192.168.11.1:54673] AH01991: SSL input filter read failed.

我不确定我的 Apache 配置是否正确设置为代理数据,或者它是否是我的服务器响应代码,但这是我的 Apache 配置(用于相关虚拟主机):

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>

我已经尝试了ProxyPassRewrite规则的各种变体,但无济于事。

我的环境:

  • Apache/2.4.51 (Fedora)
  • Chrome 版本 103.0.5060.53

事实证明,这实际上是我的服务器回复,而不是我的 Apache 配置:

首先,我的 base64 编码字符串是“字符串化”SHA1 哈希而不是二进制版本(例如b1feae...而不是0xb1 0xfe 0xae ... ),其次我没有明确返回Sec-WebSocket-Protocol某些情况(在我的一些测试中,FireFox 似乎并不关心,而 Chrome 会关闭连接 [应该])。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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