SSD Nodes Learn 🎉 VPS desde $5.50/mes
Guías Matt ConnorPor Matt Connor

Configurar sudo-rs en Ubuntu: cambios en sudoers

Ubuntu 26.04 utiliza sudo-rs por defecto. Aprenda a ajustar sus reglas sudoers, ya que el soporte para comodines en argumentos de comandos cambia frente a la versión original en C.

Cambios de sudo-rs en Ubuntu

Ubuntu 26.04 LTS incluye sudo-rs como el sudo predeterminado, por lo que el comando sudo en un servidor nuevo ejecuta la reimplementación en Rust en lugar del programa original en C. La mayoría de los archivos sudoers siguen funcionando exactamente igual. La regla que falla es aquella que contiene un comodín dentro de los argumentos de un comando, ya que sudo-rs no compara patrones glob con el texto de los argumentos.

Ubuntu 25.10 realizó el cambio primero y 26.04 LTS lo mantuvo. Ubuntu 24.04 LTS no se ve afectado, ya que sigue seleccionando el sudo original a menos que instale sudo-rs manualmente. El momento en que esto es relevante es cuando realiza una actualización de Ubuntu 24.04 a 26.04, o cuando configura un servidor nuevo con la versión más reciente. Si también utiliza las versiones intermedias, cómo difieren las versiones LTS e intermedias de Ubuntu en un servidor explica qué máquina recibe un cambio como este primero.

Compruebe qué versión de sudo está ejecutando realmente su servidor

No intente deducirlo a partir del número de versión. Pregúntele a la máquina.

sudo --version
update-alternatives --config sudo
dpkg -l 'sudo*'

Confíe en sudo --version en su propio equipo por encima de cualquier tabla de versiones en Internet, incluida esta página. update-alternatives --config sudo es la otra mitad de la respuesta: enumera todos los proveedores instalados de /usr/bin/sudo y marca el seleccionado. Que un paquete esté instalado no significa que esté seleccionado, así que lea la selección, no la lista de paquetes.

Ambas implementaciones se empaquetan durante la transición. La versión en Rust es sudo-rs, en la versión 0.2.13 en 26.04 a fecha de agosto de 2026. La original, mantenida por Todd C. Miller, se empaqueta como sudo.ws, y sus programas llevan el sufijo .ws: sudo.ws y visudo.ws.

Por qué Ubuntu cambió a sudo-rs

sudo tiene el bit setuid root. Cualquier usuario en el sistema puede ejecutarlo y este inicia con privilegios totales, por lo que un error de memoria en su código constituye una vulnerabilidad de escalada de privilegios local. El CVE-2021-3156 fue exactamente eso: un desbordamiento de búfer en el heap accesible por cualquier usuario local, el cual permaneció en el código distribuido durante cerca de diez años. Rust detecta esa clase de errores en tiempo de compilación, lo cual constituye el argumento principal para su reescritura.

La segunda razón es el alcance, y es la que afecta a su configuración. El sudo original ha acumulado un gran conjunto de funciones a lo largo de tres décadas, y cada función implica más código ejecutándose como root. sudo-rs implementa un subconjunto de forma deliberada. Todo lo que sus autores consideraron especializado o potencialmente perjudicial fue excluido, por lo que una regla de sudoers que funcionó durante años puede simplemente no existir. Su regla con comodines es uno de esos casos.

La seguridad de memoria elimina una clase de errores. No hace que un programa esté libre de fallos, y sudo-rs ha publicado sus propias correcciones de seguridad desde que se convirtió en el valor predeterminado. Aplique parches como lo haría con cualquier otro componente.

Qué reglas de sudoers siguen funcionando

