Configurando servidor DHCP (Kea DHCP) no Debian 12, com hosts configurados diretamente no banco de dados

Kea DHCP com hosts configurados diretamente no banco de dados MySQL.

SistemaApachePHPMysqlkea-dhcp4
Debian GNU/Linux 12 (bookworm)Apache/2.4.61PHP 8.2.205.1 Distrib 10.11.6-MariaDB2.2.0

Configuração das interfaces de rede

# vim /etc/network/interfaces
# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug ens33
iface ens33 inet static
	address 192.168.0.xx/24
	gateway 192.168.0.xx
	# dns-* options are implemented by the resolvconf package, if installed
	dns-nameservers 192.168.0.xx 192.168.x.xx

# The secondary network interface (DHCP)
auto ens37
iface ens37 inet static
    address 192.168.1.1
    netmask 255.255.255.0
    network 192.168.1.0
# systemctl restart networking && ping 192.168.1.1 -c3

Instalação do KEA DHCP Server

# apt-get install kea-dhcp4-server kea-admin kea-common kea-ctrl-agent kea-dhcp-ddns-server -y

MYSQL

apt-get install default-mysql-server -y
mysql -u root -p (Enter, não tem senha)
CREATE DATABASE kea;
ALTER USER 'root'@'localhost' IDENTIFIED BY '@1234';
flush privileges;
USE kea;
SOURCE /usr/share/kea/scripts/mysql/dhcpdb_create.mysql;
ALTER TABLE hosts ADD COLUMN dhcp_identifier_compare varbinary(128) DEFAULT NULL AFTER dhcp_identifier;
ALTER TABLE hosts ADD COLUMN register timestamp NULL DEFAULT current_timestamp();
ALTER TABLE hosts ADD COLUMN observations TEXT;
ALTER TABLE hosts ADD COLUMN model VARCHAR(255) DEFAULT NULL;
ALTER TABLE hosts ADD COLUMN ping TINYINT(1) DEFAULT 0;
exit;

Arquivo de configuração KEA DHCP

# cp /etc/kea/kea-dhcp4.conf /etc/kea/kea-dhcp4.conf.bkp && vim /etc/kea/kea-dhcp4.conf
{
    "Dhcp4": {
        "interfaces-config": {
            "interfaces": ["ens37"]
        },
        "hosts-database": {
            "type": "mysql",
            "host": "localhost",
            "name": "kea",
            "user": "root",
            "password": "@1234"
        },
        "valid-lifetime": 7200, // O tempo total (em segundos) que um lease é válido, configurado para 7200 segundos (2 horas).
        "renew-timer": 3600, // O tempo (em segundos) após o qual o cliente tentará renovar o lease. Aqui, definido para 3600 segundos (1 hora).
        "rebind-timer": 5400, // O tempo (em segundos) após o qual o cliente tentará rebind do lease com qualquer servidor DHCP disponível. Configurado para 5400 segundos (1 hora e 30 minutos).
        "subnet4": [
            {
                "subnet": "192.168.1.0/24",
                #"pools": [{"pool": "192.168.1.10 - 192.168.1.100"}],
                "option-data": [
                    {
                        "name": "subnet-mask",
                        "data": "255.255.255.0"
                    },
                    {
                        "name": "routers",
                        "data": "192.168.1.1"
                    },
                    {
                        "name": "domain-name-servers",
                        "data": "8.8.8.8, 8.8.4.4"
                    },
                    {
                        "name": "domain-name",
                        "data": "jrf.local"
                    }
                ]
            }
        ],
        "loggers": [
            {
                "name": "kea-dhcp4",
                "output_options": [
                    {
                        "output": "/var/log/kea/kea-dhcp4.log",
                        "pattern": "%-5p %m\n",  // Padrão de log simples
                        "flush": true,  // Garante que o log é gravado imediatamente
                        "maxsize": 1048576,  // Gira o log após 1MB de tamanho
                        "maxver": 8  // Mantém até 8 versões de logs girados
                    }
                ],
                "severity": "INFO",
                "debuglevel": 0
            }
        ]
    }
}

Inserção de Dados no Banco de Dados

INSERT INTO hosts (dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, ipv4_address, hostname, observations)
VALUES (UNHEX(REPLACE('00:0c:29:db:9b:b3', ':', '')), 0, 1, INET_ATON('192.168.1.X'), 'srvDHCP', 'Servidor DHCP (não remover)');

