代码之家  ›  专栏  ›  技术社区  ›  The Nomad

带有Nginx的SSL websockets无法连接

  •  0
  • The Nomad  · 技术社区  · 8 年前

    在获取方面有问题 Nginx proxy_pass 使用websockets和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
      }
    };
    

    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在本地测试了服务器,它工作得很好。我怎样才能让它工作?

    1 回复  |  直到 8 年前
        1
  •  3
  •   Steffen Ullrich    8 年前

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

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

        proxy_pass         http://localhost:8989/graphql;
    

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

    location /ws {
       ...
    }
    
    listen 443 ssl; # managed by Certbot
    

    ws://site.io:8989/graphql 直接访问websocket而不使用TLS或 wss://site:io/ws wss://site.io:8989/ws 就像你试过的。