06 - DHCP: Kea

En esta práctica, vamos a instalar y configurar un servidor DHCP Kea utilizando Docker. Kea es una solución moderna y potente para la gestión de direcciones IP en redes.

A diferencia del antiguo ISC DHCP Server, Kea está construido con un enfoque moderno y modular, permitiendo una mayor flexibilidad y escalabilidad. Kea soporta una amplia gama de características avanzadas, incluyendo soporte para múltiples subredes, reservas de IP, y almacenamiento de datos en bases de datos SQL como MySQL o PostgreSQL.

Empezaremos creando un servidor DHCP Kea y un par de clientes que obtendrán sus direcciones IP del servidor. Posteriormente, iremos ampliando la funcionalidad con características avanzadas como la reserva de IPs por dirección MAC, la configuración de múltiples subredes y el uso de MySQL como almacenamiento de datos…

Para esta práctica, lo primero que haremos será crear la máquina virtual derivada de Alpine_base que será nuestro servidor DHCP. Esta máquina tendrá dos adaptadores de red:

  • Adpatador 1: Adaptador puente, que nos servirá para conectarnos vía SSH y facilitarnos la configuración del servidor
  • Adaptador 2: Red interna, con nombre intnet1, que será la red donde nuestro servidor DHCP servirá IPs

Usaremos la imagen smr-kea-server para crear nuestro contenedor docker;

name: dhcp-kea

services:
  dhcp-server:
    image: smr/kea-server
    container_name: dhcp-kea
    network_mode: host
    volumes:
      - ./config:/etc/kea
      - ./lib:/var/lib/kea
    restart: always

Detalles importantes

  • network_mode: host: Permite que Kea escuche directamente en la interfaz de red de la VM. Es imprescindible para DHCP, porque los paquetes DHCP son broadcast y no atraviesan las redes virtuales de Docker. No hace falta mapear puertos con ports:.
  • Volúmenes (volumes)
    • ./config:/etc/kea → Aquí van tus archivos de configuración: kea-dhcp4.conf y kea-ctrl-agent.conf.
    • ./lib:/var/lib/kea → Aquí Kea guarda los leases (las IPs asignadas).
  • Reinicio automático (restart: always): Garantiza que el contenedor se levante automáticamente si la VM se reinicia.

Una vez tenemos nuestro contenedor listo, es hora de configurar el servidor DHCP. Para ello, necesitamos crear dos archivos de configuración: kea-ctrl-agent.conf y kea-dhcp4.conf dentro de nuestra carpeta config.

Copia el siguiente contenido en el archivo kea-ctrl-agent.conf:

                                                                                          
{
    "Control-agent": {
        "http-host": "0.0.0.0",
        "http-port": 8000,
        "control-sockets": {
            "dhcp4": {
                "socket-type": "unix",
                "socket-name": "/run/kea/control_socket_4"
            }
        },
        "loggers": [
            {
                "name": "kea-ctrl-agent",
                "output_options": [
                    {
                        "output": "stdout"
                    }
                ],
                "severity": "INFO"
            }
        ]
    }
}

En esta práctica, no nos detendremos en los detalles específicos de cada opción en el archivo de configuración kea-ctrl-agent.conf. Dado que el archivo es relativamente sencillo y se utiliza para configurar aspectos básicos del agente de control de Kea, la explicación detallada de cada opción no es necesaria para los objetivos de esta práctica. Nos centraremos en la funcionalidad general del servidor DHCP y la interacción con los clientes.

Si quieres saber más de cómo configurar este archivo, visita este enlace

El contenido del archivo kea-dhcp4.conf será:

{
  "Dhcp4": {

    # First we set up global values
    "valid-lifetime": 4000,
    "renew-timer": 1000,
    "rebind-timer": 2000,

    # Next we set up the interfaces to be used by the server.
    "interfaces-config": {
        "interfaces": ["eth1"]
    },

    # And we specify the type of lease database
    "lease-database": {
        "type": "memfile",
        "persist": true,
        "name": "/var/lib/kea/dhcp4.leases"
    },

    # Finally, we list the subnets from which we will be leasing addresses.
    "subnet4": [
        {
            "id": 1,
            "subnet": "172.18.2.0/24",
            "pools": [
                {
                    "pool": "172.18.2.70 - 172.18.2.90"
                }
            ],
            "interface": "eth1"
        }
    ]
  }
}

