Score:0

NGINX double proxy ไม่อนุญาตให้มีการเชื่อมต่อ websocket

ธง lb

ฉันมีการตั้งค่าพร็อกซี nginx สองตัวบนเครื่องของฉัน อันหนึ่งสำหรับแกะ SSL และอีกอันสำหรับทำพร็อกซีเฉพาะแอปพลิเคชัน (เฉพาะอันที่สองเท่านั้นที่ควบคุมเวอร์ชัน) เมื่อฉันมีพรอกซีเพียงอันเดียว ฉันก็สามารถเชื่อมต่อเว็บซ็อกเก็ตได้สำเร็จ แต่หลังจากย้ายไปสองคำขออัปเกรดเว็บซ็อกเก็ตทั้งหมดจะได้รับการตอบสนองด้วยข้อผิดพลาด 502 Bad Gateway ฉันสามารถยืนยันได้ว่าคำขอ http/https ปกติทำงานกับการตั้งค่าพร็อกซีคู่ของฉัน นี่คือการกำหนดค่าปัจจุบันของฉัน

หนังสือมอบฉันทะ1

เซิร์ฟเวอร์ {

        # การกำหนดค่า SSL
        #
        # ฟัง 443 ssl default_server;
        # ฟัง [::]:443 ssl default_server;
        #
        # หมายเหตุ: คุณควรปิดการใช้งาน gzip สำหรับการรับส่งข้อมูล SSL
        # ดู: https://bugs.debian.org/773332
        #
        # อ่านข้อมูลเพิ่มเติมเกี่ยวกับ ssl_ciphers เพื่อให้แน่ใจว่ามีการกำหนดค่าที่ปลอดภัย
        # ดู: https://bugs.debian.org/765782
        #
        # ใบรับรองที่ลงนามด้วยตนเองที่สร้างขึ้นโดยแพ็คเกจ ssl-cert
        # ห้ามใช้ในเซิร์ฟเวอร์ที่ใช้งานจริง!
        #
        # รวมตัวอย่าง/snakeoil.conf;

        server_name staging.ambitx.io;

        ที่ตั้ง / {
                proxy_pass http://127.0.0.1:81;
                รวม proxy_params;
        }

    ฟัง [::]:443 ssl ipv6only=เปิด; # จัดการโดย Certbot
    ฟัง 443 ssl; # จัดการโดย Certbot
    ssl_certificate /etc/letsencrypt/live/staging.ambitx.io/fullchain.pem; # จัดการโดย Certbot
    ssl_certificate_key /etc/letsencrypt/live/staging.ambitx.io/privkey.pem; # จัดการโดย Certbot
    รวม /etc/letsencrypt/options-ssl-nginx.conf; # จัดการโดย Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # จัดการโดย Certbot

}
เซิร์ฟเวอร์ {
    ถ้า ($host = staging.ambitx.io) {
        ส่งคืน 301 https://$host$request_uri;
    } # จัดการโดย Certbot

        ฟัง 80 default_server;
        ฟัง [::]:80 default_server;

        server_name staging.ambitx.io;
    กลับ 404; # จัดการโดย Certbot

}

proxy_params

proxy_set_header โฮสต์ $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-ส่งต่อ-สำหรับ $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

หนังสือมอบฉันทะ2

(ทำงานบนนักเทียบท่าที่มีพอร์ต 81 บนเครื่องโฮสต์ที่เชื่อมโยงกับพอร์ต 80 บนคอนเทนเนอร์)

ตัวแก้ไข 127.0.0.11 ipv6=ปิด;

เซิร์ฟเวอร์ {
  ฟัง 80;
  ฟัง [::]:80;

  ที่ตั้ง / {
    รูท /var/www/staticfiles;
    ดัชนี index.html index.htm;
    try_files $uri /index.html =404;
  }
  
  ที่ตั้ง /ws {
    access_log off;

    proxy_pass http://wsserver;

    proxy_http_version 1.1;
    proxy_set_header อัพเกรด $http_upgrade;
    proxy_set_header การเชื่อมต่อ "อัพเกรด";
  }

  ที่ตั้ง /api {
    proxy_pass http://apiserver;
  }
}

เดิมฉันมีข้อความด้านล่างใน ที่ตั้ง /ว บล็อกการกำหนดค่าของ Proxy 2...

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header โฮสต์ $host;
proxy_set_header X-ส่งต่อ-สำหรับ $proxy_add_x_forwarded_for;

แต่ฉันลบออกเพราะจะเขียนทับส่วนหัวที่กำหนดโดย Proxy 1

