NGINX để đảo ngược websockets proxy và kích hoạt SSL (wss: //)?


136

Tôi rất lạc lõng và mới tự mình xây dựng NGINX nhưng tôi muốn có thể kích hoạt các websockets an toàn mà không cần thêm một lớp.

Tôi không muốn bật SSL trên máy chủ websocket mà thay vào đó tôi muốn sử dụng NGINX để thêm một lớp SSL vào toàn bộ.

Mỗi trang web trên mạng nói rằng tôi không thể làm điều đó, nhưng tôi biết tôi có thể! Nhờ ai (bản thân) có thể chỉ cho tôi cách!

Câu trả lời:


185

Chỉ cần lưu ý rằng nginx hiện đã hỗ trợ cho Websockets trên phiên bản 1.3.13. Ví dụ sử dụng:

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;

}

Bạn cũng có thể kiểm tra thay đổi nginx và tài liệu ủy quyền WebSocket .


Nó có cùng các vấn đề về thời gian chờ như đã trình bày ở trên;)
3Eden

5
@ 3rdEden: Đối với các vấn đề thời gian chờ, proxy_read_timeoutcông việc, tôi đã chỉnh sửa câu trả lời.
Steve Kehlet

2
Tôi nên đặt cấu hình này ở đâu và backend_host là gì?
Aysennoussi

3
@Sekai: Một lệnh locationđược đặt trong một serverhoặc một lệnh khác location(xem tài liệu vị trí ). backend_hostlà một upstream(xem tài liệu ngược dòng ) - một hoặc một nhóm máy chủ mà bạn sẽ ủy quyền.
Radko Dinev

1
Còn vấn đề thời gian chờ này thì sao? Chúng ta có thực sự phải đặt nó thành một số rất lớn để tránh nó không? Bây giờ không có giải pháp thanh lịch hơn?
Mohammed Noureldin

54

Đừng sợ, bởi vì một nhóm lập trình viên Ops dũng cảm đã giải quyết tình huống bằng một thương hiệu mới nginx_tcp_proxy_module

Được viết vào tháng 8 năm 2012, vì vậy nếu bạn đến từ tương lai, bạn nên làm bài tập về nhà.

Điều kiện tiên quyết

Giả sử bạn đang sử dụng CentOS:

  • Xóa phiên bản NGINX hiện tại (đề xuất sử dụng máy chủ dev cho việc này)
  • Nếu có thể, hãy lưu các tệp cấu hình NGINX cũ của bạn để bạn có thể sử dụng lại chúng (bao gồm init.d/nginxtập lệnh của bạn )
  • yum install pcre pcre-devel openssl openssl-devel và bất kỳ libs cần thiết nào khác để xây dựng NGINX
  • Nhận nginx_tcp_proxy_module từ GitHub tại đây https://github.com/yaoweibin/nginx_tcp_proxy_module và nhớ thư mục nơi bạn đặt nó (đảm bảo rằng nó không bị nén)

Xây dựng NGINX mới của bạn

Một lần nữa, giả sử 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 (bạn có thể thêm nhiều mô-đun nếu bạn cần chúng)
  • make
  • make install

Không bắt buộc:

  • sudo /sbin/chkconfig nginx on

Thiết lập Nginx

Hãy nhớ sao chép các tập tin cấu hình cũ trước nếu bạn muốn sử dụng lại chúng.

Quan trọng: bạn sẽ cần tạo một lệnh tcp {}ở mức cao nhất trong conf của bạn. Hãy chắc chắn rằng nó không nằm trong http {}chỉ thị của bạn .

Cấu hình ví dụ dưới đây cho thấy một máy chủ websocket ngược dòng duy nhất và hai proxy cho cả SSL và 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
Điều này khá hữu ích, nhưng tôi vẫn nhận được thời gian chờ ở mức 60 giây. Tôi đã cố gắng khắc phục điều này bằng cách cài đặt như sau: hết thời gian 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;
jbg

2
Cảm ơn đã chia sẻ điều đó! Sau đó tôi nhận ra mình đang gặp vấn đề tương tự, và tình cờ, chính yaoweibin cũng trả lời vấn đề GitHub của tôi với một liên kết đến nhận xét của bạn về Vấn đề # 28. Thế giới nhỏ bé ...
crockpotveggies

