it-swarm.dev

Come mantenere in modo affidabile un tunnel SSH aperto?

Uso un tunnel SSH dal lavoro per aggirare vari firewall idotici (è ok con il mio capo :)). Il problema è che dopo un po 'la connessione ssh di solito si blocca e il tunnel è rotto.

Se potessi almeno monitorare automaticamente il tunnel, potrei riavviare il tunnel quando si blocca, ma non ho nemmeno immaginato un modo per farlo.

Punti bonus per chi può dirmi come impedire che la mia connessione SSH appaia, ovviamente!

223
Peltier

Sembra che tu abbia bisogno di autossh . Questo controllerà un tunnel ssh e lo riavvierà secondo necessità. L'abbiamo usato per un paio d'anni e sembra funzionare bene.

autossh -M 20000 -f -N your_public_server -R 1234:localhost:22 -C

Maggiori dettagli sul parametro -M qui

267
KeithB

Tutti i firewall stateful dimenticano una connessione dopo non aver visto un pacchetto per quella connessione per un po 'di tempo (per evitare che le tabelle di stato si riempiano di connessioni dove entrambe le estremità sono morte senza chiudere la connessione). La maggior parte delle implementazioni TCP invierà un pacchetto keepalive dopo un lungo periodo di tempo senza essere ascoltato dall'altra parte (2 ore è un valore comune). Se, tuttavia, esiste un firewall di stato che si dimentica della connessione prima che i pacchetti keepalive possano essere inviati, una connessione inattiva ma prolungata morirà.

In questo caso, la soluzione è impedire che la connessione diventi inattiva. OpenSSH ha un'opzione chiamata ServerAliveInterval che può essere usata per impedire che la connessione rimanga inattiva troppo a lungo (come bonus, rileverà quando il peer è morto prima, anche se la connessione è inattiva).

37
CesarB

Sulla tua mac o linux machine configura il tuo ssh tieni il server ssh vivo ogni 3 minuti. Apri un terminale e porta il tuo invisibile .ssh nella tua casa:

cd ~/.ssh/ 

quindi creare un file di configurazione a 1 riga con:

echo "ServerAliveInterval 180" >> config

dovresti anche aggiungere:

ServerAliveCountMax xxxx (high number)

il valore predefinito è 3, quindi ServerAliveInterval 180 interromperà l'invio dopo 9 minuti (3 dell'intervallo di 3 minuti specificato da ServerAliveInterval).

23
David Shaw

Ho usato il seguente script Bash per continuare a generare nuovi tunnel ssh quando il precedente muore. L'utilizzo di uno script è utile quando non si desidera o non è possibile installare pacchetti aggiuntivi o utilizzare il compilatore.

while true
do
  ssh <ssh_options> [[email protected]]hostname
  sleep 15
done

Si noti che questo richiede un file di chiavi per stabilire automaticamente la connessione, ma è il caso anche di autossh.

21
Jawa

Systemd è l'ideale per questo.

Creare un file di servizio /etc/systemd/system/sshtunnel.service contenente:

[Unit]
Description=SSH Tunnel
After=network.target

[Service]
Restart=always
RestartSec=20
User=sshtunnel
ExecStart=/bin/ssh -NT -o ServerAliveInterval=60 -L 5900:localhost:5900 [email protected]

[Install]
WantedBy=multi-user.target

(Modifica il comando ssh per adattarlo)

  • questo verrà eseguito come utente sshtunnel quindi assicurati che l'utente esista per primo
  • emettere systemctl enable sshtunnel per impostarlo per l'avvio al momento dell'avvio
  • emettere systemctl start sshtunnel per iniziare immediatamente

Aggiornamento gennaio 2018 : alcune distribuzioni (ad es. Fedora 27) possono utilizzare la politica SELinux per impedire l'uso di SSH da systemd init, nel qual caso sarà necessario creare una politica personalizzata per fornire le esenzioni necessarie.

13
IanB

Mi sembra che tu stia interpretando erroneamente ServerAliveCountMax. Come ho capito i documenti, è il numero di messaggi server alive che possono rimanere senza risposta senza che la connessione venga interrotta. Quindi, in casi come quello di cui stiamo discutendo qui, impostarlo su un valore elevato si limiterà a garantire che una connessione sospesa non venga rilevata e terminata!

La semplice impostazione di ServerAliveInterval dovrebbe essere sufficiente per risolvere il problema con un firewall che dimentica la connessione e lasciare basso ServerAliveCountMax consentirà al terminale di origine di notare l'errore e terminare se la connessione fallisce comunque.

Quello che vuoi è, 1) che la connessione rimanga aperta in modo permanente in circostanze normali, 2) che la connessione non venga rilevata e che il lato originario esca in caso di errore, e 3) che il comando ssh venga nuovamente emesso ogni volta che uscite (il modo in cui lo fai è molto dipendente dalla piattaforma, lo script "while true" suggerito da Jawa è unidirezionale, su OS XI è in realtà impostato un oggetto launchd).

9
user2793784

Usa sempre l'opzione SSH ServerAliveInterval nel caso in cui i problemi del tunnel siano generati dalle sessioni NAT scadute.

