WebSocket连接异常排查:Caddy、Node.js或前端问题定位
问题分析与排查方案
问题背景
我使用Caddy作为文件服务器,Caddyfile配置如下:
foobar.nl { redir https://www.{host}{uri} } www.foobar.nl { file_server browse reverse_proxy /wss59fps localhost:9090 handle_path /59fps/* { rewrite * /59fps/client{uri} file_server } }
同时运行Node.js服务在9090端口处理/wss59fps路径的WebSocket请求,代码如下:
const express = require('express'); const WebSocket = require('ws'); const app = express(); const server = require('http').createServer(app); const wss = new WebSocket.Server({ server, path: '/wss59fps' }); const PORT = process.env.PORT || 9090;
在前端index.html中尝试连接WebSocket时遇到两个错误:
- 使用ws协议连接:
const socket = new WebSocket('ws://foobar.nl:9090/wss59fps');DOMException: The operation is insecure.
- 使用wss协议连接:
const socket = new WebSocket('wss://foobar.nl:9090/wss59fps');Firefox can’t establish a connection to the server at wss://foobar.nl:9090/wss59fps.
已确认Node.js服务正常运行,且ufw已开放9090端口,需定位问题并排查。
核心问题根源
- ws连接报错原因:当前页面通过HTTPS访问(Caddy已将
foobar.nl重定向到HTTPS的www.foobar.nl),浏览器的安全策略禁止HTTPS页面发起未加密的ws请求,因此直接使用ws://xxx:9090必然报错。 - wss连接报错原因:你的Node服务是纯HTTP服务器(用
http.createServer创建),未配置SSL证书,无法处理wss加密请求;同时前端直接连接9090端口的操作完全绕过了Caddy的反向代理配置,违背了原本的架构逻辑。
分步排查与解决
第一步:修正前端连接地址
前端应通过Caddy的反向代理访问WebSocket,而非直接连接9090端口。正确的连接写法有两种:
// 明确指定wss协议和域名路径 const socket = new WebSocket('wss://www.foobar.nl/wss59fps');
或使用相对路径(浏览器会自动匹配当前页面的协议):
const socket = new WebSocket('/wss59fps');
第二步:验证Caddy反向代理有效性
- 确保Caddy配置生效:执行
caddy reload重载配置,然后通过caddy logs查看日志,确认是否有/wss59fps路径的请求转发记录。 - 本地测试Node服务可用性:在服务器上执行
curl http://localhost:9090/wss59fps,若返回400 Bad Request(WebSocket握手需要特定请求头,此响应属于正常),说明Node服务本地监听正常。 - 测试Caddy转发能力:在本地执行
curl -H "Upgrade: websocket" -H "Connection: Upgrade" https://www.foobar.nl/wss59fps,若返回400类响应,说明Caddy已成功转发请求到Node服务;若返回502错误,需检查Node服务是否真的在9090端口监听(执行netstat -tulpn | grep 9090查看)。
第三步:确认Node服务的WebSocket配置
- 检查路径一致性:确保Node服务中WebSocket的
path配置(/wss59fps)与Caddy反向代理的路径完全匹配,当前代码已符合要求。 - 确认端口监听状态:执行
netstat -tulpn | grep node,查看是否有127.0.0.1:9090或0.0.0.0:9090的监听记录,若为特定IP监听,需确保Caddy能访问该IP。
第四步:排查额外网络安全问题
- 外部防火墙检查:若之前错误地让前端直接连9090端口,需确认云服务商的安全组是否开放9090,但按照正确配置,前端无需直接访问该端口,此步骤可忽略,只需确保Caddy能访问本地9090即可。
- Caddy SSL证书验证:访问
https://www.foobar.nl,查看浏览器地址栏的锁图标是否正常,若证书存在错误,会导致wss连接失败。
总结
最关键的错误是前端绕过Caddy反向代理直接连接Node服务的9090端口。正确的架构是:前端通过Caddy的443端口(HTTPS)发起wss请求,由Caddy将请求反向代理到本地9090端口的Node服务;Node服务只需处理HTTP协议的WebSocket握手,无需自行配置SSL,同时也符合浏览器的安全策略。
内容的提问来源于stack exchange,提问作者clankill3r
相关产品推荐
相关产品推荐

