Schermo o simile, per riprendere automaticamente una connessione ssh instabile


18

Spesso devo collegarmi a un server tramite ssh in un ambiente wifi inaffidabile. Sul server, eseguo schermo, quindi se mi disconnetto, posso riconnettermi e riprendere la sessione dello schermo e riprendere da dove avevo interrotto, ma la perdita di connessione è ancora un grosso problema: se la connessione si interrompe mentre io Sono sul server, la finestra del terminale tende a bloccarsi. Devo uccidere quella scheda, aprirne una nuova, ssh di nuovo sul server e riprendere la sessione dello schermo. Ho provato questo con lo schermo in esecuzione sul server e lo schermo localmente. In entrambi i casi tende a bloccarsi quando la connessione si interrompe.

Esiste un modo per avere qualcosa di simile allo schermo, o forse lo stesso schermo, che proverà automaticamente a riconnettersi e mantenere la sessione in esecuzione, quindi non devo continuare a riconnettermi manualmente? Spesso quando perdo la connessione penso che sia solo per un periodo molto breve - forse meno di un secondo.

Sto usando Ubuntu 14.04 LTS, edizione MATE. Grazie


4
Ri "la finestra della shell tende a bloccarsi": Questo perché il tuo ssh locale non sa che la connessione è interrotta. Premi <Enter>e digita ~.per dire al tuo lato di abbandonare la connessione e puoi semplicemente ripetere l'ultimo comando ssh per riconnetterti (ad esempio con la freccia su o !!).
alexis,

@alexis sembra un modo più veloce per riconnetterti, grazie! Mi piacerebbe che succedesse automaticamente però ...
Max Williams,

Risposte:


23

Puoi guardare usando mosh: https://mosh.org/

È possibile impostare un server "jump" con una connessione Internet affidabile a cui si utilizza moshper connettersi, quindi tenere sshsessioni per ciascun server gestito. Il motivo per cui suggerisco di utilizzare un server jump è che potresti non voler installare moshsui server che gestisci.

Un altro vantaggio moshè che si basa su UDP anziché su TCP e la tua sessione può sopravvivere a un cambiamento di indirizzo IP, ad esempio passando da WiFi a una connessione Internet mobile.

Giusto per chiarire, moshnon è un sostituto per screen, ma piuttosto ssh. È comunque una buona idea usarlo screen, poiché di per moshsé non fornisce un modo per riconnettersi alla sessione se il client muore per qualche motivo.


Grazie, è solo un server (il più delle volte) e lo possediamo, quindi dovrei essere in grado di installare Mosh. Io lo verificherò.
Max Williams,

