Điểm:0

Proxy kép NGINX không cho phép kết nối websocket

lá cờ lb

Tôi có hai thiết lập proxy nginx trên máy của mình, một để hủy kích hoạt SSL và cái còn lại để thực hiện ủy quyền dành riêng cho ứng dụng (chỉ cái thứ hai được kiểm soát theo phiên bản). Khi tôi chỉ có một proxy, tôi có thể tạo kết nối websocket thành công, nhưng sau khi chuyển sang hai proxy, tất cả các yêu cầu nâng cấp websocket đều được phản hồi với lỗi 502 Bad Gateway. Tôi có thể xác nhận rằng các yêu cầu http/https thông thường đang hoạt động với thiết lập proxy kép của tôi. Đây là cấu hình hiện tại của tôi.

ủy quyền 1

người phục vụ {

        # Cấu hình SSL
        #
        # nghe 443 ssl default_server;
        # lắng nghe [::]:443 ssl default_server;
        #
        # Lưu ý: Bạn nên tắt gzip cho lưu lượng SSL.
        # Xem: https://bugs.debian.org/773332
        #
        # Đọc ssl_ciphers để đảm bảo cấu hình an toàn.
        # Xem: https://bugs.debian.org/765782
        #
        # Chứng chỉ tự ký được tạo bởi gói ssl-cert
        # Đừng sử dụng chúng trong máy chủ sản xuất!
        #
        # bao gồm đoạn trích/snakeoil.conf;

        server_name staging.ambitx.io;

        địa điểm / {
                proxy_pass http://127.0.0.1:81;
                bao gồm proxy_params;
        }

    lắng nghe [::]:443 ssl ipv6only=on; # được quản lý bởi Certbot
    nghe 443 ssl; # được quản lý bởi Certbot
    ssl_certificate /etc/letsencrypt/live/staging.ambitx.io/fullchain.pem; # được quản lý bởi Certbot
    ssl_certificate_key /etc/letsencrypt/live/staging.ambitx.io/privkey.pem; # được quản lý bởi Certbot
    bao gồm /etc/letsencrypt/options-ssl-nginx.conf; # được quản lý bởi Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # được quản lý bởi Certbot

}
người phục vụ {
    nếu ($host = staging.ambitx.io) {
        trả lại 301 https://$host$request_uri;
    } # được quản lý bởi Certbot

        nghe 80 default_server;
        lắng nghe [::]:80 default_server;

        server_name staging.ambitx.io;
    trả lại 404; # được quản lý bởi Certbot

}

proxy_params

proxy_set_header Máy chủ $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

ủy quyền 2

(chạy trên docker với cổng 81 trên máy chủ được liên kết với cổng 80 trên vùng chứa)

trình phân giải 127.0.0.11 ipv6=tắt;

người phục vụ {
  nghe 80;
  nghe [::]:80;

  địa điểm / {
    gốc/var/www/tệp tĩnh;
    chỉ mục index.html index.htm;
    try_files $uri /index.html =404;
  }
  
  vị trí /ws {
    truy cập_đăng xuất;

    proxy_pass http://wsserver;

    proxy_http_version 1.1;
    proxy_set_header Nâng cấp $http_upgrade;
    proxy_set_header Kết nối "nâng cấp";
  }

  vị trí /api {
    proxy_pass http://apiserver;
  }
}

Ban đầu tôi đã có những tuyên bố dưới đây trong vị trí /ws khối cấu hình của Proxy 2...

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Máy chủ lưu trữ $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

nhưng tôi đã xóa chúng vì chúng sẽ ghi đè lên các tiêu đề do Proxy 1 đặt.

Bất kỳ ý tưởng? Xin hãy để tôi biết nếu bạn cần nhiều thông tin hơn.

Điểm:0
lá cờ gr

Tất nhiên, bạn không nên bỏ hỗ trợ ủy quyền WebSocket từ bất kỳ máy chủ proxy trung gian nào của mình. WebSocket proxying là rất nhiệm vụ đặc biệt, để cho phép chuyển đổi giao thức và giữ cho kết nối WebSocket được thiết lập và hoạt động, bạn cũng nên trả lại sự hỗ trợ của nó cho proxy nginx đầu tiên của mình:

...
địa điểm / {
    proxy_pass http://127.0.0.1:81;
    bao gồm proxy_params;
}
vị trí /ws {
    proxy_pass http://127.0.0.1:81;
    bao gồm proxy_params;
    proxy_http_version 1.1;
    proxy_set_header Nâng cấp $http_upgrade;
    proxy_set_header Kết nối "nâng cấp";
}
...

Loại bỏ cả ba proxy_set_header chỉ thị từ proxy nginx thứ hai của bạn cũng là một ý tưởng tồi. Trong khi X-Real-IPX-Forwarded-For các tiêu đề sẽ được chuyển đến ứng dụng WebSocket của bạn chính xác như được đặt bởi proxy đầu tiên của bạn, Chủ nhà tiêu đề là một cái đặc biệt. Trừ khi được đặt rõ ràng, nó sẽ được chuyển bằng tên ngược dòng được sử dụng trong proxy_pass chỉ thị, tức là Máy chủ: wsserver. Như bạn có thể đọc từ proxy_set_header chỉ thị tài liệu:

Theo mặc định, chỉ có hai trường được xác định lại:

proxy_set_header Máy chủ $proxy_host;
proxy_set_header Đóng kết nối;

(cái thứ hai chắc chắn cũng sẽ phá vỡ mọi nỗ lực thiết lập kết nối WebSocket). Vì vậy, để giữ bản gốc Chủ nhà tiêu đề từ yêu cầu của khách hàng (thường là một ý kiến ​​hay, bạn có thể đọc thêm về tiêu đề này đây), trả lại

proxy_pass Máy chủ $http_host;

dòng cho cả hai địa điểm / { ... }vị trí /ws {...} của cấu hình proxy nginx thứ hai của bạn.

Simon Richard avatar
lá cờ lb
Điều này làm việc cho tôi, cảm ơn. Với mục đích giữ cho proxy 1 không tin vào proxy 2 (vì proxy 1 hiện không được kiểm soát phiên bản), tôi đã quyết định sử dụng "ví dụ phức tạp hơn" (ví dụ thứ hai) được liệt kê trên trang web này: https://nginx.org /en/docs/http/websocket.html và chỉ cần thêm nó vào khối `location / { ... }` trong proxy 1. Theo cách đó, nếu tôi thay đổi url websocket nhưng quên proxy 1 thì nó sẽ không bị hỏng. Nhược điểm duy nhất của điều này mà tôi có thể nghĩ đến là nó sẽ không thể xử lý http/2.0, nhưng dù sao thì máy chủ của tôi vẫn chưa được thiết lập để xử lý nó.
Ivan Shatsky avatar
lá cờ gr
Điều đó nghe có vẻ hợp lý, tôi cũng thích cách ủy quyền WebSocket đó hơn. Về HTTP/2, bạn có thể thấy chuỗi [this](https://serverfault.com/questions/765258/use-http-2-0-between-nginx-reverse-proxy-and-backend-webserver) khá thú vị.

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.