Resolver Azure Private Links desde una VPN con un DNS Forwarder

Ayer te conté cómo podía conectarme desde local, usando VPN P2S, a un clúster privado de AKS, para que la comunicación con el API Server sea a través de IP privada. Cuando elegimos esta configuración lo que ocurre es que se crea un private link para el servicio, el cual está asociado a un Private DNS que «desde arriba» podemos utilizar pero «desde abajo» directamente no y es por ello que necesitamos algo más para «resolver» 🙂 esta situación. En este artículo te cuento cómo.

Situación actual: no puedo resolver el private link

Como no soy experta en networking, y para mi no es tan obvio, he hecho un dibujo que ayude a entender en qué punto nos encontrábamos ayer:

No podía resolver el private link desde casa conectado a la VPN usando Point to Site

Una vez que se creó el clúster como privado y utilicé el siguiente comando para recuperar las credenciales del clúster:

az aks get-credentials -n $AKS_NAME -g $RESOURCE_GROUP

Si intentaba hacer cualquier operación esta comunicación con el API Server no funcionaba. Como se ve en el dibujo anterior esto es así porque mi máquina está intentando resolver el private link con el servidor DNS que tengo configurado en ella, que en este caso es el 1.1.1.1 y este no sabe de private links. La solución alternativa ayer era modificar el archivo /etc/hosts con la entrada exacta que necesitaba resolver, esto es:

10.10.1.4 private-ak-private-aks-ca0cd4-1ca3b861.c1a215f7-292d-47ea-825e-2f8af8ffefa1.privatelink.northeurope.azmk8s.io

Sin embargo, como también comentaba ayer esto no es muy operativo (ni productivo) porque tendría que mantener todos los /etc/hosts de todas las máquinas que tengan que acceder a estos recursos y añadir o modificar según el entorno vaya creciendo. Es por ello que es recomendable delegar esta tarea en un servidor DNS, el cual en este caso es mi Private DNS creado durante la generación del clúster, pero el problema es que este solo es accesible desde las redes a las cuales esté asociado, pero no «desde abajo». Es por ello, que ayer al final del artículo comenté que necesitábamos un DNS forwarder tal y como indica la documentación, pero yo, que no sé tanto de servidores DNS, con la imagen donde se explica el cómo se hace no me enteraba tanto. Entonces, ¿Cómo hacemos esto? Empecemos por el DNS forwarder.

¿Qué hace el DNS forwarder?

Para añadir esta pieza a nuestra arquitectura tenemos que cambiar la foto de la siguiente manera:

Usar un DNS forwarder en la misma red que tiene linkada el private DNS

Nota para navegantes: esto es una PoC que solo tiene la intención de explicar cómo funciona pero no está pensado ni mucho menos para un entorno productivo, solo para entender 😀

Para poder resolver el nombre de mi private link desde mi conexión VPN tengo que modificar mi archivo /etc/resolv.conf, es decir la lista de servidores DNS que mi máquina usa para resolver nombres, para que pregunte a alguien que si sepa o al menos que sepa a quién puede preguntar. ¿Por qué digo «que sepa a quién preguntar»? Porque en realidad lo que tenemos que hacer es que este servidor DNS que me voy a crear, que tampoco tiene la respuesta, pregunte desde mi red en Azure a la IP 168.63.129.16, la cual a su vez se corresponde al servidor DNS proporcionado por Azure que sabe quién pregunta y si desde donde pregunta tiene acceso al DNS privado que tiene el registro que estamos intentando resolver. Lo guay de todo esto es que esta parte es transparente para ti 😀

Cómo configuro el DNS Forwarder

Vale, entonces ¿cómo configuramos un servidor DNS para esto? En esta prueba de concepto lo que he hecho ha sido montar un servidor DNS con bind usando un contenedor de Docker. Para ello, he creado este Dockerfile:

FROM internetsystemsconsortium/bind9:9.16

COPY bind/named.conf.options /etc/bind/named.conf.options

Donde copio la configuración que necesito para reenviar las peticiones a la IP del DNS de Azure:

options {
	directory "/var/cache/bind";

	listen-on port 53 { 
        any;
    };
    listen-on-v6 port 53 { 
        ::1;
    };
    allow-query { 
        any;
    };
    recursion yes;
    dnssec-enable yes; 
    dnssec-validation yes; 
    forwarders { 
        168.63.129.16;
    };
};

Para este ejemplo la he publicado en Docker Hub y con ello creo un contenedor en Azure Container Instances que inyecto en la red:

ACI_SUBNET_CIDR=10.10.3.0/24

az container create \
  --name dnsforwarder \
  --resource-group $RESOURCE_GROUP \
  --image 0gis0/dnsforwarder  \
  --vnet $VNET_NAME \
  --vnet-address-prefix $AKS_VNET_CIDR \
  --subnet aci-subnet \
  --subnet-address-prefix $ACI_SUBNET_CIDR

Cómo utilizo este DNS Forwarder

Como veíamos en la foto lo único que queda por hacer es modificar el archivo /etc/resolv.conf con la IP privada de este contenedor en ACI que tiene nuestro servidor DNS, en mi caso la 10.10.3.4:

#
# macOS Notice
#
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
#   scutil --dns
#
# SEE ALSO
#   dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 10.10.3.4
nameserver 1.1.1.1
nameserver 1.0.0.1

Debes ponerlo en primera posición porque de lo contrario seguirá intentando resolver el nombre con 1.1.1.1. A partir de ahora, si estás conectado a la red de Azure a través de VPN y tienes uno o tu máquina ya sabrá a quién preguntar para que este lo resuelva.

He actualizado el repositorio de GitHub anterior con estos pasos.

¡Saludos!