1
Tôi muốn phân phát các websockets khỏi cùng một cổng http và chỉ sau khi trình duyệt được xác thực. Có vẻ như điều này không thể xử lý các ổ cắm web trên cùng một cổng. Làm thế nào để mọi người xử lý này?
uroc

1
Nó sẽ mất một số sửa đổi phần mềm để phát hiện giao thức đến. Vì websockets thực sự bắt đầu như một cái bắt tay HTTP (mức phần mềm cao hơn TCP), bạn phải điều chỉnh ứng dụng của mình để xử lý cả lưu lượng TCP và HTTP. Tôi không thể đề nghị một cách để làm điều này chưa.
crockpotveggies

2
Trong trường hợp những người khác từ năm 2018 đến đây, những chỉ thị này không còn hiệu quả nữa. Tới nginx.org/en/docs/http/websocket.html để được hướng dẫn gần đây hoặc xem câu trả lời Harlan T Wood dưới đây.
GaryO

37

Điều này làm việc cho tôi:

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

- mượn từ: https://github.com/nicokaiser/nginx-websocket-proxy/blob/df67cd92f71bfcb513b343beaa89cb33ab09fb05/simple-wss.conf


3
Tôi gặp sự cố khi các ổ cắm web của TeamCity hoạt động sau proxy ngược của tôi. # WebSocket supportSnipped của bạn đã làm điều đó cho tôi. Trước đây tôi đã cố gắng chuyển tiếp cổng 400, tuy nhiên wss hoạt động trên 443. Độc giả tương lai của FYI :)
Mario Tacke

Bạn đã tìm ra giải pháp? Vì tôi cũng đã để đối mặt với một vấn đề tương tự stackoverflow.com/q/53411060/7713811
Nɪsʜᴀɴᴛʜ

Tôi thích câu trả lời này tốt nhất, vì nhiều người (như chính bạn) sử dụng / cho cả websockets và HTTP2 thông thường.
mikemaccana

@ Bất cứ ai sẽ gọi Javascript là gì?
Andrew Simpson

17

cho .net core 2.0 Nginx với SSL

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

Điều này làm việc cho tôi


mã c # là gì. Tôi hiện đang có cái này cho windows / iis _server = new WebSocketServer ("wss: //0.0.0.0: 8200 / MessageRelayer") {Chứng chỉ = new X509Cert ve2 (PfxFileName, SslPassword), RestartAfterListenEr
Andrew Simpson

Tôi đang sử dụng SignalR
Altair CA

Đây là giải pháp duy nhất hiệu quả với tôi. Cảm ơn!
m-ketan

8

Đối với tôi, nó đi xuống proxy_passcài đặt vị trí. Tôi cần thay đổi sang sử dụng giao thức HTTPS và có chứng chỉ SSL hợp lệ được thiết lập ở phía máy chủ nút. Theo cách đó, khi tôi giới thiệu một máy chủ nút bên ngoài, tôi chỉ phải thay đổi IP và mọi thứ khác vẫn giữ nguyên cấu hình.

Tôi hy vọng điều này sẽ giúp ai đó trên đường đi ... Tôi đã nhìn chằm chằm vào vấn đề suốt ... thở dài ...

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

Tôi đã thử localtion /horizon, nhưng nó không hoạt động. Chỉ localtion /hoặc location /websockifyhoạt động. Không biết tại sao ...
njuguoyi

6

Một bài viết hay, súc tích của Pankaj Malhotra thảo luận về cách làm điều này với NGINX và có sẵn ở đây .

Cấu hình NGINX cơ bản được sao chép dưới đây:

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
Các phiên bản hiện đại của NGINX cũng giải quyết các vấn đề thời gian chờ?
crockpotveggies

2

Sử dụng nginx / 1.14.0

Tôi có một máy chủ websocket chạy trên cổng 8097 và người dùng kết nối từ đến wss trên cổng 8098, nginx chỉ giải mã nội dung và chuyển tiếp đến máy chủ websocket

Vì vậy, tôi có tập tin cấu hình này (trong trường hợp của tôi /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;

    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.