El archivo es el mismo. sudo-rs lee /etc/sudoers y los archivos adicionales en /etc/sudoers.d/, y las configuraciones habituales que escribe un operador de servidor son compatibles:

  • deploy ALL=(ALL:ALL) ALL, y formatos de grupo como %sudo ALL=(ALL:ALL) ALL
  • las etiquetas NOPASSWD: y PASSWD:
  • User_Alias, Runas_Alias, Host_Alias y Cmnd_Alias
  • un comando con una lista de argumentos exacta, por ejemplo /usr/bin/systemctl restart app-api
  • un comando seguido de "", que permite el comando solo sin ningún argumento
  • un comando seguido de * como su argumento final, que permite cualquier argumento posterior
  • una ruta de directorio que termina en /, que permite cualquier comando en ese directorio
  • ! para restar un comando de una lista
  • un subconjunto útil de Defaults, incluyendo secure_path, env_keep, env_check, timestamp_timeout, passwd_tries, editor, umask, targetpw, rootpw y use_pty

Dos valores predeterminados se comportan de forma distinta y suelen confundir a los usuarios. env_reset no se puede desactivar en sudo-rs: siempre está activo. use_pty está activado por defecto, por lo que el comando se ejecuta en su propio pseudo-terminal.

Por qué su regla comodín en sudoers dejó de coincidir

Los comodines siguen permitidos en un lugar: el nombre de archivo del comando. Una regla de %ops ALL = /sbin/fsck* aún permite sudo fsck y sudo fsck_exfat, porque el * es parte de la ruta que se compara con el sistema de archivos.

Dentro de la lista de argumentos, sudo-rs solo acepta dos formas especiales, y ninguna es un patrón. "" significa sin argumentos. Un * final significa cualquier argumento posterior. Cualquier otro argumento se compara como texto literal. Por lo tanto, %ops ALL = /sbin/service ntp * es correcto, porque ntp es literal y el * está al final. Sin embargo, una regla como esta no otorga nada de lo que usted pretendía:

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*

app-* es un patrón en medio de un argumento. sudo-rs no lo expande, por lo que la regla no cubre systemctl restart app-api y sudo rechaza el comando. Dos comandos le dicen la verdad sobre cualquier regla en su propio servidor: sudo -l -U deploy, ejecutado como root, imprime lo que esa cuenta puede ejecutar realmente, y sudo visudo -c le indica si el archivo se analiza correctamente. Ejecútelos antes de empezar a editar al azar.

La regla de comodines siempre fue una vulnerabilidad

En el sudo original, los argumentos que usted escribe se unen en una sola cadena y se comparan con la cadena de argumentos de la regla mediante un glob. Un glob coincide con los espacios en blanco. Esa es la parte que casi todo el mundo pasa por alto.

La documentación de sudo-rs ofrece la demostración más clara. Una regla de /bin/rm *.txt también permite sudo rm -rf /home .txt, porque el * absorbe -rf /home y la cadena unida sigue terminando en .txt. La regla se interpreta como "solo archivos de texto". Significa "cualquier argumento, siempre que la línea termine en .txt".

Lo mismo se aplica al ejemplo de systemctl. Debido a que los argumentos se comparan como una sola cadena unida, un patrón al final también coincide con cualquier cosa que usted añada después, por lo que restart app-* cubre restart app-api más cualquier argumento adicional que el llamador añada. Un patrón dentro de un argumento revela los argumentos que lo rodean, y los argumentos son donde reside el poder de un comando. sudo-rs rechaza esta construcción en lugar de intentar hacerla segura, porque no existe una forma general segura de utilizarla.

Reemplace el comodín con una lista de comandos explícita

La mayoría de las reglas con comodines existen porque alguien no quiso escribir cuatro líneas. Escriba las cuatro líneas.

Cmnd_Alias APP_RESTART = /usr/bin/systemctl restart app-api, /usr/bin/systemctl restart app-worker
Cmnd_Alias APP_STATUS = /usr/bin/systemctl status app-api, /usr/bin/systemctl status app-worker
deploy ALL=(root) NOPASSWD: APP_RESTART, APP_STATUS

