Come mantenere affidabile un tunnel SSH aperto?

Io uso un tunnel SSH dal lavoro per andare intorno a diversi firewall idotiche (va bene con il mio capo :)). Il problema è che dopo un istante la connessione ssh si blocca e il tunnel è rotto.

Se potessi alless controllare automaticamente il tunnel, potrei riavviare il tunnel quando si blocca, ma non ho nemless pensato a come farlo.

Punti bonus per colui che mi può dire come impedire la connessione ssh da attaccare, naturalmente!

Sembra che tu abbia bisogno di autossh . Questo monitorerà un tunnel di ssh e riavvia come necessario. Abbiamo usato per un paio di anni e sembra funzionare bene.

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

Ulteriori dettagli sul parametro -M qui

Tutte le firewall stateful dimenticano di una connessione dopo che non vedono un pacchetto per quella connessione per un certo tempo (per evitare che le tabelle di stato diventino piene di connessioni where entrambe le estremità sono morte senza chiudere la connessione). La maggior parte delle implementazioni TCP invierà un pacchetto keepalive dopo un lungo periodo senza udire dall'altro lato (2 ore è un valore comune). Se però è presente un firewall di stato che dimentica della connessione prima che i pacchetti keepalive possano essere inviati, una connessione lunga, ma inattesa, morirà.

Se questo è il caso, la soluzione è impedire che la connessione diventi intriggers. OpenSSH ha un'opzione denominata ServerAliveInterval che può essere utilizzata per impedire che la connessione sia inattesa troppo a lungo (come bonus, rileverà quando il peer è morto prima anche se la connessione è intriggers).

Nella tua macchina mac o linux configurare il tuo ssh mantenere il server ssh vivo each 3 minuti. Apri un terminal e vai nella tua casa invisibile .ssh:

 cd ~/.ssh/ 

quindi creare un file di configuration di 1 linea con:

 echo "ServerAliveInterval 180" >> config 

si dovrebbe anche aggiungere:

 ServerAliveCountMax xxxx (high number) 

l'impostazione predefinita è 3, quindi ServerAliveInterval 180 interrompe l'invio dopo 9 minuti (3 dell'intervallo di 3 minuti specificato da ServerAliveInterval).

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

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

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

Certamente mi sembra che tu sia tutto errato interpretare ServerAliveCountMax. Come faccio a capire i documenti, è il numero di messaggi di server vivi che possono andare senza risposta senza che la connessione sia terminata. Quindi, nei casi in cui stiamo discutendo qui, impostandolo ad un valore elevato, assicureremo solo che una connessione impiccata non verrà rilevata e terminata!

La semplice impostazione di ServerAliveInterval dovrebbe essere sufficiente per risolvere il problema con un firewall che dimentica la connessione e lasciare che il server LowCountMax basso consentirà alla fine originale di notare l'errore e termina se la connessione comunque fallisce.

Quello che volete è, 1) che la connessione rimanga aperta definitivamente in circostanze normali, 2) se non si riesce a rilevare il collegamento e che il lato iniziale esca dal guasto, e 3) che il command ssh venga rilasciato each volta che uscire (come si fa molto dipendente dalla piattaforma, lo script "while true" suggerito da Jawa è un modo, in realtà OS XI ha impostato un elemento di launchd).

Utilizzare sempre l'opzione ServerAliveInterval nel caso in cui i problemi del tunnel siano generati da sessioni NAT scadute.

Utilizzare sempre un metodo di resawning nel caso in cui la connettività scenda completamente, hai qui alless tre opzioni:

  • programma autossh
  • script bash ( while true do ssh ...; sleep 5; done ) non rimuove il command sleep, ssh potrebbe non riuscire rapidamente e ti rischierà troppi processi
  • /etc/inittab , per accedere a una casella spedita e installata in un altro Paese, dietro NAT, senza l'inoltro della port alla casella, è ansible configurarlo 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, where /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 methods.

Ho risolto questo problema con questo:

Modifica

 ~/.ssh/config 

E aggiungi

 ServerAliveInterval 15 ServerAliveCountMax 4 

Secondo la pagina man 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 importnt 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. 

Systemd è 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 

(Modificare il command ssh per adattarlo)

  • questo verrà eseguito come utente sshtunnel modo da assicurarsi che l'utente esista in primo luogo
  • emettere systemctl enable sshtunnel per impostarlo per avviarsi all'avvio
  • emettere systemctl start sshtunnel per avviare immediatamente

ExitOnForwardFailure yes è un buon complemento agli altri suggerimenti. Se si connette, ma non riesce a stabilire l'inoltro della port, è altrettanto inutile per te come se non fosse collegata a tutti.

Ho avuto la necessità 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 rispecchia ssh utilizzando l'authentication basata su chiave.

Non sono sicuro di quello che appende, ma ho avuto dei tunnel che muoiono a causa di timeout.

Mi piacerebbe fornire il codice per il respawner, ma non riesco a trovare subito.

mentre ci sono strumenti come autossh che aiuta a riavviare la session ssh … quello che trovo per essere davvero utile è quello di eseguire il command 'schermo'. Consente di riprendere le sessioni ssh anche dopo aver scollegato. Particolarmente utile se la tua connessione non è affidabile quanto dovrebbe essere.

… non dimenticare di segnare questa è la risposta "corretta" se ti aiuta k! 😉

Un po 'di un hack, ma mi piace usare schermo per mantenere questo. Attualmente ho un forward remoto che è stato in esecuzione per settimane.

Esempio, avviando localmente:

 screen ssh -R ...... 

Quando si utilizza l'avanzamento remoto e si dispone di una shell nel computer remoto:

 screen Ctrl + a + d 

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

Recentemente ho avuto questo problema, perché queste soluzioni richiedono di reinserire la password each volta se utilizzi un login di password ho usato sshpass in un ciclo con un prompt di text per evitare di avere la password nel file batch.

Pensavo che avrei condiviso la mia soluzione in questo caso se qualcun altro avesse lo stesso problema:

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

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

La soluzione era quella di configurare una connessione VPN su UDP (stavo usando OpenVPN). Questa connessione era più tollerante a quanto causato dalle disconnessioni. Quindi puoi eseguire qualsiasi servizio tramite questa connessione.

Ci possono essere ancora problemi con la connessione, ma poiché il tunnel sarà più tollerante, qualsiasi session di ssh si sentirà una breve durata anziché essere disconnesso.

Per farlo è necessario un servizio VPN in linea che è ansible impostare sul proprio server.

Poiché l' autossh non soddisfa le nostre esigenze (esiste con errore se non è in grado di connettersi al server al primo tentativo), abbiamo scritto un'applicazione pura: https://github.com/aktos-io/link -Con server

Per impostazione predefinita, viene creato un tunnel inverso per la port Sshd (22) NODE sul server. Se è necessario eseguire altre azioni (ad esempio l'inoltro di porte aggiuntive, l'invio di posta in connessione, ecc.) È ansible posizionare gli script on-connect e on-disconnect cartelle.