2010-09-09 27 views
5

¿Alguien tiene algún código que determine si una dirección IP (IPv4 o IPv6) está en la misma subred que la máquina que ejecuta la aplicación? He visto numerosos ejemplos de código que hace esto con IPv4 pero no puedo encontrar ninguno que admita IPv6.Es la dirección IP en la misma subred que la máquina local (con soporte IPv6)

EDIT:

no estoy seguro si estoy entendiendo todas las diferencias entre v4 y v6 tiene de aquí un poco más a mi pregunta. Tengo una aplicación que sirve tanto a clientes de Internet como a clientes de intranet, es decir, hay clientes que están en la misma red física que el servidor. Entonces, a veces hay enrutadores entre el cliente y otras veces no. Con IPv4 puedo determinar esto marcando la dirección IP del cliente en contra de la dirección IP del servidor y la subred de modo que si de IP y la máscara de subred son, respectivamente, mi servidor:

192.168.123.15 255.255.255.0

y el servidor recibe una solicitud del cliente de 192.168.123.100 Sé que no hay enrutador entre el cliente y el servidor. Sin embargo, si el servidor recibe una solicitud del cliente de 192.168.1.100 o quizás 67.7.23.4, sé que hay un enrutador entre esos clientes y el servidor. En .Net puedo recopilar las direcciones IP del cliente y del servidor (tanto v4 como v6), pero no puedo encontrar la máscara de subred IPv6.

¿Hay alguna manera de recopilar esta información en .Net o hay alguna diferencia entre IPv4 e IPv6 que estoy entendiendo mal?

EDITAR x2:

Me ha publicado esto en el MS conectar sitio para ver si es algo que están trabajando o si hay una razón por la que no ha añadido una propiedad IPv6Mask a la clase UnicastIPAddressInformation.

https://connect.microsoft.com/VisualStudio/feedback/details/643031/unicastipaddressinformation-class-has-no-ipv6mask-property

También he publicado la misma pregunta en los foros de MSDN en la misma época. 1800+ visitas y ni una sola respuesta. Supongo que no soy el único que siente curiosidad por esto.

http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/dd30e161-9be5-4d70-97c0-22e2756ce953

+0

¿Cómo se ofrece la dirección IPv6? ¿Hay algún mecanismo de transición en uso o es DHCPv6? – Abhi

+0

Bueno, estoy tratando de hacerlo funcionar bajo cualquier cantidad de circunstancias, entonces digamos las dos? –

+0

tal vez esto debería ser realmente preguntado desde serverfault.com –

Respuesta

3

No se ve como el marco tiene una manera de hacer esto. La forma más precisa sería hacer una búsqueda de ruta, pero no veo una buena manera de hacerlo en C#. (Bajo Linux, haría /sbin/ip -6 route get <ipv6-addr> y veré qué ruta se devuelve.) Tendría que encontrar una llamada nativa para hacer esto en Windows; No veo una aplicación de línea de comandos.

La mejor manera podría ser analizar la salida de netsh interface ipv6 show route verbose. Puedes buscar prefijos que no sean// 128 y hacer un prefijo más largo en esos. (bueno, si presionas a/128, esa es una dirección asignada a la casilla)

También puedes consultar la tabla de vecinos. (netsh interface ipv6 show neighbors), pero es posible que no contenga la entrada que está buscando si no ha hablado con ese host recientemente.

Otros posibles problemas que tendrá que tener en cuenta:

  • Link-local addresses (fe80::/10) (y multicast, de bucle invertido, y no especificadas - todo en la mesa)
  • El hecho de que en IPv6, una dirección asignada no implica un prefijo en el enlace.La tabla de prefijos está separada. No está claro cómo probar esto en Windows, pero netsh interface ipv6 show siteprefixes podría ayudar. Parece que Windows realmente podría tratar esto más como IPv4 de lo que espera el estándar.

Editar: Suena como la comprobación de la tabla de vecinos será el camino de menor resistencia para que usted pueda hacer esto; si está aceptando una conexión desde la intranet y luego girando y verificando la tabla vecina, puede estar razonablemente seguro de que si el vecino es local, existirá en la tabla. Si revisa la tabla vecina, , TENGA CUIDADO para ver solo la tabla vecina para las interfaces LAN. (La interfaz ISATAP, instalado por defecto en muchos sistemas de Windows, expone internet toda IPv4 como una "subred" de enlace local.)

Una vez más, las direcciones IPv6 no tienen el concepto de una "máscara de red", ya que el de -la tabla de prefijo de enlace está separada de la asignación de dirección. Sin embargo,, si tiene un servidor sentado en alguna parte, probablemente tenga 99% de certeza de que está en un /64. (Aunque habría que tener cuidado, y si sí era un extremo del túnel, a veces me he visto prefijo mayor asignados para túneles 6en4) Así que un algoritmo rápido y sucio sería:

  • Ignorar todas las direcciones donde el primeros 64 bits son 0 (loopback local)
  • ignorar todas las direcciones que coinciden FF00 ::/8 (multicast)
  • Si la dirección coincide con fe80 ::/10, es interfaz local. Tenga cuidado con esto, porque si tiene habilitada una interfaz ISATAP, "link-local" significa "túnel automático para todo Internet IPv4". (no es bueno). Por lo tanto, es mejor no confiar en las direcciones locales del enlace a menos que esté seguro de que proceden de una interfaz LAN. (no se pueden enrutar)
  • (Ahora la parte complicada) Determine si la dirección es un vecino. (Búsqueda de vecinos) La solución de hack-and-slash es verificar todas las direcciones IPv6 configuradas en el sistema (autoconfiguradas mediante autoconfiguración de direcciones sin estado, DHCPv6 o estática, si puede determinarlas) y verificar los primeros 64 bits. En un servidor (suponiendo que los túneles funky no estén configurados con prefijos/64), esto será un error en casos excepcionales, ya que, nuevamente, no puede estar seguro si la dirección está realmente en enlace a menos que verifique tabla de prefijos en el enlace. (que Windows no tiene un concepto de, parece estar almacenado en la tabla de rutas). La mayoría de los dispositivos de red que se pueden configurar para enviar anuncios de enrutador en una interfaz Ethernet siempre anunciarán un prefijo/64. Si puede verificar que el paquete entró en una interfaz LAN, será aún menos probable que esto sea un error.

Editar 2

he escrito algo de código para analizar la tabla de enrutamiento IPv6 y lo publicó here. Todavía no resuelve los problemas difíciles planteados en esta pregunta, pero es un paso en la dirección correcta.

+0

Tiene que haber una forma más nativa de hacerlo que generar una aplicación y ver su resultado. –

+0

@Steven, si desea usar P/Invoke y descubrir las llamadas, eso funcionaría, o encontrar a alguien que haya escrito una biblioteca Windows .NET que haga lo mismo. Yo argumentaría que generar una aplicación con un resultado conocido posiblemente sería menos propenso a errores que hacer llamadas nativas (con suerte, 'netsh' se actualizaría en diferentes versiones de Windows si las llamadas nativas cambian; generar una aplicación lo aisla de esa confusión potencial)) – mpontillo

+0

Es posible que tenga razón, como cuestión práctica, al decir que una interfaz de línea de comandos es más rápida de implementar y más probable que sobreviva a los cambios. De alguna manera, no puedo respaldarlo, sin embargo. –

2

El equivalente moral de la máscara de red IPv4 en IPv6 se denomina longitud de prefijo . (En realidad, nos gusta hablar sobre la longitud del prefijo en lugar de la máscara de red en IPv4 también, pero algunas personas aún no han recibido la nota.)

Una arruga adicional en IPv6 que no incluye IPv4 es la predeterminada los enrutadores anuncian su presencia en el enlace respondiendo las consultas de solicitud del enrutador de los hosts. Los hosts mantienen una lista de todos los enrutadores predeterminados que encuentran de esta manera junto con sus tiempos de vida válidos y preferidos.Los enrutadores también pueden anunciar cero, uno o más prefijos para los que sirven como un enrutador predeterminado, y los hosts mantienen una lista de estos junto con sus enrutadores asociados y sus tiempos de vida válidos y preferidos individuales.

