Automatización de la configuración DNS en Linux con Bash: Un enfoque dinámico y adaptable

Artículos Guías Manuales Sistemas Linux Windows Redes MySql Binario 0 Binario Cero Artículos Guías Manuales Sistemas Linux Windows Redes MySql Binario 0 Binario Cero

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:

Binario 0
Resumen de privacidad

Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.