networking ipv6 setsockopt

networking - ¿Cuál fue la motivación para agregar la bandera IPV6_V6ONLY?



setsockopt (7)

En la red IPv6, el indicador IPV6_V6ONLY se utiliza para garantizar que un socket solo use IPv6 y, en particular, que la asignación de IPv4 a IPv6 no se use para ese socket. En muchos sistemas operativos, el IPV6_V6ONLY no está configurado por defecto, pero en algunos sistemas operativos (por ejemplo, Windows 7), está configurado de forma predeterminada.

Mi pregunta es: ¿Cuál fue la motivación para introducir esta bandera? ¿Hay algo acerca de la asignación de IPv4 a IPv6 que estaba causando problemas y, por lo tanto, las personas necesitaban una forma de desactivarlo? Me parece que si alguien no quisiera usar la asignación de IPv4 a IPv6, simplemente no podría especificar una dirección IPv6 asignada por IPv4. ¿Que me estoy perdiendo aqui?


Hay formas plausibles en las que las direcciones (mal nombradas) "asignadas por IPv4" se pueden utilizar para eludir sistemas mal configurados, o malas pilas, o incluso en un sistema bien configurado que podría requerir cantidades onerosas de protección contra errores. Un desarrollador puede desear usar esta bandera para hacer que su aplicación sea más segura al no utilizar esta parte de la API.

Ver: http://ipv6samurais.com/ipv6samurais/openbsd-audit/draft-cmetz-v6ops-v4mapped-api-harmful-01.txt


Hay un ejemplo muy común en el que la dualidad del comportamiento es un problema. La llamada estándar getaddrinfo() con indicador AI_PASSIVE ofrece la posibilidad de pasar un parámetro de nombre de nodo y devuelve una lista de direcciones para escuchar. Se acepta un valor especial en forma de cadena NULL para nombre de nodo e implica escuchar en direcciones comodín.

En algunos sistemas, 0.0.0.0 y :: se devuelven en este orden. Cuando el socket dual-stack está habilitado por defecto y no configura el socket IPV6_V6ONLY , el servidor se conecta a 0.0.0.0 y luego no se conecta a dual-stack :: y por lo tanto (1) solo funciona en IPv4 y (2) informa error

Consideraría que el orden es incorrecto ya que se espera que IPv6 sea el preferido. Pero incluso cuando intenta por primera vez dual-stack :: y solo IPv4-only 0.0.0.0 , el servidor aún informa un error para la segunda llamada.

Personalmente considero la idea de un socket de doble pila como un error. En mi proyecto, preferiría siempre configurar explícitamente IPV6_V6ONLY para evitar eso. Aparentemente, algunas personas lo vieron como una buena idea, pero en ese caso probablemente IPV6_V6ONLY explícitamente IPV6_V6ONLY y traduzca NULL directamente a 0.0.0.0 pasar por el mecanismo getaddrinfo() .


Imagine un protocolo que incluya en la conversación una dirección de red, por ejemplo, el canal de datos para FTP. Al usar IPv6, usted va a enviar la dirección IPv6; si el destinatario es una dirección mapeada IPv4, no tendrá forma de conectarse a esa dirección.


La razón más frecuentemente mencionada es para el caso en que el servidor tiene alguna forma de ACL (Lista de control de acceso). Por ejemplo, imagine un servidor con reglas como:

Allow 192.0.2.4 Deny all

Se ejecuta en IPv4. Ahora, alguien lo ejecuta en una máquina con IPv6 y, dependiendo de algunos parámetros, las solicitudes IPv4 son aceptadas en el socket IPv6, mapeadas como :: 192.0.2.4 y luego ya no coinciden con la primera ACL. De repente, el acceso sería denegado.

Ser explícito en su aplicación (usando IPV6_V6ONLY) resolvería el problema, cualquiera que sea el predeterminado del sistema operativo.


No sé por qué sería un defecto; pero es el tipo de banderas que siempre pondría explícito, sin importar cuál sea el valor predeterminado.

Acerca de por qué existe en primer lugar, supongo que le permite mantener servidores existentes solo IPv4, y simplemente ejecutar nuevos en el mismo puerto, pero solo para conexiones IPv6. O tal vez el nuevo servidor simplemente puede proxy clientes a la anterior, por lo que la funcionalidad de IPv6 fácil y sin complicaciones para agregar a los servicios anteriores.


No todas las plataformas compatibles con IPv6 son compatibles con sockets de doble pila, por lo que la pregunta es cómo las aplicaciones que necesitan maximizar la compatibilidad con IPv6 saben que es compatible con dualstack o que se unen separadamente cuando no es así. La única respuesta universal es IPV6_V6ONLY.

Una aplicación que ignora IPV6_V6ONLY o escrita antes de que existan pilas de IP compatibles con dualstack puede encontrar que el enlace por separado a V4 falla en un entorno de doble pila, ya que el socket de doble pila IPv6 se une a IPv4 y evita el enlace de socket IPv4. La aplicación también puede no estar esperando IPv4 sobre IPv6 debido a preocupaciones de direccionamiento de protocolo o nivel de aplicación o controles de acceso IP.

Esta o situaciones similares probablemente indujeron a MS y otros a establecer el valor predeterminado en 1 incluso aunque RFC3493 declare 0 como predeterminado. 1 teóricamente maximiza la compatibilidad hacia atrás. Específicamente, Windows XP / 2003 no es compatible con sockets dualstack.

Tampoco faltan aplicaciones que lamentablemente necesitan pasar información de capa inferior para funcionar correctamente, por lo que esta opción puede ser bastante útil para planificar una estrategia de compatibilidad IPv4 / IPv6 que mejor se adapte a los requisitos y las bases de códigos existentes.


Para Linux, al escribir un servicio que escucha en ambos sockets de IPv4 e IPv6 en el mismo puerto de servicio, por ejemplo, el puerto 2001, DEBE llamar a setsockopt (s, SOL_IPV6, IPV6_V6ONLY, y one, sizeof (one)); en el socket IPv6. Si no lo hace, la operación bind () para el socket IPv4 falla con la "Dirección ya en uso".