--- title: "GeoDNS con BIND en Ubuntu 24.04: balanceo geográfico" description: "Configura BIND 9 en Ubuntu 24.04 con la base GeoLite2 y vistas por continente para que cada visitante reciba la IP del centro de datos más cercano a él." category: "Proxy y Equilibrio de Carga" language: es source: https://cubepath.com/es/docs/proxy-y-equilibrio-de-carga/equilibrio-de-carga-geografico-con-dns updated: 2026-09-25 --- # GeoDNS con BIND en Ubuntu 24.04: balanceo geográfico El balanceo de carga geográfico por DNS (GeoDNS) responde a la misma consulta con direcciones distintas según desde dónde se haga. Si tienes tu aplicación desplegada en Europa y en Norteamérica, un visitante de Madrid recibirá la IP del servidor europeo y uno de Houston la del americano, lo que reduce la latencia y reparte la carga entre regiones. En esta guía configurarás un servidor DNS autoritativo BIND 9 en Ubuntu 24.04 que usa la base de datos GeoLite2 de MaxMind y vistas por continente para servir registros diferentes a cada región. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS que hará de DNS autoritativo, por ejemplo un VPS de CubePath. En producción necesitarás al menos dos, idealmente en regiones distintas. - Un usuario no root con privilegios `sudo`. - Un dominio (`your_domain`) cuya zona puedas delegar a tus propios servidores de nombres en el registrador. - Al menos dos servidores con tu aplicación en regiones distintas. En los ejemplos: `203.0.113.10` (Europa) y `198.51.100.10` (Norteamérica). - Una cuenta gratuita de MaxMind para descargar GeoLite2 y una clave de licencia generada en su portal. - El puerto 53 abierto por TCP y UDP. ## Cómo funciona y qué limitaciones tiene Un servidor autoritativo no ve la IP del usuario final, sino la del resolvedor recursivo que le pregunta (el de su operador, el de su empresa o uno público). BIND busca esa IP en la base GeoIP, la asigna a una vista y responde con la zona de esa vista. Normalmente el resolvedor está cerca del usuario, así que el resultado es correcto, pero hay dos consecuencias a tener en cuenta: - Un usuario que usa un resolvedor lejano recibirá la región de ese resolvedor. - Los resolvedores guardan la respuesta en caché durante el TTL del registro. Usa TTL cortos (60 a 300 segundos) en los registros geográficos para que los cambios se apliquen rápido. BIND no comprueba si los servidores de destino están vivos. El GeoDNS decide por ubicación; la conmutación por fallo requiere cambiar la zona o usar otro mecanismo, como se explica al final. ## Paso 1: Instalar BIND ```bash sudo apt update sudo apt install bind9 bind9-utils bind9-dnsutils ``` El paquete de Ubuntu está compilado con soporte para las bases MaxMind GeoIP2 (`libmaxminddb`). Compruébalo: ```bash named -V | grep -i 'linked to maxminddb' ``` ```output linked to maxminddb version: 1.9.1 ``` Si aparece esa línea (la versión puede variar), BIND puede usar ACL con `geoip`. Comprueba también que el servicio está activo: ```bash systemctl status named --no-pager ``` ## Paso 2: Descargar la base GeoLite2 La herramienta oficial `geoipupdate` descarga y actualiza las bases de MaxMind: ```bash sudo apt install geoipupdate ``` Edita su configuración con tu ID de cuenta y tu clave de licencia: ```bash sudo nano /etc/GeoIP.conf ``` ```ini AccountID your_account_id LicenseKey your_license_key EditionIDs GeoLite2-Country DatabaseDirectory /usr/share/GeoIP ``` Protege el archivo, porque contiene tu clave, y descarga la base: ```bash sudo chmod 600 /etc/GeoIP.conf sudo mkdir -p /usr/share/GeoIP sudo geoipupdate -v ls -l /usr/share/GeoIP/ ``` ```output -rw-r--r-- 1 root root 9453010 Sep 25 10:12 GeoLite2-Country.mmdb ``` MaxMind actualiza GeoLite2 dos veces por semana. Programa la actualización con cron: ```bash echo '17 4 * * 3,6 root /usr/bin/geoipupdate && /usr/sbin/rndc reload >/dev/null' | sudo tee /etc/cron.d/geoipupdate-bind ``` `rndc reload` hace que BIND vuelva a abrir la base tras la descarga. ## Paso 3: Configurar las opciones globales Este servidor será solo autoritativo, sin recursión, y debe saber dónde está la base GeoIP. Edita las opciones: ```bash sudo nano /etc/bind/named.conf.options ``` ```text options { directory "/var/cache/bind"; geoip-directory "/usr/share/GeoIP"; recursion no; allow-transfer { none; }; listen-on { any; }; listen-on-v6 { any; }; }; ``` ## Paso 4: Definir ACL por región y vistas Cuando usas vistas en BIND, todas las zonas deben estar dentro de alguna vista. Ubuntu incluye por defecto `named.conf.default-zones` fuera de las vistas, lo que provoca un error al arrancar. Como este servidor no hace recursión, esas zonas no son necesarias. Edita el archivo principal: ```bash sudo nano /etc/bind/named.conf ``` Comenta la línea de las zonas por defecto para que quede así: ```text include "/etc/bind/named.conf.options"; include "/etc/bind/named.conf.local"; //include "/etc/bind/named.conf.default-zones"; ``` Ahora define las regiones y las vistas en `named.conf.local`: ```bash sudo nano /etc/bind/named.conf.local ``` ```text acl "region-eu" { geoip continent EU; geoip continent AF; }; acl "region-na" { geoip continent NA; geoip continent SA; }; view "eu" { match-clients { region-eu; }; zone "your_domain" { type primary; file "/etc/bind/zones/db.your_domain.eu"; }; }; view "na" { match-clients { region-na; }; zone "your_domain" { type primary; file "/etc/bind/zones/db.your_domain.na"; }; }; view "default" { match-clients { any; }; zone "your_domain" { type primary; file "/etc/bind/zones/db.your_domain.default"; }; }; ``` Las vistas se evalúan en orden y gana la primera que coincide, así que la vista `default` con `any` debe ir la última: recoge Asia, Oceanía y las IP que no aparecen en la base. Los códigos de continente son de dos letras: `AF`, `AN`, `AS`, `EU`, `NA`, `OC` y `SA`. Si prefieres afinar por país, usa `geoip country ES;` con el código ISO del país. ## Paso 5: Crear los archivos de zona Crea el directorio y la zona para Europa: ```bash sudo mkdir -p /etc/bind/zones sudo nano /etc/bind/zones/db.your_domain.eu ``` ```text $TTL 3600 @ IN SOA ns1.your_domain. hostmaster.your_domain. ( 2026092501 ; serial 3600 ; refresh 600 ; retry 1209600 ; expire 300 ) ; negative cache TTL @ IN NS ns1.your_domain. @ IN NS ns2.your_domain. ns1 IN A 192.0.2.53 ns2 IN A 192.0.2.54 @ 60 IN A 203.0.113.10 www 60 IN A 203.0.113.10 ``` Crea la de Norteamérica partiendo de la anterior y cambia solo las IP de la aplicación: ```bash sudo cp /etc/bind/zones/db.your_domain.eu /etc/bind/zones/db.your_domain.na sudo sed -i 's/203\.0\.113\.10/198.51.100.10/' /etc/bind/zones/db.your_domain.na ``` La zona por defecto puede apuntar a la región que mejor atienda al resto del mundo. En este ejemplo, a Europa: ```bash sudo cp /etc/bind/zones/db.your_domain.eu /etc/bind/zones/db.your_domain.default ``` Los registros NS, SOA y de correo deben ser idénticos en todas las variantes; solo cambian los registros que quieres geolocalizar. Sustituye `192.0.2.53` y `192.0.2.54` por las IP reales de tus servidores de nombres. ## Paso 6: Validar y cargar la configuración Comprueba la sintaxis global y cada zona antes de recargar: ```bash sudo named-checkconf sudo named-checkzone your_domain /etc/bind/zones/db.your_domain.eu sudo named-checkzone your_domain /etc/bind/zones/db.your_domain.na sudo named-checkzone your_domain /etc/bind/zones/db.your_domain.default ``` ```output zone your_domain/IN: loaded serial 2026092501 OK ``` `named-checkconf` no imprime nada si todo es correcto. Reinicia BIND y revisa el log: ```bash sudo systemctl restart named sudo journalctl -u named -n 30 --no-pager ``` Debes ver una línea `zone your_domain/IN/eu: loaded serial 2026092501` por cada vista y ningún error sobre GeoIP. Abre el puerto 53: ```bash sudo ufw allow 53/udp sudo ufw allow 53/tcp ``` ## Paso 7: Comprobar las respuestas por región Una consulta desde el propio servidor viene de `127.0.0.1`, que no está en la base GeoIP, así que debe caer en la vista `default`: ```bash dig @127.0.0.1 www.your_domain A +short ``` ```output 203.0.113.10 ``` La prueba real se hace consultando directamente a tu servidor desde máquinas situadas en cada región, por ejemplo un VPS en Europa y otro en Norteamérica: ```bash dig @your_server_ip www.your_domain A +short ``` Desde Norteamérica la respuesta debe ser `198.51.100.10` y desde Europa `203.0.113.10`. Si solo tienes acceso a una región, herramientas de medición distribuida como Globalping o RIPE Atlas permiten lanzar consultas DNS desde sondas en otros países. Cuando todo responda como esperas, crea en tu registrador los registros de pegamento (glue) para `ns1.your_domain` y `ns2.your_domain` y delega el dominio en ellos. El segundo servidor de nombres debe tener exactamente la misma configuración de vistas y zonas. ## Conmutación por fallo BIND no sabe si `203.0.113.10` ha dejado de responder. Tienes varias opciones: - **Manual o con tu monitorización**: cuando una región cae, cambia la IP en la zona afectada, incrementa el serial y ejecuta `sudo rndc reload`. Con TTL de 60 segundos el cambio se propaga en pocos minutos. - **Varias IP por región**: publica dos registros `A` en cada vista (por ejemplo, un servidor principal y uno de otra región). Los navegadores prueban la siguiente dirección si la primera no conecta, aunque con cierto retraso. - **PowerDNS con registros LUA**: PowerDNS Authoritative permite registros que comprueban la disponibilidad antes de responder, por ejemplo `www IN LUA A "ifportup(443, {'203.0.113.10', '198.51.100.10'})"` con `enable-lua-records=yes` en su configuración. Si necesitas geolocalización y comprobaciones de salud en la misma pieza, es una opción a valorar. ## Solución de problemas - **`when using 'view' statements, all zones must be in views`.** Queda alguna zona fuera de las vistas, normalmente por el `include` de `named.conf.default-zones`. Coméntalo como en el paso 4. - **Errores sobre GeoIP en `journalctl -u named`.** Revisa que `/usr/share/GeoIP/GeoLite2-Country.mmdb` existe. Si el log muestra `Permission denied`, AppArmor está bloqueando la lectura: añade la línea `/usr/share/GeoIP/** r,` a `/etc/apparmor.d/local/usr.sbin.named` y recarga el perfil con `sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.named`. - **Todas las consultas reciben la vista `default`.** La base no se ha cargado o las ACL no coinciden. Comprueba el continente de una IP concreta con `mmdblookup`, del paquete `mmdb-bin`: `mmdblookup --file /usr/share/GeoIP/GeoLite2-Country.mmdb --ip 198.51.100.10 continent code`. - **Los cambios no se ven.** Olvidaste incrementar el serial o los resolvedores aún tienen la respuesta en caché. Consulta directamente a tu servidor con `dig @your_server_ip` para descartar la caché. ## Conclusión Tu servidor BIND responde ahora a cada región con la IP de su centro de datos más cercano, usando GeoLite2 actualizado automáticamente y TTL cortos para poder reaccionar ante cambios. Como siguientes pasos, replica la configuración en un segundo servidor de nombres (con transferencias de zona por vista protegidas con TSIG o gestionando los archivos con Ansible), firma la zona con DNSSEC y conecta tu monitorización para automatizar el cambio de IP cuando una región deje de responder.