Indique la ruta correcta. Una regla que nombra /bin/systemctl en un sistema donde el binario es /usr/bin/systemctl nunca coincidirá, y el fallo parece idéntico a un problema de permisos. Confirme con command -v systemctl y pegue lo que imprima.

Coloque la regla en su propio archivo de configuración (drop-in) en lugar de en /etc/sudoers, para que una actualización del paquete nunca entre en conflicto con su edición:

sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deploy

Nombre el archivo sin un punto y sin una tilde al final. El comando sudo original ignora los archivos en sudoers.d cuyos nombres contienen un punto, por lo que 90-deploy.conf es una operación nula silenciosa clásica, y mantener la convención no tiene coste alguno.

Utilice un wrapper propiedad de root cuando la lista sea extensa

Cuando el conjunto permitido es demasiado grande para enumerarlo, traslade la decisión fuera de sudoers a un pequeño programa propiedad de root.

sudo tee /usr/local/sbin/app-restart >/dev/null <<'EOF'
#!/bin/sh
set -eu
case "${1:-}" in
  app-api|app-worker) ;;
  *) echo "app-restart: not allowed: ${1:-}" >&2; exit 1 ;;
esac
exec /usr/bin/systemctl restart "$1"
EOF
sudo chown root:root /usr/local/sbin/app-restart
sudo chmod 0755 /usr/local/sbin/app-restart
ls -l /usr/local/sbin/app-restart

La parte de sudoers entonces nombra un solo comando:

deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *

El * al final es aceptable aquí porque el script, no sudo, decide qué está permitido. Esto solo es válido mientras el script sea propiedad de root y nadie más pueda escribir en él. Si deploy puede escribir en el archivo, deploy puede reemplazar su contenido y ejecutar cualquier cosa como root, lo cual es peor que la regla de comodín que eliminó. Compruebe el modo con ls -l y, si el resultado no le resulta evidente, leer la cadena de permisos drwxr-xr-x toma cinco minutos de aprendizaje. La misma regla cubre el directorio: /usr/local/sbin tampoco debe ser escribible por la cuenta, ya que un directorio escribible significa que el archivo puede ser reemplazado por completo.

Asigne al trabajo su propia cuenta en lugar de una regla sudo

La pregunta más adecuada suele ser por qué el comando necesita privilegios de root en absoluto. Un servicio que se ejecuta con su propio usuario puede ser gestionado por dicho usuario, sin necesidad de incluir líneas en sudoers. Para las unidades del sistema, systemd ya delega esa decisión en polkit, por lo que una regla puede especificar una unidad y un operador:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        action.lookup("unit") == "app-api.service" &&
        subject.user == "deploy") {
        return polkit.Result.YES;
    }
});

Guárdelo como /etc/polkit-1/rules.d/50-app-api.rules y deploy podrá ejecutar systemctl restart app-api sin necesidad de sudo. Realice la prueba desde el contexto exacto que utilizará el comando, ya que es recomendable confirmar que una regla que funciona en su sesión SSH también lo hace desde cron antes de depender de ella. En cualquier caso, la cuenta que realiza el trabajo debe existir exclusivamente para esa tarea, lo cual sigue el mismo principio que las cuentas de usuario con privilegios mínimos en un VPS.

Qué más omite sudo-rs

sudo -E no está implementado. Nombre las variables que necesite con Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" en su lugar, y recuerde que env_reset siempre está activado, por lo que todo lo que no se conserve se borra.

El almacenamiento centralizado de sudoers en LDAP ha desaparecido. sudoers.ldap y cvtsudoers no están implementados, y el paquete sudo-ldap se eliminó en 26.04. La autenticación LDAP a través de PAM o SSSD sigue funcionando. La parte de políticas en un directorio es lo que queda fuera del alcance.

INTERCEPT, que intentaba impedir escapes de shell desde un comando permitido, no está implementado. De todos modos, nunca fue efectivo contra un usuario decidido. Si una regla permite a alguien ejecutar un editor o un intérprete como root, esa persona tiene privilegios de root, y ninguna opción de sudo cambia eso.

La grabación de sesiones no está implementada, por lo que no hay registro de E/S ni sudoreplay. El registro se envía únicamente a syslog, y no existe la opción logfile para redirigirlo a otro lugar, por lo que los mensajes de sudo terminan donde sea que su sistema ya envíe los registros de syslog.

¿Debería volver a sudo.ws?

Puede hacerlo, y durante el ciclo 26.04 la versión original permanece empaquetada precisamente por este motivo.

sudo apt install sudo.ws
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.ws

Copie las rutas exactas de la salida de --config en lugar de usar las de esta página, ya que esa es la lista que su propio sistema aceptará. Volver a sudo-rs más tarde implica configurar la alternativa hacia la ruta del binario de sudo-rs que aparece en esa misma lista.

Mantenga una segunda sesión SSH abierta, iniciada e inactiva, antes de tocar cualquier cosa que afecte a sudo. Un archivo sudoers que no se pueda analizar, o una alternativa que apunte a un binario que no está instalado, puede dejarle sin forma de obtener privilegios de root en una máquina remota. Ese hábito debe formar parte de todo lo que hace en los primeros diez minutos en un VPS nuevo.

Considere el cambio de vuelta como un plazo límite y no como una solución definitiva. Le otorga una semana para reescribir las reglas correctamente, y la reescritura merece la pena por sí misma, ya que cada regla con comodines que elimine estaba otorgando más permisos de los que su autor pretendía.

FAQ

¿Por qué mi regla con comodines en sudoers dejó de funcionar en Ubuntu 26.04?

Porque Ubuntu 26.04 LTS selecciona sudo-rs como el sudo predeterminado, y sudo-rs no procesa patrones de comodines dentro de los argumentos de un comando. Permite un comodín en el nombre del archivo del comando, "" para indicar la ausencia de argumentos, y un único * como argumento final. Una regla como /usr/bin/systemctl restart app-* coloca un patrón en medio de un argumento, por lo que no otorga permisos y el comando es rechazado. Ejecute sudo -l -U deploy como root para ver qué privilegios tiene realmente la cuenta, luego reemplace la regla con los comandos exactos o con un script contenedor propiedad de root.

¿Cómo vuelvo al sudo original en Ubuntu 26.04?

El original está empaquetado como sudo.ws. Instálelo con sudo apt install sudo.ws, luego apunte la alternativa hacia él con sudo update-alternatives --set sudo /usr/bin/sudo.ws. Ejecute update-alternatives --config sudo primero para leer las rutas exactas que ofrece su sistema, y mantenga una segunda sesión SSH abierta mientras realiza el cambio. Esto no recupera sudo-ldap, que fue eliminado de 26.04 independientemente de la implementación que seleccione.

¿sudo-rs lee el mismo archivo /etc/sudoers?

Sí. sudo-rs lee /etc/sudoers y los archivos adicionales en /etc/sudoers.d/, con la misma sintaxis para usuarios, grupos, alias, especificaciones de ejecución y la etiqueta NOPASSWD. Implementa un subconjunto del lenguaje sudoers, por lo que las diferencias se manifiestan como construcciones ausentes en lugar de construcciones que se comportan de forma distinta. Edite con sudo visudo, luego verifique con sudo visudo -c antes de cerrar su sesión.

¿Qué reemplaza a sudo -E en sudo-rs?

sudo -E no está implementado, y ya estaba desaconsejado en el sudo original, debido a que entregar a un proceso root un entorno que el llamador controla es una forma conocida de alterar el comportamiento de dicho proceso. En su lugar, especifique las variables que realmente necesita en sudoers, con una línea como Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". env_reset está siempre activo en sudo-rs y no puede desactivarse, por lo que toda variable que no conserve es eliminada.

#sudo#sudo-rs#ubuntu#sudoers#permissions