[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

DNS Dinâmico



Criando seu próprio servidor de DNS dinâmico (nsupdate + bind9)

Autor: Fábio Berbert de Paula <fberbert at gmail.com>
Data: 03/07/2007

Introdução

Esse artigo é a documentação de uma rotina que bolei há uns 2 anos, porém com as famosas migrações de servidor que a gente sempre enfrenta, acabei perdendo os arquivos de configuração e só agora resolvi (re)estudar a solução para fazer novamente. E lição aprendida, documentar para não perder novamente.

Acredito que todos saibam do que se trata DNS dinâmico, certo? Hmmm, não!? Então aí vão algumas sugestões de leitura:
Resumindo, existem sites que oferecem o serviço de DNS dinâmico onde você instala um software cliente na sua máquina (IP dinâmico, que muda toda vez que se conecta) que associa seu IP com um hostname, como por exemplo casa.homelinux.org. Legal né? Sim, mas eu queria mesmo era um domínio casa.acme.com, seria legal ter meu desktop associado com meu próprio domínio. Tais serviços possuem uma lista limitada e pré-definida de domínios que você pode usar para compor seu hostname.

Imagina só se eu tivesse grana sobrando, registraria o domínio berbert.com (Berbert é meu sobrenome) e quem quisesse me encontrar (minha máquina) pingaria pra fabio.berbert.com. ééééé!!! Eu chegaria num cliente e, precisando daquele tal arquivo diria: "acessa fabio.berbert.com aí".

Para acompanhamento do artigo vamos assumir o domínio fictício "acme.com", onde queremos como host dinâmico o "casa.acme.com" e nosso servidor/provedor roda bind9 como software DNS. Na máquina cliente (desktop) precisaremos somente do utilitário nsupdate, que no Debian faz parte do pacote dnsutils. Sendo assim:

# apt-get install dnsutils

Ah, como o objetivo é configurar DNS dinâmico, estou partindo do princípio de que seu servidor DNS já esteja configurado e em pleno funcionamento.


Segurança: preparando a chave de assinatura do servidor

Vamos começar preparando o servidor para receber as atualizações de DNS a partir de seu desktop. O pulo-do-gato dessa rotina está na opção "allow-update" que será incluída na configuração de zona do seu domínio.

Como estou falando de administrador para administrador, estou certo de que você sabe o que é uma zona né? Se não sabe, consulte alguma literatura sobre fundamentos de DNS aqui mesmo no site.

Mas aí você pergunta, ué... não é inseguro liberar meu servidor para receber updates de outras máquinas pela internet? Não, a segurança é feita a partir de chaves criptografadas de até 512 bits conhecidas como assinaturas de transação, ou TSIG (Transaction SIGnature).

De posse de um terminal no servidor, digite:

# cd /etc/bind
# dnssec-keygen -a HMAC-MD5 -b 512 -n HOST server


Acessamos o diretório de configuração do bind (/etc/bind no Debian) e criamos uma assinatura TSIG da seguinte forma:
  • -a HMAC-MD5: algoritmo utilizado para criação da chave;
  • -b 512: tamanho em bits da chave. Esse número varia de acordo com o algoritmos escolhido na opção anterior;
  • -n HOST: o tipo de dono da chave (case-sensitive);
  • server: o nome da chave em si.

Para maiores explicações sobre os parâmetros usados, digite:

$ man dnssec-keygen

Se tudo correu bem foram gerados 2 arquivos no seguinte formato:

K<keyname>+157+<keyid>.private
K<keyname>+157+<keyid>.key

Onde keyname é o nome da chave (server em nosso exemplo) e keyid o número de identificação único para a chave. Veja:

# ls K*
Kserver.+157+31518.key Kserver.+157+31518.private

A informação que vamos usar adiante é o campo "Key" de qualquer dos arquivos:

# grep ^Key Kserver.+157+31518.private
Key: FGbUIzPEbJgyEkDxEYccrxVTLQ==

NOTA: Por questões de didática "cortei" um bom pedaço do hash da chave gerada. O que vamos usar é neste artigo é o "FGbUIzPEbJgyEkDxEYccrxVTLQ==" e o nome da chave, "server".


Configurando o BIND

Aqui vamos partir direto para o arquivo de configuração do bind, o named.conf, que geralmente fica em /etc/named, /etc/bind ou em /etc. No caso particular do Debian usei o /etc/bind/named.conf.local, mas aí vai da preferência de cada administrador. O arquivo principal é o /etc/bind/named.conf nessa distro.

# vim /etc/bind/named.conf

Adicione em algum lugar antes das declarações de zona a definição da chave que geramos anteriormente:

key "server" {
algorithm HMAC-MD5;
secret "FGbUIzPEbJgyEkDxEYccrxVTLQ==";
};

Onde:
  • server: nome da chave gerada pelo comando dnssec-keygen;
  • FGbUIzPEbJgyEkDxEYccrxVTLQ==: hash da chave, lembram do comando grep da página anterior!?

Agora localize a definição de zona do domínio desejado e adicione a opção allow-update:

zone "acme.com" {
type master;
file "/var/cache/bind/acme.com.db";
allow-update { key server; };
};

Dispensa maiores explicações né?

Reinicie o bind e pronto, estamos com o servidor DNS apto a receber updates:

# /etc/init.d/bind9 restart


Configurando seu desktop/ADSL para atualizar o DNS

Agora começa a parte divertida da história. Primeiro você precisa saber em qual interface seu modem se conecta e recebe o IP dinâmico. Aqui uso Velox e o mesmo se conecta criando a interface ppp0. Exemplo:

$ ifconfig
...
ppp0 Encapsulamento do Link: Protocolo Ponto-a-Ponto
inet end.: 189.25.11.232 P-a-P:200.222.118.26 Masc: 255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1492 Métrica:1
RX packets:9410 errors:0 dropped:0 overruns:0 frame:0
TX packets:14634 errors:0 dropped:0 overruns:0 carrier:0
colisões:0 txqueuelen:3
RX bytes:2274514 (2.1 MiB) TX bytes:6312084 (6.0 MiB)

Resumindo, precisamos ter definidas as seguintes informações para prosseguir:
  • Nome da chave gerada: server;
  • Hash da chave: FGbUIzPEbJgyEkDxEYccrxVTLQ==;
  • Interface que recebe o IP dinâmico: ppp0;
  • Servidor DNS (ip ou hostname) - sim, o dito cujo das páginas anteriores: ns.acme.com;
  • Zone/domínio: acme.com;
  • Host a ser criado/associado: casa.acme.com;

Então vamos à criação do script de atualização:

# vim /usr/local/bin/nsupdate.sh

#!/bin/bash

# variáveis de ambiente - edite aqui
KEYNAME="server"
HASH="FGbUIzPEbJgyEkDxEYccrxVTLQ=="
INTERFACE="ppp0"
SERVER="ns.acme.com"
ZONE="acme.com"
HOST="casa.acme.com"

# descobrir o IP atual da interface dinâmica
IP=`ifconfig $INTERFACE | grep inet | cut -d ":" -f 2 | tr -d a-z,A-Z,- | sed 's/\s//g';`

# definir comando de update
NSUPDATE="/usr/bin/nsupdate -y $KEYNAME:$HASH"

# conteúdo a ser enviado ao servidor
EXEC="server $SERVER\n
zone $ZONE\n
update delete $HOST A\n
update add $HOST 1440 A $IP\n
show\n
send"

# executar a atualização
echo -e $EXEC | $NSUPDATE

Pronto, pra atualizar o domínio e ter casa.acme.com apontando pro seu IP basta digitar:

# nsupdate.sh

Para testar:

$ ping casa.acme.com
ou
$ dig casa.acme.com
ou
$ dig casa.acme.com @ns.acme.com

Mas ainda pode melhorar! Podemos automatizar o processo. No Debian existe um script que é executado toda vez que a interface recebe um IP, trata-se do /etc/ppp/ip-up. Adicione a seguinte linha no final do arquivo:

# vim /etc/ppp/ip-up

/usr/local/bin/nsupdate.sh

Caso use outra distribuição, procure saber onde fica o arquivo similar.


Bônus: Gambiarra pra liberar acesso ao meu IP dinâmico

Depois de ter meu domínio casa.acme.com funcionando redondo, surgiu a necessidade (ou seria luxuosidade?) de, por exemplo, liberar determinadas portas privilegiadas para meu IP dinâmico.

Situação: Liberar a porta 3306 do MySQL para meu host dinâmico.

Solução: Criar um script no servidor que de tempos em tempos renova suas regras de iptables baseando-se no IP resolvido pelo nome do host dinâmico (casa.acme.com).

# vim /root/regras.sh

#!/bin/bash

# caminho do iptables
IPT="/sbin/iptables"

# apaga as 3 primeiras regras do canal INPUT
$IPT -D INPUT 3
$IPT -D INPUT 2
$IPT -D INPUT 1

# adiciona 3 regras no canal início do canal INPUT
$IPT -I INPUT -p tcp --dport 3306 -j DROP
$IPT -I INPUT -p tcp -i lo --dport 3306 -j ACCEPT
$IPT -I INPUT -p tcp -s casa.acme.com --dport 3306 -j ACCEPT

Deve existir solução mais bonita, mas funciona! :)

