Post

Configurações Avançadas do BIND: Secundário, Chroot e Alta Disponibilidade

Configurações Avançadas do BIND: Secundário, Chroot e Alta Disponibilidade

Este é o sétimo artigo de nossa série sobre implementação e configuração do DNS BIND no Oracle Linux 9. Nos artigos anteriores, abordamos os conceitos fundamentais do DNS, a instalação e configuração básica, a configuração de zonas DNS, a implementação de views e DNS Split-Horizon, a segurança e hardening e o logging, monitoramento e troubleshooting. Agora, vamos explorar configurações avançadas do BIND.

Introdução

Uma infraestrutura DNS robusta vai além de um único servidor bem configurado. Para ambientes de produção, é essencial implementar redundância, isolamento de segurança, alta disponibilidade e integração com outros serviços.

Neste artigo, abordaremos configurações avançadas do BIND no Oracle Linux 9, incluindo a configuração de servidores secundários, implementação em ambiente chroot, estratégias de alta disponibilidade, integração com DHCP, políticas de resposta e muito mais.

Estas configurações avançadas são essenciais para ambientes corporativos e de provedores de serviço, onde a disponibilidade, segurança e desempenho do DNS são críticos para a operação dos negócios.

Configuração de Servidor DNS Secundário

Um servidor DNS secundário (slave) fornece redundância e balanceamento de carga, garantindo que o serviço DNS permaneça disponível mesmo se o servidor primário falhar.

Conceitos Fundamentais de Servidores Secundários

Um servidor secundário mantém cópias das zonas do servidor primário, atualizadas através de transferências de zona. Principais características:

  • Redundância: Fornece backup para o servidor primário
  • Balanceamento de carga: Distribui consultas DNS entre múltiplos servidores
  • Proximidade geográfica: Permite posicionar servidores mais próximos dos usuários
  • Transferência de zona: Mecanismo para sincronizar dados entre servidores

Planejamento da Infraestrutura

Antes de configurar servidores secundários, é importante planejar adequadamente:

  1. Topologia: Determine quantos servidores secundários são necessários e onde serão posicionados
  2. Conectividade: Garanta conectividade confiável entre servidores primário e secundários
  3. Segurança: Planeje como proteger as transferências de zona
  4. Notificações: Decida como os secundários serão notificados sobre alterações

Configuração do Servidor Primário

Para permitir transferências de zona para servidores secundários, configure o servidor primário:

1
2
# Editar named.conf no servidor primário
sudo vi /etc/named.conf

Adicione ou atualize as ACLs:

1
2
3
4
5
6
// ACLs
acl "dns_servers" {
    localhost;
    192.168.200.49;  // Servidor primário
    192.168.200.50;  // Servidor secundário
};

Configure as zonas para permitir transferências:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
zone "example.com" IN {
    type master;
    file "zones/example.com.zone";
    allow-transfer { dns_servers; };
    also-notify { 192.168.200.50; };
    notify yes;
};

zone "200.168.192.in-addr.arpa" IN {
    type master;
    file "zones/200.168.192.in-addr.arpa.zone";
    allow-transfer { dns_servers; };
    also-notify { 192.168.200.50; };
    notify yes;
};

Parâmetros importantes:

  • allow-transfer: Define quem pode solicitar transferências de zona
  • also-notify: Lista de servidores a notificar quando a zona é atualizada
  • notify: Habilita notificações automáticas

Verifique e recarregue a configuração:

1
2
sudo named-checkconf
sudo rndc reload

Configuração do Servidor Secundário

No servidor secundário, instale o BIND:

1
sudo dnf install bind bind-utils -y

Configure a estrutura de diretórios:

1
2
3
4
5
sudo mkdir -p /var/named/slaves
sudo chown named:named /var/named/slaves
sudo chmod 770 /var/named/slaves
sudo semanage fcontext -a -t named_cache_t "/var/named/slaves(/.*)?"
sudo restorecon -Rv /var/named/slaves

Configure o named.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// ACLs
acl "dns_servers" {
    localhost;
    192.168.200.49;  // Servidor primário
    192.168.200.50;  // Servidor secundário (este servidor)
};

options {
    directory "/var/named";
    
    listen-on port 53 { 
        127.0.0.1;
        192.168.200.50;  // IP deste servidor
    };
    listen-on-v6 port 53 { ::1; };
    
    allow-query { any; };
    recursion yes;
    allow-recursion { 
        localhost;
        192.168.200.0/24;  // Rede interna
    };
    
    // Configurações adicionais
    dnssec-validation auto;
    
    // Logging
    // ... (configuração de logging similar ao primário)
};

// Zonas
zone "example.com" IN {
    type slave;
    masters { 192.168.200.49; };
    file "slaves/example.com.zone";
};

zone "200.168.192.in-addr.arpa" IN {
    type slave;
    masters { 192.168.200.49; };
    file "slaves/200.168.192.in-addr.arpa.zone";
};

// Incluir zonas padrão
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

Parâmetros importantes:

  • type slave: Define a zona como secundária
  • masters: Lista de servidores primários para esta zona
  • file: Caminho onde a zona transferida será armazenada

Inicie e habilite o serviço:

1
sudo systemctl enable --now named

Configure o firewall:

1
2
sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --reload

Transferências de Zona Seguras com TSIG

Para proteger as transferências de zona, implemente TSIG (Transaction Signature):

Geração de Chave TSIG

No servidor primário:

1
2
3
4
5
# Gerar chave TSIG
sudo dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST xfer-key

# Extrair a chave
sudo cat Kxfer-key.*.private | grep Key | awk '{print $2}'

Configuração de TSIG no Servidor Primário

Adicione a definição da chave ao named.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Chave TSIG
key "xfer-key" {
    algorithm hmac-sha256;
    secret "a2xhc2Rqa2xhanNka2xqYWtsc2RqYWtsc2RqbGFrc2o=";  // Substitua pela chave gerada
};

// Configurar servidor secundário para usar a chave
server 192.168.200.50 {
    keys { xfer-key; };
};

// Atualizar zonas para usar a chave
zone "example.com" IN {
    type master;
    file "zones/example.com.zone";
    allow-transfer { key xfer-key; };
    also-notify { 192.168.200.50; };
    notify yes;
};

Configuração de TSIG no Servidor Secundário

