En entornos corporativos o de laboratorio, configurar correctamente los servidores DNS es una tarea crítica que puede variar según el sistema operativo, el gestor de red en uso y la forma en que se administra el archivo resolv.conf
. Para facilitar esta labor, presentamos un script Bash robusto y automatizado que adapta la configuración DNS a diferentes entornos Linux, detectando dinámicamente el método de resolución DNS en uso.
Objetivo del script
El objetivo principal es automatizar la configuración de servidores DNS en sistemas Linux, contemplando los siguientes escenarios:
- Sistemas que utilizan
systemd-resolved
- Sistemas gestionados por NetworkManager
- Configuraciones manuales tradicionales (modificación directa de
/etc/resolv.conf
)
Características principales
- Soporte para entornos Debian, Ubuntu, CentOS, RHEL, y derivados.
- Autodetección del método de resolución DNS activo.
- Registro detallado en un fichero de log (
/var/log/dns_config_auto.log
). - Configuración segura y persistente del archivo
/etc/resolv.conf
. - Capacidad de ser invocado con variables de entorno (
DNS_SERVERS
) para personalizar los servidores DNS.
#!/bin/bash
set -e
# === Variables de entorno o argumentos ===
DNS_SERVERS=(${DNS_SERVERS:-"1.1.1.1" "8.8.8.8"})
LOGFILE="/var/log/dns_config_auto.log"
# === Función de log ===
log() {
local MSG="$1"
echo "$(date '+%Y-%m-%d %H:%M:%S') - $MSG" | tee -a "$LOGFILE"
}
# === Requiere root ===
check_root() {
if [[ $EUID -ne 0 ]]; then
log "Acceso denegado. Este script debe ejecutarse como root."
exit 1
fi
}
# === Detectar sistema operativo ===
detect_os() {
if [[ -f /etc/os-release ]]; then
. /etc/os-release
OS_ID=$ID
OS_VERSION=$VERSION_ID
log "Sistema detectado: $OS_ID $OS_VERSION"
else
log "No se pudo detectar el sistema operativo."
exit 1
fi
}
# === Detectar gestor de DNS activo ===
detect_dns_method() {
if systemctl is-active --quiet systemd-resolved; then
DNS_METHOD="systemd-resolved"
elif systemctl is-active --quiet NetworkManager; then
if grep -q "dns=" /etc/NetworkManager/NetworkManager.conf /etc/NetworkManager/conf.d/* 2>/dev/null | grep -q "dns=none"; then
DNS_METHOD="manual"
else
DNS_METHOD="networkmanager"
fi
else
DNS_METHOD="manual"
fi
log "Método de resolución DNS detectado: $DNS_METHOD"
}
# === Configurar systemd-resolved ===
configure_systemd_resolved() {
log "Configurando systemd-resolved..."
# Crear archivo /etc/systemd/resolved.conf
{
echo "[Resolve]"
for dns in "${DNS_SERVERS[@]}"; do
echo "DNS=$dns"
done
echo "FallbackDNS=1.1.1.1 8.8.8.8"
} > /etc/systemd/resolved.conf
systemctl restart systemd-resolved
log "systemd-resolved configurado y reiniciado."
}
# === Configurar NetworkManager ===
configure_networkmanager() {
log "Configurando DNS en NetworkManager..."
mkdir -p /etc/NetworkManager/conf.d
echo -e "[main]\ndns=none" > /etc/NetworkManager/conf.d/dns.conf
configure_resolv_conf
systemctl restart NetworkManager
log "NetworkManager reiniciado."
}
# === Configurar /etc/resolv.conf manualmente ===
configure_resolv_conf() {
log "Configurando /etc/resolv.conf manualmente..."
# Eliminar symlink si existe
if [[ -L /etc/resolv.conf ]]; then
log "Eliminando enlace simbólico en /etc/resolv.conf"
rm -f /etc/resolv.conf
fi
: > /etc/resolv.conf
for dns in "${DNS_SERVERS[@]}"; do
echo "nameserver $dns" >> /etc/resolv.conf
done
chmod 644 /etc/resolv.conf
log "Contenido final de /etc/resolv.conf:"
cat /etc/resolv.conf | tee -a "$LOGFILE"
}
# === Programa principal ===
main() {
check_root
detect_os
detect_dns_method
case "$DNS_METHOD" in
systemd-resolved)
configure_systemd_resolved
;;
networkmanager)
configure_networkmanager
;;
manual)
configure_resolv_conf
;;
*)
log "Método DNS no reconocido: $DNS_METHOD"
exit 1
;;
esac
log "Configuración de DNS completada."
log "SUCCESS"
}
main
Análisis del flujo del script
1. Validación de permisos de ejecución
check_root() {
if [[ $EUID -ne 0 ]]; then
log "Acceso denegado. Este script debe ejecutarse como root."
exit 1
fi
}
Este chequeo inicial garantiza que el script se ejecuta con privilegios de superusuario, condición indispensable para modificar configuraciones de red y archivos del sistema.
2. Detección del sistema operativo
detect_os() {
if [[ -f /etc/os-release ]]; then
. /etc/os-release
OS_ID=$ID
OS_VERSION=$VERSION_ID
...
}
Aunque el script no utiliza directamente OS_ID
y OS_VERSION
, deja sentadas las bases para adaptar comportamientos en función de la distribución, si se requiere en futuras ampliaciones.
3. Detección del método de resolución DNS
detect_dns_method() {
...
}
Este bloque detecta si el sistema utiliza:
systemd-resolved
NetworkManager
- Configuración manual (por descarte)
Incluso contempla si NetworkManager está configurado con dns=none
, forzando el método manual.
4. Configuración por método
a. Systemd-resolved
configure_systemd_resolved()
Se crea/modifica el archivo /etc/systemd/resolved.conf
y se establece un conjunto de DNS principales y de respaldo (FallbackDNS
), reiniciando luego el servicio.
b. NetworkManager
configure_networkmanager()
Desactiva el control de DNS de NetworkManager (dns=none
), lo cual implica que se gestionará de forma externa. Luego invoca configure_resolv_conf
y reinicia el servicio.
c. Manual
configure_resolv_conf()
Este método elimina cualquier enlace simbólico en /etc/resolv.conf
(muy común si se usa systemd-resolved
) y escribe directamente las direcciones de los servidores DNS proporcionados.
Personalización vía variables de entorno
Puedes ejecutar el script con una lista personalizada de servidores DNS sin modificarlo:
DNS_SERVERS=("9.9.9.9" "149.112.112.112") ./dns_config.sh
Registro de operaciones
El script genera un log detallado en:
/var/log/dns_config_auto.log
Este log permite auditar la operación completa, incluyendo la configuración final de /etc/resolv.conf
.
Conclusión
Este script ofrece una solución flexible, portable y mantenible para la configuración de servidores DNS en entornos heterogéneos. Su enfoque autodetectable lo hace ideal para su integración en sistemas de aprovisionamiento automático, como scripts de post-instalación, playbooks de Ansible o políticas de configuración en herramientas como Puppet o NinjaOne.
Recomendaciones adicionales
- Incluir validación de formato IP para los servidores DNS proporcionados.
- Incorporar soporte para entornos sin
systemd
o con gestores alternativos (ej.netplan
). - Adaptar el script para contenedores o entornos WSL si se requiere.
Compartir: