Creación de un sistema de DNS dinámico sin servidor con AWS

¿Qué le pareció este contenido?

Esta publicación se publicó originalmente en diciembre de 2015. Se actualizó en julio de 2023 para que la solución fuera más rentable y eficiente. Esta publicación se actualizó para reemplazar Amazon API Gateway con URL de funciones de AWS Lambda y Amazon Simple Storage Service (Amazon S3) con Amazon DynamoDB. El uso de las URL de funciones de Lambda reduce el costo total de la solución. Esta característica no tiene costo adicional cuando se utiliza el servicio de Lambda y proporciona un punto de conexión HTTP de RESTful con el que nuestro cliente interactúa. La sustitución de Amazon S3 por DynamoDB aumenta la eficiencia de la solución y reduce la latencia general al consultar datos.

Las startups que se encuentran en las primeras etapas, los negocios pequeños y las redes domésticas suelen tener direcciones IP públicas dinámicas que pueden cambiar sin previo aviso. Debido a este cambio de dirección, no se puede acceder de manera confiable a los sistemas de estas redes desde el exterior. Para las startups que se encuentran en las primeras etapas de su ciclo de vida, es importante ofrecer un servicio fiable y de alta disponibilidad para ganarse la confianza del primer grupo de clientes.

Los sistema de DNS dinámico resuelven este problema mediante la ejecución de un agente de software dentro de la red para mantener un registro de DNS actualizado con la dirección IP pública más reciente. Mientras el registro de DNS esté actualizado, podrá encontrar su red y los clientes podrán acceder a su servicio de forma fiable.

En esta publicación, describimos cómo crear su propio sistema de DNS dinámico mediante los servicios de AWS sin servidor. Crear un sistema sin servidor utilizando únicamente los servicios de Amazon Web Services (AWS) y unas pocas líneas de código es sencillo, rentable y escalable, y le permite centrarse en la lógica empresarial principal de su startup, en lugar de preocuparse por escalar y mantener la infraestructura subyacente.

Servicios de AWS que utilizamos en nuestro sistema de DNS dinámico

En las siguientes secciones, le mostramos cómo utilizar los siguientes servicios de AWS para crear una solución de DNS dinámico:

  • El servicio AWS Lambda le permite ejecutar código sin tener que administrar los servidores subyacentes. El código siempre está listo para ejecutarse, pero solo se le cobrará por invocar la función, en incrementos de 1 milisegundo. El servicio de Lambda puede interactuar con otros servicios de AWS a través de los SDK de AWS.
  • Las URL de la función de Lambda proporcionan un punto de conexión HTTPS dedicado para su función de Lambda. Esto le permite invocar directamente la función desde su aplicación cliente sin necesidad de utilizar un SDK de AWS ni de invocar la función mediante un servicio de proxy adicional. Esta característica no tiene ningún costo adicional para el servicio de Lambda.
  • Amazon Route 53 es un servicio de DNS administrado que le permite registrar y alojar dominios y zonas de DNS desde una red global de servidores de DNS. Como ocurre con todos los servicios de AWS, Route 53 se puede administrar mediante las API.
  • DynamoDB es una base de datos NoSQL de valores clave, sin servidores y totalmente administrada, diseñada para ejecutar aplicaciones de alto rendimiento a cualquier escala. DynamoDB ofrece seguridad integrada, copias de seguridad continuas, replicación automatizada en varias regiones, almacenamiento en caché en memoria y herramientas de importación y exportación de datos.

Flujo lógico del sistema de DNS dinámico

En la figura 1 se muestra cómo un cliente encuentra su propia dirección IP al realizar una solicitud de la API a un servicio creado con una función de Lambda y la URL de la función adjunta.

Como se muestra en la figura 2, ahora que el cliente conoce su IP pública, hace otra solicitud a nuestro servicio para establecer un registro de DNS. La función de Lambda consulta primero el registro almacenado en nuestra tabla de DynamoDB para validar la solicitud. Si la comprobación se aprueba, la función de Lambda establece la entrada de DNS en Route 53 mediante una llamada a la API. Ahora, la IP actual de la red está en el DNS público y se puede encontrar mediante una consulta de DNS estándar.