Usa sempre un metodo di rigenerazione nel caso in cui la connettività vada giù completamente, hai almeno tre opzioni qui:

  • programma autossh
  • lo script di bash (while true do ssh ...; sleep 5; done) non rimuove il comando sleep, ssh potrebbe fallire rapidamente e rigenererai troppi processi
  • /etc/inittab, per avere accesso a una scatola spedita e installata in un altro paese, dietro NAT, senza il port forwarding alla casella, è possibile configurarla per creare un tunnel ssh:

    tun1:2345:respawn:/usr/bin/ssh -i /path/to/rsaKey -f -N -o "ServerAliveInterval 180" -R 55002:localhost:22 [email protected] 'sleep 365d'
    
  • script upstart su Ubuntu, dove /etc/inittab non è disponibile:

    start on net-device-up IFACE=eth0
    stop on runlevel [01S6]
    respawn
    respawn limit 180 900
    exec ssh -i /path/to/rsaKey -N -o "ServerAliveInterval 180" -R 55002:localhost:22 [email protected]
    post-stop script
        sleep 5
    end script
    

o utilizzare sempre entrambi i metodi.

9
claudiuf

Ho risolto questo problema con questo:

Modificare

~/.ssh/config

E aggiungi

ServerAliveInterval 15
ServerAliveCountMax 4

Secondo man page per ssh_config:

ServerAliveCountMax
         Sets the number of server alive messages (see below) which may be
         sent without ssh(1) receiving any messages back from the server.
         If this threshold is reached while server alive messages are
         being sent, ssh will disconnect from the server, terminating the
         session.  It is important to note that the use of server alive
         messages is very different from TCPKeepAlive (below).  The server
         alive messages are sent through the encrypted channel and there‐
         fore will not be spoofable.  The TCP keepalive option enabled by
         TCPKeepAlive is spoofable.  The server alive mechanism is valu‐
         able when the client or server depend on knowing when a connec‐
         tion has become inactive.

         The default value is 3.  If, for example, ServerAliveInterval
         (see below) is set to 15 and ServerAliveCountMax is left at the
         default, if the server becomes unresponsive, ssh will disconnect
         after approximately 45 seconds.  This option applies to protocol
         version 2 only.

 ServerAliveInterval
         Sets a timeout interval in seconds after which if no data has
         been received from the server, ssh(1) will send a message through
         the encrypted channel to request a response from the server.  The
         default is 0, indicating that these messages will not be sent to
         the server.  This option applies to protocol version 2 only.
6
nachopro

ExitOnForwardFailure yes è un buon complemento agli altri suggerimenti. Se si connette ma non riesce a stabilire il port forwarding, è altrettanto inutile per te come se non fosse affatto connesso.

3
jcomeau_ictx

Un po 'un trucco, ma mi piace usare lo schermo per mantenere questo. Al momento ho un inoltro remoto che è stato in esecuzione per settimane.

Esempio, iniziando localmente:

screen
ssh -R ......

Quando viene applicato l'inoltro remoto e si dispone di una shell sul computer remoto:

screen
Ctrl + a + d

Ora hai un avanzamento remoto ininterrotto. Il trucco è quello di eseguire schermo su entrambe le estremità

1
landypro

Recentemente ho avuto questo problema da solo, perché queste soluzioni richiedono di reinserire la password ogni volta se si utilizza una password di accesso Ho usato sshpass in un loop con un prompt del testo per evitare di avere la password nel file batch.

Ho pensato di condividere la mia soluzione su questo punto nel caso in cui qualcun altro abbia lo stesso problema:

#!/bin/bash
read -s -p "Password: " pass
while true
do
    sshpass -p "$pass" ssh [email protected] -p port
    sleep 1
done
1
Brainfloat

Ho avuto bisogno di mantenere un tunnel SSH a lungo termine. La mia soluzione era in esecuzione da un server Linux, ed è solo un piccolo programma C che respawn ssh usando l'autenticazione basata su chiave.

Non sono sicuro riguardo l'impiccagione, ma ho perso i tunnel a causa dei timeout.

Mi piacerebbe fornire il codice per il respawner, ma non riesco a trovarlo in questo momento.

1
baumgart

mentre ci sono strumenti come autossh che aiutano a riavviare la sessione ssh ... quello che trovo veramente utile è eseguire il comando 'screen'. Ti permette di RIPRENDERE le tue sessioni ssh anche dopo che ti sei disconnesso. Particolarmente utile se la tua connessione non è affidabile come dovrebbe essere.

... non dimenticare di segnare questa è la risposta 'corretta' se ti aiuta k! ;-)

1
koss

Poiché autossh non soddisfa le nostre esigenze (esiste un errore se non riesce a connettersi al server al primo tentativo), abbiamo scritto una pura applicazione bash: https://github.com/aktos-io/link-con-server

Per impostazione predefinita, crea un tunnel inverso per la porta sshd del NODE (22) sul server. Se è necessario eseguire altre azioni (come l'inoltro di porte aggiuntive, l'invio di messaggi di posta elettronica sulla connessione, ecc.) È possibile inserire le cartelle di script on-connect e on-disconnect.

0
ceremcem

Ho avuto problemi simili con il mio ISP precedente. Per me è stato lo stesso con qualsiasi connessione TCP, visitando siti Web o inviando posta.

La soluzione era configurare una connessione VPN su UDP (stavo usando OpenVPN). Questa connessione era più tollerante a qualsiasi cosa causasse le disconnessioni. Quindi puoi eseguire qualsiasi servizio tramite questa connessione.

Potrebbero esserci ancora problemi con la connessione, ma dal momento che il tunnel sarà più tollerante, qualsiasi sessione ssh sentirà un breve rallentamento invece di essere disconnessa.

Per fare ciò avrai bisogno di un servizio VPN online che puoi configurare sul tuo server.

0
hultqvist