Nginx的SSL WebSocket无法连接 [英] SSL websockets with Nginx cannot connect

查看:1177
本文介绍了Nginx的SSL WebSocket无法连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用网络套接字和SSL(WSS)将Nginx升级为proxy_pass时遇到问题.

Having issues with getting Nginx to proxy_pass with websockets and SSL (WSS).

NGINX配置

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
    server_name site.io www.site.io;

    location / {
        proxy_pass         https://localhost:3000;
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   Host $http_host;
    }

    location /ws {
        proxy_pass         http://localhost:8989/graphql;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection "upgrade";
        proxy_set_header   Host $host;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/site.io/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/site.io/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
    if ($host = www.site.io) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = site.io) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name site.io www.site.io;
    return 404; # managed by Certbot
}

服务器代码

const initApiServer = () => {
  try {
    const app = express();

    // Allow CORS
    app.use((req, res, next) => {
      res.header('Access-Control-Allow-Origin', '*');
      res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
      next();
    });

    // Set security-related HTTPS headers
    app.use(helmet());

    // Setup for JSON and url encoded bodies
    app.use(express.json());
    app.use(express.urlencoded({ extended: true }));

    app.use('/', apiRouter); // Apply API routes
    const apollo = new ApolloServer({
      typeDefs,
      resolvers,
      context: { db },
      introspection: true, // enabled playground in prod
      playground: true, // enabled playground in prod
    });
    apollo.applyMiddleware({ app });

    const server = createServer(app);
    apollo.installSubscriptionHandlers(httpServer);

    server.listen(8989, () => {
      getLogger().info(`API served at ${Config.PROTOCOL}://${Config.HOSTNAME}:${Config.PORT_API}`);
    });
  } catch (err) {
    getLogger().error(`Error starting API Server: ${err.message}`);
    require('../server').exit('SIGTERM'); // eslint-disable-line
  }
};

我收到各种不同的错误:

I receive a variety of different errors:

WebSocket connection to 'wss://site.io:8989/ws' failed: WebSocket is closed before the connection is established.
WebSocket connection to 'wss://site.io:8989/ws' failed: Error during WebSocket handshake: Unexpected response code: 400

我已经使用非SSL在本地测试了服务器,并且工作正常.我怎样才能使它正常工作?

I have tested the server locally with non-SSL and it works fine. How can I get this to work?

推荐答案

与'wss://site.io:8989/ws'的WebSocket连接失败:WebSocket握手期间出错:意外的响应代码:400

WebSocket connection to 'wss://site.io:8989/ws' failed: Error during WebSocket handshake: Unexpected response code: 400

此错误消息表明您尝试在端口8989上使用TLS(即wss://)访问websocket服务器.

This error message suggests that you try to access the websocket server with TLS (i.e. wss://) on port 8989.

    proxy_pass         http://localhost:8989/graphql;

这部分配置建议服务器在端口8989上不期望使用TLS,即应使用ws://.

This part of the configurations suggests that on port 8989 the server is not expecting TLS, i.e. ws:// should be used.

location /ws {
   ...
}

listen 443 ssl; # managed by Certbot

这表明您已经在端口443(标准端口)上设置了TLS.这意味着您的访问应该是ws://site.io:8989/graphql直接访问websocket而没有TLS,或者wss://site:io/ws(没有端口8989,即标准端口443)访问nginx后面的websocket.不应像您尝试的那样是wss://site.io:8989/ws.

And this suggests that you've setup the TLS on port 443 (standard port). This means your access should be either for ws://site.io:8989/graphql to access the websocket directly and without TLS or for wss://site:io/ws (without port 8989, i.e. standard port 443) to access the websocket behind the nginx. It should not be wss://site.io:8989/ws as you've tried.

这篇关于Nginx的SSL WebSocket无法连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