คุณต้องการคำสั่งฟัง IPv4 และ IPv6 แยกกันใน nginx หรือไม่?


71

ฉันเห็นตัวอย่างการกำหนดค่าต่างๆสำหรับการจัดการโฮสต์เสมือน IPv4 และ IPv6 แบบดูอัลสแต็กบน nginx หลายคนแนะนำรูปแบบนี้:

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

เท่าที่ฉันเห็นสิ่งนี้ประสบความสำเร็จเหมือนกับ:

listen [::]:80 ipv6only=off;

ทำไมคุณถึงใช้อดีต เหตุผลเดียวที่ฉันคิดได้ก็คือถ้าคุณต้องการพารามิเตอร์เพิ่มเติมที่เฉพาะเจาะจงสำหรับแต่ละโปรโตคอลตัวอย่างเช่นถ้าคุณต้องการตั้งค่าdeferredบน IPv4 เท่านั้น


Deffered ไม่มีส่วนเกี่ยวข้องกับ IP stack version เป็นตัวเลือก TCP
Xavier Lucas

1
แน่นอน แต่คุณตั้งไว้ในlistenคำสั่งและตัวเลือกที่ใช้ต่อโฮสต์: คู่พอร์ต
ซิงโคร

ฉันไม่สามารถจินตนาการถึงกรณีที่คุณต้องการทำเช่นนั้น ฉันคิดว่าเหตุผลเดียวคือประวัติศาสตร์และไมเคิลแฮมพ์ตันตอกย้ำมัน
Xavier Lucas

คำตอบ:


48

นั่นอาจเป็นเหตุผลเดียวที่คุณจะใช้โครงสร้างเดิมวันนี้

เหตุผลที่คุณเห็นสิ่งนี้อาจเป็นเพราะค่าเริ่มต้นของการipv6onlyเปลี่ยนแปลงใน nginx 1.3.4 ก่อนหน้านั้นมันเริ่มต้นไปที่off; onในรุ่นใหม่เป็นค่าเริ่มต้น

สิ่งนี้เกิดขึ้นกับการโต้ตอบกับตัวเลือกซ็อกเก็ต IPV6_V6ONLY บน Linux และตัวเลือกที่คล้ายกันในระบบปฏิบัติการอื่นซึ่งค่าเริ่มต้นไม่จำเป็นต้องคาดเดาได้ ดังนั้นโครงสร้างเดิมจำเป็นต้องมี pre-1.3.4 เพื่อให้แน่ใจว่าคุณกำลังฟังการเชื่อมต่อทั้ง IPv4 และ IPv6

การเปลี่ยนค่าเริ่มต้น nginx เพื่อipv6onlyให้แน่ใจว่าค่าเริ่มต้นของระบบปฏิบัติการสำหรับซ็อกเก็ตสแต็คคู่ไม่เกี่ยวข้อง ตอนนี้ nginx เชื่อมโยงกับ IPv4, IPv6 หรือทั้งคู่อย่างชัดเจนไม่ขึ้นกับระบบปฏิบัติการเพื่อสร้างซ็อกเก็ตสแต็คคู่โดยค่าเริ่มต้น

ที่จริงแล้วมาตรฐาน nginx ของฉันกำหนดค่าสำหรับ pre-1.3.4 มีการกำหนดค่าแรกและ post-1.3.4 ทั้งหมดมีการกำหนดค่าที่สอง

แม้ว่าเนื่องจากการรวมซ็อกเก็ตสแต็คคู่เป็นสิ่งเดียวที่ใช้กับ Linux การกำหนดค่าปัจจุบันของฉันจึงดูเหมือนเป็นตัวอย่างแรก แต่ไม่มีการipv6onlyตั้งค่าให้กับปัญญา:

listen [::]:80;
listen 80;

4
ระบบปฏิบัติการบางระบบไม่ได้ใช้ซ็อกเก็ตคู่ ipv4 และ ipv6 เลยเช่น OpenBSD ดังนั้นคุณจะต้องฟังสองครั้ง
Justin Cormack

@JustinCormack ใช่คุณพูดถูกและฉันได้นำมาพิจารณาในบางครั้ง เพิ่งอัปเดตโพสต์นี้ไม่ได้จนกว่าจะถึงตอนนี้
Michael Hampton

1
listen localhost:8080;ดูเหมือนว่าจะฟังทั้ง (1.12.2) และการใช้proxy_pass http://localhost:8080จะโหลดยอดคงเหลือระหว่าง :: 1 และ 127.0.0.1 - ฉันต้องเพิ่มบรรทัดสำหรับ ipv6 เพื่อรับ ip จริงในบันทึกset_real_ip_from 127.0.0.1; set_real_ip_from ::1; real_ip_header X-Forwarded-For;
Antony Gibbs

