React+Express+Socket.io使用Ngrok无法建立连接的问题求助
Socket.io通过Ngrok跨网连接失败问题
版本信息
客户端:socket.io-client@4.7.2 服务端:socket.io@4.7.2
服务端代码(server/server.js)
const express = require('express'); const { createServer } = require('http'); const { Server } = require('socket.io'); const socketioJwt = require('socketio-jwt'); const cors = require('cors'); const helmet = require('helmet'); const app = express(); // 启用全局CORS app.use(cors()); // 启用代理信任 app.set("trust proxy", 1); // 启用Helmet增强安全 app.use(helmet()); // 解析请求中的JSON数据 app.use(express.json()); const httpServer = createServer(app); const io = new Server(httpServer, { cors: { origin: "http://localhost:3000", // 替换为Ngrok客户端HTTPS地址 methods: ["GET", "POST"], credentials: true, }, }); const port = process.env.PORT || 4821; io.use((socket, next) => { const clientIP = socket.handshake.address; // 配置JWT认证中间件 io.use( socketioJwt.authorize({ secret: secretKey, // 来自.env文件的密钥 handshake: true, }) ); });
客户端代码(client/src/App.js)
import React, { useState, useEffect } from 'react'; import io from 'socket.io-client'; import './styles.css'; const jwt = require('jsonwebtoken'); const token = jwt.sign( { username: "myUsername", }, process.env.REACT_APP_JWT_SECRET ); const socket = io("http://localhost:4821", { // 替换为Ngrok服务端HTTPS地址 query: { token }, }); socket.on('connect', () => { console.log('Connected to the server'); }); socket.on('error', (error) => { console.error('WebSocket Error:', error); });
Ngrok配置步骤
服务端配置(Linux Ubuntu虚拟机/Node.js LTS 18)
- 执行
sudo ufw status确认防火墙已激活,执行sudo ufw allow 4821开放端口,再执行sudo ufw reload生效 - 启动服务端:
npm start(启动脚本为nodemon node server.js) - 启动Ngrok隧道:
ngrok start server(ngrok.yml配置为http localhost:4821) - 复制Ngrok生成的HTTPS服务端地址
- 将该地址替换到客户端代码的Socket.io连接地址中,重启客户端
客户端配置(MAC)
- 启动客户端:
npm start - 启动Ngrok隧道:
ngrok start client(ngrok.yml配置为http localhost:3000) - 复制Ngrok生成的HTTPS客户端地址
- 将该地址替换到服务端代码的CORS origin配置中,重启服务端
问题现象
- 本地环境下,客户端
localhost:3000与服务端localhost:4821的Socket.io连接完全正常 - 通过Ngrok隧道访问时,无法建立Socket.io连接,且浏览器控制台无任何报错信息
浏览器网络面板详情
轮询请求(ALL标签)
Request URL: https://f65b-185-213-154-249.ngrok-free.app/socket.io/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InNhdG9zaGlAMjFubWlsbC5pbyIsImlhdCI6MTY5ODUwNjE1M30.v5hCOKlmMHf3RSEdXTumzO7PEtKzYz-XZrA6CqPsCkg&EIO=4&transport=polling&t=OjssoEr Request Method: GET Status Code: 200 OK (from service worker) Referrer Policy: strict-origin-when-cross-origin Access-Control-Allow-Origin: * Content-Length: 1396 Content-Security-Policy: default-src 'self' https://cdn.ngrok.com 'unsafe-eval' 'unsafe-inline'; img-src data: w3.org/svg/2000 Content-Type: text/html Date: Sat, 28 Oct 2023 15:15:55 GMT Ngrok-Trace-Id: 7ca3e23723940ef090231cf42ad421a1 Referrer-Policy: no-referrer X-Content-Type-Options: nosniff Accept: */* Referer: https://ed5e-185-213-154-249.ngrok-free.app/ Sec-Ch-Ua: "Chromium";v="118", "Brave";v="118", "Not=A?Brand";v="99" Sec-Ch-Ua-Mobile: ?0 Sec-Ch-Ua-Platform: "macOS"
WebSocket请求(WS标签)
Request URL: wss://ed5e-185-213-154-249.ngrok-free.app/sockjs-node Request Method: GET Status Code: 101 Switching Protocols Connection: Upgrade Ngrok-Trace-Id: 58a6ffcdbd0cd5a1ef2d633378c24398 Sec-Websocket-Accept: ONgwe/ms0WvXB6Tb2eIyPvx6dVo= Upgrade: websocket Accept-Encoding: gzip, deflate, br Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 Cache-Control: no-cache Connection: Upgrade Cookie: abuse_interstitial=ed5e-185-213-154-249.ngrok-free.app Host: ed5e-185-213-154-249.ngrok-free.app Origin: https://ed5e-185-213-154-249.ngrok-free.app Pragma: no-cache Sec-Gpc: 1 Sec-Websocket-Extensions: permessage-deflate; client_max_window_bits Sec-Websocket-Key: QQjVTB/9a2Ou5OcaPX2YnA== Sec-Websocket-Version: 13 Upgrade: websocket User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
问题猜测与待验证方案
- 怀疑问题源于Ngrok未配置Let's Encrypt SSL证书
- 不确定是否需要在客户端Socket.io配置中添加以下参数:
// client/src/App.js 修改后的Socket连接配置 const socket = io("https://ngrok-url.com", { query: { token }, withCredentials: true, // 新增 transports: ['websocket', 'polling'], // 新增(注意参数名应为transports而非transport) });
内容的提问来源于stack exchange,提问作者mrbpp
相关产品推荐
相关产品推荐

