Hoy (01/04/2010), mientras preparaba la próxima entrada del blog "casualmente" tenía wireshark corriendo y me encontré con un paquete que me llamó poderosamente la atención. El protocolo es MDNS, lo había visto antes pero siempre creí que se trataba de alguna de las aplicaciones que estaba corriendo.
Intro:
Googleando un poco encontré de que se trata: "Multicast DNS is a way of using familiar DNS programming interfaces, packet formats and operating semantics, in a small network where no conventional DNS server has been installed." (http://www.multicastdns.org/). Es decir, se trata de una implementación del protocolo de resolución de nombres (DNS) para redes de área local, donde no existe un servidor DNS real. Producto de los grupos Zero Configuration Networking y DNS Extensions, creado con el objetivo de facilitar la configuración de redes locales que no cuentan con un servidor de nombres propio.
Según el draft (http://files.multicastdns.org/draft-cheshire-dnsext-multicastdns.txt) "Clients performing DNS-like queries for DNS-like resource records by sending DNS-like UDP query and response packets over IP Multicast to UDP port 5353." se trata de clientes realizando consultas tipo DNS por registros tipo DNS enviando paquetes (tipo DNS) al puerto 5353 UDP sobre direcciones IP Multicast (JA!, para los que creen que las clase D no se usan jajaaj).
Las direcciones Multicast o clase D van de 224.0.0.0 a 239.255.255.255, y se caracterizan por: una dirección Multicast está asociada con un grupo de receptores interesados, cuando uno de los interesados envía un paquete a una dirección Multicast todos los demás lo reciben, los routers que se encuentren entre estos interesados deben ser capaces de reenviar estos paquetes a cada uno de ellos.
Al tratarse de una dirección Multicast, todos los asociados reciben todos los paquetes, y de esta manera las caches de nombres se mantienen actualizadas. Cada respuesta a una consulta Multicast DNS trae un campo donde se especifica el tiempo de validez que tiene la respuesta, luego de que expire ese tiempo es necesario volver a efectuar la consulta.
Este servicio de DNS cuenta también con un TLD (Top-Level Domain) propio y es ".local.". Todo FQDN (Fully Qualified Domain Name, nombre completo xD) que finalice con ".local." se lo considera de enlace local, es decir... es un análogo a las direcciones IP privadas, que sólo valen en el ámbito local de la red y de nada sirven fuera de ella. Toda consulta DNS que finalice con ".local." debe ser enviada a la dirección 224.0.0.251 (si se trata de IPv4, o FF02::FB si se trata de IPv6).
Existen 3 tipo de consultas: las consultas convencionales 1-consulta->1-respuesta, 1-consulta->N-respuestas y el ultimo tipo que consiste en consultas continuas.
En fin... eso es mas o menos a modo de introducción :D. Si realmente querés saber mas, está el link del borrador mas arriba, de ahora en mas voy a intentar controlar/activar/desactivar este servicio de mi laptop. Resulta ser que en la mayoría de las distribuciones de GNU/Linux viene instalado por defecto un servicio que implementa este protocolo, y se llama Avahi (http://avahi.org/). Avahi es capaz de publicar y descubrir dispositivos, y servicios disponibles en la red local, sin necesidad de realizar configuración alguna.
Veamos si el servicio está corriendo :D (hagamos de cuenta que nunca vi el paquete con wireshark xD):
"Lo sospeché desde un principio..." asi es, tengo corriendo como demonio a avahi-daemon
Buscando un poco mas se puede ver que escucha en el puerto UDP 5353 de todas las interfaces disponibles, a la espera de consultas/respuestas que pueden provenir de cualquier dirección de red.
Ahora probemos la facilidad de uso de este protocolo. La lan de prueba está compuesta por 2 hosts, la laptop con direccion 192.168.206.1 (nombre moon) y una vm con dirección 192.168.206.134 (nombre ubuntu). Ambos hosts tienen instalado Ubuntu 9.10, que trae por defecto instalado avahi-daemon versión 0.6.25. Ninguno de los host recibió algún tipo de configuración de este servicio, ambos corren como fueron instalados. En el host moon estará nuestro amigo wireshark capturando los paquetes para ver lo que sucede :D.
Buscando a "ubuntu" desde "moon":
Sabemos que está conectadp a la red un host de nombre "ubuntu", pero no sabemos la dirección IP que le fue asignada, y no contamos con un servidor DNS local :D, maldita sea!, pero para eso está corriendo avahi-daemon. Para conocer la dirección de ese host nos basta con hacer un "ping ubuntu.local.", como muestra la imagen
ahora veamos lo que capturó nuestro amigo :D.
Wireshark nos muestra 4 paquetes MDNS, los dos primeros son la resolución directa del nombre de host "ubuntu.local.".
-192.168.206.1 (moon) envía una consulta MDNS a 224.0.0.251 (Multicast IP Address) preguntando por la dirección de "ubuntu.local.".
-192.168.206.134 (ubuntu) envía una respuesta MDNS a 224.0.0.251 (Multicast IP Address) diciendo que 192.168.206.134 corresponde al "host ubuntu.local.".
Los últimos dos paquetes son la resolución inversa, es decir, intenta averiguar el nombre que le corresponde a la dirección 192.168.206.134, esto debe ser una suerte de mecanismo de seguridad, para ver que sean consistentes:
-192.168.206.1 (moon) envía una consulta inversa a la dirección 224.0.0.251, consultando por el nombre que le corresponde a "134.206.168.192.in-addr.arpa.".
-192.168.206.134 (ubuntu) rsponde a la dirección 224.0.0.251, diciendo que esa dirección le corresponde al nombre "ubuntu.local.".
Exáctamente lo mismo podemos observar si ahora realizamos el ping desde ubuntu hacia moon.local.
Publicando y Descubriendo servicios:
Junto con MDNS se puede utilizar algo llamado DNS-SD (DNS-Service Discovery), que consiste en dar a conocer y encontrar servicios locales utilizando MDNS. De nuevo se trata de algo de simple puesta en marcha. Como ejemplo publicaremos dos servicios en el host de nombre moon (FQDN moon.local.), un servidor web en el puerto 80 y un ftp en el puerto 21. El proceso de publicación de los servicios consiste en crear un archivo con sintaxis XML en el directorio /etc/avahi/services/, con la condición que el nombre del archivo debe finalizar en ".service" (sin las comillas :D), como el siguiente:
Para entender bien la sintaxis basta con dar una breve leída a "man avahi.service" :D. Luego de configurar adecuadamente los servicios que querramos reiniciamos el demonio avahi con "avahi-daemon -r" y listo, toda la magia de la publicación de servicios es esa jajaja. Ahora hay que comprobar que los servicios están siendo publicados, para eso instalé dos porgramas mdns-scan y mzclient, NO instalen mdns-scan es DEMASIADO BASICO (ni siquiera recibe parámetros y solo busca types "_workstation"). Primero veamos los hosts que se encuentran utilizando MDNS ejecutamos mzclient como en la próxima imagen (-r se encarga de resolver los nombres de los hosts):
moon tiene 3 direcciones MAC diferentes porque se trata de las 3 interfaces de red, dos virtuales y la eth0 real. Entonces los hosts siguen bien configurados, ahora busquemos los servicios publicados :D. Para eso usamos la opcion -t, que indica la etiqueta type del archivo de servicios, buscamos primero si hay servicios tipo "_http._tcp", incluimos -r para que resuelva nombres:
Ahora busquemos el ftp :D:
Ambos servicios fueron asociados al nombre "moon.local" con dirección 192.168.206.1, como lo configuramos y como debe ser. Eso es gran parte de la publicación de servicios, para mas información http://avahi.org :P.
Deteniendo el demonioooooooo:
Si nos iteresa detener el demonio solo por un momento o reiniciarlo, lo podemos hacer directamente mediante el script ubicado en /etc/init.d. Ejecutamos sudo /etc/init.d/avahi-daemon stop, o mas elegantemente sudo service avahi-daemon stop, para detenerlo, cambiamos stop por restart, para reiniciarlo y start para iniciarlo cuando está detenido.
Deshabilitando temporalmente al demonio:
Si queremos deshabilitarlo temporalmente pero no borrarlo del sistema podemos recurrir a un pequeño truquillo :D. La idea básicamente consiste en que sencillamente el demonio nunca se inicie xD, y esto lo podemos lograr alterando el script de inicio del demonio, ubicado en "/etc/init/avahi-daemon.conf". Como se ve en la imagen hay que comentar la linea de "start".
En definitiva, se trata de un servicio bastante útil, pero que sinceramente no necesito tener activo en este momento. Posiblemente en una LAN donde todo el tiempo entran y salen dispositivos diferentes sea de suma utilidad, pero no lo veo tan así en una LAN chica con poco cambio de los dispositivos.