¿Necesita directivas de escucha IPv4 e IPv6 separadas en nginx?

72

He visto varios ejemplos de configuración para manejar hosts virtuales IPv4 e IPv6 de doble pila en nginx. Muchos sugieren este patrón:

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

Hasta donde puedo ver, esto logra exactamente lo mismo que:

listen [::]:80 ipv6only=off;

¿Por qué usarías el primero? La única razón por la que puedo pensar es si necesita parámetros adicionales que sean específicos para cada protocolo, por ejemplo, si solo desea establecer deferredIPv4.

Synchro
fuente
Diferido como nada que ver con la versión de pila IP, es una opción TCP.
Xavier Lucas
1
Claro, pero lo configura en listendirectivas, y las opciones se aplican por host: par de puertos.
Synchro
Hum, realmente no puedo imaginar un caso en el que quieras hacer eso. Creo que la única razón es histórica y Michael Hampton lo logró.
Xavier Lucas

Respuestas:

48

Esa es probablemente la única razón por la que usaría la construcción anterior, en estos días.

La razón por la que está viendo esto es probablemente porque el valor predeterminado de ipv6onlycambiado en nginx 1.3.4. Antes de eso, el valor predeterminado era off; en versiones más nuevas por defecto on.

Esto sucede para interactuar con la opción de socket IPV6_V6ONLY en Linux y opciones similares en otros sistemas operativos, cuyos valores predeterminados no son necesariamente predecibles. Por lo tanto, la construcción anterior se requería antes de 1.3.4 para garantizar que realmente estaba escuchando conexiones tanto en IPv4 como en IPv6.

El cambio al valor predeterminado de nginx ipv6onlygarantiza que el valor predeterminado del sistema operativo para los sockets de doble pila es irrelevante. Ahora, nginx se vincula explícitamente a IPv4, IPv6 o ambos, y nunca depende del sistema operativo para crear un socket de doble pila de forma predeterminada.

De hecho, mis configuraciones nginx estándar para pre-1.3.4 tienen la primera configuración, y después de 1.3.4 tienen la segunda configuración.

Sin embargo, dado que vincular un socket de doble pila es algo exclusivo de Linux, mis configuraciones actuales ahora se parecen más al primer ejemplo, pero sin ipv6onlyestablecer, a saber:

listen [::]:80;
listen 80;
Michael Hampton
fuente
44
Algunos sistemas operativos no tienen sockets duales ipv4 e ipv6, como OpenBSD, por lo que tendrá que escuchar dos veces.
Justin Cormack
@JustinCormack Sí, tienes razón, y lo he tenido en cuenta por algún tiempo. Simplemente no había actualizado esta publicación hasta ahora.
Michael Hampton
1
listen localhost:8080;parece escuchar a ambos (1.12.2) y usar proxy_pass http://localhost:8080balance de carga entre :: 1 y 127.0.0.1 - Tuve que agregar una línea para ipv6 para obtener una IP real en los registrosset_real_ip_from 127.0.0.1; set_real_ip_from ::1; real_ip_header X-Forwarded-For;
Antony Gibbs
65

Si aloja varios dominios vhost con una sola instancia de Nginx, no puede usar la única directiva de escucha combinada

listen [::]:80 ipv6only=off;

para cada uno de ellos Nginx tiene una peculiaridad extraña en la que solo puede especificar el ipv6onlyparámetro una vez para cada puerto, o no se iniciará. Eso significa que no puede especificarlo para cada bloque de servidor de dominio vhost.

Como Michael mencionó, comenzando con Nginx 1.3.4, el ipv6onlyparámetro predeterminado es on.

Por lo tanto, si desea alojar múltiples dominios en IPv4 e IPv6 con un solo servidor Nginx, se ve obligado a utilizar dos directivas de escucha para cada bloque de servidor de dominio:

listen 80;
listen [::]:80; 

Además, como mencionó Sander, el uso ipv6only=offtiene el inconveniente de que las direcciones IPv4 se traducen a IPv6. Esto puede causar problemas si su aplicación verifica IP en listas negras como Akismet o StopForumSpam porque a menos que construya en una capa de traducción inversa, su aplicación verificará la traducción IPv6 de la dirección IPv4 del spammer, que no coincidirá con ninguna de las direcciones IPv4 en la lista negra.

Jeff Widman
fuente
2
Sí, es lo mismo que mencioné deferredy otras directivas por protocolo. Sería útil si pudieran especificarse por separado de la directiva de escucha por la razón que usted dice.
Sincronización
1
Y el núcleo del asunto es que debe especificar la directiva de escucha para cada dominio por separado. De lo contrario, ¿qué pasaría? el sitio funcionaría bien a través de ipv4 y a través de ipv6, mostraría la página de bienvenida de nginx. ROFL
Silver Moon
2
¡Gracias por la explicación detallada! Estaba recibiendo un error confuso cuando especifiqué ipv6only=offpara el mismo puerto dos veces. ¡Tu respuesta resolvió el problema!
1
Además, si desea utilizar 2 vhosts ambos escuchando 443: listen 443; listen [::]:443;. Usar listen [::]:80 ipv6only=off;arrojará un error nginx de que el puerto ya está en uso
lukeaus
16

Con el ipv6only=offestilo de configuración, las direcciones IPv4 pueden mostrarse como direcciones IPv6 utilizando las direcciones IPv6 asignadas por IPv4 (solo software) en, por ejemplo, archivos de registro, variables de entorno (REMOTE_ADDR), etc.

Sander Steffann
fuente
3
Sí, se muestran de esta manera.
Michael Hampton
2

A mi entender (y de acuerdo con los documentos en http://nginx.org/en/docs/http/ngx_http_core_module.html#listen ), usando solo

listen 80;

... es suficiente si desea canalizar el tráfico IPv4 e IPv6 en el mismo puerto.

fevangelou
fuente
1
Eso ya ha sido establecido y mencionado en la pregunta. Por favor, vea las otras respuestas para la diferencia.
Synchro
3
No fue para mí, necesitaba los dos. wget y curl fallaron cuando usé ipv6 hasta que agregué la línea "listen [::]: 80 ipv6only = on;"
Basil A