In realtà risulta che poiché il nostro server è piuttosto vecchio (o in esecuzione un vecchio Ubuntu, dovrei dire) è troppo difficile da installare. :(
Max Williams,

@MaxWilliams quanti anni ha? Anche LTS 12.4 non è più supportato. E perché non provare a compilarlo da soli
phuclv,

Mentre leggo i documenti di mosh, hai bisogno di mosh-server su ogni host che intendi gestire da remoto. Comunque, decisamente interessante.
Wildcard il

1
La connessione a un terminale TMux su mosh è la soluzione più stabile per me.
Nemo,

3

Sto usando tmuxda alcuni anni e nella mia esperienza, si riconnette automaticamente. Almeno quando la connessione fallisce solo per un tempo relativamente breve. Nota che effettivamente uso byobucon tmux come backend. Non so se questa robustezza è una caratteristica di tmuxo di byobuo anche della combinazione dei due, ma vi suggerisco di dare entrambi una prova.

Mi collego dalla mia installazione Arch locale a vari server Ubuntu remoti tramite una VPN. L'ho provato proprio ora scollegando il cavo di rete mentre ero collegato al telecomando. La sessione si è bloccata, ma non appena il cavo è stato ricollegato, è ripreso senza interruzioni.

Tuttavia, quando ho provato riavviando il mio router, la connessione non è tornata. Presumo che abbia qualcosa a che fare con il tempo in cui la rete è rimasta inattiva, ma sembra riconnettersi se è inattivo solo pochi secondi.

Nel caso sia rilevante, faccio tutto questo usando terminatorcome emulatore di terminale.

Tutti e tre sono disponibili nei repository Ubuntu:

sudo apt-get install tmux terminator byobu

Tuttavia, non sono affatto sicuro che sia tmuxo byobusia meglio gestire le disconnessioni ssh. So solo che nella mia esperienza, spesso ritornano da brevi perdite di connessione. Ciò potrebbe dipendere da altri aspetti della mia configurazione.


1
Quando hai riavviato il router, è possibile che ti sia stato assegnato un indirizzo IP pubblico diverso, che avrebbe interrotto la tcpconnessione. Dalla mia esperienza sshpuò essere molto resistente agli interruzioni di rete intermittenti, non penso che questo abbia nulla a che fare con il fatto che stai usando tmuxall'interno della sshfinestra.
Rusty Shackleford,

3
Stavo per dire lo stesso: anche con SSH semplice, puoi fare una breve disconnessione, purché la connessione TCP non muoia. Quale potrebbe essere, se la tua interfaccia viene arrestata o un router troppo zelante lo uccide (i router NAT potrebbero dimenticare lo stato NAT al riavvio e interrompere le connessioni esistenti), o ClientAlive/ ServerAliveinnesca, o ... Non ho idea di cosa byobufaccia, però .
ilkkachu,

Sì, ma l'OP sembra subire un blocco in caso di errore di connessione, mentre io no. Ma sì, hai ragione, lo vedo anche con un semplice ssh e senza tmux. Tuttavia, forse lo schermo non ce la fa?
terdon

2
@MaxWilliams tmuxè sostanzialmente un'alternativa più moderna a screen, sì. Quando ho iniziato a lavorare come faccio adesso e avevo bisogno di questo genere di cose, la mia lettura sommaria mi ha suggerito che tmuxè la scelta migliore in questi giorni. Inoltre, non sono sicuro al 100% che abbia una migliore gestione delle connessioni perse, tutto quello che so è che si riprende da brevi interruzioni della mia esperienza. Che si tratti di tmuxo qualcos'altro, non lo so. Ma vale la pena provare :). Byobu è fondamentalmente un frontend per screen / tmux, non un emulatore di terminale GUI. È estremamente utile però: byobu.org
terdon

2
tmux non fa nulla riguardo alle interruzioni della connessione. Funziona con il dispositivo terminale fornito da ssh. Tutto sta e cade con la connessione ssh.
Jonas Schäfer,

2

Utilizzare le ServerAliveopzioni di ssh per rilevare quando la connessione non è riuscita.

ServerAliveCountMax
Imposta il numero di messaggi attivi del server (vedere di seguito) che possono essere inviati senza che ssh (1) riceva alcun messaggio dal server. Se questa soglia viene raggiunta durante l'invio di messaggi attivi del server, ssh si disconnetterà dal server, terminando la sessione. È importante notare che l'uso di messaggi di server attivi è molto diverso da TCPKeepAlive (di seguito). I messaggi attivi del server vengono inviati attraverso il canale crittografato e pertanto non saranno falsificabili. L'opzione keepalive TCP abilitata da TCPKeepAlive è falsificabile. Il meccanismo attivo del server è utile quando il client o il server dipendono dal sapere quando una connessione è diventata inattiva.

Il valore predefinito è 3. Se, ad esempio, ServerAliveInterval (vedi sotto) è impostato su 15 e ServerAliveCountMax viene lasciato sul valore predefinito, se il server non risponde, ssh si disconnetterà dopo circa 45 secondi.

ServerAliveInterval
Imposta un intervallo di timeout in secondi dopo il quale, se non sono stati ricevuti dati dal server, ssh (1) invierà un messaggio attraverso il canale crittografato per richiedere una risposta dal server. Il valore predefinito è 0, a indicare che questi messaggi non verranno inviati al server.

Quindi, se si imposta ServerAliveIntervalsu 5, sshsi disconnetterà automaticamente se la rete si interrompe per 15 secondi.