Adicione a mesma definição de chave ao named.conf:

1
2
3
4
5
6
7
8
9
10
11
12
// Chave TSIG (mesma do primário)
key "xfer-key" {
    algorithm hmac-sha256;
    secret "a2xhc2Rqa2xhanNka2xqYWtsc2RqYWtsc2RqbGFrc2o=";  // Substitua pela chave gerada
};

// Configurar servidor primário para usar a chave
server 192.168.200.49 {
    keys { xfer-key; };
};

// Zonas (não é necessário modificar)

Verificação e Testes

Verifique se as transferências de zona estão funcionando:

1
2
3
4
5
6
7
8
9
10
# No servidor secundário
sudo rndc reload
sudo ls -la /var/named/slaves/

# Verificar logs
sudo grep "transfer" /var/log/named/general.log

# Testar resolução
dig @192.168.200.50 example.com
dig @192.168.200.50 -x 192.168.200.10
+---------------------+        +---------------------+
| Servidor Primário   |        | Servidor Secundário |
| (Master)            |        | (Slave)             |
| IP: 192.168.200.49  |        | IP: 192.168.200.50  |
+----------+----------+        +----------+----------+
           |                           ^
           | 1. Edita Zona             |
           |    (Incrementa Serial)    |
           V                           |
+----------+----------+                |
| named.conf:         |                |
| zone "example.com" {|                |
|   type master;      |                |
|   allow-transfer { |                |
|     key xfer-key;  |                |
|   };               |                |
|   also-notify {    |                |
|     192.168.200.50;|                |
|   };               |                |
| }                   |                |
+----------+----------+                |
           |                           |
           | 2. NOTIFY (via UDP/53)    |
           |-------------------------->|
           |                           |
           |                           | 3. Recebe NOTIFY
           |                           |    Verifica Serial
           |                           |
           | <-------------------------| 4. Solicita SOA
           |                           |
           | 5. Responde SOA           |-->
           |                           |
           |                           | 6. Compara Serial
           |                           |    (Serial Primário > Serial Local?)
           |                           |       | Sim
           |                           |       V
           | <-------------------------| 7. Solicita Transferência
           |                           |    (AXFR/IXFR + TSIG)
           |                           |
           | 8. Verifica TSIG e        |-->
           |    Envia Zona             |
           |    (+ TSIG)               |
           |                           |
           |                           | 9. Verifica TSIG
           |                           |    Atualiza Zona Local
           |                           |    (/var/named/slaves/...)

Figura 1: Fluxo Detalhado de Notificação e Transferência de Zona (Primário/Secundário com TSIG)

Configuração com Views

Configuração com Views

Se você estiver usando views (como configurado em artigos anteriores), a configuração do servidor secundário deve refletir a mesma estrutura:

Servidor Primário com Views

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
view "internal" {
    match-clients { internal_clients; };
    
    zone "example.com" IN {
        type master;
        file "zones/internal/example.com.zone";
        allow-transfer { key xfer-key; };
        also-notify { 192.168.200.50; };
        notify yes;
    };
    
    // Outras zonas...
};

view "external" {
    match-clients { any; };
    
    zone "example.com" IN {
        type master;
        file "zones/external/example.com.zone";
        allow-transfer { key xfer-key; };
        also-notify { 192.168.200.50; };
        notify yes;
    };
    
    // Outras zonas...
};

Servidor Secundário com Views

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
view "internal" {
    match-clients { internal_clients; };
    
    zone "example.com" IN {
        type slave;
        masters { 192.168.200.49; };
        file "slaves/internal/example.com.zone";
    };
    
    // Outras zonas...
};

view "external" {
    match-clients { any; };
    
    zone "example.com" IN {
        type slave;
        masters { 192.168.200.49; };
        file "slaves/external/example.com.zone";
    };
    
    // Outras zonas...
};

Crie os diretórios necessários:

1
2
3
4
5
sudo mkdir -p /var/named/slaves/{internal,external}
sudo chown -R named:named /var/named/slaves
sudo chmod -R 770 /var/named/slaves
sudo semanage fcontext -a -t named_cache_t "/var/named/slaves(/.*)?"
sudo restorecon -Rv /var/named/slaves

Implementação de BIND em Ambiente Chroot

Executar o BIND em um ambiente chroot adiciona uma camada extra de segurança, isolando o processo do restante do sistema.

Conceitos de Chroot

O chroot (change root) é uma operação que altera o diretório raiz aparente para um processo e seus filhos, criando um ambiente isolado:

  • Isolamento: O processo não pode acessar arquivos fora do ambiente chroot
  • Mitigação: Limita o impacto de uma possível exploração do serviço
  • Contenção: Restringe o acesso a recursos do sistema

Métodos de Implementação

Existem duas abordagens principais para implementar o BIND em chroot:

  1. Usando o pacote bind-chroot: Método mais simples, com estrutura pré-configurada
  2. Configuração manual: Oferece mais controle, mas requer mais trabalho

Método 1: Usando o Pacote bind-chroot

Instalação

1
sudo dnf install bind bind-utils bind-chroot -y

Configuração

O pacote bind-chroot cria automaticamente a estrutura de diretórios em /var/named/chroot/:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Parar o serviço BIND
sudo systemctl stop named

# Verificar a estrutura criada
ls -la /var/named/chroot/

# Copiar arquivos de configuração
sudo cp -r /etc/named* /var/named/chroot/etc/

