Nginx

SSL 上帶有 Sails.js/Node.js 和 NGINX 的 Socket.io:網關錯誤

  • February 9, 2017

我剛開始涉足 NGINX 和 SSL。

使用 Ubuntu 16.04。

我在標準的 1337 埠上執行 Sails 伺服器,並使用 SSL 設置 NGINX(使用letsencrypt)。埠 80 被重定向到 443,上游轉到 Sails。

我還有一個 Tomcat 伺服器在 8080 上偵聽並使用 NGINX 以相同的方式重定向。

一切正常:我可以在 https 上瀏覽兩台伺服器,而無需瀏覽器上的特殊埠。

我已將 socket.io 設置為僅使用 websockets 協議(無輪詢)。這是在伺服器和瀏覽器客戶端上設置的。

但是,socket.io (sails.io) 在瀏覽器中拋出 502 錯誤。(投票也出錯了)

這是我的 NGINX 站點,可用於 Sails 伺服器:

upstream sails {
  server 127.0.0.1:1337 fail_timeout=0;
}

server {
  listen 80;
  listen [::]:80;
  server_name mysails.server.com;
  return 301 https://$server_name$request_uri;
}

server {
  listen 443;
  listen [::]:443 ssl http2;
  server_name mysails.server.com;
  include snippets/ssl-mysails.server.conf;
  include snippers/ssl-params.conf;
  large_client_header_buffers 8 32k;

  location / {
     proxy_pass http://sails/;
     proxy_http_version 1.1;
     proxy_redirect off;
     proxy_set_header Host $host;
     proxy_set_header Port $server_port;
     proxy_set_header X-Real-IP $remot_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-NginX-Proxy true;
     proxy_pass_request_headers on;

  }

  location /socket.io/ {
     proxy_pass http://sails/;
     proxy_http_version 1.1;
     proxy_redirect off;
     proxy_set_header Host $host;
     proxy_set_header Port $server_port;
     proxy_set_header X-Real-IP $remot_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-NginX-Proxy true;
     proxy_pass_request_headers on;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection "upgrade";
     proxy_buffers 8 32k;
     proxy_buffer_size 64k;

  }   
}

snippets/ssl-mysails.server.conf文件snippers/ssl-params.conf包含:

ssl_certificate /path/to/letsencrypt/fullchain.pem;
ssl_certificate_key /path/to/letsencrypt/privkey.pem;

# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_dhparam /etc/ssl/certs/dhparam.pem;

任何人都知道發生了什麼……?

更新錯誤日誌和奇怪的行為

我的 nginx 錯誤日誌這樣說:

upstream prematurely closed connection while reading response header from upstream, client: XXXXXXXX, server: mysals.server.com, request: "GET /socket.io/?__sails_io_sdk_version=0.13.8&__sails_io_sdk_platform=browser&__sails_io_sdk_language=javascript&EIO=3&transport=websocket HTTP/1.1", upstream: "http://127.0.0.1:1337/?__sails_io_sdk_version=0.13.8&__sails_io_sdk_platform=browser&__sails_io_sdk_language=javascript&EIO=3&transport=websocket", host: "mysails.server.com"

而且我的 Sails 詳細日誌不一致。它可能會這樣說:

*verbose*: Rendering view: "homepage" (located @ "/opt/FillForm/views/homepage")
*verbose*: • using configured layout:: layout (located @ "/opt/FillForm/views/layout")
*verbose*: Rendering view: "homepage" (located @ "/opt/FillForm/views/homepage")
*verbose*: • using configured layout:: layout (located @ "/opt/FillForm/views/layout")
*verbose*: Rendering view: "fileLink" (located @ "/opt/FillForm/views/fileLink")
*verbose*: • using configured layout:: layout (located @ "/opt/FillForm/views/layout")
*verbose*: Sending 404 ("Not Found") response
*verbose*: Sending 404 ("Not Found") response
*verbose*: Rendering view: "fileLink" (located @ "/opt/FillForm/views/fileLink")
*verbose*: • using configured layout:: layout (located @ "/opt/FillForm/views/layout")
*verbose*: Sending 404 ("Not Found") response
*verbose*: Sending 404 ("Not Found") response

/opt/FillForm/views/fileLink這很奇怪,因為視圖/頁面應該只有一個請求。

如果您刷新頁面 (F5),瀏覽器上的 Javascript 控制台可能只會顯示:

Socket is trying to reconnect to Sails...
_-|>_-  (attempt #7)

每次嘗試都會導致一系列

verbose: Rendering view: "homepage" (located @ "/opt/FillForm/views/homepage")
verbose: • using configured layout:: layout (located @ "/opt/FillForm/views/layout")

Sails 詳細日誌上的消息。為什麼套接字請求會導致 Sails 呈現首頁視圖?

如果您使用忽略記憶體 (shift+F5) 刷新,Javascript 控制台開始顯示嘗試和 502 bad gateway 消息:

WebSocket connection to 'wss://mysqils.server.com/socket.io/?__sails_io_sdk_version=0.13.8&__sails_io_s…tform=browser&__sails_io_sdk_language=javascript&EIO=3&transport=websocket' failed: Error during WebSocket handshake: Unexpected response code: 502
       Socket is trying to reconnect to Sails...
_-|>_-  (attempt #20)

Sails 詳細日誌僅顯示以下消息的兩個實例:

verbose: Sending 404 ("Not Found") response
verbose: Sending 404 ("Not Found") response

並且它停止顯示任何其他錯誤(不像在前面的場景中,每次 websocket 嘗試都會導致視圖呈現消息。)

在這種情況下,似乎 wss 請求沒有通過 Nginx 到達 Sails。

所以問題是 NGINX sites-avalable conf 文件的錯誤配置。

location /socket.io/ {
     proxy_pass http://sails/;
...
}

應該

location /socket.io/ {
     proxy_pass http://sails/socket.io/;
...
}

非常基本的東西:“位置”沒有轉發到 proxy_pass(為什麼會這樣,對嗎?)——所以你需要確保套接字請求被重定向到確切的套接字端點。

引用自:https://serverfault.com/questions/829100