65

หากคุณโฮสต์หลายโดเมน vhost ด้วยอินสแตนซ์ Nginx เดียวคุณจะไม่สามารถใช้คำสั่ง Listen ที่รวมเข้าด้วยกันได้

listen [::]:80 ipv6only=off;

สำหรับแต่ละคน Nginx มีมุมแหลมแปลก ๆ ที่คุณสามารถระบุipv6onlyพารามิเตอร์ได้เพียงครั้งเดียวสำหรับแต่ละพอร์ตมิเช่นนั้นจะไม่สามารถเริ่มต้นได้ นั่นหมายความว่าคุณไม่สามารถระบุได้สำหรับแต่ละเซิร์ฟเวอร์บล็อกโดเมน vhost

ขณะที่ไมเคิลกล่าวเริ่มต้นด้วย Nginx 1.3.4 ที่ค่าเริ่มต้นของพารามิเตอร์ipv6onlyon

ดังนั้นหากคุณต้องการโฮสต์หลายโดเมนบนทั้ง IPv4 และ IPv6 ด้วยเซิร์ฟเวอร์ Nginx เดียวคุณจะถูกบังคับให้ใช้สองฟังสั่งสำหรับแต่ละเซิร์ฟเวอร์บล็อกโดเมน:

listen 80;
listen [::]:80; 

นอกจากนี้ตามที่ Sander กล่าวถึงการใช้ipv6only=offมีข้อเสียเปรียบที่ที่อยู่ IPv4 ถูกแปลเป็น IPv6 สิ่งนี้อาจทำให้เกิดปัญหาได้หากแอปของคุณทำการตรวจสอบ IP กับบัญชีดำเช่น Akismet หรือ StopForumSpam เพราะหากคุณสร้างเลเยอร์การแปลกลับแอปของคุณจะตรวจสอบการแปล IPv6 ของที่อยู่ IPv4 ของสแปมเมอร์ บัญชีดำ


2
ใช่มันเหมือนกับที่ฉันพูดถึงdeferredและคำสั่งต่อโปรโตคอลอื่น ๆ มันจะมีประโยชน์หากพวกเขาสามารถระบุแยกต่างหากจากคำสั่งฟังด้วยเหตุผลที่คุณพูด
ซิงโคร

1
และหลักของเรื่องคือคุณต้องระบุคำสั่งฟังสำหรับแต่ละโดเมนแยกจากกัน มิฉะนั้นจะเกิดอะไรขึ้น ไซต์จะทำงานได้ดีผ่าน ipv4 และผ่าน ipv6 มันจะแสดงหน้าต้อนรับของ nginx ROFL
Silver Moon

2
ขอบคุณสำหรับคำอธิบายอย่างละเอียด! ฉันได้รับข้อผิดพลาดที่สับสนเมื่อฉันระบุipv6only=offสำหรับพอร์ตเดียวกันสองครั้ง คำตอบของคุณแก้ไขปัญหาได้!

1
นอกจากนี้หากคุณต้องการที่จะใช้ 2 vhosts ทั้งฟัง listen 443; listen [::]:443;443: การใช้listen [::]:80 ipv6only=off;จะโยนข้อผิดพลาด nginx ที่พอร์ตนั้นถูกใช้งานแล้ว
lukeaus

16

ด้วยipv6only=offรูปแบบการกำหนดค่าที่อยู่ IPv4 อาจแสดงเป็นที่อยู่ IPv6 โดยใช้ที่อยู่ IPv6 (เฉพาะซอฟต์แวร์เท่านั้น) ที่อยู่ IPv6 ที่แมปในตัวอย่างเช่นล็อกไฟล์ตัวแปรสภาพแวดล้อม (REMOTE_ADDR) เป็นต้น


3
ใช่พวกเขาจะแสดงด้วยวิธีนี้
Michael Hampton

2

เพื่อความเข้าใจของฉัน (และอ้างอิงจากเอกสารที่http://nginx.org/en/docs/http/ngx_http_core_module.html#listen ) โดยใช้เพียง

listen 80;

... เพียงพอหากคุณต้องการรับส่งข้อมูลทั้ง IPv4 และ IPv6 ที่พอร์ตเดียวกัน


1
ที่ได้รับการจัดตั้งขึ้นและกล่าวถึงในคำถาม โปรดดูคำตอบอื่น ๆ สำหรับความแตกต่าง
ซิงโคร

3
มันไม่ได้สำหรับฉันฉันต้องการทั้งสองอย่าง wget และ curl เมื่อล้มเหลวเมื่อใช้ ipv6 จนกว่าฉันจะเพิ่มบรรทัด "Listen [::]: 80 ipv6only = on;"
เพรา A
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.