Túnel SSH: "bind: Address already in use" y "remote port forwarding failed"

Algo ya escucha en el puerto que quiere tu túnel. Con -L ese puerto está en tu máquina, y con -R está en el servidor. Muchas veces es una sesión SSH antigua que sigue sujetando el túnel. Búscala con lsof -nP -iTCP:8080 -sTCP:LISTEN y luego detén ese proceso o usa otro puerto. Añade -o ExitOnForwardFailure=yes, porque sin esa opción SSH inicia sesión igualmente y te deja sin túnel.

Actualizada el . Todos los mensajes y comandos se reprodujeron con OpenSSH 10.3 en macOS contra un servidor OpenSSH 10.0 en Linux.

Reenvío local (-L): el puerto está ocupado en tu máquina

Con ssh -L 8080:localhost:80 user@server puede aparecer:

bind [127.0.0.1]:8080: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 8080
Could not request local forwarding.

Averigua quién ocupa el puerto. Esto funciona en macOS y Linux:

lsof -nP -iTCP:8080 -sTCP:LISTEN
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ssh     4242 user    4u  IPv4 ...         0t0  TCP 127.0.0.1:8080 (LISTEN)

En Windows usa netstat -ano | findstr :8080.

  • ssh: un túnel anterior sigue en marcha, a menudo iniciado con -f y olvidado. Ejecuta kill 4242 con el PID que aparece, o mira la sección sobre conexiones compartidas más abajo.
  • Un servidor de desarrollo, Docker o una base de datos: elige otro puerto local. Solo hay que cambiar el número de la izquierda: ssh -L 18080:localhost:80 user@server.
  • En macOS, ControlCe en el puerto 5000 o 7000 es el receptor de AirPlay. Elige otro puerto, o desactiva el receptor de AirPlay en Ajustes del Sistema.

¿No sabes qué opción necesitas? Túneles SSH: redirección local, remota y dinámica compara los tres.

Solo apareció la primera línea

Si ves únicamente bind [127.0.0.1]:8080: Address already in use y la sesión se abre, SSH enlazó el lado IPv6 pero no el IPv4. -L 8080:... intenta ambos. El puerto queda a medias: los clientes que usan 127.0.0.1 llegan al otro programa, no a tu túnel. Indica la dirección y SSH informará del fallo como es debido:

ssh -o ExitOnForwardFailure=yes -L 127.0.0.1:8080:localhost:80 user@server

Reenvío remoto (-R): el puerto está ocupado en el servidor

Con ssh -R 8080:localhost:80 user@server:

Warning: remote port forwarding failed for listen port 8080

La sesión se abre igualmente y el aviso es fácil de pasar por alto. La causa está en el servidor, y su log contiene la misma línea bind. Mira allí quién ocupa el puerto:

ssh user@server "ss -ltnp | grep ':8080'"

El nombre del proceso solo aparece para tus propios procesos, salvo que lo ejecutes con sudo. A veces el dueño es sshd o sshd-session: la conexión anterior desde tu portátil o tu script de túnel murió sin que el servidor se enterara, y sigue sujetando el puerto. Busca y termina esa sesión en el servidor:

sudo ss -ltnp | grep ':8080'
sudo kill PID

Para que el servidor las limpie por sí solo, añade esto a sshd_config y recarga el servicio. Desconecta a un cliente que lleve unos 90 segundos en silencio:

ClientAliveInterval 30
ClientAliveCountMax 3

Un puerto ocupado no es el único motivo de este aviso. Si el puerto está libre, puede que el servidor prohíba el reenvío, caso que se trata en administratively prohibited.

Si no necesitas un puerto fijo, deja que el servidor elija uno. El cliente muestra el puerto que le tocó:

ssh -R 0:localhost:80 user@server
Allocated port 38587 for remote forward to localhost:80

Haz que un túnel fallido falle a la vista

Por defecto SSH inicia sesión aunque el reenvío haya fallado, así que los scripts siguen adelante y fallan más tarde por un motivo confuso. Con esta opción termina con el código 255:

ssh -o ExitOnForwardFailure=yes -N -L 127.0.0.1:8080:localhost:80 user@server

Con -R, el mensaje es entonces:

Error: remote port forwarding failed for listen port 8080

Usa esta opción en todo lo automatizado, incluido autossh. Así un bucle de reintentos puede ver el fallo y volver a intentarlo cuando el puerto esté libre.

Las conexiones compartidas también ocupan puertos

Con ControlMaster, el reenvío pertenece al proceso maestro en segundo plano, de modo que cerrar la terminal no libera el puerto. Puedes hablar con el maestro usando el mismo host y la misma configuración:

ssh -O check user@server
ssh -O cancel -L 127.0.0.1:8080:localhost:80 user@server
ssh -O exit user@server

Consulta multiplexación SSH para más detalles.

Preguntas

¿Cómo sé qué proceso usa un puerto?

En macOS y Linux ejecuta lsof -nP -iTCP:8080 -sTCP:LISTEN, o ss -ltnp en Linux. En Windows usa netstat -ano | findstr :8080. La salida muestra el programa y su PID.

¿Por qué SSH inicia sesión aunque la redirección de puertos haya fallado?

Por defecto, una redirección fallida es solo un aviso. Añade -o ExitOnForwardFailure=yes y ssh termina con estado 255, así los scripts se enteran.

¿Cómo cierro un túnel SSH que corre en segundo plano?

Busca su proceso ssh con lsof y ejecuta kill con su PID. Si pertenece a una conexión ControlMaster, usa ssh -O cancel o ssh -O exit con el mismo host.

Fuentes

Más en Mensajes de error

Todas las guías