Nombres de "host" a partir de DHCP en Debian y Ubuntu

, , 1 comment
Ésta es una de esas entradas rápidas que le pegan más a Javier. Pero como me he pasado un día entero preguntándome por qué no funcionaba, y ahora al menos sé cómo hacer que funcione de forma más o menos limpia, lo pongo por aquí para que Google lo encuentre y les ahorre el trabajo a otros.

DHCP


No hace falta que explique qué es DHCP, ¿verdad? Todos hemos configurado algún servidor DHCP, sea para una red casera o para algo más serio. Lo típico es configurar una sección subnet para asignar direcciones IP en una red determinada. Un ejemplo sacado de la documentación del ISC DHCP Server (el servidor DHCP estándar):


subnet 10.254.239.0 netmask 255.255.255.224 {
  range 10.254.239.10 10.254.239.20;
  option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org;
}

Definimos la red 10.254.239.0/27 y asignamos direcciones IP entre la 10 y la 20 de ese rango. Como "bonus", también les decimos a nuestros clientes que los routers de la red son rtr-239-0-1.example.org y rtr-239-0-2.example.org. Personalmente pondría las direcciones IP y no los nombres DNS, porque no le hemos dicho a los clientes dónde está el servidor DNS; pero esto es sólo un ejemplo, y yo estoy divagando.

Aparte de esta definición, otra menos frecuente es la de host, con la que asignamos una dirección IP concreta a un dispositivo identificado por su MAC. Por ejemplo:

host pruebita {
  hardware ethernet 08:00:27:9c:28:77;
  fixed-address 192.168.1.198;
}

Que es lo mismo que decir: al dispositivo con MAC 08:00:27:9c:28:77 le das siempre la dirección IP 192.168.1.198. Yo lo he usado sobre todo para dispositivos como impresoras, en los que es más fácil dejar DHCP y asignar la IP en la configuración del servidor que pelearse con los menúes en miniatura que traen en el panel de control. También es práctico para otros equipos de gestión incómoda, como controladoras de cabinas de discos y similares.

Asignando nombres


Una opción adicional que podemos añadir al ejemplo anterior es la de host-name, con la que (en teoría) el equipo se pondrá el nombre que le indiquemos.



host pruebita {
  hardware ethernet 08:00:27:9c:28:77;
  fixed-address 192.168.1.198;
  option host-name "pruebita";
}

Casos de uso: si tenemos varios equipos que han sido instalados con una imagen genérica, y queremos darle a cada uno un nombre distinto. Por ejemplo, los equipos de un laboratorio, varias máquinas virtuales, etc.

Pues bien. Resulta que en Debian y Ubuntu esto no funciona. Para no ofender a nadie, voy a decirlo de otra forma: yo no conseguí hacerlo funcionar, y todos los comentarios que vi en Internet decían lo mismo.

La solución es hacer lo que pone en este artículo de Debian Administration: un script en /etc/dhcp/dhclient-exit-hooks.d que actualiza el hostname cuando dhclient obtiene una dirección IP. Pero el script que pone de ejemplo aquí no es muy limpio. Si se fijan, para obtener el nombre del equipo hace un host de la dirección IP y parsea la salida. Sucio. Feo. Poco elegante.

Así que, henchido de vanidad y con la inmodestia que me caracteriza, propongo una alternativa mucho más sencilla:

#!/bin/sh
h=$new_host_name
if [ "$h" ]; then hostname $h && echo $h > /etc/hostname; fi

(que iría como /etc/dhcp/dhclient-exit-hooks.d/hostname)

La variable "$new_host_name" es el nombre que ha asignado el servidor DHCP para el cliente, proporcionada por dhclient a los scripts que ejecuta como hooks. No hace falta recurrir al DNS, y de hecho ni siquiera tendría por qué estar funcionando (aunque es muy recomendable; os ocurrirán cosas horribles si tenéis un DNS mal configurado).

Y con eso quedaría solucionado el problema ... si no fuera por NetworkManager.

NetworkManager


Todo lo anterior sirve cuando hemos configurado el interfaz de red en /etc/network/interfaces. Nuestra configuración será algo así:

auto eth0
iface eth0 inet dhcp

En ese caso, todo funcionará como decía: se ejecutará dhclient y se actualizará el hostname con los datos de servidor. Pero en los equipos que instalan una Ubuntu o Debian moderna, "para escritorio", la configuración de red no se hace ahí: se hace mediante NetworkManager.

Este engendro programa no ejecuta los hooks de dhclient, aunque sea lo que usa "por debajo". Tiene su propio (e incompatible) sistema para acciones que se llevan a cabo tras la configuración de un interfaz de red en /etc/NetworkManager/dispatcher.d.

Los scripts ejecutados en ese directorio reciben ciertas variables de entorno de NetworkManager, incluyendo las relativas a DHCP. Éstas tienen la forma DHCP4_*, y en concreto la del nombre del equipo es DHCP4_HOST_NAME. Por lo tanto, tenemos que hacer una versión del script anterior para NetworkManager, y usando esta variable. Yo lo he puesto en /etc/NetworkManager/dispatcher.d/99hostname, con esto:

#!/bin/sh

case "$2" in
    up)
        hostname $DHCP4_HOST_NAME && echo $DHCP4_HOST_NAME > /etc/hostname
        ;;
esac

Esto, por fin, funciona. Es posible que al equipo no le guste mucho arrancar con un hostname y que luego, cuando ya hay servicios funcionando, cambie a otro. Aunque me duele decirlo, lo mejor en estos casos es un reinicio para que todo arranque con el nuevo hostname. A lo mejor llega con reiniciar lightdm o su equivalente, pero no puedo asegurarlo.



1 comentario:

  1. Bueno, te puedes ahorrar una variable:

    #!/bin/sh
    if [ "$new_host_name" ]; then hostname $new_host_name && echo $new_host_name > /etc/hostname; fi

    :)

    ResponderEliminar