Detenga dos servicios de Linux que compiten por /etc/resolv.conf
Averigüe quién es dueño del archivo antes de editarlo. El atributo inmutable oculta el conflicto, y las reconexiones o las renovaciones de DHCP deshacen una y otra vez la reparación manual del DNS.
El DNS vuelve una y otra vez a su estado anterior, la reconexión de la VPN deshace su corrección y alguien del equipo acaba proponiendo bloquear el archivo. Esa secuencia es un síntoma, no una solución: dos componentes creen ambos que son dueños de /etc/resolv.conf, y gana el que escribe al final. Bloquear el archivo no resuelve el conflicto de propiedad, solo lo oculta mientras rompe el componente que usted realmente quería. Haga las cuatro comprobaciones siguientes en orden y corrija la disposición en el nivel que la posee, no en el archivo.
Comprobación 1: ¿es un enlace simbólico y hacia qué
Empiece por el propio archivo, porque la ruta que está editando puede no ser el archivo en absoluto. Un enlace simbólico al directorio de ejecución de un resolutor se comporta de forma completamente distinta a un archivo normal que un script de cliente reescribe:
ls -l /etc/resolv.conf
readlink -f /etc/resolv.conf
cat /etc/resolv.conf
Un enlace a una ruta stub de systemd-resolved significa que el contenido del archivo se genera, y la edición manual se sobrescribirá en el siguiente evento. Un archivo normal con líneas nameserver suele escribirlo el cliente o el gancho DHCP que se ejecuta al conectar. Ambos son legítimos; lo que importa es saber cuál tiene antes de cambiar nada.
Comprobación 2: qué demonio se está ejecutando
Averigüe qué está realmente activo, no qué está instalado. En una distribución moderna puede haber varios resolutores, y el que ocupa el puerto 53 en la interfaz loopback es el que responde:
systemctl status systemd-resolved --no-pager
resolvectl status
ss -lunp | grep ':53'
La salida de estado nombra los servidores DNS por enlace y los dominios de enrutamiento, que es el mapa que necesita para el DNS dividido. Si los nombres internos deben ir a un servidor interno y todo lo demás a uno público, esa política vive en los dominios por enlace, y aplanarla en una lista estática de nameserver dentro del archivo pierde esa distinción en silencio.
La propia configuración de NetworkManager decide cuál de estos backends utiliza. Su ajuste dns= en el archivo de configuración principal elige entre su resolutor interno, dnsmasq, systemd-resolved y none, y puede que la distribución haya elegido por usted. Lea ese ajuste antes de decidir qué significa “arreglar el DNS” en este equipo.
Comprobación 3: qué puede escribir el cliente de VPN
Aquí suele vivir el conflicto. Un cliente de VPN que reescribe directamente el archivo del resolutor peleará con cualquier servicio que también lo mantenga, y el perdedor es el que se ejecuta primero. Las versiones recientes de OpenVPN pueden entregar los ajustes de DNS a systemd-resolved en lugar de reescribir el archivo, que es el comportamiento cooperativo que usted quiere; los scripts más antiguos y los ganchos escritos a mano a menudo llaman a un auxiliar obsoleto o simplemente sobrescriben el archivo.
La situación de WireGuard es similar en forma: la configuración de la interfaz no gestiona el DNS, lo hacen las herramientas que la rodean, mediante un auxiliar de resolutor o la integración con resolved. Si hay dos de esos auxiliares instalados, ambos intentarán aplicar su visión del mundo al conectar.
Lea los ganchos de subida y bajada del cliente en lugar de adivinar. Unas pocas líneas de shell en /etc/openvpn/up.sh o en un directorio equivalente explican un comportamiento que de otro modo parece aleatorio, y también son el lugar donde puede hacer que el cliente coopere en vez de competir.
Comprobación 4: corríjalo en el dueño, no en el archivo
Una vez que conozca al dueño, configure el DNS a través de la interfaz que ese dueño admite. Para systemd-resolved eso significa ajustes por enlace y dominios de enrutamiento en lugar de un archivo estático; para NetworkManager significa los ajustes de DNS del perfil de conexión y el backend elegido; para una distribución con integración de resolvconf significa escribir a través de ese auxiliar.
No haga el archivo inmutable. El atributo inmutable detiene las renovaciones legítimas de DHCP y las actualizaciones de la VPN junto con las que usted combatía, y deja el sistema en un estado en el que la siguiente actualización de paquetes o reconexión produce un fallo que nadie puede explicar a partir de la configuración. Oculta el conflicto de propiedad, que es precisamente lo que intentaba resolver.
Cuando dos componentes realmente deben coexistir, déles trabajos distintos. Deje que el gestor de red sea dueño de la configuración a nivel de interfaz, deje que el cliente de VPN aporte DNS y dominios por enlace mediante la misma integración, y elimine el tercer script que escribe el archivo directamente. La documentación de systemd-resolved expone los modos que admite y qué expone cada uno en /etc/resolv.conf. Elija el modo que encaje con la cantidad de política que necesita conservar. Si el DNS dividido importa, la disposición stub con dominios por enlace lo conserva, mientras que el modo que copia los servidores upstream al archivo lo aplana en silencio.
Verifique después de una reconexión, no después de la edición
Un archivo que parece correcto justo después de su cambio no demuestra nada, porque el siguiente evento aún no ha ocurrido. Active la secuencia que antes lo rompía: baje y vuelva a subir el túnel, renueve la concesión DHCP o cambie la interfaz, y luego lea de nuevo los mismos valores.
resolvectl query build.corp.example
resolvectl query example.com
resolvectl status | head -40
Después confirme la distinción que importa: el nombre interno se resuelve mediante el servidor interno mientras el nombre público sigue funcionando. Una configuración que envía todo al servidor interno parece correcta hasta que alguien intenta llegar a internet por el túnel, y una configuración que envía todo al público filtra nombres internos.
Anote el dueño, el backend y el modo de enlace simbólico en las notas de despliegue. Ese único párrafo convierte una futura actualización de paquetes de incidente en elemento de revisión, y evita que la siguiente persona redescubra el mismo conflicto con un comando chattr.