Apakah Anda perlu IPv4 dan IPv6 terpisah untuk mendengarkan arahan dalam nginx?

72

Saya telah melihat berbagai contoh konfigurasi untuk menangani dual-stack IPv4 dan IPv6 virtual hosts di nginx. Banyak yang menyarankan pola ini:

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

Sejauh yang saya bisa lihat, ini mencapai hal yang persis sama dengan:

listen [::]:80 ipv6only=off;

Mengapa Anda menggunakan yang pertama? Satu-satunya alasan yang dapat saya pikirkan adalah jika Anda memerlukan params tambahan yang khusus untuk setiap protokol, misalnya jika Anda hanya ingin mengatur deferredIPv4.

Sinkron
sumber
Ditangguhkan karena tidak ada hubungannya dengan versi IP stack, ini adalah opsi TCP.
Xavier Lucas
1
Tentu, tetapi Anda mengaturnya dalam listenarahan, dan opsi diterapkan per host: pasangan port.
Sinkronisasi
Hum saya benar-benar tidak bisa membayangkan kasus di mana Anda ingin melakukan itu. Saya pikir satu-satunya alasan adalah sejarah dan Michael Hampton memahaminya.
Xavier Lucas

Jawaban:

48

Yang mungkin adalah tentang satu-satunya alasan Anda akan menggunakan bekas konstruksi, hari ini.

Alasan Anda melihat ini mungkin karena default ipv6onlydiubah di nginx 1.3.4. Sebelum itu, defaultnya adalah off; dalam versi yang lebih baru defaultnya adalah on.

Ini terjadi untuk berinteraksi dengan opsi soket IPV6_V6ONLY di Linux, dan opsi serupa pada sistem operasi lain, yang standarnya tidak selalu dapat diprediksi. Oleh karena itu, konstruk sebelumnya diperlukan sebelum 1.3.4 untuk memastikan bahwa Anda benar-benar mendengarkan koneksi pada IPv4 dan IPv6.

Perubahan ke standar nginx untuk ipv6onlymemastikan bahwa standar sistem operasi untuk soket tumpukan ganda tidak relevan. Sekarang, nginx secara eksplisit mengikat ke IPv4, IPv6, atau keduanya, tidak pernah bergantung pada OS untuk membuat soket tumpukan ganda secara default.

Memang, konfigurasi nginx standar saya untuk pre-1.3.4 memiliki konfigurasi pertama, dan post-1.3.4 semua memiliki konfigurasi kedua.

Meskipun, karena mengikat soket tumpukan ganda adalah hal yang hanya Linux, konfigurasi saya saat ini lebih mirip contoh pertama, tetapi tanpa ipv6onlyset, untuk menjelaskan:

listen [::]:80;
listen 80;
Michael Hampton
sumber
4
Beberapa sistem operasi tidak melakukan soket dual ipv4 dan ipv6 sama sekali, seperti OpenBSD, jadi untuk itu Anda harus mendengarkan dua kali.
Justin Cormack
@JustinCormack Ya, Anda benar, dan saya sudah memperhitungkannya untuk beberapa waktu. Hanya belum memperbarui pos ini sampai sekarang.
Michael Hampton
1
listen localhost:8080;tampaknya mendengarkan keduanya (1.12.2) dan menggunakan proxy_pass http://localhost:8080akan memuat keseimbangan antara :: 1 dan 127.0.0.1 - Saya harus menambahkan baris untuk ipv6 untuk mendapatkan ip nyata dalam logset_real_ip_from 127.0.0.1; set_real_ip_from ::1; real_ip_header X-Forwarded-For;
Antony Gibbs
65

Jika Anda meng-host beberapa domain vhost dengan instance Nginx tunggal, Anda tidak dapat menggunakan arahan mendengarkan gabungan tunggal

listen [::]:80 ipv6only=off;

untuk masing-masing. Nginx memiliki kekhasan aneh di mana Anda hanya dapat menentukan ipv6onlyparameter satu kali untuk setiap port, atau gagal memulai. Itu berarti Anda tidak dapat menentukannya untuk setiap blok server domain vhost.

Seperti yang disebutkan Michael, dimulai dengan Nginx 1.3.4, ipv6onlyparameternya adalah default on.

Oleh karena itu, jika Anda ingin meng-host beberapa domain pada IPv4 dan IPv6 dengan server Nginx tunggal, Anda terpaksa menggunakan dua arahan mendengarkan untuk setiap blok server domain:

listen 80;
listen [::]:80; 

Selain itu, seperti yang disebutkan Sander, menggunakan ipv6only=offmemiliki kelemahan bahwa alamat IPv4 diterjemahkan ke IPv6. Ini dapat menyebabkan masalah jika aplikasi Anda melakukan pemeriksaan IP terhadap daftar hitam seperti Akismet atau StopForumSpam karena kecuali Anda membuat lapisan terjemahan terbalik, aplikasi Anda akan memeriksa terjemahan IPv6 dari alamat IPv4 pengirim spam, yang tidak akan cocok dengan alamat IPv4 mana pun di Daftar hitam.

Jeff Widman
sumber
2
Ya, itu sama dengan yang saya sebutkan deferred, dan arahan per-protokol lainnya. Akan bermanfaat jika mereka dapat ditentukan secara terpisah dari arahan mendengarkan karena alasan yang Anda ucapkan.
Sinkronisasi
1
Dan inti dari masalahnya adalah, Anda perlu menentukan arahan mendengarkan untuk setiap domain secara terpisah. Kalau tidak, apa yang akan terjadi? situs akan berfungsi dengan baik melalui ipv4 dan melalui ipv6 akan menampilkan halaman selamat datang nginx. ROFL
Silver Moon
2
Terima kasih atas penjelasannya! Saya mendapatkan kesalahan yang membingungkan ketika saya menetapkan ipv6only=offuntuk port yang sama dua kali. Jawaban Anda memecahkan masalah!
1
Juga jika Anda ingin menggunakan 2 vhosts baik mendengarkan 443: listen 443; listen [::]:443;. Menggunakan listen [::]:80 ipv6only=off;akan melempar kesalahan nginx bahwa port sudah digunakan
lukeaus
16

Dengan ipv6only=offgaya konfigurasi, alamat IPv4 mungkin ditampilkan sebagai alamat IPv6 menggunakan alamat IPv6 (hanya perangkat lunak) yang dipetakan di misalnya file log, variabel lingkungan (REMOTE_ADDR) dll.

Sander Steffann
sumber
3
Ya, mereka ditampilkan seperti ini.
Michael Hampton
2

Untuk pemahaman saya (dan menurut dokumen di http://nginx.org/en/docs/http/ngx_http_core_module.html#listen ), menggunakan hanya

listen 80;

... cukup jika Anda ingin menyalurkan lalu lintas IPv4 & IPv6 pada port yang sama.

fevangelou
sumber
1
Itu sudah ditetapkan, dan disebutkan dalam pertanyaan. Silakan lihat jawaban lain untuk perbedaannya.
Sinkronisasi
3
Itu bukan untuk saya, saya membutuhkan keduanya. wget dan curl ketika gagal ketika menggunakan ipv6 sampai saya menambahkan baris "listen [::]: 80 ipv6only = on;"
Basil A