Ventajas del DNS dinámico con Lambda y Route 53

Estas son algunas de las ventajas que obtendrá al ejecutar un sistema de DNS dinámico sin servidor:

  • Más fácil de configurar. Hay un cliente de muestra junto con todo el código, la configuración y las instrucciones para configurarlo en su propia cuenta de AWS.
  • Cliente escaso o nulo. Se necesitan tres comandos para actualizar la API. Puede crear su propio cliente en la mayoría de los lenguajes y ejecutarlo en plataformas como Windows, Linux, macOS, Raspberry Pi, Chrome OS y el firmware del router DD-WRT/Tomato USB.
  • Compatibilidad con un número arbitrario de clientes, nombres de host y dominios. Los límites y cuotas de servicio de Route 53 se encuentran en la sección “Cuotas” de la Guía para desarrolladores de Route 53.
  • Rentable: de 1 a 2 USD al mes. Cada zona de Route 53 cuesta 0,50 USD al mes, 1 000 000 de consultas de DNS cuestan 0,40 USD y 10 000 solicitudes de funciones de Lambda para actualizar el DNS cuestan menos de 0,01 USD.
  • Arquitectura sin servidor. Las tecnologías sin servidor de AWS incluyen escalado automático, alta disponibilidad integrada y un modelo de facturación de pago por uso para aumentar la agilidad y optimizar los costos.
  • Los permisos granulares permiten que solo los clientes autorizados actualicen su propio nombre de host. Los clientes solo pueden actualizar el sistema desde la dirección que se agrega al DNS.
  • Se requieren cambios menores en la configuración de DNS actual. Puede dejar su zona primaria .com con su proveedor de DNS actual y utilizar una zona secundaria dynamic.example.com en AWS. Consulte la sección “Creación de una zona alojada pública en la Guía para desarrolladores de Route 53 para obtener más información sobre la creación de zonas alojadas en Route 53.

Requisitos previos

Necesitará dos cosas para crear esta solución:

  1. Una cuenta de AWS. Las cuentas nuevas pueden optar al nivel gratuito de AWS.
  2. Un dominio de su propiedad, alojado en Route 53 u otro proveedor. Si es necesario, puede registrar dominios a través de Route 53 desde tan solo 3,00 USD. Consulte los precios de Amazon Route 53 para el registro de dominios para obtener los precios completos.

Cómo crear un sistema de DNS dinámico en su cuenta

En este punto, tiene suficiente información para empezar a crear su propia copia del sistema. Si quiere obtener más información sobre cómo funciona, siga leyendo.

Si quiere empezar a crear, el DNS dinámico de Route 53 con Lambda está disponible en GitHub. Proporciona instrucciones ilustradas y todo el código y la configuración necesarios.

Cómo funciona el nuevo sistema

En primer lugar, el cliente necesita encontrar la IP pública asignada a su red. Si realiza una solicitud desde su red a un servicio de Internet, ese servicio verá que la solicitud proviene de su dirección IP externa.

A continuación, el cliente realiza una solicitud HTTP POST a la URL de la función de Lambda con un cuerpo de solicitud de {"execution_mode":"get"} y obtiene una respuesta que contiene la dirección IP pública actual:

HTTP POST
> https://.....lambda-url.eu-west-1.on.aws

{“return_message”:
“176.32.100.36”, “return_status”: “success”}

Durante este proceso, la URL de la función de Lambda convierte la solicitud HTTP en JSON, incluidos todos los parámetros de la solicitud, y pasa la dirección IP de origen del solicitante a una función de Lambda de Python. A continuación, la función de Lambda envía una respuesta JSON con la IP al cliente.

En la figura 3 se muestra una solicitud para obtener una IP pública.

El cliente ahora crea un token de solicitud vinculando la dirección IP pública devuelta por la solicitud HTTP POST, el nombre de host de DNS y un secreto compartido. Por ejemplo, si la dirección IP es 176.32.100.36, , el nombre de host es host1.dyn.example.com y el secreto compartido es shared_secret_1, la cadena enlazada será la siguiente:

176.32.100.36host1.dyn.example.comshared_secret_1