Per interrompere una sessione SSH con la forza, premo ~.(o prima Invio, quindi ~.) composto da: il personaggio escape ~e il comando per interrompere la sessione.
imz - Ivan Zakharyaschev

@ imz - IvanZakharyaschev Questo presuppone che tu possa dire che la connessione è bloccata. L'uso di keepalive di SSH rileverà automaticamente l'errore.
Barmar,

Sembra davvero utile, grazie, ci proverò sicuramente la prossima volta che sarò nella "zona traballante".
Max Williams,

@Barmar Sì, vero. Ho anche pensato al problema di determinare se la connessione è davvero bloccata, o se premendo qualcosa si può accidentalmente inviare questi tasti al lato remoto ... E non conosco una buona soluzione.
imz - Ivan Zakharyaschev,

2

In condizioni simili, tendo a usare eshellTRAMP (over ssh) all'interno di Emacs. TRAMP si occupa di riconnettersi quando necessario senza causare molti problemi per me dando i comandi desiderati per la shell remota.

Tuttavia, eshell non è buono come un terminale, cioè per eseguire comandi che fanno qualcosa di speciale con il terminale o che funzionano per un periodo di tempo significativo stampando continuamente (in modo incrementale) qualcosa.

Fondamentalmente, è abbastanza semplice iniziare a usarlo in Emacs con TRAMP:

M-x eshell
cd /user@host:

1

disconoscimento

Se la tua connessione SSH non sopravvive a brevi interruzioni di rete, allora c'è qualcos'altro che non sta permettendossh e TCP fa la cosa normale.

Vedi sotto per i dettagli. Comunque:

La soluzione senza dipendenze più rapida e sporca

Crea uno script shell come questo:

#!/bin/sh -

# Tune these numbers depending on how aggressively
# you want your SSH session to get reconnected.
timeout_options='-o ServerAliveInterval=4 -o ServerAliveCountMax=2'

# 255 is the status OpenSSH uses to signal SSH errors, which
# means we want to connect. All other exit statuses suggest
# an intentional exit.
status=255

# Keep opening the SSH connection and immediately dropping into
# `screen` until an intentional exit happens.
while [ "$status" = 255 ]
do
    ssh $timeout_options -t "$@" screen -dR
    status=$?
    # You can add a `sleep` command here or a counter or whatever
    # you might need as far as rate/retry limiting.
done
exit "$status"

Questo eseguirà solo un ciclo stupido-semplice che continua a provare a connettersi sshe connettersi screen. Passa l'host o qualsiasi altra cosa che normalmente passeresti alla tua sshinvocazione come argomenti da riga di comando.

La riconnessione si basa solo sul fatto che SSH segnala un errore con la connessione, il che significa che non ha intelligenza per rilevare errori non SSH come "non hai letteralmente acceso WiFI" o altro, ma probabilmente non importa per voi.

Suppongo che tu abbia ssh-agentuna chiave SSH senza passphrase che consentirà alle riconnessioni di funzionare semplicemente senza input aggiuntivo da parte tua.

Ci sarà una minuscola condizione di gara in cui se colpisci ^Cdurante la giusta frazione umano impercettibile di secondo durante una riconnessione potresti finire per uccidere lo script invece di passare ^Cattraverso il terminale client, quindi se sospetti che la connessione si blocchi non schiacciare^C troppo zelantemente.

La soluzione software aggiuntiva più semplice

Puoi provare il programma autossh , che dovrebbe essere disponibile nel tuo repository di pacchetti Ubuntu.

Se devi compilare dal sorgente o controllarlo, è un singolo programma C che si compila senza librerie aggiuntive come dipendenze, sembra avere più intelligenza sul controllo della vivacità della connessione rispetto al mio hack sopra, e viene fornito con un comodo rscreencomando di script che auto -attacca a screen.

Dettagli

Come sshnormalmente recupera

Giusto per verificare, poiché non mi piace dire le cose senza controllarmi, ho eseguito un piccolo test prima di rispondere:

Ho ottenuto il mio WiFi con un dispositivo Linux, ho effettuato una connessione SSH a un altro dispositivo sulla mia LAN, verificato che avevo una sshconnessione funzionante all'altra estremità (poteva eseguire comandi, ecc.), Quindi sul client ho disconnesso il WiFi (causando l'interfaccia da deconfigurare: niente più indirizzi IP), ho digitato un sacco di caratteri in più nella sessione ssh (nessuna risposta, ovviamente) e poi ricollegato al mio WiFi - la riconnessione in realtà non è riuscita almeno una volta a causa di un cattivo segnale e di altri fattori , poi finalmente riconnesso: ho aspettato circa cinque secondi per il sshripristino della sessione, non è successo nulla, quindi ho premuto un altro tasto e la sshsessione è tornata immediatamente in vita, con tutti i tasti digitati durante la disconnessione che appaiono sulla riga di comando.

Vedi, sshscrive / legge nel socket di rete TCP fino a quando il sistema operativo non avverte che qualcosa è andato storto e TCP è in realtà molto tollerante nei confronti di interruzioni prolungate della connessione.

Lasciato ai propri dispositivi con le impostazioni del kernel predefinite, lo stack TCP in Linux tollererà felicemente che la connessione diventi completamente silenziosa per molti minuti prima di dichiarare la connessione interrotta e riportare un errore ssh- al momento in cui si arrende finalmente stiamo parlando nel ballpark di ~ 30 minuti, o almeno sicuramente abbastanza a lungo per resistere al singhiozzo della connessione della durata di un secondo o un minuto.

Sotto le copertine, lo stack TCP Linux ritrova gradualmente i messaggi con ritardi sempre più lunghi, tuttavia, il che significa che, quando la connessione verrà ripristinata, potresti vedere un ulteriore ritardo prima che la sshsessione sembri tornare "viva".

Perché a volte questo si rompe

Spesso qualcosa provoca attivamente la chiusura della connessione dopo un periodo di inattività significativamente più breve rispetto alla quantità che lo stack TCP tollererà e quindi non riesce a riportare lo stato della connessione al sshclient.

I candidati probabili includono:

  1. Firewall o router NAT, che devono utilizzare la memoria per ricordare ogni connessione TCP attiva - come ottimizzazione e attenuazione degli attacchi DOS, a volte dimenticano semplicemente la connessione e quindi ignorano silenziosamente i conseguenti pacchetti, poiché i pacchetti nel nel mezzo di una connessione quando non ricordi che la connessione esistente sembra non valida.

  2. I firewall / router meglio educati inietteranno un pacchetto TCP RST, che in genere si manifesta come un connection reset by peermessaggio di errore, ma il pacchetto di ripristino è un incendio e dimentica, quindi se la connessione al client presenta ancora problemi in quel momento e interrompe il reimpostare anche il pacchetto, il client penserà che la connessione sia ancora attiva.

  3. Il server stesso potrebbe avere una politica firewall per eliminare silenziosamente i pacchetti imprevisti, interrompendo i tentativi di ripresa della connessione del client ogni volta che il server ritiene che la connessione sia chiusa ma il client no: il client continua a provare a continuare la connessione, ma il server è solo ignorandolo perché non esiste una connessione attiva a cui appartengono questi pacchetti nello stato firewall del server.

    Dal momento che stai usando Linux, controlla attentamente il tuo server iptables/ ip6tables(o nftse stai usando le nuove cose) per esattamente quello che stai permettendo rispetto al rilascio. È molto comune consentire pacchetti nuovi / stabiliti / correlati sulla porta TCP SSH, ma non quelli " non validi" - se si rilascia silenziosamente tutto ciò che non è consentito, questa configurazione comune potrebbe causare questo tipo di blocchi dopo brevi problemi di connessione .

  4. Il server SSH stesso potrebbe essere configurato per chiudere la connessione dopo un periodo di inattività, utilizzando una delle opzioni OpenSSH per i pacchetti keepalive client TCP o SSH. Di per sé questo non causerà blocchi indefiniti, ma può metterti in uno degli stati sopra descritti.

  5. È possibile che tu non gli stia concedendo abbastanza tempo per "staccare" da solo dopo essere entrato nello stato in cui la sshsessione si blocca.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.