ความคิดใด ๆ ? โปรดแจ้งให้เราทราบหากคุณต้องการข้อมูลเพิ่มเติม

Score:0
ธง gr

แน่นอน คุณไม่ควรยกเลิกการสนับสนุนพร็อกซี WebSocket จากพร็อกซีเซิร์ฟเวอร์ระดับกลางใดๆ ของคุณ การมอบฉันทะของ WebSocket เป็นสิ่งที่สำคัญมาก งานพิเศษเพื่ออนุญาตให้มีการสลับโปรโตคอลและคงการเชื่อมต่อ WebSocket ไว้และใช้งานได้ คุณควรคืนการสนับสนุนไปยังพร็อกซี nginx ตัวแรกของคุณด้วย:

...
ที่ตั้ง / {
    proxy_pass http://127.0.0.1:81;
    รวม proxy_params;
}
ที่ตั้ง /ws {
    proxy_pass http://127.0.0.1:81;
    รวม proxy_params;
    proxy_http_version 1.1;
    proxy_set_header อัพเกรด $http_upgrade;
    proxy_set_header การเชื่อมต่อ "อัพเกรด";
}
...

ถอดทั้ง 3 ตัว proxy_set_header คำสั่งจากพรอกซี nginx ที่สองของคุณก็เป็นความคิดที่ไม่ดีเช่นกัน ในขณะที่ เอ็กซ์-เรียล-ไอพี และ X-ส่งต่อ-สำหรับ ส่วนหัวจะถูกส่งต่อไปยังแอป WebSocket ของคุณเหมือนกับที่พร็อกซีตัวแรกของคุณตั้งค่าไว้ นั่นคือ เจ้าภาพ ส่วนหัวเป็นแบบพิเศษ เว้นแต่จะตั้งค่าอย่างชัดเจน มันจะถูกส่งผ่านเท่ากับชื่ออัปสตรีมที่ใช้ใน proxy_pass คำสั่งเช่น โฮสต์: wsserver. เท่าที่อ่านได้จาก proxy_set_header คำสั่ง เอกสาร:

ตามค่าเริ่มต้น จะมีการกำหนดใหม่เพียงสองฟิลด์เท่านั้น:

proxy_set_header โฮสต์ $proxy_host;
ปิดการเชื่อมต่อ proxy_set_header;

(อันที่สองจะทำลายความพยายามในการสร้างการเชื่อมต่อ WebSocket ด้วยเช่นกัน) ดังนั้นเพื่อให้คงเดิมไว้ เจ้าภาพ ส่วนหัวจากคำขอของลูกค้า (โดยปกติแล้วเป็นความคิดที่ดี คุณสามารถอ่านเพิ่มเติมเกี่ยวกับส่วนหัวนี้ได้ ที่นี่) ส่งคืน

proxy_pass โฮสต์ $http_host;

ไลน์ไปทั้งคู่ ที่ตั้ง / { ... } และ ที่ตั้ง /ws { ... } ของการกำหนดค่าพร็อกซี nginx ที่สองของคุณ

Simon Richard avatar
lb flag
สิ่งนี้ใช้ได้สำหรับฉัน ขอบคุณ เพื่อจุดประสงค์ในการรักษาพร็อกซี 1 ที่ไม่เชื่อเรื่องพระเจ้าของพร็อกซี 2 (เนื่องจากพร็อกซี 1 ยังไม่ได้ควบคุมเวอร์ชัน) ฉันตัดสินใจใช้ "ตัวอย่างที่ซับซ้อนมากขึ้น" (ตัวอย่างที่สอง) ที่ระบุไว้ในเว็บไซต์นี้: https://nginx.org /en/docs/http/websocket.html แทน และเพียงเพิ่มลงในบล็อก `location / { ... }` ในพร็อกซี 1 ด้วยวิธีนี้ หากฉันเปลี่ยน URL ของ websocket แต่ลืมพร็อกซี 1 มันจะไม่เสียหาย ข้อเสียเพียงอย่างเดียวที่ฉันคิดได้คือมันไม่สามารถจัดการ http/2.0 ได้ แต่เซิร์ฟเวอร์ของฉันไม่ได้ตั้งค่าให้จัดการมันอยู่ดี
Ivan Shatsky avatar
gr flag
ฟังดูสมเหตุสมผล ฉันชอบวิธีพร็อกซี WebSocket แบบนั้นมากกว่า เกี่ยวกับ HTTP/2 คุณอาจพบเธรด [this](https://serverfault.com/questions/765258/use-http-2-0-between-nginx-reverse-proxy-and-backend-webserver) ที่น่าสนใจทีเดียว

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา