โฮสต์เสมือนแบบอิงชื่อ nginx บน IPv6


44

ฉันมีเซิร์ฟเวอร์ nginx ที่ให้บริการเว็บไซต์ที่แตกต่างกันเกือบครึ่งโหล มันกำลังทำงานบน Linode ที่เพิ่งรองรับ IPv6 ดั้งเดิม (ศูนย์ข้อมูลดัลลัส) และฉันพยายามกำหนดค่าไซต์ส่วนใหญ่ของฉันสำหรับการดำเนินการแบบ dual-stack ฉันได้โดเมนแรกและทำงานโดยใช้โดเมนย่อย IPv6 เท่านั้นเช่น:

server {
    listen [::]:80 ipv6only=on;
    listen 80;

    server_name example.com ipv6.example.com;

    root /var/www/example.com/htdocs;

    #More stuff, including PHP, WordPress
}

สิ่งนี้ใช้งานได้ดี - example.com เป็น IPv4 เท่านั้น (ตอนนี้) และ ipv6.example.com นั้นเป็น IPv6 เท่านั้น (ส่วนใหญ่มีไว้เพื่อการทดสอบ) ฉันทำได้ping6 ipv6.example.comและแม้จะwget ipv6.example.comไม่ทำให้เหงื่อออก - มันก็ไม่เจ็บปวดอย่างน่าพอใจ (หลังจากค้นหา "gotcha" ด้วยวิธีที่ nginx ผูกโฮสต์เสมือนไว้โดยไม่จำเป็นต้องipv6only=onโต้แย้งและlistenแนวทางคู่)

อย่างไรก็ตามตอนนี้ฉันกำลังพยายามขยายเพื่อรองรับโดเมนอื่น ๆ ของฉันเริ่มต้นจาก static.example.com เมื่อฉันใช้วิธีเดียวกันกับข้างต้นแม้ว่า ( listenคำสั่งคู่รวมถึงการipv6only=onโต้แย้ง) ฉันได้รับข้อผิดพลาดต่อไปนี้เมื่อรีสตาร์ท nginx:

* Starting Nginx Server...
nginx: [emerg] a duplicate listen options for [::]:80 in /etc/nginx/sites-enabled/example.com.conf:3

ดูเหมือนว่าวิธีการของ nginx ในการเชื่อมต่อกับ IPv6 ไม่อนุญาตให้โฮสต์เสมือนตามชื่อใช่หรือไม่ ฉันจะต้องได้รับที่อยู่ IPv6 เพิ่มเติมจากโฮสต์ของฉัน (ไม่ใช่ปัญหา) และใช้การโฮสต์เสมือนบน IP บน IPv6 ที่มีการโฮสต์เสมือนตามชื่อผ่าน IPv4 หรือไม่ หรือฉันขาดวิธีแก้ปัญหาที่จะช่วยให้การกำหนดค่าของฉันยังคงสอดคล้องกับทั้งสองกอง?

ฉันหวังว่าจะให้เว็บไซต์ของฉันใช้งาน IPv6 ได้ทันตามกำหนดเวลาสำหรับวัน IPv6 ของโลกแต่ถ้าฉันไม่สามารถเคลียร์สิ่งนี้ได้อย่างรวดเร็วฉันอาจไม่พร้อม ไม่ใช่เรื่องใหญ่จากมุมมองเชิงปฏิบัติใด ๆ - ไม่มีไซต์ของฉันที่มีคุณสมบัติเป็น "องค์กรหลัก" โดยจินตนาการที่กว้างไกล - แต่ช่วยฉันประหยัดความน่าเชื่อถือ!

แก้ไขเพื่อเพิ่ม:

ขอบคุณคำตอบจาก @kolbyjack ตอนนี้ฉันมีเว็ปเซิร์ฟเวอร์คู่ทำงานได้อย่างสมบูรณ์แล้ว เพียงเพื่อประโยชน์ของความชัดเจนฉันกำลังแก้ไขในวิธีการแก้ปัญหาที่เขาให้ฉันเพื่อให้ทุกคนสามารถเห็นได้อย่างชัดเจนว่าคำตอบคืออะไร

catchall vhost ของฉันมีlistenคำสั่งดังต่อไปนี้:

listen 80 default_server;
listen 8080 default_server;
listen [::]:80 default_server ipv6only=on;
listen [::]:8080 default_server ipv6only=on;

ฉันไม่ทราบว่าคำสั่งซื้อนั้นสำคัญ แต่มีอยู่หรือไม่ จากนั้นแต่ละ vhost เพิ่มเติมมีlistenคำสั่งต่อไปนี้:

listen 80;
listen [::]:80;

