suplantacion - Resolución DNS no bloqueante(asíncrona) en Java
que es un ataque de dns (6)
Creo que usted tendrá que implementar el protocolo del cliente DNS usted mismo sobre el UDP sin procesar usando soporte de sockets base, o sobre el TCP usando los canales NIO.
¿Hay una forma clara de resolver una consulta DNS (obtener IP por nombre de host) en Java de forma asíncrona, de forma no bloqueante (es decir, máquina de estado, no 1 consulta = 1 hilo - Me gustaría ejecutar decenas de miles de consultas simultáneamente, pero no ejecutar decenas de miles de hilos)?
Lo que he encontrado hasta ahora:
- La implementación estándar de
InetAddress.getByName()
está bloqueando y parece que las bibliotecas estándar de Java carecen de implementaciones sin bloqueo. - La resolución de DNS en una pregunta masiva analiza un problema similar, pero la única solución que se encuentra es el enfoque de subprocesos múltiples (es decir, un hilo que trabaja en solo 1 consulta en cada momento dado de un momento), que en realidad no es escalable.
- dnsjava biblioteca dnsjava también está bloqueando solamente.
- Existen antiguas extensiones sin bloqueo para dnsjava que datan de 2006, por lo que carecen de cualquier elemento moderno de simultaneidad Java, como el uso
Future
paradigmas y, por desgracia, la implementación de colas muy limitadas. - dnsjnio proyecto dnsjnio también es una extensión de dnsjava, pero también funciona en un modelo enhebrado (es decir, 1 consulta = 1 hilo).
- asyncorg parece ser la mejor solución disponible que he encontrado hasta el momento para atacar este problema, pero:
- también es de 2007 y parece abandonado
- carece de casi cualquier documentación / javadoc
- usa muchas técnicas no estándar, como la clase de
Fun
¿Alguna otra idea / implementación que me he perdido?
Aclaración Tengo una cantidad bastante grande (varios TB por día) de registros. Cada línea de registro tiene un nombre de host que puede ser de casi cualquier lugar en Internet y necesito una dirección IP para ese nombre de host para mis cálculos estadísticos posteriores. El orden de las líneas realmente no importa, entonces, básicamente, mi idea es comenzar 2 hilos: primero para iterar sobre las líneas:
- Lea una línea, analícela, obtenga el nombre de host
- Envíe una consulta al servidor DNS para resolver un nombre de host dado, no bloquee para obtener una respuesta
- Almacene la línea y el asa del socket de consulta DNS en algún búfer en memoria
- Ir a la siguiente línea
Y un segundo hilo que:
- Espere a que el servidor DNS responda cualquier consulta (usando
epoll
/kqueue
como técnica) - Lea la respuesta, encuentre en qué línea estaba en un buffer
- Escribir línea con IP resuelto en la salida
- Proceda a esperar la siguiente respuesta
Una simple implementación de modelo en Perl usando AnyEvent
me muestra que mi idea es generalmente correcta y que puedo alcanzar velocidades como 15-20K consultas por segundo de esta manera (la implementación ingenua de bloqueo tiene como 2-3 consultas por segundo, solo por comparación) entonces eso es como una diferencia de 4 órdenes de magnitud). Ahora necesito implementar lo mismo en Java, y me gustaría omitir el despliegue de mi propia implementación de DNS;)
Es posible que la implementación de Servicios de Directorio Apache de DNS sobre MINA sea lo que estás buscando. Los JavaDocs y otras guías útiles se encuentran en esa página, en la barra lateral izquierda.
Hay algo de trabajo en DNS no bloqueado en netty , pero todavía es trabajo en progreso en probablemente será lanzado solo en 5.0
Linux tiene una función de búsqueda DNS asincrónica: http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html
Si estás en Linux, solo tienes que resumirlo en algún JNI.
No tengo una respuesta a su pregunta (no sé si hay una biblioteca de DNS que operará en el modo asíncrono que desee) y esto es demasiado largo para hacer un comentario.
Sin embargo, debería ser capaz de producir rápidamente una función asincrónica sin tener que escribir el manejador DNS completo usted mismo. Advertencia, no he hecho esto, así que podría estar equivocado.
Comenzando con el código dnsjava, debería poder implementar su propia resolución que le proporcionará tanto un método de remitente como de receptor. Mira SimpleResolver y mira el método de send
. Debería poder dividir este método en dos métodos, uno para enviar su solicitud que se ejecute hasta la llamada al TCPClient o al UDPClient (usted manejaría el real en el envío del cable en este punto, como describió, con su primer hilo), y uno para recibir, que sería llamado por su segundo hilo como respuesta a una lectura de socket, y manejar el análisis de la respuesta. Es posible que tenga que copiar todo el código de SimpleResolver (muchos métodos privados que necesitará y la licencia lo permite ), o bien, puede crear su propia versión y simplemente cargarla antes que la jared en su classpath , o, podría reflejar su camino a los métodos en cuestión y establecerlos accesibles .
Puede construir rápidamente el lado del cliente de red con netty o mina . Prefiero netty para los documentos.
Si sigues este camino y puedo / deseo abrirlo, puedo dedicar algo de tiempo para ayudarte si te metes en problemas.
Tienes múltiples opciones
Opción 1: ejecutores de Java 5
- Un grupo de subprocesos fijos: Executors.newFixedThreadPool (int)
- Future : un futuro representa el resultado de un cálculo asincrónico. Se proporcionan métodos para verificar si el cálculo está completo, para esperar su finalización y para recuperar el resultado del cálculo.
Opción 2: JMS con MessageListener
- Requiere dependencia del proveedor JMS, etc.
Opción 2: marco basado en actores
Puedes escalar esto bien con esto. Mira a Akka .