Riesgos del reenvío del agente SSH (agent forwarding) y alternativas

Con ssh -A, tu agente se queda en tu ordenador, pero el host remoto recibe un socket que habla con él. Root en ese host puede usar el socket para entrar en cualquier sitio donde funcionen tus claves, mientras sigas conectado. La clave en sí no se copia. Usa ssh -J para pasar por un jump host.

Actualizada el . Probado con OpenSSH 10.3 en macOS y un ssh-agent de prueba aparte contra OpenSSH 10.0 en Debian 13.

Qué hace -A

Sin reenvío, tus claves no sirven de nada una vez que estás dentro de un servidor, así que un segundo salto desde allí no puede usarlas. ssh -A lo resuelve conectando el host remoto de vuelta a tu agente:

ssh -A user@server
echo "$SSH_AUTH_SOCK"
/tmp/ssh-G63yAM532X/agent.1441

Esa ruta es un socket Unix en el servidor. Todo lo que se envía a él viaja de vuelta al agente de tu ordenador, que firma lo que se le pide y devuelve el resultado. El servidor nunca recibe la clave privada.

La ubicación depende de la versión del servidor. Vimos /tmp/ssh-XXXXXXXXXX/agent.<pid> en OpenSSH 10.0. La versión 10.1 movió los sockets de agente a ~/.ssh/agent/.

Para cargar antes las claves en un agente local, consulta ssh-agent y el llavero de macOS.

Qué puede hacer root en el host remoto

Los permisos de archivo protegen el socket frente a otros usuarios normales, y root los ignora. Lo probamos en un servidor mientras un usuario estaba conectado con -A. Como root:

# find /tmp -type s -name 'agent.*'
/tmp/ssh-G63yAM532X/agent.1441

# SSH_AUTH_SOCK=/tmp/ssh-G63yAM532X/agent.1441 ssh-add -l
256 SHA256:IikDwOZxEooOrmm+d3MXJXlobc7rwEyUrQNIBXHzXaU key (ED25519)

# SSH_AUTH_SOCK=/tmp/ssh-G63yAM532X/agent.1441 ssh user@203.0.113.11 id -un
user

Así, root usó la clave para entrar en otra máquina, sin ningún aviso en el lado del usuario. Este es el cuadro completo:

  • Puede: usar todas las claves de tu agente, para entrar en cualquier servidor o servicio que las acepte, incluida una cuenta de alojamiento de código. También puede listar tus claves públicas y quitar claves de tu agente: ssh-add -D ejecutado en el servidor vació nuestro agente local.
  • No puede: copiar la clave privada. El agente no la entrega. Un socket robado deja de funcionar cuando termina tu sesión, y confirmamos que el socket desaparece en ese momento.
  • Otro usuario normal fue rechazado: Error connecting to agent: Permission denied.

Aquí "root" incluye a cualquiera que haya entrado en el servidor y obtenido root. Un acceso hecho mientras estás conectado puede dejar su propia clave en el destino y mantener el acceso mucho después de que te vayas. Por eso la corta vida del socket tranquiliza menos de lo que parece.

La alternativa: ProxyJump

La mayoría usa el reenvío para pasar por un bastión. Con -J, tu ordenador abre una conexión cifrada a través del jump host hasta el servidor final, y las claves se usan solo desde tu ordenador:

ssh -J user@bastion user@server

O en ~/.ssh/config:

Host server
    HostName 10.0.0.5
    ProxyJump user@bastion

En nuestra prueba la conexión funcionó, $SSH_AUTH_SOCK estaba vacío en el destino y no existía ningún socket de agente en el jump host. Un bastión comprometido no obtiene nada que usar. Consulta ProxyJump y jump hosts.

Si de verdad necesitas el reenvío

Un caso típico es ejecutar git pull en un servidor con tus credenciales personales. Primero pregúntate si bastaría una deploy key para ese único repositorio, guardada en el servidor. Si aun así necesitas el reenvío, reduce lo que expone.

Pregunta antes de cada uso: ssh-add -c

ssh-add -c ~/.ssh/id_ed25519

Ahora tu agente pide confirmación en tu propia pantalla cada vez que se usa la clave, así que una petición inesperada se ve. Si la rechazas, el inicio de sesión falla:

sign_and_send_pubkey: signing failed for ED25519 "key" from agent: agent refused operation

Necesita un programa ssh-askpass en tu ordenador, que quizá tengas que instalar. En macOS no encontramos ninguno por defecto. Sin él, pruébalo antes de fiarte.

Expón menos claves

  • Ejecuta un agente aparte que contenga solo la clave necesaria, y reenvía ese con ForwardAgent /path/to/agent.sock en el bloque del host.
  • Limita el tiempo que las claves permanecen cargadas con ssh-add -t 1h ~/.ssh/id_ed25519.
  • Usa una clave que abra solo lo que necesita este trabajo, y no tu clave principal.
  • Mira las restricciones de destino, ssh-add -h, que limitan dónde puede usarse una clave.

Reenvía solo a hosts concretos

Host build-box
    ForwardAgent yes

No pongas nunca ForwardAgent yes bajo Host *. Está desactivado por defecto, y es lo correcto. Un solo ssh descuidado a un servidor en el que no confías del todo le daría tu agente durante la sesión.

Cuándo es aceptable

Es un compromiso razonable cuando se cumple todo esto: confías en todos los que tienen root en ese host, y confías en que el host no está comprometido; la sesión es corta; y no podrías hacer el trabajo con -J ni con una deploy key. Evítalo en servidores compartidos, en hosts expuestos a internet que gestionan otros, y en cualquier máquina a la que no dejarías tu portátil desbloqueado.

Desactivarlo en un servidor

AllowAgentForwarding no

Con esto en sshd_config, ssh -A conectó con normalidad en nuestra prueba pero no apareció ningún socket. El manual advierte de que los usuarios con acceso a shell aún pueden montar sus propios reenviadores, así que considéralo un valor por defecto que evita accidentes, y no una barrera infranqueable.

Preguntas

¿Es seguro el reenvío del agente SSH?

Solo en servidores donde confías en todos los que tienen root. Mientras estás conectado, root puede usar tus claves para entrar en otros sitios como tú. No puede copiar la clave privada.

¿Qué diferencia hay entre ssh -A y ssh -J?

-A deja que el host remoto use tu agente. -J pasa por un host de salto hasta el destino, y las claves se usan solo desde tu ordenador: el host de salto no tiene nada que aprovechar.

¿Cómo desactivo el reenvío del agente en un servidor?

Pon AllowAgentForwarding no en sshd_config y recarga sshd. Quien tenga una shell puede montar su propio reenvío, así que es una protección contra descuidos, no una barrera.

Fuentes

Más en Proteger un servidor

Todas las guías