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

发布于 2025-02-13 09:27:31 字数 3856 浏览 0 评论 0原文

我正在尝试使用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 HASH,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中的按钮发送),但立即将econnreset错误时,JS WebSocket使用错误代码1006(异常终止)关闭,而我的Apache日志报告以下:

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

我不确定我是否将Apache配置设置为正确的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>

我尝试了proxypass重写规则,无济于事。

我的环境:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌酱 2025-02-20 09:27:32

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

首先,我的base64编码字符串是“字符串”的sha1 hash而不是二进制版本(例如b1feae)。 ..而不是0xb1 0xfe 0xae ...),其次,我没有明确返回sec-websocket-protocol在某些情况下(在Chrome做到并将关闭连接时,Firefox似乎在我的某些测试中不在乎[Firefox])。

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 (e.g. 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]).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文