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
| |