Vamos a explicar brevemente cada concepto:

  • valid-lifetime: Define el tiempo en segundos durante el cual una dirección IP es válida después de ser asignada a un cliente.
  • renew-timer: Especifica el tiempo en segundos que el cliente debe esperar antes de intentar renovar su dirección IP.
  • rebind-timer: Indica el tiempo en segundos que el cliente debe esperar antes de intentar volver a solicitar una dirección IP en caso de que la renovación haya fallado.
  • interfaces-config: Configura las interfaces de red en las que el servidor DHCP escuchará y responderá a las solicitudes DHCP.
    • [“eth1”]: Indica que el servidor escuchará en la interfaz eth1.
  • lease-database: Define la base de datos utilizada para almacenar la información de los arrendamientos de IP.
    • type: “memfile”: Especifica que la base de datos se almacenará en un archivo en disco.
    • persist: true: Indica que la base de datos debe persistir y conservar los arrendamientos incluso después de reiniciar el servidor.
    • name: La ruta del archivo de base de datos de arrendamientos. En este caso, /var/lib/kea/dhcp4.leases.
  • subnet4: Define las subredes de las cuales el servidor DHCP asignará direcciones IP.
    • id: Identificador único para esta subred en particular.
    • subnet: La dirección de la subred y la máscara de red. En este caso, 172.18.2.0/24 cubre la gama de direcciones IP desde 172.18.2.1 hasta 172.18.2.255.
    • pools: Especifica el rango de direcciones IP disponibles para asignar a los clientes dentro de la subred.
      • pool: Rango de IPs desde 172.18.2.70 hasta 172.18.2.90.
    • interface: Define la interfaz de red en la que el servidor escuchará y asignará direcciones IP para esta subred.
Aquí tienes la documentación completa de cómo configurar Kea

Además, crearemos el archivo dhcp4.leases (vacío) en ./lib, que será donde kea almacenará las IPs asignadas.

Asegúrate que los archivos tengan los permisos adecuados, en especial el de escritura en dhcp4.leases

Antes de levantar el entorno de laboratorio final, necesitamos que nuestro servidor DHCP tenga una IP estática y que la red sea interna, de forma que los clientes puedan comunicarse solo dentro del entorno controlado.

Configurar IP estática en la VM del servidor

Edita el archivo de interfaces de red en Alpine:

sudo nano /etc/network/interfaces

Y asegúrate de tener algo similar a:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
   address 172.18.2.2
   netmask 255.255.255.0

Explicación:

  • address → IP fija de la VM servidor (dentro de la subred que definimos en Kea).
  • netmask → máscara de red /24.

Guarda los cambios y reinicia la interfaz de red:

sudo service networking restart

Verifica la IP:

ip a

Debe mostrar 172.18.2.2/24 en eth1.

Una vez tenemos nuestro servidor configurado y en marcha, creamos una máquina virtual a partir de Alpine base con red interna (asegúrate de que tiene el mismo nombre de red que el servidor).

Si todo ha ido bien, debería obtener la ip del servidor al arrancar:

udhcpc: started, v1.37.0
udhcpc: broadcasting discover
udhcpc: broadcasting discover
udhcpc: broadcasting select for 172.18.2.70, server 172.18.2.2
udhcpc: lease of 172.18.2.70 obtained from 172.18.2.2, lease time 4000

Crearemos otra máquina igual a la que llamaremos impresora, para poder probar la reserva de host.

Una reserva de host en un servidor DHCP permite asignar una dirección IP específica a un dispositivo basándose en su dirección MAC. Esto asegura que el dispositivo recibirá siempre la misma IP cada vez que se conecte a la red. Esta función es especialmente útil en escenarios donde se necesita una IP fija, como en servidores, impresoras de red, o cámaras de seguridad, facilitando la gestión y el acceso constante a estos dispositivos sin necesidad de configurarlos manualmente en cada uno de ellos.

Para probar esta funcionalidad, configuraremos Kea para indicar que reserve una IP para la máquina con la MAC de nuestra “impresora”. Ésto se puede hacer mediante la opción reservations en el archivo de configuración kea-dhcp4.conf:

    "subnet4": [
        {
            "id": 1,
            "subnet": "172.18.2.0/24",
            "pools": [
                {
                    "pool": "172.18.2.70 - 172.18.2.90"
                }
            ],
            "interface": "eth1",
            "reservations": [
              {
                "hw-address": "CC:DD:EE:FF:00:11",
                "ip-address": "172.18.2.84"
              }
            ]
        }
    ]

En hw-address debes poner la MAC de tu máquina virtual que simula la impresora.

Reiniciamos nuestro contenedor docker y al arrancar la máquina virtual “impresora”, debería darnos siempre la 172.168.2.84:

udhcpc: started, v1.37.0
udhcpc: broadcasting discover
udhcpc: broadcasting discover
udhcpc: broadcasting select for 172.18.2.84, server 172.18.2.2
udhcpc: lease of 172.18.2.84 obtained from 172.18.2.2, lease time 4000

La capacidad de un servidor DHCP para servir diferentes rangos de IP a diferentes subredes permite una gestión más eficiente y flexible de redes complejas. Esto es útil en entornos donde existen múltiples subredes que requieren configuraciones de red específicas, como oficinas con departamentos separados, redes de invitados y redes internas. Al administrar varios rangos de IP, el servidor DHCP puede asignar automáticamente las direcciones adecuadas a cada dispositivo según la subred a la que pertenece, lo que facilita la segmentación de la red, mejora la seguridad y optimiza el uso de los recursos de red.

Vamos a simular un entorno con diferentes subredes. Para ello, crearemos 2 adaptadores de red en nuestro servidor. Ambos estarán en “Red interna”, con nombre intnet1 y intnet2 respectívamente. El primer cliente lo añadiremos a la red intnet1 y la impresora a intnet2. La primera subred tendrá el rango de direcciones 172.18.2.0/24 y la segunda 172.18.3.0/24.

Además, tendremos que configurar IP fija para ambos adaptadores de red de nuestro servidor:

auto lo
iface lo inet loopback
 
auto eth0
iface eth0 inet dhcp
 
auto eth1
iface eth1 inet static
   address 172.18.2.2
   netmask 255.255.255.0
   
auto eth2
iface eth2 inet static
   address 172.18.3.2
   netmask 255.255.255.0

{
  "Dhcp4": {

    "valid-lifetime": 4000,
    "renew-timer": 1000,
    "rebind-timer": 2000,

    "interfaces-config": {
      "interfaces": ["eth1", "eth2"]
    },

    "lease-database": {
      "type": "memfile",
      "persist": true,
      "name": "/var/lib/kea/dhcp4.leases"
    },

    "subnet4": [
      {
        "id": 1,
        "subnet": "172.18.2.0/24",
        "pools": [
          {
            "pool": "172.18.2.70 - 172.18.2.90"
          }
        ],
        "interface": "eth1",
        "reservations": [
          {
            "hw-address": "08:00:27:CD:6D:00",
            "ip-address": "172.18.2.84"
          }
        ]
      },
      {
        "id": 2,
        "subnet": "172.18.3.0/24",
        "pools": [
          {
            "pool": "172.18.3.70 - 172.18.3.90"
          }
        ],
        "interface": "eth2"
      }
    ]
  }
}

Fíjate que en el archivo de configuración configuramos las dos interfaces: eth1 y eth2. Ésto es para indicar a Kea que el servidor DHCP servirá IPs por ambas interfaces

Lo último será cambiar los nombres de red de nuestros dos clientes: intnet1 a la impresora (para que le de la IP fija que configuramos) y intnet2 a la otra máquina.

En nuestra configuración de Kea, indicamos al principio que la base de datos utilizada para almacenar la información de los arrendamientos de IP era en memoria mediante la opción lease-database:

    "lease-database": {
        "type": "memfile",
        "persist": true,
        "name": "/var/lib/kea/dhcp4.leases"
    }

De hecho, si arrancamos el contenedor Docker y hacemos varias peticiones al servidor para que sirva IPs, podemos ver en el contenido de ese archivo (/var/lib/kea/dhcp4.leases) las IPs que ha ido sirviendo el servidor:

