【问题标题】:SSL websockets with Nginx cannot connect带有 Nginx 的 SSL websockets 无法连接
【发布时间】:2018-08-22 16:57:46
【问题描述】:

在使用 websockets 和 SSL (WSS) 将 Nginx 转换为 proxy_pass 时遇到问题。

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
  }
};

我收到各种不同的错误:

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 测试了服务器,它工作正常。我怎样才能让它工作?

【问题讨论】:

    标签: ssl nginx websocket


    【解决方案1】:

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

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

        proxy_pass         http://localhost:8989/graphql;
    

    这部分配置表明服务器在端口 8989 上不需要 TLS,即应该使用ws://

    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 你已经尝试过。

    【讨论】:

    • 非常感谢!现在效果很好。我最终将 nginx 更改为路由到 https 并删除端口就像一个魅力。一直在这个问题上敲我的头。非常感谢!
    • 我要快速添加的一件事是我需要为我添加一个斜杠。 wss://foo.com/ws-link/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    • 2021-08-06
    • 1970-01-01
    • 1970-01-01
    • 2022-06-29
    • 2021-09-17
    • 1970-01-01
    相关资源
    最近更新 更多