Dynamic DNS

Digamos que quieres acceder a tu red de casa desde cualquier lugar pero la IP de tu casa cambia continuamente. Podrías utilizar una combinación de buena memoria y buena suerte o un servicio de DNS dinámico como NoIP o DynDNS, o podrías construirte uno tú mismo utilizando Amazon Route53.

Para construir tu propio servicio de DNS dinámico necesitarás unas pocas cosas:

  • Una cuenta AWS.
  • Una hosted zone en Amazon Route53.
  • Un usuario IAM.
  • Un dominio.
  • Algo que se encargue de actualizar to IP.

Vayamos paso a paso.

Una cuenta AWS

No hay mucho que explicar aquí, simplemente ve a AWS y crea una nueva cuenta. Te pedirán una tarjeta de crédito pero solo te cobrarán por lo que uses. Todo lo descrito aquí te costará alrededor de $0.5 por mes.

De todas formas, cuando se usa AWS es siempre una buena idea configurar AWS Budgets donde puedes establecer un presupuesto y alarmas que te avisarán antes de que lo excedas.

Una hosted zone en Amazon Route53

Hosted zone es el nombre que le da AWS a una zona DNS, el lugar donde se definen los registros de un nombre DNS. Ve a la documentación completa de AWS para saber más sobre como crear una hosted zone pública.

La zona que hayas creado tendrá un registro NS que contendrá las direcciones de 4 servidores DNS que servirán la zona. Necesitarás configurar estos servidores como los servidores DNS de tu dominio.

Cada zona tiene un identificador único con un formato similar a ZXXXXXXXXXXXXX. Encuéntralo y apunta el ID de la zona que acabas de crear porque lo necesitarás en los pasos siguientes.

Un usuario IAM

Un usuario IAM es una entidad que es usada para interacturar con AWS. En este caso proporcionará los permisos necesarios para modificar un conjunto de registros de la zona usando un par de credenciales.

Sigue la documentación de AWS para crear un usuario IAM y asocia la siguente política:

{
    "Version": "2012-10-17",
    "Statement": [{
        "Sid": "Stmt1597880289163",
        "Action": [
            "route53:ChangeResourceRecordSets"
        ],
        "Effect": "Allow",
        "Resource": "arn:aws:route53:::hostedzone/hosted_zone_ID"
    }]
}

Apunta (en un lugar seguro) la access key y la secret key del usuario IAM, los necesitarás más tarde.

Un dominio

Puedes registrar un dominio en diferentes lugares, por ejemplo Gandi.net, GoDaddy, o Amazon Route53.

Para este ejemplo usaremos el dominio example.com.

Algo que mantenga tu IP actualizada

Usaremos Python para crear un pequeño programa que obtenga nuestra IP pública actual y actualice la zona de Amazon Route 53.

Lo primero que necesitamos es obtener la IP actual y para eso podemos usar ifconfig.co:

def get_ip():
    r = requests.get('https://ifconfig.co/ip')
    if r.status_code == 200:
        return r.text.strip()
    else:
        return None

Esta minúscula función devolverá tu IP pública actual como una cadena.

A continuación usaremos boto3, el AWS SDK para Python, para interactuar con AWS y actualizar la zona de Amazon Route 53. Una única llamada a la API ChangeResourceRecordSets es todo lo que es necesario. Usando boto3 necesitaremos obtener un cliente de Route53 y llamar change_resource_record_sets. Hay mucha documentación pero siempre es bueno ver código que functiona así que aquí lo tienes:

client = boto3.client('route53')

response = client.change_resource_record_sets(
    HostedZoneId=hosted_zone,
    ChangeBatch={
        "Comment": "Automatic record update",
        "Changes": [{
            "Action": "UPSERT",
            "ResourceRecordSet": {
                "Name": name,
                "Type": "A",
                "TTL": 300,
                "ResourceRecords": [{
                    "Value": <THE IP>
                }]
            }
        }]
    }
)

Ahora que tenemos todas las piezas, solo tenemos que ponerlas todas juntas y encontrar una forma de llamarlo periódicamente. Puedes ver el código completo de DNSupdater en GitHub.

Copia el script a tu servidor doméstico y usa cron para ejecutarlo periódicamente, una vez por hora debería ser suficiente:

0 * * * * not_root_user_please ./dnsupdater.py --hosted-zone-id ZXXXXXXXXXXXXX --name home.example.com

Descubrirás que tienes que configurar las credenciales de alguna manera. La forma más fácil es configurarlas en el archivo ~/.aws/credentials en el directorio del usuario que ejecutará el script. Aquí tienes la documentación sobre configuración de credenciales en caso de que quieras profundizar.

Si configuras las credenciales bajo un perfil específico puedes seleccionar el perfil que usará en script declarando una variable de entorno.

0 * * * * not_root_user_please AWS_PROFILE=profile ./dnsupdater.py --hosted-zone-id ZXXXXXXXXXXXXX --name home.example.com