You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HTTPS环境下Nginx代理的Socket.IO服务移动端连接失败求助

Socket.IO 移动端(Android/iOS)无法通过Nginx HTTPS反向代理连接问题

问题现象

  • PC端Windows/MacOS/Linux浏览器均可正常建立Socket.IO连接
  • Android/iOS应用无法连接,Nginx及Node.js服务无报错日志
  • 通过chrome://inspect/#devices查看移动端网络请求:xhr polling请求先处于pending状态半秒后变为canceled,请求地址为mydomain.com/socket.io/?EIO=4&transport=polling&t=Oc7fPq6
  • Android应用日志显示SSL握手失败:[ERROR:ssl_client_socket_impl.cc(978)] handshake failed; returned -1, SSL error code 1, net_error -202
  • 已尝试添加transports: ['websocket', 'xhr-polling', 'polling']参数,问题仍未解决

相关配置代码

服务端(Socket.IO与Express代码)

let SocketServer = require('./core/socket_server.js');
const bodyparser = require('body-parser');

const cors = require('cors');
const express = require('express');
const app = express();

const server = require('http').createServer(app);

const io = require('socket.io')(server, {
  cors: {
    origin: "*",
    methods: ["GET", "POST"],
    transports: ['websocket', 'xhr-polling'],
    credentials: false
  },
  allowEIO3: true
});

let SockServer = new SocketServer(io);

app.set('view engine', 'ejs');
app.use(bodyparser.json());

app.use('/call/:room_id/:user_id/:video_state', express.static('public'));

app.get('/call/:room_id/:user_id/:video_state', async (request, response) => {

  await response.render('video_chat', {
      room_id: request.params.room_id,
      user_id: request.params.user_id,
      video_state: Number(request.params.video_state)
      });
});

server.listen(5001, "0.0.0.0");
SockServer.ServerInitialize();

app.use(cors({
  origin: "*"
}));

Nginx配置

events {
    worker_connections 1024;
}

http {

    server {
        listen 443 ssl;
        server_name mydomain.com www.mydomain.com;

        resolver 127.0.0.11;

        ssl_certificate /etc/certificates/cert.pem;
        ssl_certificate_key /etc/certificates/privkey.pem;

        location /socket.io/ {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            
            proxy_pass http://nodejs_container:5001;
            
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";

        }

        location /videochat {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            
            proxy_pass http://nodejs_container:5001;
            
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }

        location /users {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            
            proxy_pass http://nodejs_container:5001;
            
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }

        location ~ ^/call/([^/]+)/([^/]+)/([^/]+) {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            
            proxy_pass http://nodejs_container:5001;
            
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }
}

Docker-compose配置

version: '3'
services:
  nodejs_container:
    build:
      context: app
      dockerfile: ../docker/NodeJs/DockerFile
    networks:
      - backend
    environment:
      - NODE_ENV=production
    volumes:
      - ./app:/home/app
    command: sh -c "npm install && npm run start:prod"

  coturn_container:
    image: coturn/coturn
    ports:
      - "3478:3478/udp"
      - "5349:5349/udp"
      - "3478:3478/tcp"
      - "5349:5349/tcp"
    depends_on:
      - nodejs_container
    volumes:
      - ./coturn/turnserver/dhp.pem:/etc/turnserver/dhp.pem
      - ./coturn/turnserver.conf:/etc/turnserver.conf
      - ./coturn/certificates:/etc/coturn/certificates
    networks:
      - backend

  nginx_container:
    image: nginx
    ports:
      - 443:443
    depends_on:
      - nodejs_container
      - coturn_container
    networks:
      - backend
    volumes:
      - ./coturn/certificates:/etc/coturn/certificates
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certificates:/etc/certificates
    command: [nginx, '-g', 'daemon off;']

networks:
  backend:
    driver: bridge

SocketServer类构造函数片段

class SocketServer{
  constructor(main_socket){
    this.ServerConnections = {
      database: undefined,
      socket_server: main_socket,
      Server_NSP: {
        Users: main_socket.of(ServerNamespaces.USERS),
        VideoChat: main_socket.of(ServerNamespaces.VIDEOCHAT)
      }
    };
  }
// ServerNamespaces.USERS = "/users"
// ServerNamespaces.VIDEOCHAT = "/videochat"

排查解决方案

1. 优先检查SSL证书有效性

移动端对SSL证书校验比PC浏览器严格,确认以下几点:

  • 证书是否为受信任的正规CA颁发(自签名证书需手动导入到移动端系统,否则默认拒绝)
  • 证书是否包含完整的证书链(仅部署leaf证书会导致移动端握手失败)
  • 证书的subjectAltName字段是否包含mydomain.com和www.mydomain.com
  • 证书有效期正常,服务器与移动端时间同步

2. 优化Nginx SSL配置适配移动端

在Nginx的server块中添加以下配置,确保支持移动端常用的加密协议和套件:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

3. 修正Socket.IO配置

  • 移除服务端cors.transports配置,让Socket.IO自动协商传输方式
  • 移动端客户端显式指定transports: ['websocket'],优先使用WebSocket协议绕过polling的SSL问题
  • 确认服务端allowEIO3: true配置与客户端Socket.IO版本匹配(若客户端为v3版本则需保留)

4. 完善Nginx代理头信息

在/socket.io/的location块中添加以下配置:

proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;

5. 验证证书链完整性

执行命令openssl s_client -connect mydomain.com:443,检查输出中是否有Verify return code: 0 (ok),确认证书链无问题


内容的提问来源于stack exchange,提问作者Andrei Tricolici

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 05:17:08