(หรือ 8080 สำหรับคนที่ฟังในพอร์ตที่แทน.) ส่วนที่สำคัญที่นี่ดูเหมือนจะขาดรวมของการขัดแย้งใด ๆ เพิ่มเติมในทุก แต่ vhost เริ่มต้นของlistenคำสั่ง - ipv6only=onคือการซ้ำซ้อนของไม่มี

ขอขอบคุณ @kolbyjack อีกครั้งสำหรับวิธีการแก้ปัญหาที่นี่!


ด้วย Nginx 1.2.1 ipv6only=onฉันไม่ได้มีการระบุ ทุกอย่างยังคงเหมือนเดิมขอบคุณสำหรับสิ่งนี้!
BeepDog

คำตอบ:


46

คุณต้องการเพียงฟังทางเลือกในการประกาศเพียงครั้งเดียว โดยทั่วไปคุณจะใส่ไว้ในการประกาศที่มีการตั้งค่าสถานะ default_server ด้วย แต่สำหรับตัวเลือกบางตัวฉันคิดว่าคุณสามารถตั้งค่าให้พวกเขาฟังคำสั่งใดก็ได้ เพียงแค่ลบ ipv6only = on ออกจาก listens ทั้งหมดยกเว้นอันเดียว


2
เดี๋ยวก่อนฉันสับสน ฉันคิดว่าอย่างน้อยหนึ่งฟังคำสั่งต่อการประกาศเซิร์ฟเวอร์จำเป็น - มิฉะนั้นจะรู้ได้อย่างไรว่า nginx บล็อกเซิร์ฟเวอร์ใดที่มีจุดประสงค์เพื่อตอบสนองพอร์ตใด ฉันไม่ได้พูดถึงข้างต้นเพราะฉันไม่ได้คิดว่ามันเกี่ยวข้อง แต่ฉันมีเซิร์ฟเวอร์หนึ่งตัวที่ 8080 ที่เหลืออยู่ที่ 80 และฉันตั้งใจจะเสนอ 443 ให้กับคู่รักเช่นกันทันทีที่ฉันถูกรีดออกและ จากนั้นรับใบรับรอง SSL ด้วยตัวเอง
Kromey

ตกลงดูที่เอกสารอีกครั้งไซต์ที่อยู่ในพอร์ต 80 ดูเหมือนว่าพวกเขาไม่ต้องการฟังคำสั่งเลยเพียงแค่มีค่าเริ่มต้น default_server บน catchall vhost ของฉัน อย่างไรก็ตามนี่ยังคงล้มเหลวสำหรับเซิร์ฟเวอร์ของฉันใน 8080 ซึ่งฉันยังใช้ catchall เริ่มต้น (catchall ถูกเขียนเพื่อละเว้นการร้องขอใด ๆ สำหรับชื่อโฮสต์ที่ฉันไม่ได้กำหนดค่าอย่างชัดเจนใน vhost อื่น)
Kromey

1
ฉันไม่ได้บอกว่าจะลบคำสั่งการฟังทั้งหมดของคุณ เพียงแค่ลบ ipv6only = บนธงจากทั้งหมดยกเว้นหนึ่งในนั้น หากไม่มีคำสั่งฟังในแต่ละเซิร์ฟเวอร์พวกเขาจะเริ่มต้นเพียงรับฟัง 80 เท่านั้น ซึ่งอาจรวมหรือไม่รวม ipv6 ฉันคิดว่าวิธีการที่ถูกต้องคือการรวมทั้งฟังคำสั่งในแต่ละเซิร์ฟเวอร์ แต่ใส่ ipv6only = ในเพียงหนึ่งในเซิร์ฟเวอร์
kolbyjack

4
อ่าฉันเห็นแล้วว่าคุณหมายถึงอะไร ฉันอ่านผิดโพสต์เดิม สิ่งนี้ได้ผลสำหรับฉัน: ipv6only=onแสดงเฉพาะ (สำหรับแต่ละพอร์ตที่ฉันฟัง) ใน vhost เริ่มต้นของฉัน (ข้างdefault_server) แต่ละ vhost นั้นเพียงระบุlisten 80;และlisten [::]:80(ไม่มีพารามิเตอร์เพิ่มเติมเลย) เพื่อทำงานกับทั้ง IPv4 และ IPv6 ตอนนี้สิ่งที่ฉันต้องทำคือเพิ่มระเบียน AAAA สำหรับโดเมนดูอัลสแต็กของฉันให้เสร็จและฉันควรจะไปที่นี่ ขอบคุณ!
Kromey

1
ทำงานให้ฉันด้วย แต่ฉันก็ไม่เข้าใจว่าทำไมฉันจึงสามารถฟัง ipv4 สำหรับบล็อกหลาย ๆ อันได้ แต่ไม่ใช่ ipv6 . คุณสามารถอธิบาย ?
Adeerlike
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.