Tunnel SSH: "bind: Address already in use" e "remote port forwarding failed"

Qualcosa è già in ascolto sulla porta che il tuo tunnel vuole usare. Con -L quella porta è sul tuo computer, con -R è sul server. Spesso è una vecchia sessione SSH che tiene ancora aperto il tunnel. Trovala con lsof -nP -iTCP:8080 -sTCP:LISTEN, poi ferma quel processo o usa un'altra porta. Aggiungi -o ExitOnForwardFailure=yes: senza, SSH ti fa comunque entrare e ti lascia senza tunnel.

Aggiornata il . Tutti i messaggi e i comandi sono stati riprodotti con OpenSSH 10.3 su macOS contro un server OpenSSH 10.0 su Linux.

Inoltro locale (-L): la porta è occupata sul tuo computer

Con ssh -L 8080:localhost:80 user@server puoi vedere:

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.

Scopri chi occupa la porta. Funziona su macOS e 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)

Su Windows usa netstat -ano | findstr :8080.

  • ssh: un tunnel precedente è ancora attivo, spesso avviato con -f e dimenticato. Esegui kill 4242 con il PID mostrato, oppure vedi la sezione sulle connessioni condivise più sotto.
  • Un server di sviluppo, Docker o un database: scegli un'altra porta locale. Va cambiato solo il numero a sinistra: ssh -L 18080:localhost:80 user@server.
  • Su macOS, ControlCe sulla porta 5000 o 7000 è il ricevitore AirPlay. Scegli un'altra porta, oppure disattiva il ricevitore AirPlay in Impostazioni di Sistema.

Non sai quale opzione ti serve? Tunnel SSH: inoltro locale, remoto e dinamico confronta i tre tipi.

È comparsa solo la prima riga

Se vedi solo bind [127.0.0.1]:8080: Address already in use e la sessione si apre, SSH ha agganciato il lato IPv6 ma non quello IPv4. -L 8080:... prova entrambi. La porta funziona a metà: i client che usano 127.0.0.1 raggiungono l'altro programma, non il tuo tunnel. Indica l'indirizzo e SSH segnalerà l'errore correttamente:

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

Inoltro remoto (-R): la porta è occupata sul server

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

Warning: remote port forwarding failed for listen port 8080

La sessione si apre comunque e l'avviso è facile da perdere. La causa è sul server, e il suo log contiene la stessa riga bind. Guarda chi occupa la porta lì:

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

Il nome del processo compare solo per i tuoi processi, a meno che tu non lo esegua con sudo. A volte il proprietario è sshd o sshd-session: la connessione precedente dal tuo portatile o lo script del tuo tunnel è morto senza che il server se ne accorgesse, e la porta è ancora occupata. Trova e chiudi quella sessione sul server:

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

Per far pulire questi casi al server da solo, aggiungi questo a sshd_config e ricarica il servizio. Scollega un client rimasto in silenzio per circa 90 secondi:

ClientAliveInterval 30
ClientAliveCountMax 3

Una porta occupata non è l'unico motivo di questo avviso. Se la porta è libera, il server potrebbe vietare l'inoltro, caso trattato in administratively prohibited.

Se non ti serve una porta fissa, lascia che sia il server a sceglierla. Il client stampa la porta ottenuta:

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

Far fallire un tunnel in modo evidente

Per impostazione predefinita SSH ti fa entrare anche quando l'inoltro è fallito, quindi gli script vanno avanti e falliscono dopo per un motivo poco chiaro. Con questa opzione invece esce con stato 255:

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

Con -R, il messaggio diventa:

Error: remote port forwarding failed for listen port 8080

Usa questa opzione in tutto ciò che è automatizzato, anche in autossh. Così un ciclo di tentativi vede il fallimento e riprova quando la porta è libera.

Anche le connessioni condivise occupano porte

Con ControlMaster, l'inoltro appartiene al processo master in background, quindi chiudere il terminale non libera la porta. Puoi parlare con il master usando lo stesso host e la stessa configurazione:

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

Per saperne di più vedi SSH multiplexing.

Domande

Come trovo quale processo usa una porta?

Su macOS e Linux esegui lsof -nP -iTCP:8080 -sTCP:LISTEN, oppure ss -ltnp su Linux. Su Windows usa netstat -ano | findstr :8080. L'output mostra il programma e il suo PID.

Perché SSH entra anche se il port forwarding è fallito?

Di base un inoltro fallito è solo un avviso. Aggiungi -o ExitOnForwardFailure=yes e ssh esce con stato 255, così gli script se ne accorgono.

Come chiudo un tunnel SSH in background?

Trova il suo processo ssh con lsof ed esegui kill con il PID. Se appartiene a una connessione ControlMaster, usa ssh -O cancel o ssh -O exit con lo stesso host.

Fonti

Altro in Messaggi di errore

Tutte le guide