Cada prefijo tiene dos bits auxiliares en el anuncio, A y L, que se unen por los hosts cuando se agregan a la lista de prefijos. El bit A = 1 indica si los hosts pueden configurar automáticamente una dirección de interfaz con ese prefijo, mientras que A = 0 significa que los hosts deben obtener una dirección con ese prefijo a través de DHCPv6 o manualmente. El L = 1 bit indica que el prefijo está "en enlace" y el host puede usar el descubrimiento vecino (el equivalente IPv6 de ARP) para enviar directamente a través de la red, mientras que L = 0 indica que el prefijo es "fuera de enlace" y los hosts deben enviar todo el tráfico de ese prefijo a un enrutador predeterminado.

Resumen breve: si desea saber que una dirección IPv6 está "en el enlace", debe recorrer la lista de prefijos IPv6 y comparar cada una con la dirección y también mirar el bit L para asegurarse de que es un prefijo en el enlace. Por desgracia, solo conozco la forma en que el sistema BSD examina la lista de prefijos, es decir, sysctl(ICMPV6CTL_ND6_PRLIST, ...). Realmente no estoy seguro de que haya algo que MSFT haya puesto a disposición de los desarrolladores de C# para eso.

Sí, me doy cuenta de que esta no es una respuesta completa. Ay.

+0

Sigue siendo útil. –

+0

Sí, mientras más información, mejor. +1 Entonces, creo que la forma en que un cliente en una red IPv4 desea establecer una conexión con otra computadora determinaría si necesita enviar el paquete a la puerta de enlace predeterminada sería comparar la dirección IP de destino, la propia máscara de red del cliente y la la dirección IP del cliente. Si la máscara aplicada a ambas direcciones IP no coincide, el paquete se enviará a la puerta de enlace. ¿Puede explicar un poco más cómo un cliente haría esto en IPv6 y qué información utiliza? –

+0

IPv4 no tiene la noción de "off-link" vs. "on-link", por lo tanto, si una dirección de destino comparte el mismo prefijo con una dirección de interfaz, entonces la suposición es que está en el mismo enlace, y el host es requerido a ARP para la dirección de la capa de enlace de destino. Es por eso que lo que estás haciendo en IPv4 es suficiente. –

2

He estado buscando en la documentación de wmi tratando de encontrar el prefijo de ipv6 y también estoy luchando por encontrarlo. Sin embargo, tengo código de trabajo para IPv4.

Creo que se puede asumir con seguridad que el prefijo es/64 para ese segmento de red. Si haces eso, puedes simplemente comparar los primeros 8 bytes de cada dirección. La mayoría de las veces, las redes locales individuales que ejecutan aplicaciones serán un/64, incluso los enlaces punto a punto a menudo reciben un rango completo/64, aunque solo se utilizan 2.

+0

+1, [RFC 4291] (http://tools.ietf.org/html/rfc4291#section-2.5.1) requiere identificadores de interfaz de 64 bits, aunque [RFC 4862] (http://tools.ietf.org /html/rfc4862#section-5.5.3) deja abierta la posibilidad de longitudes de prefijo no/64. Esta es la solución más simple (con las advertencias que mencioné en mi respuesta) – mpontillo

+0

Sí, también la distribución de direcciones a través del enrutador Anuncio solo funciona con/64 prefijos, debido al requisito del identificador de interfaz de 64 bits. Puede usar diferentes estáticamente o con DHCPv6, pero nunca he visto nada más que un/64 en uso. – Andee

1

En el 99% de los casos, esto es simple. Todas las subredes en IPv6 son/64 prefijos, por lo tanto, si los 64 bits más a la izquierda de un prefijo son idénticos, se encuentran en la misma subred.

Ahora es cierto que algunas personas están haciendo cosas extrañas y creando subredes con prefijos más largos, pero la mayoría de esto se trata de circuitos punto a punto donde usan un/126 para numerar los dos puntos finales y luego RESERVAR el/64 que contiene el/126. Una aplicación nunca se encontraría en esta situación ya que no hay servidores involucrados.

No hay una buena razón para admitir tamaños de subred que no sean/64.

+0

No sé si puedo estar de acuerdo con "No hay una buena razón para admitir tamaños de subred que no sean/64". La violación de las especificaciones es la forma en que terminamos con Internet Explorer. –

Cuestiones relacionadas