address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context,pool_id
172.18.2.70,00:11:22:33:44:55,,4000,1724234915,1,0,0,2d1a2137a76e,0,,0
172.18.3.70,66:77:88:99:aa:bb,,4000,1724234927,2,0,0,7366e6e03c6d,0,,0
172.18.3.84,cc:dd:ee:ff:00:11,,4000,1724234943,2,0,0,d3b9c1306036,0,,0
172.18.3.84,cc:dd:ee:ff:00:11,,4000,1724235702,2,0,0,d3b9c1306036,0,,0
172.18.3.70,66:77:88:99:aa:bb,,4000,1724235760,2,0,0,7366e6e03c6d,0,,0
172.18.2.70,00:11:22:33:44:55,,4000,1724235778,1,0,0,2d1a2137a76e,0,,0

Podemos variar este comportamiento para hacer que toda esa información se almacene en una bbdd, lo que ofrece varios beneficios:

  • Persistencia de datos: El almacenamiento en memoria se pierde si el servidor Kea se reinicia o se apaga. Al usar una base de datos, los datos se mantienen a salvo incluso después de reinicios o caídas del sistema.
  • Escalabilidad: Con una base de datos, Kea puede manejar un mayor volumen de direcciones IP y reservas, lo que lo hace más adecuado para entornos más grandes o distribuidos.
  • Centralización: En escenarios donde varios servidores DHCP necesitan acceder a la misma información, el uso de una base de datos permite una administración centralizada de direcciones IP y reservas.
  • Mejor administración de la red: Te permitirá tener un mayor control sobre las asignaciones de IP, estadísticas y registros que pueden ser fácilmente consultados o gestionados desde la base de datos.

Para implementar este cambio, realizaremos los siguientes ajustes:

  • Añadir un contenedor MySQL en Docker Compose: Kea se conectará a esta base de datos MySQL para almacenar las asignaciones y reservas de IP.
  • Configurar Kea para usar MySQL: Cambiaremos la configuración de Kea para que utilice la base de datos en lugar de la memoria. Esto implica modificar el archivo de configuración kea-dhcp4.conf para que apunte al contenedor MySQL.
  • Crear la base de datos y tablas necesarias: Kea necesita ciertas tablas en la base de datos para funcionar correctamente. El esquema de la base de datos deberá ser creado, y podemos utilizar los scripts de instalación que proporciona Kea.

Uno de los primeros problemas que debemos enfrentar es garantizar que, al iniciar el servidor Kea, la base de datos ya esté lista. Esto es importante porque, si Kea intenta conectarse a la base de datos antes de que esta esté completamente operativa, generará errores de conexión. Para solucionar esto, normalmente podríamos usar una herramienta como kea-admin para crear la base de datos y las tablas necesarias antes de que el servidor Kea comience a funcionar.

Sin embargo, utilizar kea-admin complica el proceso de creación de contenedores. Esto nos obliga a buscar una solución que sea más sencilla y automática dentro del entorno de Docker.

En lugar de utilizar kea-admin, optamos por una solución más directa: crear la base de datos y las tablas necesarias a través de un dhcpdb_create.zip. Este script contendrá todas las instrucciones necesarias para crear la base de datos y las tablas que Kea necesita para funcionar correctamente.

Guardaremos este script en una carpeta llamada script dentro de nuestro proyecto. Luego, aprovechamos una funcionalidad de MySQL en Docker: cuando iniciamos un contenedor de MySQL, el propio contenedor ejecuta automáticamente cualquier script que esté en la carpeta docker-entrypoint-initdb.d.

Al mapear la carpeta script a docker-entrypoint-initdb.d en nuestro archivo docker-compose.yml, logramos que MySQL ejecute el script automáticamente al iniciarse el contenedor. De esta forma, la base de datos y las tablas estarán listas antes de que Kea intente conectarse, resolviendo el problema de dependencia entre los dos servicios.

Este enfoque no solo simplifica el proceso de creación de la base de datos, sino que también asegura que el contenedor MySQL siempre tenga la estructura correcta sin necesidad de ejecutar comandos adicionales o complicar el flujo de creación de contenedores.