Explicação dos Parâmetros:

  1. dhcp_identifier:
    • Este campo armazena o identificador do cliente DHCP, que neste caso é o endereço MAC do dispositivo que vai receber o endereço IP reservado.
    • O valor fornecido no exemplo é o endereço MAC 00:0C:29:DB:9B:B3. Como o Kea armazena o identificador do cliente em formato binário, usamos as funções UNHEX(REPLACE()) para convertê-lo adequadamente:
      • REPLACE('00:0C:29:DB:9B:B3', ':', ''): Remove os dois pontos do endereço MAC, resultando em 000C29DB9BB3.
      • UNHEX(): Converte a sequência hexadecimal 000C29DB9BB3 em formato binário, que é como o Kea espera armazenar o identificador.
  2. dhcp_identifier_type:
    • Este campo define o tipo de identificador usado para o cliente DHCP.
    • No exemplo, o valor é 0, que indica que o identificador do cliente é um endereço MAC. Outros valores podem ser usados para diferentes tipos de identificadores (por exemplo, identificadores DUID para IPv6).
  3. dhcp4_subnet_id:
    • Este campo identifica a sub-rede associada à reserva de IP.
    • No exemplo, o valor é 1, que representa o ID da sub-rede 192.168.1.0/24 definida na configuração do Kea. Cada sub-rede configurada no Kea tem um identificador único, e esse valor deve corresponder ao ID da sub-rede na qual a reserva será feita.

Kea Logs

# touch /var/log/kea/kea-dhcp4.log
# chown _kea:_kea /var/log/kea/kea-dhcp4.log

Reiniciar o Kea DHCP

# systemctl restart kea-dhcp4-server && sleep 3 && systemctl status kea-dhcp4-server

Alterando IP

UPDATE hosts
SET ipv4_address = INET_ATON('192.168.1.222')
WHERE host_id = 1;

Verificar a Inserção: Depois de inserir o registro, você pode verificar se foi inserido corretamente:

SELECT host_id, HEX(dhcp_identifier) AS mac, INET_NTOA(ipv4_address) AS ip, hostname FROM hosts;

Painel administrativo

Um simples painel administrativo em PHP que permite incluir, editar e apagar máquinas no DHCP.

Instalação dos pacotes necessários

# apt install fping apache2 php php-mysqli -y

Copiar os scripts PHP para a pasta /var/www/html/

IonCube

cp /var/www/html/ioncube/ioncube_loader_lin_8.2.so /usr/lib/php/20220829
echo "zend_extension = /usr/lib/php/20220829/ioncube_loader_lin_8.2.so" > /etc/php/8.2/apache2/conf.d/00-ioncube.ini
systemctl restart apache2

Acesse o link: http://192.168.X.X/ioncube/loader-wizard.php

rm -rf /var/www/html/ioncube/

Altere o arquivo de conexão com o banco de dados

# vim /var/www/html/db_connect.php

Acesse a URL: http://192.168.X.X para acessar o sistema.

Crontab

vim /etc/crontab

*Vamos verificar o Ping a cada minuto (sinta-se à vontade para ajustar conforme preferir) e a checagem do MAC vendor a cada 5 minutos.

# Ping (não remover)
* * * * * www-data /usr/bin/php /var/www/html/cron/ping.php
# Mac vendor (não remover)
*/5 * * * * www-data /usr/bin/php /var/www/html/cron/mac_vendor.php

Dicas

Para adicionar uma nova sub-rede, você precisará configurar uma nova interface ou adaptar a configuração de rede existente para suportar múltiplas sub-redes no servidor.

# Secondary subnet on the ens33 interface
auto ens33:1
iface ens33:1 inet static
    address 192.168.10.1
    netmask 255.255.255.0
    network 192.168.10.0

Essa configuração utiliza a interface ens33 existente, adicionando uma subinterface (ens33:1) com o IP da nova sub-rede.

Atualizar as Rotas

ip route add 192.168.10.0/24 via 192.168.1.1 dev ens33

Essa rota específica indica que o tráfego destinado à sub-rede 192.168.10.0/24 deve passar pelo gateway 192.168.1.1 via a interface ens33.

Adicionar outro objeto de sub-rede dentro do array "subnet4".

{
    "Dhcp4": {
        "interfaces-config": {
            "interfaces": ["ens33"]
        },
        "hosts-database": {
            "type": "mysql",
            "host": "localhost",
            "name": "kea",
            "user": "root",
            "password": "@1234"
        },
        "valid-lifetime": 7200,
        "subnet4": [
            {
                "subnet": "192.168.10.0/24",
                #"pools": [{"pool": "192.168.10.10 - 192.168.10.100"}],
                "option-data": [
                    {
                        "name": "subnet-mask",
                        "data": "255.255.255.0"
                    },
                    {
                        "name": "routers",
                        "data": "192.168.10.1"
                    },
                    {
                        "name": "domain-name-servers",
                        "data": "8.8.8.8, 192.168.x.x, 192.168.x.x"
                    }
                ]
            },
            {
                "subnet": "192.168.1.0/24",
                #"pools": [{"pool": "192.168.1.50 - 192.168.1.100"}],
                "option-data": [
                    {
                        "name": "subnet-mask",
                        "data": "255.255.255.0"
                    },
                    {
                        "name": "routers",
                        "data": "192.168.1.1"
                    },
                    {
                        "name": "domain-name-servers",
                        "data": "8.8.4.4, 1.1.1.1"
                    }
                ]
            }
        ]
    }
}