O que o script faz? Apaga e insere novamente 3 regras no início do canal INPUT do iptables:
  • Recusar (DROP) conexões na porta 3306;
  • Aceitar (ACCEPT) conexões na porta 3306 vindas de localhost (interface lo);
  • Aceitar (ACCEPT) conexões na porta 3306 vindas de casa.acme.com. Aqui o iptables resolve o nome para o IP atual de casa.acme.com.

O parâmetro "-I" do iptables adiciona a regra no início do canal, sendo assim as regras acima devem ser lidas de trás pra frente.

Por fim adicionei o script no cron para rodar a cada 5 minutos, uma vez que a qualquer momento o IP de casa.acme.com pode mudar, daí o tempo máximo de falta de acesso por IP diferente de hostname será esse.

# crontab -e

*/5 * * * * /root/regras.sh

Pessoalmente não gostei desse lance de apagar as rules por número, na verdade eu só queria atualizar (iptables -R = replace) a regra que libera a porta para o host dinâmico, o problema é que quando o host muda de IP a regra não é mais identificada usando os mesmos parâmetros, visto que o IP é diferente - não casa. Acredito que criando uma tabela pra essa regra resolva, mas já estou sem saco pra pesquisar isso, fica como dever de casa. :)

Espero que o texto seja útil.

Um abraço,
Fábio


--
Administrador de Sistemas GNU/Linux

HomePage: www.dias.eti.br
Email: tiago@dias.eti.br
          
"A mente que se abre a uma nova idéia jamais voltará ao seu tamanho original"

(Albert Einstein)
Reply to: