Blog


View CommentsView Comments

Controlando DNS round-robin de um Blackberry/IPhone

08.Oct.2008 Tags: bind, blackberry, dns, iphone, linux, programacao, python

Tive que fazer uma interface de gerenciamento de DNS round-robin para fazer um "poor high-availability". Consiste em de um telefone celular ou de qualquer browser controlar os servidores que fazem parte de uma entrada round-robin do DNS. Utilizei python para fazer um CGI simples que faz uma consulta no servidor de DNS para ver quais servidores estão atualmente respondendo e a página abre com estes servidores pré-selecionados. Você seleciona os servidores que deverão ser utilizados para a entrada e da um atualizar e ele atualiza via dynamic update no BIND.

Primeiro, vamos configurar o bind para permitir dynamic update. Você precisa criar uma chave de host(que chamarei de pauba) utilizando o comando:

# dnssec-keygen -a HMAC-MD5 -b 512 -n host pauba

Este comando irá criar dois arquivos no diretório que você estiver:

Kpauba.um_monte_de_numero.key
Kpauba.um_monte_de_numero.private

No arquivo .private, você precisa pegar a Key que ele gerou e acrescentar no named.conf(substituia sua key pelos XXXXXX== abaixo):

key "pauba" {
    algorithm hmac-md5;
    secret "XXXXXXXXXXXXXXXXXXXXXXXXXX==";
};

zone "suazona.com.br" {
    type master;
    allow-transfer { 1.2.3.4; };
    notify yes;
    allow-update { key "pauba."; };
    file "/var/lib/bind/db.suazona.com.br";
};

Com isto o bind vai permitir atualização dinâmica da zona de qualquer um utilizando a chave acima.

Agora vamos ao programa. Você vai precisar do dnspython, no ubuntu, aptitude install python-dnspython.

No host que você irá criar o programa, o apache precisa estar configurado para permitir ExecCGI e o ScriptAlias precisa estar configurado também.

O código está abaixo.

#!/usr/bin/env python
import dns.query
import dns.tsigkeyring
import dns.update
import dns.resolver
import dns.rdataset
import cgi
import sys

keyring = dns.tsigkeyring.from_text({
    'pauba.' : 'XXXXXXXXXXXXXXXXX=='
})

# A entrada round-robin
entrada = 'www'
# O dominio
dominio = '.suazona.com.br'
# O servidor de DNS master com BIND configurado
servidor_master = '4.3.2.1'

class clsServers:
name = ""
address = ""
checked = ""
def __init__(self, name="", address="", checked=""):
    self.name = name
    self.address = address
    self.checked = checked

servidores = []
servidores.append(clsServers('img1-us', '1.1.1.1'))
servidores.append(clsServers('img2-us', '1.1.1.2'))
servidores.append(clsServers('img1-br', '1.1.2.1'))
servidores.append(clsServers('img2-br', '1.1.2.2'))
servidores.append(clsServers('img1-ne', '1.1.3.1'))
servidores.append(clsServers('img2-ne', '1.1.3.2'))

servidores_no_ar=dns.resolver.query(entrada+dominio, 'A')
for rdata in servidores_no_ar:
    for servidor in servidores:
        if (servidor.address == rdata.address):
            servidor.checked="checked"

def generateHeader():
    print "Content-type: text/html\n"
    print "<html>"
    print "<head><title>Atualizacao de DNS de Imagens</title></head>"
    print "</head>"
    print "<body>"

def generateFooter():
    print "</body>"
    print "</html>"

def generateForm():
    print "<h3>Selecione os Servidores</h3>"
    print "<form method='post' action='/cgi-bin/dnsupdate.py'>"
    for servidor in servidores:
        print "<input type='checkbox' name='" + servidor.name + "' value='" + servidor.address + "' " + servidor.checked + " />" + servidor.name + "<br/>"
    print "<br/>"
    print "<input type='submit' name='btnEnviar' value='Enviar'>"
    print "</form>"

def main():
    form = cgi.FieldStorage()
    if (form.has_key("btnEnviar")):
        generateHeader()
        update = dns.update.Update(dominio, keyring=keyring)
        update.delete(entrada)
        for key in form.keys():
            if (key.find('img') == 0):
                update.add(entrada, 300, 'A', form.getvalue(key))
        response = dns.query.tcp(update, servidor_master)
        generateFooter()
    else:
        generateHeader()
        generateForm()
        generateFooter()

main()

E é isto. Dúvidas, críticas e sugestões, os comentários estão aí para isto.


blog comments powered by Disqus