NGINX反向代理websocket并启用SSL(wss://)?


136

我很迷茫,不愿独自构建NGINX,但我希望能够启用安全的websocket,而无需增加额外的层。

我不想在websocket服务器本身上启用SSL,而是想使用NGINX在整个过程中添加SSL层。

那里的每个网页都说我做不到,但是我知道我可以!感谢任何人(我自己)可以向我展示如何!

Answers:


185

只是要注意,nginx现在在1.3.13版本上支持Websockets。使用示例:

location /websocket/ {

    proxy_pass ​http://backend_host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 86400;

}

您还可以查看nginx changelogWebSocket代理文档。


它具有与上述相同的超时问题;)
3rdEden 2013年

5
@ 3rdEden:对于超时问题,proxy_read_timeout有效,我编辑了答案。
史蒂夫·凯莱特

2
我应该在哪里放置此配置,什么是backend_host?
Aysennoussi 2014年

3
@Sekai:一个location指令放在server另一个location指令中(请参阅location docs)。backend_host是一个upstream(请参阅上游文档)-您将代理到的一个或一组服务器。
Radko Dinev 2014年

1
那这个超时问题呢?为了避免它,我们是否真的必须将其设置为很大的数字?现在没有更优雅的解决方案了吗?
Mohammed Noureldin

54

别担心,因为一群勇敢的Ops编程人员以崭新的nginx_tcp_proxy_module品牌解决了这种情况

写于2012年8月,因此,如果您是未来的人,应该做作业。

先决条件

假设您正在使用CentOS:

  • 删除NGINX的当前实例(建议为此使用开发服务器)
  • 如果可能,请保存旧的NGINX配置文件,以便您可以重复使用它们(包括init.d/nginx脚本)
  • yum install pcre pcre-devel openssl openssl-devel 以及用于构建NGINX的任何其他必要的库
  • 在此处https://github.com/yaoweibin/nginx_tcp_proxy_module上从GitHub 获取nginx_tcp_proxy_module,并记住放置它的文件夹(确保未压缩)

建立新的NGINX

同样,假设CentOS:

  • cd /usr/local/
  • wget 'http://nginx.org/download/nginx-1.2.1.tar.gz'
  • tar -xzvf nginx-1.2.1.tar.gz
  • cd nginx-1.2.1/
  • patch -p1 < /path/to/nginx_tcp_proxy_module/tcp.patch
  • ./configure --add-module=/path/to/nginx_tcp_proxy_module --with-http_ssl_module (如果需要,您可以添加更多模块)
  • make
  • make install

可选的:

  • sudo /sbin/chkconfig nginx on

设置Nginx

如果要重复使用它们,请记住先复制旧的配置文件。

重要提示:您将需要tcp {}在conf中的最高级别创建一个指令。确保它不在您的http {}指令中。

下面的示例配置显示了一个上游websocket服务器,以及两个SSL和Non-SSL代理。

tcp {
    upstream websockets {
        ## webbit websocket server in background
        server 127.0.0.1:5501;
        
        ## server 127.0.0.1:5502; ## add another server if you like!

        check interval=3000 rise=2 fall=5 timeout=1000;
    }   

    server {
        server_name _;
        listen 7070;

        timeout 43200000;
        websocket_connect_timeout 43200000;
        proxy_connect_timeout 43200000;

        so_keepalive on;
        tcp_nodelay on;

        websocket_pass websockets;
        websocket_buffer 1k;
    }

    server {
        server_name _;
        listen 7080;

        ssl on;
        ssl_certificate      /path/to/cert.pem;
        ssl_certificate_key  /path/to/key.key;

        timeout 43200000;
        websocket_connect_timeout 43200000;
        proxy_connect_timeout 43200000;

        so_keepalive on;
        tcp_nodelay on;

        websocket_pass websockets;
        websocket_buffer 1k;
    }
}

5
这很有帮助,但是我仍然在60秒时超时。我设法通过设置以下内容解决此问题:超时43200000; websocket_connect_timeout 43200000; websocket_read_timeout 43200000; websocket_send_timeout 43200000; proxy_connect_timeout 43200000; proxy_read_timeout 43200000; proxy_send_timeout 43200000;
2012年

2
感谢您的分享!后来我意识到自己遇到了类似的问题,巧合的是,yaoweibin本人也回答了我的GitHub问题,并提供了您对第28期的评论的链接。小世界...
crockpotveggies 2012年

1
我只想在浏览器通过身份验证后才在同一个http端口上提供websocket。看来这无法在同一端口上处理websocket。人们如何处理?
uroc

1
需要进行一些软件修改才能检测到传入的协议。由于websocket实际上是从HTTP握手开始的(软件级别高于TCP),因此您必须调整应用程序以处理TCP和HTTP流量。我目前尚不推荐这样做的方法。
crockpotveggies 2012年

2
万一2018年的其他人来了,这些指令将不再起作用。请访问nginx.org/en/docs/http/websocket.html以获取最新说明,或参阅下面的Harlan T Wood的答案。
GaryO

37

这对我有用:

location / {
    # redirect all HTTP traffic to localhost:8080
    proxy_pass http://localhost:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

-从以下网站借来的:https : //github.com/nicokaiser/nginx-websocket-proxy/blob/df67cd92f71bfcb513b343beaa89cb33ab09fb05/simple-wss.conf


3
我很难让TeamCity的Web套接字在我的反向代理后面工作。你# WebSocket supportsn了我。我以前尝试转发端口400,但WSS的作品超过443 FYI未来的读者:)
马里奥塔克

您找到解决方案了吗?由于我只好也面临类似的问题 stackoverflow.com/q/53411060/7713811
Nɪsʜᴀɴᴛʜ

我喜欢这个答案最好,因为许多人(如您自己)都将/用于网络套接字和常规HTTP2。
mikemaccana19年

@Anyone调用Javascript是什么?
安德鲁·辛普森

17

用于带有SSL的.net core 2.0 Nginx

location / {
    # redirect all HTTP traffic to localhost:8080
    proxy_pass http://localhost:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
}

这对我有用


什么是C#代码。我目前在Windows / iis中有此_server = new WebSocketServer(“ wss://0.0.0.0:8200 / MessageRelayer”){证书= new X509Certificate2(PfxFileName,SslPassword),RestartAfterListenError = true};
安德鲁·辛普森

我正在使用SignalR
Altair CA

这是唯一对我有用的解决方案。谢谢!
m-ketan

8

对我来说,它取决于proxy_pass位置设置。我需要切换为使用HTTPS协议,并在节点服务器端设置有效的SSL证书。这样,当我引入一个外部节点服务器时,我只需要更改IP,其他所有配置都保持不变。

我希望这可以对整个过程有所帮助...我一直都在盯着这个问题...

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
upstream nodeserver {
        server 127.0.0.1:8080;
}
server {
        listen 443 default_server ssl http2;
        listen [::]:443 default_server ssl http2 ipv6only=on;
        server_name mysite.com;
        ssl_certificate ssl/site.crt;
        ssl_certificate_key ssl/site.key;
        location /websocket { #replace /websocket with the path required by your application
                proxy_pass https://nodeserver;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $connection_upgrade;
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_intercept_errors on;
                proxy_redirect off;
                proxy_cache_bypass $http_upgrade;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-NginX-Proxy true;
                proxy_ssl_session_reuse off;
            }
}

我试过了localtion /horizon,但是没有用。仅localtion /location /websockify有效。不知道为什么...
njuguoyi

6

Pankaj Malhotra撰写的一篇简洁明了的文章讨论了如何使用NGINX进行此操作,可在此处获得

以下是NGINX的基本配置:

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

upstream appserver {
    server 192.168.100.10:9222; # appserver_ip:ws_port
}

server {
    listen 8888; // client_wss_port

    ssl on;
    ssl_certificate /path/to/crt;
    ssl_certificate_key /path/to/key;


    location / {
        proxy_pass http://appserver;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

1
现代版本的NGINX是否也解决了超时问题?
crockpotveggies 2015年

2

使用nginx / 1.14.0

我有一个运行在端口8097上的websocket服务器,用户从端口8098上的wss连接,nginx只是解密内容并将其转发到websocket服务器

所以我有这个配置文件(以我为例/etc/nginx/conf.d/default.conf

server {
    listen   8098;
        ssl on;
        ssl_certificate      /etc/ssl/certs/combined.pem;
        ssl_certificate_key  /root/domain.key;
    location / {

        proxy_pass http://hostname:8097;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;

    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.