# Copiar zonas
sudo mkdir -p /var/named/chroot/var/named/zones
sudo cp -r /var/named/zones/* /var/named/chroot/var/named/zones/

# Criar diretório para logs
sudo mkdir -p /var/named/chroot/var/log/named
sudo chown named:named /var/named/chroot/var/log/named

# Configurar contextos SELinux
sudo semanage fcontext -a -t named_conf_t "/var/named/chroot/etc/named(/.*)?"
sudo semanage fcontext -a -t named_zone_t "/var/named/chroot/var/named/zones(/.*)?"
sudo semanage fcontext -a -t named_log_t "/var/named/chroot/var/log/named(/.*)?"
sudo restorecon -Rv /var/named/chroot

# Desabilitar o serviço named padrão e habilitar o named-chroot
sudo systemctl disable named
sudo systemctl enable --now named-chroot

Verificação

1
2
3
4
5
# Verificar status do serviço
sudo systemctl status named-chroot

# Verificar processo
ps aux | grep named

Verificação

1
2
3
4
5
# Verificar status do serviço
sudo systemctl status named-chroot

# Verificar processo
ps aux | grep named
+--------------------------------+      +--------------------------------+
| Método 1: bind-chroot Pkg      |      | Método 2: Chroot Manual        |
+--------------------------------+      +--------------------------------+
| /var/named/chroot/             |      | /chroot/named/ (ou outro)      |
|  |-- etc/ (Copiado de /etc)    |      |  |-- etc/ (Copiado de /etc)    |
|  |-- var/                      |      |  |-- var/                      |
|  |   |-- named/ (Zonas, etc.) |      |  |   |-- named/ (Zonas, etc.) |
|  |   |-- run/named/           |      |  |   |-- run/named/           |
|  |   `-- log/named/           |      |  |   `-- log/named/           |
|  |-- dev/ (null, random)      |      |  |-- dev/ (null, random)      |
|  |-- usr/sbin/ (named binário)|      |  |-- usr/sbin/ (named binário)|
|  `-- lib64/ (Bibliotecas)     |      |  `-- lib64/ (Bibliotecas)     |
+--------------------------------+      +--------------------------------+
| Vantagens:                     |      | Vantagens:                     |
| - Mais simples                 |      | - Maior controle               |
| - Estrutura pré-definida       |      | - Flexibilidade de localização |
| - Integração com systemd       |      +--------------------------------+
| Desvantagens:                  |      | Desvantagens:                  |
| - Menos flexível               |      | - Mais complexo                |
| - Depende do pacote            |      | - Requer cópia manual de libs  |
+--------------------------------+      +--------------------------------+

Figura 2: Comparação entre Estruturas de Chroot (bind-chroot vs. Manual)

O processo deve mostrar o caminho chroot.

Criação da Estrutura de Diretórios

1
2
3
4
5
6
7
8
9
10
11
# Criar estrutura de diretórios
sudo mkdir -p /chroot/named/{etc,var/named,var/run/named,var/log/named,dev}

# Criar dispositivos necessários
sudo mknod /chroot/named/dev/null c 1 3
sudo mknod /chroot/named/dev/random c 1 8
sudo chmod 666 /chroot/named/dev/{null,random}

# Configurar permissões
sudo chown -R named:named /chroot/named/var/{named,run/named,log/named}
sudo chmod 770 /chroot/named/var/{named,run/named,log/named}

Cópia de Arquivos e Bibliotecas

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Copiar arquivos de configuração
sudo cp -r /etc/named* /chroot/named/etc/

# Copiar zonas
sudo mkdir -p /chroot/named/var/named/zones
sudo cp -r /var/named/zones/* /chroot/named/var/named/zones/

# Copiar bibliotecas necessárias
sudo mkdir -p /chroot/named/lib64
for lib in $(ldd /usr/sbin/named | awk '{print $3}' | grep -v "^$"); do
    sudo cp $lib /chroot/named$(dirname $lib)
done

# Copiar o binário
sudo cp /usr/sbin/named /chroot/named/usr/sbin/

Configuração do SELinux

1
2
3
4
5
6
# Configurar contextos SELinux
sudo semanage fcontext -a -t named_conf_t "/chroot/named/etc/named(/.*)?"
sudo semanage fcontext -a -t named_zone_t "/chroot/named/var/named/zones(/.*)?"
sudo semanage fcontext -a -t named_log_t "/chroot/named/var/log/named(/.*)?"
sudo semanage fcontext -a -t named_var_run_t "/chroot/named/var/run/named(/.*)?"
sudo restorecon -Rv /chroot/named

Criação de Unidade Systemd

1
sudo vi /etc/systemd/system/named-chroot-custom.service

Adicione:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=Berkeley Internet Name Domain (DNS) with custom chroot
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/sbin/named -u named -t /chroot/named -c /etc/named.conf
ExecReload=/usr/sbin/rndc reload
ExecStop=/usr/sbin/rndc stop
Restart=on-failure

[Install]
WantedBy=multi-user.target

Inicie e habilite o serviço:

1
2
3
sudo systemctl daemon-reload
sudo systemctl disable named
sudo systemctl enable --now named-chroot-custom

Considerações para Ambiente Chroot

Logs e Rotação

Configure o rsyslog para enviar logs para o ambiente chroot:

1
sudo vi /etc/rsyslog.d/named-chroot.conf

Adicione:

1
2
3
# Enviar logs do named para o ambiente chroot
if $programname == 'named' then /chroot/named/var/log/named/named.log
& stop

Configure o logrotate:

1
sudo vi /etc/logrotate.d/named-chroot

Adicione:

1
2
3
4
5
6
7
8
9
10
11
12
13
/chroot/named/var/log/named/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 0640 named named
    sharedscripts
    postrotate
        /usr/bin/systemctl reload named-chroot.service > /dev/null 2>&1 || true
    endscript
}

Atualizações e Manutenção

Ao atualizar o BIND, você precisará atualizar também o ambiente chroot:

1
2
3
4
5
6
7
8
9
10
# Após atualizar o BIND
sudo cp /usr/sbin/named /chroot/named/usr/sbin/

# Atualizar bibliotecas
for lib in $(ldd /usr/sbin/named | awk '{print $3}' | grep -v "^$"); do
    sudo cp $lib /chroot/named$(dirname $lib)
done

# Reiniciar o serviço
sudo systemctl restart named-chroot-custom

Configuração de Alta Disponibilidade

Para ambientes críticos, a alta disponibilidade do DNS é essencial. Vamos explorar diferentes estratégias.

Conceitos de Alta Disponibilidade para DNS

A alta disponibilidade para DNS envolve:

  • Redundância: Múltiplos servidores DNS
  • Distribuição geográfica: Servidores em diferentes locais
  • Balanceamento de carga: Distribuição de consultas
  • Failover automático: Recuperação automática de falhas

Estratégia 1: Múltiplos Servidores NS

A estratégia mais básica é configurar múltiplos registros NS para o domínio:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Exemplo de zona com múltiplos NS
$TTL 86400
@       IN SOA  ns1.example.com. admin.example.com. (
                    2025052301  ; Serial
                    10800       ; Refresh (3 hours)
                    3600        ; Retry (1 hour)
                    604800      ; Expire (1 week)
                    86400 )     ; Minimum TTL (1 day)

        IN NS   ns1.example.com.
        IN NS   ns2.example.com.
        IN NS   ns3.example.com.

ns1     IN A    192.168.200.49
ns2     IN A    192.168.200.50
ns3     IN A    192.168.200.51

Certifique-se de que todos os servidores NS listados estejam configurados corretamente como primário ou secundários.

Estratégia 2: Anycast DNS

O Anycast permite que múltiplos servidores compartilhem o mesmo endereço IP, com o roteamento direcionando consultas para o servidor mais próximo:

  1. Configuração de rede: Configure o mesmo endereço IP em múltiplos servidores
  2. Configuração de roteamento: Use BGP para anunciar o endereço
  3. Configuração do BIND: Idêntica em todos os servidores

Esta é uma configuração avançada que requer conhecimentos de roteamento e BGP.

Estratégia 3: Keepalived com IP Virtual

O Keepalived permite implementar um IP virtual que flutua entre servidores:

Instalação do Keepalived

1
sudo dnf install keepalived -y

Configuração no Servidor Primário

1
sudo vi /etc/keepalived/keepalived.conf

Adicione:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
vrrp_script check_named {
    script "/usr/bin/systemctl is-active named"
    interval 2
    weight 2
}

vrrp_instance VI_DNS {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 101
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass dns_secret
    }
    virtual_ipaddress {
        192.168.200.100/24
    }
    track_script {
        check_named
    }
}

Configuração no Servidor Secundário

1
sudo vi /etc/keepalived/keepalived.conf

Adicione:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
vrrp_script check_named {
    script "/usr/bin/systemctl is-active named"
    interval 2
    weight 2
}

vrrp_instance VI_DNS {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass dns_secret
    }
    virtual_ipaddress {
        192.168.200.100/24
    }
    track_script {
        check_named
    }
}

Iniciar e Habilitar Keepalived

1
sudo systemctl enable --now keepalived

Configuração do BIND para o IP Virtual

Em ambos os servidores, configure o BIND para escutar no IP virtual:

1
2
3
4
5
6
7
8
options {
    listen-on port 53 { 
        127.0.0.1;
        192.168.200.49;  // IP real do servidor primário
        192.168.200.100; // IP virtual
    };
    // ...
};

Estratégia 4: DNS Dinâmico com Atualizações Automáticas

Para ambientes dinâmicos, configure atualizações automáticas de DNS:

Configuração do Servidor Primário

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Gerar chave para atualizações dinâmicas
sudo dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST update-key

// Extrair a chave
sudo cat Kupdate-key.*.private | grep Key | awk '{print $2}'

// Configurar named.conf
key "update-key" {
    algorithm hmac-sha256;
    secret "a2xhc2Rqa2xhanNka2xqYWtsc2RqYWtsc2RqbGFrc2o=";  // Substitua pela chave gerada
};

zone "example.com" IN {
    type master;
    file "zones/example.com.zone";
    allow-update { key update-key; };
    // ...
};

Script de Atualização Automática

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
# Script para atualizar registro DNS dinamicamente

# Configuração
DOMAIN="example.com"
HOSTNAME="service1"
SERVER="192.168.200.49"
TTL=300
KEY_FILE="/path/to/Kupdate-key.+007+12345.private"

# Obter IP atual
CURRENT_IP=$(ip addr show eth0 | grep 'inet ' | awk '{print $2}' | cut -d/ -f1)

# Atualizar DNS
nsupdate -k $KEY_FILE << EOF
server $SERVER
zone $DOMAIN
update delete $HOSTNAME.$DOMAIN A
update add $HOSTNAME.$DOMAIN $TTL A $CURRENT_IP
send
EOF

Este script pode ser executado periodicamente via cron ou quando o IP muda.

Testes de Failover

Para verificar a configuração de alta disponibilidade:

1
2
3
4
5
6
7
8
9
10
11
# Teste básico de resolução
dig @192.168.200.100 example.com

# Simular falha no servidor primário
sudo systemctl stop named  # No servidor primário

# Verificar se o IP virtual migrou
ip addr show eth0  # No servidor secundário

# Testar resolução novamente
dig @192.168.200.100 example.com  # Deve resolver através do secundário

Integração com DHCP para Atualizações Dinâmicas

A integração do BIND com o DHCP permite atualizações automáticas de registros DNS quando endereços IP são atribuídos.

Conceitos de Integração DNS-DHCP

A integração DNS-DHCP oferece:

  • Atualizações automáticas: Registros DNS atualizados quando IPs são atribuídos
  • Consistência: Garante que registros DNS correspondam a atribuições DHCP
  • Gerenciamento centralizado: Simplifica a administração

Instalação do ISC DHCP Server

1
sudo dnf install dhcp-server -y

Geração de Chave para Atualizações Dinâmicas

1
2
3
4
5
# Gerar chave
sudo dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST dhcp-key

# Extrair a chave
sudo cat Kdhcp-key.*.private | grep Key | awk '{print $2}'

Configuração do BIND para Atualizações Dinâmicas

1
2
# Editar named.conf
sudo vi /etc/named.conf

Adicione:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Chave para atualizações dinâmicas do DHCP
key "dhcp-key" {
    algorithm hmac-sha256;
    secret "a2xhc2Rqa2xhanNka2xqYWtsc2RqYWtsc2RqbGFrc2o=";  // Substitua pela chave gerada
};

// Configurar zona para permitir atualizações
zone "example.com" IN {
    type master;
    file "zones/example.com.zone";
    allow-update { key dhcp-key; };
    // ...
};

zone "200.168.192.in-addr.arpa" IN {
    type master;
    file "zones/200.168.192.in-addr.arpa.zone";
    allow-update { key dhcp-key; };
    // ...
};

Recarregue a configuração:

1
sudo rndc reload

Configuração do DHCP Server

1
2
# Editar dhcpd.conf
sudo vi /etc/dhcp/dhcpd.conf

Adicione:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# Configuração global
option domain-name "example.com";
option domain-name-servers 192.168.200.49, 192.168.200.50;
default-lease-time 600;
max-lease-time 7200;
ddns-update-style interim;
update-static-leases on;

# Chave para atualizações dinâmicas
key dhcp-key {
    algorithm hmac-sha256;
    secret "a2xhc2Rqa2xhanNka2xqYWtsc2RqYWtsc2RqbGFrc2o=";  // Substitua pela chave gerada
};

# Configuração de zona
zone example.com. {
    primary 192.168.200.49;
    key dhcp-key;
}

zone 200.168.192.in-addr.arpa. {
    primary 192.168.200.49;
    key dhcp-key;
}

# Subnet
subnet 192.168.200.0 netmask 255.255.255.0 {
    range 192.168.200.150 192.168.200.200;
    option routers 192.168.200.1;
    option broadcast-address 192.168.200.255;
    ddns-domainname "example.com.";
    ddns-rev-domainname "in-addr.arpa.";
}

# Host estático com atualização DNS
host workstation1 {
    hardware ethernet 00:11:22:33:44:55;
    fixed-address 192.168.200.101;
    ddns-hostname "workstation1";
}

Inicie e habilite o serviço DHCP:

1
sudo systemctl enable --now dhcpd

Verificação da Integração

1
2
3
4
5
6
7
8
9
10
11
12
# Verificar logs do DHCP
sudo tail -f /var/log/messages | grep dhcpd

# Verificar logs do BIND
sudo tail -f /var/log/named/general.log

# Verificar atualizações de zona
sudo rndc dumpdb -zones
cat /var/named/data/named_dump.db

# Testar resolução de um host atribuído via DHCP
dig @192.168.200.49 workstation1.example.com

Implementação de Response Policy Zones (RPZ)

As RPZs permitem bloquear ou redirecionar consultas DNS para domínios maliciosos ou indesejados.

Conceitos de RPZ

As RPZs funcionam como “listas negras” para DNS:

  • Filtragem de conteúdo: Bloquear domínios maliciosos ou indesejados
  • Redirecionamento: Redirecionar consultas para outros destinos
  • Políticas personalizadas: Aplicar diferentes políticas para diferentes clientes

Configuração Básica de RPZ

1
2
# Editar named.conf
sudo vi /etc/named.conf

Adicione:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Configuração de RPZ
options {
    // ...
    response-policy {
        zone "rpz.example.com";
    };
};

// Zona RPZ
zone "rpz.example.com" IN {
    type master;
    file "zones/rpz.example.com.zone";
    allow-query { none; };
    allow-transfer { none; };
};

Crie o arquivo de zona RPZ:

1
sudo vi /var/named/zones/rpz.example.com.zone

Adicione:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$TTL 86400
@       IN SOA  localhost. root.localhost. (
                    2025052301  ; Serial
                    10800       ; Refresh (3 hours)
                    3600        ; Retry (1 hour)
                    604800      ; Expire (1 week)
                    86400 )     ; Minimum TTL (1 day)

        IN NS   localhost.

; Bloquear domínios maliciosos
malware.example.net        CNAME   .
*.malware.example.net      CNAME   .

; Redirecionar domínios
redirect.example.org       CNAME   blocked.example.com.
*.redirect.example.org     CNAME   blocked.example.com.

; Bloquear endereços IP específicos
32.3.2.1.in-addr.arpa      CNAME   .

Defina as ações:

  • CNAME .: Retorna NXDOMAIN (domínio não existe)
  • CNAME *.: Retorna NODATA (domínio existe, mas sem registros do tipo solicitado)
  • CNAME example.com.: Redireciona para outro domínio

Configuração Avançada de RPZ

Para configurações mais avançadas, você pode usar múltiplas zonas RPZ com diferentes políticas:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
options {
    // ...
    response-policy {
        zone "rpz-malware.example.com" policy given;
        zone "rpz-adult.example.com" policy given;
        zone "rpz-custom.example.com" policy given;
    };
};

// Zonas RPZ
zone "rpz-malware.example.com" IN {
    type master;
    file "zones/rpz-malware.example.com.zone";
    allow-query { none; };
};

zone "rpz-adult.example.com" IN {
    type master;
    file "zones/rpz-adult.example.com.zone";
    allow-query { none; };
};

zone "rpz-custom.example.com" IN {
    type master;
    file "zones/rpz-custom.example.com.zone";
    allow-query { none; };
};

Integração com Feeds de Reputação

Você pode automatizar a atualização de RPZs com feeds de reputação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash
# Script para atualizar RPZ com feed de reputação

# Configuração
RPZ_ZONE="rpz-malware.example.com"
RPZ_FILE="/var/named/zones/rpz-malware.example.com.zone"
FEED_URL="https://example.com/malware-domains.txt"
TEMP_FILE="/tmp/malware-domains.txt"

# Baixar feed
curl -s $FEED_URL -o $TEMP_FILE

# Criar cabeçalho de zona
cat > $RPZ_FILE << EOF
\$TTL 86400
@       IN SOA  localhost. root.localhost. (
                    $(date +%Y%m%d01)  ; Serial
                    10800       ; Refresh (3 hours)
                    3600        ; Retry (1 hour)
                    604800      ; Expire (1 week)
                    86400 )     ; Minimum TTL (1 day)

        IN NS   localhost.

EOF

# Processar feed e adicionar à zona
cat $TEMP_FILE | grep -v "^#" | while read domain; do
    echo "$domain CNAME ." >> $RPZ_FILE
    echo "*.$domain CNAME ." >> $RPZ_FILE
done

# Recarregar zona
rndc reload $RPZ_ZONE

# Limpar
rm $TEMP_FILE

Verificação de RPZ

1
2
3
4
5
# Testar bloqueio
dig @192.168.200.49 malware.example.net

# Verificar logs
sudo grep "rpz" /var/log/named/general.log

Estratégias de Backup e Recuperação

Um plano de backup e recuperação é essencial para garantir a continuidade do serviço DNS.

Backup de Configuração e Zonas

Script de Backup Completo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash
# Script de backup completo para servidor DNS

# Configuração
BACKUP_DIR="/backup/dns"
DATE=$(date +%Y%m%d)
BACKUP_FILE="$BACKUP_DIR/dns_backup_$DATE.tar.gz"
CONFIG_DIR="/etc/named"
ZONES_DIR="/var/named/zones"
CHROOT_DIR="/var/named/chroot"  # Se estiver usando chroot

# Criar diretório de backup
mkdir -p $BACKUP_DIR

# Backup de configuração e zonas
tar -czf $BACKUP_FILE $CONFIG_DIR $ZONES_DIR

# Backup de chroot (se aplicável)
if [ -d "$CHROOT_DIR" ]; then
    tar -czf "$BACKUP_DIR/chroot_backup_$DATE.tar.gz" $CHROOT_DIR
fi

# Dump de zonas
for zone in $(grep "zone " /etc/named.conf | grep -v "^//" | awk '{print $2}' | tr -d '"' | tr -d ' '); do
    if [ "$zone" != "." ] && [ "$zone" != "localhost" ] && [ "$zone" != "0.0.127.in-addr.arpa" ]; then
        rndc dumpdb -zones
        gzip -c /var/named/data/named_dump.db > "$BACKUP_DIR/zones_dump_$DATE.gz"
        break
    fi
done

# Manter apenas os últimos 30 backups
find $BACKUP_DIR -name "dns_backup_*.tar.gz" -type f -mtime +30 -delete
find $BACKUP_DIR -name "chroot_backup_*.tar.gz" -type f -mtime +30 -delete
find $BACKUP_DIR -name "zones_dump_*.gz" -type f -mtime +30 -delete

echo "Backup concluído: $BACKUP_FILE"

Backup Remoto

Para maior segurança, envie backups para um servidor remoto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
# Script para enviar backup para servidor remoto

# Configuração
BACKUP_DIR="/backup/dns"
DATE=$(date +%Y%m%d)
BACKUP_FILE="dns_backup_$DATE.tar.gz"
REMOTE_USER="backup"
REMOTE_HOST="backup-server.example.com"
REMOTE_DIR="/backup/dns"

# Enviar backup
scp $BACKUP_DIR/$BACKUP_FILE $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/

# Verificar status
if [ $? -eq 0 ]; then
    echo "Backup enviado com sucesso para $REMOTE_HOST"
else
    echo "Erro ao enviar backup para $REMOTE_HOST"
    # Enviar alerta
    mail -s "Erro no backup DNS" admin@example.com << EOF
Falha ao enviar backup DNS para servidor remoto.
Data: $(date)
Arquivo: $BACKUP_FILE
EOF
fi

Procedimentos de Recuperação

Recuperação de Configuração e Zonas

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/bin/bash
# Script para recuperação de servidor DNS

# Configuração
BACKUP_DIR="/backup/dns"
DATE=$1  # Data do backup a ser restaurado (formato YYYYMMDD)

if [ -z "$DATE" ]; then
    echo "Uso: $0 YYYYMMDD"
    echo "Backups disponíveis:"
    ls -1 $BACKUP_DIR/dns_backup_*.tar.gz | sed 's/.*dns_backup_\([0-9]\{8\}\).tar.gz/\1/'
    exit 1
fi

BACKUP_FILE="$BACKUP_DIR/dns_backup_$DATE.tar.gz"

if [ ! -f "$BACKUP_FILE" ]; then
    echo "Backup não encontrado: $BACKUP_FILE"
    exit 1
fi

# Parar serviço
sudo systemctl stop named

# Backup da configuração atual
sudo tar -czf "/tmp/dns_config_before_restore_$(date +%Y%m%d%H%M%S).tar.gz" /etc/named /var/named/zones

# Restaurar backup
sudo tar -xzf $BACKUP_FILE -C /

# Verificar configuração
sudo named-checkconf
if [ $? -ne 0 ]; then
    echo "Erro na configuração restaurada. Reverta manualmente."
    exit 1
fi

# Verificar zonas
for zone in $(grep "zone " /etc/named.conf | grep -v "^//" | awk '{print $2}' | tr -d '"' | tr -d ' '); do
    if [ "$zone" != "." ] && [ "$zone" != "localhost" ] && [ "$zone" != "0.0.127.in-addr.arpa" ]; then
        file=$(grep -A10 "zone \"$zone\"" /etc/named.conf | grep "file" | head -1 | awk '{print $2}' | tr -d '"' | tr -d ';')
        if [ -n "$file" ]; then
            sudo named-checkzone $zone $file
            if [ $? -ne 0 ]; then
                echo "Erro na zona $zone. Reverta manualmente."
                exit 1
            fi
        fi
    fi
done

# Iniciar serviço
sudo systemctl start named

echo "Restauração concluída com sucesso."

Recuperação de Desastre

Para recuperação em um novo servidor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/bash
# Script para recuperação em novo servidor

# Configuração
BACKUP_FILE=$1  # Caminho completo do arquivo de backup

if [ -z "$BACKUP_FILE" ] || [ ! -f "$BACKUP_FILE" ]; then
    echo "Uso: $0 caminho_do_backup"
    exit 1
fi

# Instalar pacotes necessários
sudo dnf install bind bind-utils -y

# Parar serviço
sudo systemctl stop named

# Criar estrutura de diretórios
sudo mkdir -p /var/named/zones
sudo chown -R root:named /var/named/zones
sudo chmod -R 750 /var/named/zones

# Restaurar backup
sudo tar -xzf $BACKUP_FILE -C /

# Configurar SELinux
sudo semanage fcontext -a -t named_conf_t "/etc/named(/.*)?"
sudo semanage fcontext -a -t named_zone_t "/var/named/zones(/.*)?"
sudo restorecon -Rv /etc/named /var/named/zones

# Verificar configuração
sudo named-checkconf
if [ $? -ne 0 ]; then
    echo "Erro na configuração restaurada."
    exit 1
fi

# Iniciar serviço
sudo systemctl enable --now named

echo "Recuperação concluída. Verifique o funcionamento do servidor."

Automação com Ansible

O Ansible é uma ferramenta poderosa para automação de infraestrutura, incluindo servidores DNS.

Estrutura do Playbook

Crie uma estrutura de diretórios para o playbook:

1
mkdir -p dns-ansible/{tasks,templates,vars,files,handlers}

Playbook Principal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# dns-ansible/dns.yml
---
- name: Configurar Servidores DNS BIND
  hosts: dns_servers
  become: yes
  vars_files:
    - vars/main.yml
  
  tasks:
    - name: Incluir tarefas de instalação
      include_tasks: tasks/install.yml
    
    - name: Incluir tarefas de configuração
      include_tasks: tasks/configure.yml
    
    - name: Incluir tarefas específicas para servidor primário
      include_tasks: tasks/primary.yml
      when: dns_role == "primary"
    
    - name: Incluir tarefas específicas para servidor secundário
      include_tasks: tasks/secondary.yml
      when: dns_role == "secondary"
    
    - name: Incluir tarefas de segurança
      include_tasks: tasks/security.yml
    
    - name: Incluir tarefas de logging
      include_tasks: tasks/logging.yml
  
  handlers:
    - import_tasks: handlers/main.yml

Variáveis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# dns-ansible/vars/main.yml
---
# Configuração geral
dns_listen_ipv4:
  - "127.0.0.1"
  - "{{ ansible_default_ipv4.address }}"
dns_allow_query:
  - "localhost"
  - "192.168.200.0/24"

# Configuração de servidores
dns_primary_server: "192.168.200.49"
dns_secondary_servers:
  - "192.168.200.50"

# Zonas
dns_zones:
  - name: "example.com"
    type: "{{ 'master' if dns_role == 'primary' else 'slave' }}"
    file: "{{ 'zones/example.com.zone' if dns_role == 'primary' else 'slaves/example.com.zone' }}"
    masters: "{{ [dns_primary_server] if dns_role == 'secondary' else [] }}"
  - name: "200.168.192.in-addr.arpa"
    type: "{{ 'master' if dns_role == 'primary' else 'slave' }}"
    file: "{{ 'zones/200.168.192.in-addr.arpa.zone' if dns_role == 'primary' else 'slaves/200.168.192.in-addr.arpa.zone' }}"
    masters: "{{ [dns_primary_server] if dns_role == 'secondary' else [] }}"

# Configuração de TSIG
dns_use_tsig: true
dns_tsig_key_name: "xfer-key"
dns_tsig_key_algorithm: "hmac-sha256"
dns_tsig_key_secret: "a2xhc2Rqa2xhanNka2xqYWtsc2RqYWtsc2RqbGFrc2o="  # Substitua por uma chave segura

# Configuração de chroot
dns_use_chroot: false

# Configuração de logging
dns_log_dir: "/var/log/named"
dns_log_versions: 5
dns_log_size: "20m"

Tarefas de Instalação

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# dns-ansible/tasks/install.yml
---
- name: Instalar pacotes BIND
  dnf:
    name:
      - bind
      - bind-utils
      - "{{ 'bind-chroot' if dns_use_chroot else '' }}"
    state: present

- name: Criar diretórios para zonas
  file:
    path: "/var/named/{{ item }}"
    state: directory
    owner: root
    group: named
    mode: '0750'
  loop:
    - zones
    - "{{ 'slaves' if dns_role == 'secondary' else '' }}"
    - data
  when: item != ""

- name: Criar diretório para logs
  file:
    path: "{{ dns_log_dir }}"
    state: directory
    owner: named
    group: named
    mode: '0770'

- name: Configurar contextos SELinux
  sefcontext:
    target: "{{ item.target }}"
    setype: "{{ item.setype }}"
    state: present
  loop:
    - { target: '/var/named/zones(/.*)?', setype: 'named_zone_t' }
    - { target: '/var/named/slaves(/.*)?', setype: 'named_cache_t' }
    - { target: '{{ dns_log_dir }}(/.*)?', setype: 'named_log_t' }
    - { target: '/var/named/data(/.*)?', setype: 'named_cache_t' }
  notify: Restaurar contextos SELinux

Tarefas de Configuração

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# dns-ansible/tasks/configure.yml
---
- name: Configurar named.conf
  template:
    src: named.conf.j2
    dest: /etc/named.conf
    owner: root
    group: named
    mode: '0640'
  notify: Reiniciar BIND

- name: Configurar logrotate para BIND
  template:
    src: named-logrotate.j2
    dest: /etc/logrotate.d/named
    owner: root
    group: root
    mode: '0644'

- name: Configurar firewall
  firewalld:
    service: dns
    permanent: yes
    state: enabled
  notify: Recarregar firewall

- name: Habilitar e iniciar serviço BIND
  systemd:
    name: "{{ 'named-chroot' if dns_use_chroot else 'named' }}"
    enabled: yes
    state: started

Tarefas para Servidor Primário

1
2
3
4
5
6
7
8
9
10
11
12
# dns-ansible/tasks/primary.yml
---
- name: Copiar arquivos de zona
  template:
    src: "zones/{{ item.name }}.zone.j2"
    dest: "/var/named/{{ item.file }}"
    owner: root
    group: named
    mode: '0640'
  loop: "{{ dns_zones }}"
  when: item.type == 'master'
  notify: Recarregar BIND

Tarefas para Servidor Secundário

1
2
3
4
5
6
7
8
9
10
# dns-ansible/tasks/secondary.yml
---
- name: Garantir que o diretório slaves existe
  file:
    path: /var/named/slaves
    state: directory
    owner: named
    group: named
    mode: '0770'
  notify: Restaurar contextos SELinux

Tarefas de Segurança

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# dns-ansible/tasks/security.yml
---
- name: Configurar permissões de arquivos
  file:
    path: "{{ item.path }}"
    owner: "{{ item.owner }}"
    group: "{{ item.group }}"
    mode: "{{ item.mode }}"
  loop:
    - { path: '/etc/named.conf', owner: 'root', group: 'named', mode: '0640' }
    - { path: '/var/named', owner: 'root', group: 'named', mode: '0750' }
    - { path: '/var/named/zones', owner: 'root', group: 'named', mode: '0750' }
    - { path: '/var/named/data', owner: 'named', group: 'named', mode: '0770' }
    - { path: '{{ dns_log_dir }}', owner: 'named', group: 'named', mode: '0770' }

- name: Configurar SELinux booleans
  seboolean:
    name: "{{ item.name }}"
    state: "{{ item.state }}"
    persistent: yes
  loop:
    - { name: 'named_write_master_zones', state: "{{ 'on' if dns_role == 'primary' else 'off' }}" }

Tarefas de Logging

1
2
3
4
5
6
7
8
9
10
# dns-ansible/tasks/logging.yml
---
- name: Garantir que o diretório de logs existe
  file:
    path: "{{ dns_log_dir }}"
    state: directory
    owner: named
    group: named
    mode: '0770'
  notify: Restaurar contextos SELinux

Handlers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# dns-ansible/handlers/main.yml
---
- name: Restaurar contextos SELinux
  command: restorecon -Rv /var/named /etc/named.conf {{ dns_log_dir }}
  listen: Restaurar contextos SELinux

- name: Reiniciar BIND
  systemd:
    name: "{{ 'named-chroot' if dns_use_chroot else 'named' }}"
    state: restarted
  listen: Reiniciar BIND

- name: Recarregar BIND
  command: rndc reload
  listen: Recarregar BIND

- name: Recarregar firewall
  command: firewall-cmd --reload
  listen: Recarregar firewall

Templates

Template para named.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# dns-ansible/templates/named.conf.j2
// named.conf gerado por Ansible
options {
    directory "/var/named";
    
    listen-on port 53 { 
        {% for ip in dns_listen_ipv4 %}
        {{ ip }};
        {% endfor %}
    };
    listen-on-v6 port 53 { ::1; };
    
    allow-query { 
        {% for net in dns_allow_query %}
        {{ net }};
        {% endfor %}
    };
    
    recursion yes;
    allow-recursion { 
        {% for net in dns_allow_query %}
        {{ net }};
        {% endfor %}
    };
    
    dnssec-validation auto;
    
    // Logging configuration
    logging {
        channel general_log {
            file "{{ dns_log_dir }}/general.log" versions {{ dns_log_versions }} size {{ dns_log_size }};
            severity info;
            print-time yes;
            print-severity yes;
            print-category yes;
        };
        
        channel security_log {
            file "{{ dns_log_dir }}/security.log" versions {{ dns_log_versions }} size {{ dns_log_size }};
            severity info;
            print-time yes;
            print-severity yes;
            print-category yes;
        };
        
        channel query_log {
            file "{{ dns_log_dir }}/query.log" versions {{ dns_log_versions }} size {{ dns_log_size }};
            severity info;
            print-time yes;
        };
        
        channel error_log {
            file "{{ dns_log_dir }}/error.log" versions {{ dns_log_versions }} size {{ dns_log_size }};
            severity error;
            print-time yes;
            print-severity yes;
            print-category yes;
        };
        
        category default { general_log; };
        category general { general_log; };
        category security { security_log; };
        category queries { query_log; };
        category client { general_log; };
        category network { general_log; };
        category dnssec { security_log; };
        category resolver { error_log; };
    };
};

// ACLs
acl "dns_servers" {
    localhost;
    {{ dns_primary_server }};
    {% for server in dns_secondary_servers %}
    {{ server }};
    {% endfor %}
};

{% if dns_use_tsig %}
// TSIG key
key "{{ dns_tsig_key_name }}" {
    algorithm {{ dns_tsig_key_algorithm }};
    secret "{{ dns_tsig_key_secret }}";
};

{% if dns_role == "primary" %}
{% for server in dns_secondary_servers %}
server {{ server }} {
    keys { {{ dns_tsig_key_name }}; };
};
{% endfor %}
{% else %}
server {{ dns_primary_server }} {
    keys { {{ dns_tsig_key_name }}; };
};
{% endif %}
{% endif %}

// Zone definitions
{% for zone in dns_zones %}
zone "{{ zone.name }}" IN {
    type {{ zone.type }};
    file "{{ zone.file }}";
    {% if zone.type == "master" %}
    {% if dns_use_tsig %}
    allow-transfer { key {{ dns_tsig_key_name }}; };
    {% else %}
    allow-transfer { dns_servers; };
    {% endif %}
    also-notify { 
        {% for server in dns_secondary_servers %}
        {{ server }};
        {% endfor %}
    };
    notify yes;
    {% elif zone.type == "slave" %}
    masters { 
        {% for master in zone.masters %}
        {{ master }};
        {% endfor %}
    };
    {% raw %}{% endif %}
};
{% endfor %}

// Include standard zones
include "/etc/named.rfc1912.zones";

// Include DNSSEC root key
include "/etc/named.root.key";

Template para Arquivo de Zona

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# dns-ansible/templates/zones/example.com.zone.j2
$TTL 86400
@       IN SOA  ns1.example.com. admin.example.com. (
                    {{ '%Y%m%d01' | strftime }}  ; Serial
                    10800       ; Refresh (3 hours)
                    3600        ; Retry (1 hour)
                    604800      ; Expire (1 week)
                    86400 )     ; Minimum TTL (1 day)

        IN NS   ns1.example.com.
        IN NS   ns2.example.com.

ns1     IN A    {{ dns_primary_server }}
ns2     IN A    {{ dns_secondary_servers[0] }}
www     IN A    {{ dns_primary_server }}

Template para Logrotate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# dns-ansible/templates/named-logrotate.j2
{{ dns_log_dir }}/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 0640 named named
    sharedscripts
    postrotate
        /usr/bin/systemctl reload {{ 'named-chroot' if dns_use_chroot else 'named' }}.service > /dev/null 2>&1 || true
    endscript
}

Inventário

1
2
3
4
# dns-ansible/inventory
[dns_servers]
ns1.example.com ansible_host=192.168.200.49 dns_role=primary
ns2.example.com ansible_host=192.168.200.50 dns_role=secondary

Execução do Playbook

1
ansible-playbook -i inventory dns.yml

Conclusão e Próximos Passos

Neste sétimo artigo da série, exploramos configurações avançadas do BIND no Oracle Linux 9, incluindo servidores secundários, ambiente chroot, alta disponibilidade, integração com DHCP, políticas de resposta, estratégias de backup e automação com Ansible.

Estas configurações avançadas são essenciais para ambientes corporativos e de provedores de serviço, onde a disponibilidade, segurança e desempenho do DNS são críticos para a operação dos negócios.

O que vem a seguir?

No próximo artigo, “Delegação e Subdomínios no DNS BIND”, abordaremos:

  • Conceitos fundamentais de delegação DNS
  • Implementação de subdomínios em diferentes cenários
  • Delegação para diferentes servidores DNS
  • Delegação em ambientes com views
  • Delegação segura com DNSSEC
  • Troubleshooting de problemas de delegação
  • Melhores práticas e estratégias de gerenciamento

Não perca! Nossa jornada para dominar o DNS BIND no Oracle Linux 9 continua.

Referências e Recursos Adicionais

This post is licensed under CC BY 4.0 by the author.