2009-10-24 11 views
46

Actualmente estoy trabajando en una aplicación de socket UDP y necesito construir en soporte para que las conexiones IPV4 e IPV6 puedan enviar paquetes a un servidor.Cómo admitir conexiones IPv4 e IPv6

Tenía la esperanza de que alguien pudiera ayudarme y dirigirme en la dirección correcta; la mayoría de la documentación que encontré no estaba completa. También sería útil si pudieras señalar cualquier diferencia entre los sockets de Winsock y BSD.

¡Gracias de antemano!

Respuesta

72

El mejor enfoque es crear un socket de servidor IPv6 que también pueda aceptar conexiones IPv4. Para hacerlo, cree un socket IPv6 regular, desactive la opción de socket IPV6_V6ONLY, conéctelo a la dirección "any" y comience a recibir. Las direcciones IPv4 se presentarán como direcciones IPv6, en el formato IPv4-mapped.

La principal diferencia entre los sistemas es si IPV6_V6ONLY está a) disponible, y b) está activado o desactivado de manera predeterminada. Está desactivado por defecto en Linux (es decir, permite sockets de doble pila sin setsockopt), y está encendido en la mayoría de los otros sistemas.

Además, la pila IPv6 en Windows XP no admite esa opción. En estos casos, deberá crear dos sockets de servidor separados y colocarlos en seleccionar o en varios hilos.

+1

Gracias por esta información, exactamente lo que estaba buscando. – Charles

+7

Decir que IPV6_V6ONLY está desactivado de forma predeterminada en Linux es incorrecto: depende del sistema operativo, no solo del kernel. Por ejemplo, en Debian GNU/Linux, recientemente se activó por defecto. – bortzmeyer

+1

OS X también lo tiene desactivado de forma predeterminada, pero lo mejor es configurarlo siempre explícitamente. El administrador del sistema local podría haberlo cambiado después de todo. –

6

La API de socket se rige por IETF RFC y debe ser la misma en todas las plataformas, incluida Windows WRT IPv6.

Para aplicaciones IPv4/IPv6 Es TODO sobre getaddrinfo() y getnameinfo(). getaddrinfo es un genio: examina el DNS, los nombres de los puertos y las capacidades del cliente para resolver la eterna pregunta de "¿Puedo usar IPv4, IPv6 o ambos para llegar a un destino en particular?" O si va a la ruta de doble pila y quiere que devuelva direcciones IPv6 mapeadas IPv4, también lo hará.

Proporciona una estructura sockaddr * directa que puede ser conectado a bind(), recvfrom(), sendto() y la familia de direcciones para socket() ... En muchos casos, esto significa que no hay sockaddr_in(6) estructuras desordenadas para llenar y tratar.

Para las implementaciones de UDP, tendría cuidado al configurar los sockets de doble pila o, de forma más general, el enlace a todas las interfaces (INADDR_ANY). El problema clásico es que, cuando las direcciones no están bloqueadas (ver bind()) a interfaces específicas y el sistema tiene múltiples solicitudes de interfaces, las respuestas pueden transitar desde diferentes direcciones para computadoras con múltiples direcciones basadas en los caprichos de la tabla de enrutamiento del sistema operativo, aplicación confusa protocolos, especialmente cualquier sistema con requisitos de autenticación.

Para implementaciones UDP donde esto no es un problema, o TCP, los sockets de doble pila pueden ahorrar mucho tiempo cuando IPv * -el funcionamiento de su sistema. Hay que tener cuidado de no confiar completamente en dual-stack donde no es absolutamente necesario ya que no hay escasez de plataformas razonables (Old Linux, BSD, Windows 2003) implementadas con pilas IPv6 que no sean capaces de sockets de doble pila.

2

Las RFC realmente no especifican la existencia de la opción de socket IPV6_V6ONLY, pero, si está ausente, las RFC son bastante claras de que la implementación debería ser como si esa opción fuera FALSA.

Donde la opción está presente, yo diría que debe ser FALSE por defecto, pero, por razones que pasan comprensión, las implementaciones de BSD y Windows son TRUE por defecto. Existe una extraña afirmación de que se trata de un problema de seguridad porque un programador de IPv6 desconocido podría vincularse pensando que solo estaban vinculados a IN6ADDR_ANY solo para IPv6 y accidentalmente aceptan una conexión IPv4 que causa un problema de seguridad. Creo que esto es absurdo y absurdo, además de una sorpresa para cualquiera que espera una implementación compatible con RFC.

En el caso de Windows, el incumplimiento no suele ser una sorpresa. En el caso de BSD, esto es desafortunado en el mejor de los casos.

+3

El estándar en IPv6 API, RFC 3493, describe IPV6_V6ONLY en su sección 5.3 si desea leer todos los detalles. – bortzmeyer

3

He estado jugando con esto en Windows y en realidad parece ser un problema de seguridad allí, si se une a la dirección de bucle invertido, entonces el zócalo IPv6 está correctamente vinculado a [:: 1] pero el zócalo IPv4 asignado está vinculado a INADDR_ANY, por lo que su aplicación (supuestamente) local segura solo está realmente expuesta al mundo.

Cuestiones relacionadas