martes, 1 de diciembre de 2009

Implementando cliente DNS para resolver servidores MX (MAIL EXCHANGE) con C

A continuación listo el codigo fuente totalmente comentado para resolver servidores de correo saliente a partir de un email, un servidor DNS y el puerto usado por el servidor (normalmente el 53 por UDP).

Uso del programa:

DNS-MX.exe <Email> <Servidor DNS> <Puerto servidor DNS>

DNS-MX.c

Analizando la respuesta DNS

Procederemos a analizar la respuesta que nos devuelve el servidor DNS.



Voy a pasar a comentar sólo algunos campos que nos resultan de interés para la práctica que estamos realizando.
  • Transaction ID: Como vemos, coincide el ID de la consulta con la de la respuesta.
  • Answer RRs: Nos indica que el número de servidores tipo MX resueltos.
  • Additional RRs: Son campos adicionales donde se muestran las direcciones IP de cada servidor MX resuelto.

Ahora vamos a desglosar los campos Answers donde se encuentran los servidores MX resueltos por el servidor DNS.



Datos de la estructura Answers:
  • Name: gmail.com = 0xc00c. c0 indica que hay compresión y el siguiente byte establece el byte de desplazamiento donde se encuentra la información, osea: 0c, que en decimal se traduce a 12. En la posición 12 de la respuesta se encuentra lo que buscamos. Los primeros 12 bytes de la respuesta corresponden a parámetros de la consulta, el byte siguiente, osea, el 13, nos deja justo en el campo Name de la estructura Queries, que es nada más ni nada menos que: gmail.com. Todo este procedimiento se traduce como compresión.
  • Type: MX = 0x000f. Indica el tipo de servidor (servidor de correo saliente)
  • Class: IN = 0x0001. Indica la clase de servidor (servidor de internet)
  • Time to live: 47 minutes, 52 secons = 0x00000b38. Marca de tiempo que establece el tiempo que puede ser el servidor cacheado hasta vovler a interrogar para resolverlos de nuevo.
  • Data length: 27 = 0x000b. Indica el tamaño de la cadena en bytes del servidor resuelto.
  • Preference: 5 = 0x0005. Indica preferencia de uso del servidor entre los resueltos.
  • Mail exchange: gmail-smtp-in.l.google.com

Nos detenemos en el campo Mail exchange ya que merece la pena para analizar la compresión.



Este tipo de procedimiento se repite una y otra vez mientras se pueda hacer uso de la compresión.
Como ya dije, se hace uso de la compresión para dar una rápida respuesta y demorar lo menos posible en resolver las consultas de los clientes. Es un buen mecanismo pero un tanto engorroso, se deben de tener bien claros los conceptos porque en el capítulo siguiente veremos la implementación de un cliente DNS para resolver servidores tipo Mail exchange.

Analizando la consulta DNS

Hace algún tiempo, desarrollé un cliente DNS para resolver consultas tipo MX(MAIL EXCHANGE), que no son más que consultas para resolver  servidores de correo saliente a partir de un nombre de dominio.

Para obtener más información sobre DNS RFC 1035

La siguiente captura está realizada con wireshark para ilustrar un poco que campos intervienen a la hora de realizar una consulta DNS.



Voy a explicar un poco que significan los siguientes campos.
  • Transaction ID (2 bytes): Identifica la consulta del cliente que debe conincidir con la respuesta del servidor.
  • Flags (2 bytes): Son parámetros para la consulta a realizar, si es una consulta inversa, el mensaje está truncado, etc. De momento nos basta saber que la consulta a que hemos realizado es recursiva, es decir, si el servidor DNS al que hemos realizado la consulta no contiene la información que necesitamos, éste acude a otros servidores para obtener la respuesta.
  • Questions (2 bytes): Número de consultas a realizar, por defecto sólo una.
  • Answer RRs (2 bytes): Número de entradas que aparecen en la sección de respuesta, siempre a cero en la consulta.
  • Authority RRs (2 bytes): Número de entradas que aparecen en la sección de autoridad, siempre a cero en la consulta.
  • Additional RRs (2 bytes): Número de entradas que aparecen en la sección adicional, siempre a cero en la consulta.
  • Queries
    Este campo especifica las consultas a realizar.
    En este caso es de 15 bytes
  • Name (11 bytes): Nombre del dominio a consultar para obtener los servidores de correo saliente para enviar el mensaje
  • Type (2 bytes): Tipo de consulta a realizar. En este caso es 0x000f para especificar que es tipo MX.
  • Class (2 bytes): El tipo de consulta pertenece a internet, la más usada.

A excepción del campo Queries, la cabecera de la consulta DNS tiene siempre una constante de 12 bytes.
Vamos a ver al detalle el campo Name que contiene el dominio a consultar ya que resulta un tanto interesante en la forma en la que lo hace.

1 2 3 4 5 6 7 8 9 10 11
05 g m a i l 03 c o m 00

El dominio es gmail.com, y como vemos en la anterior tabla, los puntos '.' los sustituye por un campo numérico que indica la longitud del siguiente campo. El final de la cadena siempre acaba en cero.

Parece fácil, no?

En el siguiente capítulo veremos la respuesta que nos devuelve el servidor DNS y veremos también la compresión de los mensajes que es utilizada para ahorrar tamaño en el paquete y por consiguiente demorar lo menos posible para obtener un respuesta rápida.