En nuestro entorno de Docker, es crucial asegurarnos de que el contenedor kea-server no intente conectarse a la base de datos MySQL hasta que esta esté completamente lista y aceptando conexiones. Para lograr esto, utilizamos la funcionalidad de healthcheck en Docker, que nos permite verificar si un servicio está listo antes de que otro servicio dependiente intente conectarse:

  dhcp-mysql:
    image: mysql:8.0
    container_name: kea-mysql
    networks:
      dhcp-net:
        ipv4_address: 172.18.4.3
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: dhcp_kea
    volumes:
      - ./mysql:/var/lib/mysql
      - ./script:/docker-entrypoint-initdb.d
    healthcheck:
      test: mysqladmin ping -h 127.0.0.1 -u root --password=root
      interval: 10s
      retries: 5
      start_period: 30s
      timeout: 10s

Luego, añadimos la clave depends_on en el contenedor kea-server. Esto garantiza que kea-server no se cargue hasta que el contenedor kea-mysql pase las comprobaciones de salud.

  dhcp-server:
    build: .
    depends_on:
      dhcp-mysql:
        condition: service_healthy
    container_name: kea-server
    networks:
      dhcp-1floor:
        ipv4_address: 172.18.2.2
      dhcp-2floor:
        ipv4_address: 172.18.3.2
      dhcp-net:
        ipv4_address: 172.18.4.2
    volumes:
      - ./config:/etc/kea

Fíjate que en nuestra configuración de Docker, utilizamos la opción build para crear una imagen personalizada del contenedor kea-server. Esta opción nos permite definir instrucciones adicionales en un Dockerfile que ajusta la imagen base según nuestras necesidades. En este caso, estamos utilizando un Dockerfile que extiende la imagen base de Kea para añadir algunas herramientas adicionales que requerimos en nuestro entorno:

FROM docker.cloudsmith.io/isc/docker/kea-dhcp4:2.7.0

RUN apk update && apk add --no-cache bash curl mysql-client

La opción build es necesaria porque estamos personalizando la imagen base de Kea. La imagen oficial no incluye todas las herramientas que necesitamos, como el cliente MySQL o Bash. En lugar de crear un contenedor desde una imagen que no está completamente adaptada a nuestras necesidades, utilizamos esta opción para construir una imagen que ya contiene todas las herramientas necesarias, lo que hace más eficiente el desarrollo y la ejecución de nuestra aplicación.

Al agregar estas utilidades directamente en la imagen, no tenemos que instalarlas cada vez que el contenedor se inicie, lo que ahorra tiempo y evita problemas de configuración en el futuro.

Por último, sólo nos queda cambiar la configuración de kea en el archivo kea-dhcp4.conf para indicar que vamos a utilizar MySql como almacenamiento:

"lease-database": {
        "type": "mysql",
        "host": "kea-mysql",
        "user": "root",
        "password": "root",
        "name": "dhcp_kea"
    },

Una vez que hemos configurado Kea para que utilice MySQL como almacenamiento, verificamos que las asignaciones de direcciones IP (leases) se están guardando correctamente en la base de datos. Para hacer esta comprobación, podemos realizar una consulta SQL sencilla sobre la tabla lease4, que es donde se almacenan las direcciones IPv4 asignadas.

Para ello, accedemos a cualquier cliente para pedir una IP al servidor DHCP. A continuación, entramos al contenedor mysql y ejecutamos:

mysql -u root -p

Una vez estamos conectados a MySql:

use dhcp_kea;

SELECT * FROM lease4;

Esto mostrará todas las entradas de direcciones IPv4 asignadas, junto con información relevante como el tiempo de expiración de la lease, la dirección MAC del cliente, entre otros detalles.

Configura un servidor Kea DHCP para una oficina de tres pisos. Cada piso debe tener la siguiente configuración:

Piso 1:

Subred: 192.168.1.0/24 Dispositivos: 3 PCs y una impresora Reserva de IP para una impresora: 192.168.1.20

Piso 2:

Subred: 192.168.2.0/24 Dispositivos: 2 PCs Reserva de IP para una impresora: 192.168.2.15

Piso 3:

Subred: 192.168.3.0/24 Dispositivos: 3 PCs

El almacenamiento de las asignaciones debe hacerse en una bbdd MySql.

Asegúrate de que los PCs y las impresoras obtengan las configuraciones de IP adecuadas.

  • clase/smr/sr/1eval/dhcp2.txt
  • Última modificación: 2025/10/21 13:28
  • por cesguiro