A continuación, el cliente genera una función hashSHA-256 de la cadena:

echo -n 176.32.100.36host1.dyn.example.comshared_secret_1 | shasum -a 256

Hash: 96772404892f24ada64bbc4b92a0949b25ccc703270b1f6a51602a1059815535

A continuación, el cliente solicita la actualización de DNS mediante una segunda solicitud HTTP POST. Pasa el nombre de host en texto simple como clave y la función hash como token de autenticación dentro del cuerpo de la solicitud:

HTTP POST > https://....lambda-url.eu-west-1.on.aws

{“execution_mode”:”set”, “ddns_hostname”:”host1.dyn.example.com”, “validation_hash”:”96772404892f24ada64bbc4b92a0949b25ccc703270b1f6a51602a1059815535”}

A continuación, la URL de la función de Lambda devuelve los parámetros de la solicitud a la función de Lambda.

A continuación, la función de Lambda consulta su registro de configuración JSON desde DynamoDB mediante el AWS SDK para Python (Boto3). En este sistema, las interacciones entre el servicio de Lambda, DynamoDB y Route 53 utilizan Boto3, que viene preintegrado en el entorno de tiempo de ejecución del servicio Lambda.

Una vez que nuestra función de Lambda consulta el registro de configuración de DynamoDB, utiliza el nombre del host como clave para encontrar el secreto compartido y otra configuración asociada a ese registro, similar al siguiente registro de ejemplo:

{
"host1.dyn.example.com.": {
"aws_region": "us-west-2",
"route_53_zone_id": "MY_ZONE_ID",
"route_53_record_ttl": 60,
"route_53_record_type": "A",
"shared_secret": "SHARED_SECRET_1"
},
"host2.dyn.example.com.": {.....

El cliente pasó host1.dyn.example.com como clave, por lo que la función de Lambda lee SHARED_SECRET_1 de la configuración y reconstruye el token de la función hash con el nombre de host, la dirección IP del solicitante y el secreto compartido. Si la función hash calculada por la función de Lambda y la función hash recibida del cliente coinciden, la solicitud se considera válida.

Una vez validada la solicitud, la función de Lambda usa la información de la configuración para realizar una llamada a la API a Route 53 para ver si el nombre del host de DNS ya está configurado con la IP del cliente. Si no es necesario realizar ningún cambio, la función de Lambda responde al cliente y sale:

{“return_message”: “Your IP address matches the current Route53 DNS record.”,
 “return_status”: “success”}

Si no hay ningún registro o si el registro actual y la IP del cliente no coinciden, la función de Lambda realiza una llamada a la API a Route 53 para establecer el registro, responde al cliente y sale:

{“return_message”: “Your hostname record host1.dyn.example.com. has been set to 176.32.100.36”,
 “return_status”: “success”}

En la figura 4 se muestra la solicitud para establecer el nombre del host.

¿Cómo está protegido este sistema?

  • Todas las comunicaciones que utilizan las URL de la función de Lambda están cifradas.
  • El secreto compartido nunca se transmite a través de Internet.
  • La tasa de solicitudes de los clientes se puede limitar mediante la característica de simultaneidad reservada del servicio Lambda.
  • El mecanismo de autenticación es multifactorial porque el cliente presenta el secreto compartido (“algo que tiene”) y su propia dirección IP pública (“algo que es”).
  • El archivo de configuración se puede cifrar en reposo mediante el cifrado del servidor de DynamoDB.
  • Sus credenciales de AWS no se utilizan, por lo que no pueden filtrarse.

Conclusión

El sistema de DNS dinámico que describimos en esta publicación muestra cómo crear su propia solución sin servidor en AWS para resolver un problema del mundo real: el DNS es susceptible de cambios y es posible que no lo sepa.

Utilice esta solución para ejecutar su propio DNS dinámico en AWS. También puede utilizarla como ejemplo para aprender a utilizar los servicios de AWS para crear sus propias soluciones sin servidor a cualquier escala.

Visite el repositorio Route 53 dynamic DNS with Lambda en GitHub para obtener un conjunto completo de código, configuración e instrucciones sobre cómo implementarlo.

¿Qué le pareció este contenido?