Czy potrzebujesz oddzielnych dyrektyw nasłuchiwania IPv4 i IPv6 w Nginx?

71

Widziałem różne przykłady konfiguracji obsługi wirtualnych hostów IPv4 i IPv6 na dwóch stosach na nginx. Wielu sugeruje ten wzór:

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

O ile widzę, osiąga dokładnie to samo, co:

listen [::]:80 ipv6only=off;

Dlaczego miałbyś skorzystać z tego pierwszego? Jedynym powodem, dla którego mogę wymyślić, jest to, że potrzebujesz dodatkowych parametrów, które są specyficzne dla każdego protokołu, na przykład, jeśli chcesz ustawić tylko deferredna IPv4.

Synchro
źródło
Odroczone jako nic wspólnego z wersją stosu IP, jest to opcja TCP.
Xavier Lucas,
1
Jasne, ale ustawiłeś go w listendyrektywach, a opcje są stosowane dla poszczególnych hostów: pary portów.
Synchro,
Hum Naprawdę nie wyobrażam sobie przypadku, w którym chciałbyś to zrobić. Myślę, że jedyny powód jest historyczny, a Michael Hampton go przybił.
Xavier Lucas,

Odpowiedzi:

48

Prawdopodobnie jest to jedyny powód, dla którego używałbyś obecnie tego konstruktu.

Powodem tego jest prawdopodobnie domyślna ipv6onlyzmiana w Nginx 1.3.4. Wcześniej domyślnie było off; w nowszych wersjach domyślnie jest to on.

Zdarza się to w interakcji z opcją gniazda IPV6_V6ONLY w systemie Linux i podobnymi opcjami w innych systemach operacyjnych, których ustawienia domyślne niekoniecznie są przewidywalne. Tak więc poprzednia konstrukcja była wymagana przed wersją 1.3.4, aby upewnić się, że faktycznie nasłuchujesz połączeń zarówno na IPv4, jak i IPv6.

Zmiana wartości domyślnej na nginx dla powoduje, że domyślny ipv6onlysystem operacyjny dla gniazd z dwoma stosami nie ma znaczenia. Teraz nginx albo jawnie wiąże się z IPv4, IPv6, albo z obydwoma, nigdy domyślnie w zależności od systemu operacyjnego, aby utworzyć gniazdo z dwoma stosami.

Rzeczywiście, moje standardowe konfiguracje nginx dla wersji wcześniejszej niż 1.3.4 mają pierwszą konfigurację, a wszystkie po wersji 1.3.4 mają drugą konfigurację.

Chociaż, ponieważ wiązanie gniazda podwójnego stosu jest kwestią wyłącznie Linuksa, moje obecne konfiguracje wyglądają teraz bardziej jak pierwszy przykład, ale bez ipv6onlyzestawu, to znaczy:

listen [::]:80;
listen 80;
Michael Hampton
źródło
4
Niektóre systemy operacyjne w ogóle nie obsługują podwójnych gniazd ipv4 i ipv6, na przykład OpenBSD, dlatego musisz słuchać dwa razy.
Justin Cormack
@JustinCormack Tak, masz rację i od jakiegoś czasu brałem to pod uwagę. Do tej pory nie zaktualizowałem tego postu.
Michael Hampton
1
listen localhost:8080;wydaje się nasłuchiwać zarówno (1.12.2), a użycie ładowałoby proxy_pass http://localhost:8080równowagę między :: 1 a 127.0.0.1 - Musiałem dodać linię dla ipv6, aby uzyskać prawdziwe ip w logachset_real_ip_from 127.0.0.1; set_real_ip_from ::1; real_ip_header X-Forwarded-For;
Antony Gibbs
65

Jeśli hostujesz wiele domen vhost za pomocą jednej instancji Nginx, nie możesz użyć jednej połączonej dyrektywy Listen

listen [::]:80 ipv6only=off;

dla każdego z nich. Nginx ma dziwne dziwactwo, w którym można określić ipv6onlyparametr tylko raz dla każdego portu, inaczej się nie uruchomi. Oznacza to, że nie można podać tego dla każdego bloku serwera domeny vhost.

Jak wspomniał Michael, począwszy od Nginx 1.3.4, ipv6onlydomyślnym parametrem jest on.

Dlatego jeśli chcesz hostować wiele domen zarówno na IPv4, jak i IPv6 na jednym serwerze Nginx, musisz użyć dwóch dyrektyw nasłuchu dla każdego bloku serwera domeny:

listen 80;
listen [::]:80; 

Ponadto, jak wspomniano Sander, użycie ipv6only=offma tę wadę, że adresy IPv4 są tłumaczone na IPv6. Może to powodować problemy, jeśli twoja aplikacja sprawdza IP na czarnych listach takich jak Akismet lub StopForumSpam, ponieważ jeśli nie zbudujesz warstwy tłumaczenia wstecznego, aplikacja sprawdzi tłumaczenie IPv6 adresu IPv4 spamera, który nie będzie pasował do żadnego z adresów IPv4 w czarna lista.

Jeff Widman
źródło
2
Tak, to jest to samo, o czym wspomniałem deferredi inne dyrektywy dotyczące protokołu. Byłoby użyteczne, gdyby można je było podać oddzielnie od dyrektywy Listen z podanego powodu.
Synchro
1
Istotą sprawy jest to, że musisz określić dyrektywę Listen dla każdej domeny osobno. W przeciwnym razie co by się stało? strona działałaby dobrze przez ipv4, a przez ipv6 pokazywałaby stronę powitalną nginx. ROFL
Srebrny Księżyc,
2
Dziękuję za dokładne wyjaśnienie! Otrzymałem mylący błąd, kiedy ipv6only=offdwukrotnie podałem ten sam port. Twoja odpowiedź rozwiązała problem!
1
Także jeśli chcesz używać 2 vhosty zarówno słuchanie 443: listen 443; listen [::]:443;. Użycie listen [::]:80 ipv6only=off;spowoduje zgłoszenie błędu nginx, że port jest już w użyciu
lukeaus
16

W ipv6only=offstylu konfiguracji adresy IPv4 mogą być wyświetlane jako adresy IPv6 przy użyciu adresów IPv6 odwzorowanych na IPv4 (tylko oprogramowanie), na przykład w plikach dziennika, zmiennych środowiskowych (REMOTE_ADDR) itp.

Sander Steffann
źródło
3
Tak, są pokazane w ten sposób.
Michael Hampton
2

W moim rozumieniu (i zgodnie z dokumentami na stronie http://nginx.org/en/docs/http/ngx_http_core_module.html#listen ), używając tylko

listen 80;

... jest wystarczający, jeśli chcesz kierować zarówno ruch IPv4, jak i IPv6 na tym samym porcie.

fevangelou
źródło
1
Zostało to już ustalone i wspomniane w pytaniu. Zobacz inne odpowiedzi dla różnicy.
Synchro,
3
Nie dla mnie, potrzebowałem obu. wget i curl, gdzie się nie udaje przy użyciu ipv6, dopóki nie dodałem wiersza „listen [::]: 80 ipv6only = on;”
Basil A