Cómo funciona
Una máquina detrás de NAT no puede aceptar conexiones entrantes, pero sí puede hacer conexiones salientes. Así que se conecta hacia fuera a un servidor con dirección pública y le pide que escuche en un puerto. Las conexiones a ese puerto vuelven por la conexión SSH ya existente.
Para los otros dos tipos de reenvío, consulta túneles SSH locales, remotos y dinámicos.
Entrar por SSH a la máquina oculta
La máquina oculta necesita su propio servidor SSH en marcha. En la máquina oculta:
ssh -N -o ExitOnForwardFailure=yes -R 2222:localhost:22 user@server
-N no ejecuta ningún comando remoto. -R 2222:localhost:22 significa que el puerto 2222 del servidor lleva al puerto 22 de esta máquina. Añade -f para ponerlo en segundo plano.
En el servidor, puedes ver el puerto y usarlo:
$ ss -ltn | grep 2222
LISTEN 0 128 127.0.0.1:2222 0.0.0.0:*
LISTEN 0 128 [::1]:2222 [::]:*
$ ssh -p 2222 hiddenuser@localhost
Desde tu portátil, pasa por el servidor en un solo paso:
ssh -J user@server -p 2222 hiddenuser@localhost
Para no mezclar las claves de host, ya que localhost podría significar muchas máquinas, pon esto en ~/.ssh/config:
Host home
HostName localhost
Port 2222
User hiddenuser
ProxyJump user@server
HostKeyAlias home
Mostrar una aplicación web local
ssh -N -R 8080:localhost:3000 user@server
Ahora curl http://localhost:8080/ en el servidor llega al puerto 3000 de tu máquina. En nuestra prueba, desde otra máquina, curl http://server:8080/ fue rechazado hasta que cambiamos GatewayPorts.
Con el puerto 0, el servidor elige un puerto libre y ssh lo muestra:
$ ssh -N -R 0:localhost:3000 user@server
Allocated port 33341 for remote forward to localhost:3000
GatewayPorts: quién puede llegar al puerto
Este ajuste está en el sshd_config del servidor y por defecto vale no. Lo que medimos:
| GatewayPorts | -R 8080:... | -R 0.0.0.0:8080:... |
|---|---|---|
no | Solo loopback | Solo loopback, y la dirección se ignora |
clientspecified | Solo loopback | Todas las direcciones, accesible desde otras máquinas |
yes | Todas las direcciones | Todas las direcciones |
Con yes, incluso -R localhost:8080:... escuchó en todas las direcciones en nuestra prueba. Si necesitas acceso desde fuera, clientspecified deja la decisión al cliente, y el cortafuegos todavía tiene que permitir el puerto.
Mantenerlo privado
- Deja
GatewayPorts noy usa-Jcomo se muestra arriba. Así solo puede llegar al puerto quien pueda iniciar sesión en el servidor. - Recuerda a los demás usuarios del servidor. El loopback lo comparten todos los que están conectados ahí. Pueden llegar al puerto, y el servicio que hay detrás sigue necesitando su propio inicio de sesión.
- Usa una clave y una cuenta dedicadas para el túnel, ya que la máquina detrás de NAT guarda una clave que puede entrar en tu servidor. La guía de autossh muestra una configuración restringida y probada.
Cuando el puerto está ocupado
Con ExitOnForwardFailure=yes, ssh se detiene y sale con código 255:
Error: remote port forwarding failed for listen port 2222
Sin esa opción, solo recibes un Warning y ssh sigue conectado sin túnel, algo fácil de pasar por alto. Una causa común es que una conexión antigua siga ocupando el puerto en el servidor. AllowTcpForwarding no o una regla PermitListen en el servidor producen el mismo tipo de fallo.
Mantenerlo en marcha
Un ssh -R simple termina cuando se cae la conexión, y nada lo reinicia. Para un túnel permanente, sigue autossh y systemd.
Preguntas
¿Qué diferencia hay entre ssh -L y ssh -R?
-L abre un puerto en tu máquina que lleva a algo que el servidor puede alcanzar. -R hace lo contrario: abre un puerto en el servidor que vuelve a tu máquina.
¿Por qué otras máquinas no llegan al puerto del túnel inverso?
Con el valor por defecto GatewayPorts no, el servidor solo escucha en su loopback. Pon GatewayPorts clientspecified o yes en sshd_config y abre el puerto en el cortafuegos.
¿Cómo mantengo activo un túnel SSH inverso?
Un ssh -R simple termina cuando se cae la conexión. Ejecútalo con autossh y systemd para que se reinicie solo.