termal.in

← Blog

Túneles SSH inversos (ssh -R): expón un puerto local a través de un servidor remoto

· Termalin Team sshport-forwardingtunnelingtutorial

Tienes algo corriendo en tu portátil —un servidor de desarrollo, una API, una máquina en casa tras NAT— y algo al otro lado de internet necesita llegar hasta ello. Sin IP pública, sin acceso al router, sin tiempo para montar una VPN. Ese es el trabajo del túnel SSH inverso, ssh -R: hace aparecer un puerto en un servidor al que sí puedes llegar, y canaliza en silencio todo lo que le llega de vuelta hasta tu máquina.

Es el flag que la gente entiende al revés, así que arreglemos primero el modelo mental y luego recorramos los casos reales.

El modelo mental: -L, reflejado

Todo túnel SSH abre un puerto de escucha en una máquina y envía lo que llega a algún sitio alcanzable desde la otra máquina. Con el reenvío local (-L), el puerto se abre en tu máquina y el tráfico sale por el lado del servidor. Un túnel inverso es justo la imagen reflejada:

Con -R, el puerto de escucha se abre en el servidor remoto, y las conexiones a él salen por tu lado.

Ese es todo el truco. La máquina que no puede aceptar conexiones entrantes hace en su lugar una conexión SSH saliente, y las conexiones vuelven a entrar montadas sobre ella. Si los dos aún se te mezclan, el retrato de familia completo está en reenvío de puertos SSH, explicado.

La sintaxis, leída de izquierda a derecha

ssh -R [bind_address:]remote_port:localhost:local_port user@server

Léela así: en el servidor, escucha en remote_port; reenvía lo que llegue a localhost:local_port —tal como se resuelve desde mi máquina. Así que:

ssh -R 8080:localhost:3000 deploy@vps.example.com

abre el puerto 8080 en el VPS, y cada conexión a él aterriza en el puerto 3000 de tu portátil. El destino no tiene por qué ser tu propio portátil: -R 8080:192.168.1.50:80 reenvía a otra máquina de tu LAN, usando tu portátil como salida.

Un flag que conviene conocer: -R 0:localhost:3000 deja que el servidor elija cualquier puerto libre, e imprime Allocated port 43022 for remote forward para que sepas cuál te tocó.

Tres cosas que la gente construye de verdad con esto

Enseñar un servidor de desarrollo local a un cliente. Tu trabajo en curso corre en localhost:3000. En vez de desplegarlo en algún sitio solo para una demo:

ssh -N -R 8080:localhost:3000 deploy@demo.example.com

Cualquiera que pueda llegar a demo.example.com:8080 está viendo ahora la app de tu portátil, en vivo. (-N omite la shell remota: solo quieres el túnel. Que pueda conectarse cualquiera o solo el propio servidor depende de GatewayPorts —siguiente sección.)

Llegar a una máquina de casa tras NAT. Tu equipo de casa no puede aceptar conexiones, pero sí hacerlas. Haz que mantenga un túnel de salida hacia un VPS pequeño:

# en la máquina de casa
ssh -N -R 2222:localhost:22 tunnel@vps.example.com

Ahora el puerto 2222 del VPS es el puerto SSH de la máquina de casa, y desde cualquier parte:

ssh -J vps.example.com -p 2222 you@localhost

salta a través del VPS directo a la máquina tras NAT. Esta es la respuesta autoalojada clásica a cómo entrar por SSH a tu servidor de casa.

Entregar webhooks a tu portátil. Un proveedor de pagos o un host de git necesita hacer POST a tu manejador en desarrollo. Canaliza su endpoint alcanzable de vuelta hasta ti:

ssh -N -R 9000:localhost:9000 deploy@vps.example.com

Apunta el webhook al VPS. Si mantienes el túnel atado al loopback del servidor (lo predeterminado), pon nginx o cualquier proxy inverso en el VPS delante de 127.0.0.1:9000: obtienes terminación TLS gratis y nunca expones el puerto crudo del túnel.

GatewayPorts: por qué nadie más puede llegar a tu túnel

La sorpresa número uno: el túnel funciona cuando lo pruebas desde el servidor (curl localhost:8080 tiene éxito) pero nadie de fuera puede conectarse. Es a propósito: por defecto, sshd ata los puertos reenviados remotos solo a 127.0.0.1, sin importar qué bind address pidieras.

Para abrir un túnel al mundo, el /etc/ssh/sshd_config del servidor necesita:

GatewayPorts clientspecified

luego reinicia sshd, y pide el bind de forma explícita: ssh -R 0.0.0.0:8080:localhost:3000 .... (GatewayPorts yes ata cada reenvío remoto a todas las interfaces, lo cual es más amplio de lo que normalmente quieres.) Es una decisión del lado del servidor que no puedes anular desde el cliente: un valor de seguridad deliberado, porque un túnel inverso es un agujero perforado desde dentro, y lo que exponga queda, en la práctica, de cara a internet. Trátalo así.

Dos interruptores relacionados del lado del servidor pueden morderte: AllowTcpForwarding no desactiva los túneles por completo, y PermitListen puede restringir qué puertos puede reclamar -R.

Mantenerlo vivo

Un túnel inverso es una sola conexión TCP, y las conexiones TCP ociosas mueren. Para cualquier cosa más larga que una demo:

ssh -N -R 2222:localhost:22 \
    -o ServerAliveInterval=30 \
    -o ExitOnForwardFailure=yes \
    tunnel@vps.example.com
  • ServerAliveInterval 30 mantiene el tráfico en movimiento para que las entradas de NAT y los tiempos de espera por inactividad no se lleven la conexión.
  • ExitOnForwardFailure yes hace que ssh muera de forma ruidosa si el puerto remoto no se puede atar, en vez de conectarse igualmente y no reenviar nada.
  • autossh envuelve el comando y reinicia el túnel cada vez que se cae: la herramienta estándar para túneles que deben sobrevivir a reinicios y redes inestables, normalmente ejecutada como autossh -M 0 -N -R ... bajo una unidad de systemd.

Y una vez que un túnel se gana un sitio permanente, pásalo a ~/.ssh/config con una línea RemoteForward para que viaje con la entrada del host —estructura cubierta en la guía de ssh_config (en inglés):

Host homelink
    HostName vps.example.com
    User tunnel
    RemoteForward 2222 localhost:22
    ServerAliveInterval 30
    ExitOnForwardFailure yes

-L vs -R vs -D de un vistazo

FlagEl puerto se abre enEl tráfico sale porTrabajo típico
-Ltu máquinael lado del servidortraer una BD/panel remoto a localhost
-Rel servidortu ladoexponer un servicio local; llegar a una máquina tras NAT
-Dtu máquinael lado del servidor, cualquier destinoproxy SOCKS hacia una red

Cuándo un túnel inverso es la herramienta equivocada

Un túnel inverso es una respuesta temporal soberbia: demos, depuración de webhooks, rescatar una máquina tras NAT. Es una mala respuesta permanente. Si lo que expones tiene que estar arriba durante meses, servir a usuarios reales o sobrevivir a que tu portátil se duerma, eso es tráfico de entrada, y el tráfico de entrada merece infraestructura de verdad: un proxy inverso en un servidor, una VPN o red superpuesta, un despliegue real. El encanto del túnel es que es un solo comando sin huella permanente; en cuanto estás escribiendo monitorización para él, se te ha quedado pequeño.

Resolver los fallos habituales

  • Warning: remote port forwarding failed for listen port 8080 —el puerto está ocupado en el servidor. A menudo el culpable es tu propio túnel anterior: el proceso sshd viejo retiene el puerto hasta que la conexión muerta expira. Los keepalives evitan el zombi; -R 0:... esquiva la colisión; ExitOnForwardFailure convierte el aviso en un error que no puedes pasar por alto.
  • Funciona desde el servidor, rechazado desde fuera —el puerto de escucha está en el loopback del servidor. Es el valor por defecto de GatewayPorts haciendo su trabajo; configúralo o pon un proxy inverso delante del puerto.
  • El túnel conecta pero el servicio no responde —revisa la mitad local: ¿hay de verdad algo escuchando en el puerto local que nombraste? -R 8080:localhost:3000 sin nada en tu :3000 da conexión rechazada a cada visitante.
  • La propia conexión SSH no se establece —ese es otro problema con su propia lista: conexión rechazada y agotada, descifradas.

Cuando los túneles se vuelven mobiliario

El túnel inverso que ejecutas una vez, lo tecleas. El que lleva tu laboratorio casero, tu máquina de demos y tu endpoint de webhooks es estado que reconstruyes cada mañana tras cada suspensión del portátil, y del que pierdes la pista para el jueves. El gestor de túneles guardados de Termalin mantiene los reenvíos locales, remotos y dinámicos atados al host al que pertenecen: arráncalos con un clic, ve de un vistazo cuáles están vivos, y deja que se restablezcan con la conexión en vez de reteclearlos desde el historial de la shell. La lista de hosts —claves, jump hosts, keepalives y túneles incluidos— se sincroniza entre tus máquinas con cifrado de extremo a extremo. Y cuando una máquina se queda tras NAT para siempre, su Connector solo de salida reemplaza por completo el túnel inverso hecho a mano: sin puerto de entrada, y sin unidad autossh que cuidar. La línea de comandos te enseña qué significa -R; un cliente evita que los túneles de los que dependes dependan de tu memoria.


Termalin es un cliente SSH gratis y multiplataforma con túneles integrados, SFTP y un gestor de claves — descárgalo, o mira cómo maneja tus claves de forma segura.

Pruébalo en un host.

Termalin es un cliente SSH rápido para ti y para tus agentes.

Plan gratuito · 14 días de Pro de prueba · precios