Azure Ubuntu VM部署Socket.IO服务器连接被拒绝修复方法
已知前置条件:服务本地运行正常、3002端口REST请求可正常响应、Azure门户已配置3000-3002端口入站放通规则,仅Socket.IO连接报connection refused。
按以下优先级逐一排查:
1. 确认服务监听地址
在虚拟机内部执行命令检查端口监听范围:
ss -tulpn | grep 3002
如果输出的Local Address列显示为127.0.0.1:3002,说明服务仅监听本地回环地址,外部无法访问。修改服务监听代码,显式绑定所有网卡地址:
serverHttp.listen(3002, '0.0.0.0', () => { console.log('listening on 3002'); });
改完重启服务再测试。
2. 检查虚拟机本地防火墙规则
Azure网络安全组(NSG)是外层网络策略,Ubuntu系统自带的ufw防火墙如果未放通对应端口也会拦截连接。执行以下命令检查规则:
sudo ufw status
如果输出中没有3002端口的ALLOW记录,执行命令放通:
sudo ufw allow 3002/tcp sudo ufw reload
3. 修正Socket.IO传输配置(最高发问题)
云环境网络层默认会拦截未显式声明的协议升级请求,默认的Socket.IO配置会先走HTTP长轮询再升级WebSocket,很容易被中间网络设备拦截。
服务端修改
显式声明支持的传输协议,优先走WebSocket:
const io = new Server(serverHttp, { cors: { origin: "*", methods: ["GET", "POST"], }, transports: ['websocket', 'polling'], // 显式指定传输方式,优先websocket });
客户端修改
连接时跳过自动探测,直接指定WebSocket传输:
import { io } from "socket.io-client"; const socket = io("http://<你的虚拟机公网IP>:3002", { transports: ['websocket'] });
4. 验证Socket.IO默认路径可达性
直接在浏览器访问以下地址,验证Socket.IO路由是否正常响应:
http://<你的虚拟机公网IP>:3002/socket.io/?EIO=4&transport=polling
正常情况下会返回类似以下格式的文本:
0{"sid":"xxxxxx","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000}
如果该地址返回404、超时、连接重置,说明服务端Socket.IO路由未正确挂载,或中间网络层拦截了/socket.io/路径的请求。
5. 核查Azure NSG规则配置
检查已配置的端口放通规则是否符合要求:
- 规则协议选择为TCP,不能仅选UDP
- 目标范围设置为当前虚拟机的网卡/IP,不要误选其他资源
- 规则优先级数值小于默认拒绝规则(默认拒绝规则优先级为65000,数值越小优先级越高)
- 测试阶段先将来源范围设置为
Any,连通后再按需收紧IP白名单
6. 排除边缘服务拦截
如果你的虚拟机绑定了域名、开启了Azure CDN、WAF或应用网关,这类边缘服务默认会拦截WebSocket升级请求,需要在对应服务配置中开启WebSocket支持。测试阶段可直接用虚拟机公网IP连接,绕过所有边缘层。
7. 反向代理配置检查
如果虚拟机内部部署了Nginx等反向代理服务转发3002端口请求,需要在代理配置中添加WebSocket升级请求头,否则连接会被拦截:
location /socket.io/ { proxy_pass http://127.0.0.1:3002; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; }
内容的提问来源于stack exchange,提问作者Vovozona

