Layar, atau yang serupa, untuk melanjutkan kembali koneksi ssh yang serpihan

18

Saya sering harus terhubung ke server melalui ssh di lingkungan wifi yang tidak dapat diandalkan. Di server, saya menjalankan layar, jadi jika saya terputus, saya dapat menyambung kembali dan melanjutkan sesi layar, dan mengambil di mana saya tinggalkan, tetapi kehilangan koneksi masih merupakan tenggang waktu utama: jika koneksi terputus saat saya Sedang di server, jendela terminal cenderung membeku. Saya harus membunuh tab itu, buka yang baru, ssh ke server lagi dan melanjutkan sesi layar. Saya sudah mencoba ini dengan menjalankan layar pada server dan layar secara lokal. Apa pun itu cenderung membeku ketika koneksi putus.

Apakah ada cara saya dapat memiliki sesuatu yang mirip dengan layar, atau mungkin layar itu sendiri, yang secara otomatis akan mencoba menyambung kembali dan menjaga sesi berjalan, jadi saya tidak harus terus terhubung kembali secara manual? Seringkali ketika saya kehilangan koneksi saya pikir itu hanya untuk periode yang sangat singkat - mungkin kurang dari satu detik.

Saya menggunakan Ubuntu 14.04 LTS, edisi MATE. Terima kasih

Max Williams
sumber
4
Re "the shell window cenderung membeku": Itu karena ssh lokal Anda tidak tahu koneksi sudah mati. Tekan <Enter>dan ketik ~.untuk memberi tahu sisi Anda untuk menjatuhkan koneksi, dan Anda cukup mengulangi perintah ssh terakhir untuk menyambung kembali (misalnya dengan panah atas atau !!).
alexis
@alexis yang terdengar seperti cara yang lebih cepat untuk menyambung kembali, terima kasih! Saya ingin itu terjadi secara otomatis ...
Max Williams

Jawaban:

23

Anda dapat melihat menggunakan mosh: https://mosh.org/

Anda dapat mengatur server 'lompatan' dengan koneksi internet yang andal yang Anda gunakan moshuntuk terhubung, lalu mengadakan sshsesi untuk setiap server yang Anda kelola. Alasan saya menyarankan menggunakan server lompat adalah bahwa Anda mungkin tidak ingin menginstal moshpada server yang Anda kelola.

Keuntungan lain moshadalah didasarkan pada UDP daripada TCP, dan sesi Anda dapat bertahan dari perubahan alamat IP, misalnya beralih dari WiFi ke koneksi internet seluler.

Hanya untuk memperjelas, moshbukan pengganti screen, melainkan ssh. Itu masih merupakan ide yang baik untuk digunakan screen, karena moshitu sendiri tidak menyediakan cara untuk menyambung kembali ke sesi Anda jika klien meninggal karena alasan tertentu.

shackleford berkarat
sumber
Terima kasih, ini hanya satu server (sebagian besar waktu) dan kami memilikinya jadi saya harus dapat menginstal Mosh. Saya akan mengeceknya.
Max Williams
Sebenarnya ternyata itu karena server kami cukup lama (atau menjalankan Ubuntu yang lama saya harus katakan) itu terlalu sulit untuk menginstal. :(
Max Williams
@ MaxWilliams berapa umurnya? Bahkan LTS 12.4 telah kehilangan dukungan. Dan kenapa tidak coba kompilasi sendiri
phuclv
Ketika saya membaca mosh docs, Anda perlu mosh-server pada setiap host yang ingin Anda kelola dari jarak jauh. Tetap saja, pasti menarik.
Wildcard
1
Menghubungkan ke terminal tmux melalui mosh adalah solusi paling stabil bagi saya.
Nemo
3

Saya telah menggunakan tmuxselama beberapa tahun sekarang dan dalam pengalaman saya, itu terhubung kembali secara otomatis. Setidaknya ketika koneksi hanya gagal untuk waktu yang relatif singkat. Perhatikan bahwa saya benar-benar menggunakan byobudengan tmux sebagai backend. Saya tidak tahu apakah kekokohan ini adalah fitur tmuxatau byobuatau bahkan kombinasi keduanya, tapi saya sarankan Anda mencoba keduanya.

Saya terhubung dari Arch instalasi lokal saya ke berbagai server Ubuntu jarak jauh melalui VPN. Saya mengujinya sekarang dengan mencabut kabel jaringan saya saat saya terhubung ke remote. Sesi itu terhenti, tetapi begitu kabel saya dicolokkan lagi, ia kembali lancar.

Namun, ketika saya diuji dengan me-restart router saya, koneksi tidak kembali. Saya berasumsi itu ada hubungannya dengan berapa lama jaringan itu mati, tetapi tampaknya untuk menyambung kembali jika hanya turun beberapa detik.

Dalam hal ini relevan, saya melakukan semua ini menggunakan terminatoremulator terminal saya.

Ketiganya tersedia di repositori Ubuntu:

sudo apt-get install tmux terminator byobu

Namun, saya sama sekali tidak yakin bahwa salah satu tmuxatau byobulebih baik dalam menangani pemutusan ssh. Saya hanya tahu bahwa dalam pengalaman saya, mereka sering kembali dari kehilangan koneksi singkat. Itu mungkin ke aspek lain dari konfigurasi saya.

terdon
sumber
1
Ketika Anda me-restart router Anda, Anda mungkin telah diberi alamat IP publik yang berbeda, yang akan merusak tcpkoneksi. Dari pengalaman saya sshbisa sangat tangguh untuk putus jaringan terputus-putus, saya tidak berpikir ini ada hubungannya dengan fakta yang Anda gunakan tmuxdi dalam sshjendela.
rusty shackleford
3
Saya akan mengatakan hal yang sama: bahkan dengan SSH biasa, Anda dapat menangani pemutusan yang pendek, selama koneksi TCP tidak mati. Yang mungkin, jika antarmuka Anda dimatikan, atau router yang terlalu bersemangat membunuhnya (router NAT mungkin melupakan keadaan NAT saat reboot, dan memutus koneksi yang ada), atau ClientAlive/ ServerAlivememicu, atau ... Saya tidak tahu apa yang byobuterjadi, meskipun .
ilkkachu
Ya, tetapi OP tampaknya mengalami pembekuan pada setiap kegagalan koneksi, sementara saya tidak. Tapi ya, Anda benar, saya juga melihat ini dengan ssh sederhana dan tanpa tmux. Namun demikian, mungkin layar tidak bisa menghadapinya?
terdon
2
@ MaxWilliams tmuxpada dasarnya adalah alternatif yang lebih modern screen, ya. Ketika saya pertama kali mulai bekerja seperti yang saya lakukan sekarang dan membutuhkan hal semacam ini, bacaan sepintas saya menyarankan itu tmuxadalah pilihan yang lebih baik hari ini. Saya juga tidak 100% yakin ini memiliki manajemen koneksi yang hilang yang lebih baik, yang saya tahu adalah pemulihan dari pemadaman singkat dalam pengalaman saya. Entah itu tergantung pada tmuxatau sesuatu yang lain, saya tidak tahu. Tapi sepertinya patut dicoba :). Byobu pada dasarnya adalah sebuah frontend to screen / tmux, bukan emulator terminal GUI. Ini sangat berguna: byobu.org
terdon
2
tmux tidak melakukan apa pun tentang gangguan koneksi. Ini bekerja dengan perangkat terminal yang disediakan oleh ssh. Semuanya berdiri dan jatuh dengan koneksi ssh.
Jonas Schäfer
2

Gunakan ServerAliveopsi ssh untuk mendeteksi ketika koneksi gagal.

ServerAliveCountMax
Setel jumlah pesan server yang hidup (lihat di bawah) yang dapat dikirim tanpa ssh (1) menerima pesan apa pun dari server. Jika ambang ini tercapai saat pesan server sedang dikirim, ssh akan memutuskan sambungan dari server, mengakhiri sesi. Penting untuk dicatat bahwa penggunaan pesan hidup server sangat berbeda dari TCPKeepAlive (di bawah). Pesan hidup server dikirim melalui saluran terenkripsi dan karenanya tidak akan dipalsukan. Opsi TCP keepalive yang diaktifkan oleh TCPKeepAlive dapat dipalsukan. Mekanisme server hidup berharga ketika klien atau server bergantung pada mengetahui kapan koneksi telah menjadi tidak aktif.

Nilai default adalah 3. Jika, misalnya, ServerAliveInterval (lihat di bawah) diatur ke 15 dan ServerAliveCountMax dibiarkan default, jika server menjadi tidak responsif, ssh akan terputus setelah sekitar 45 detik.

ServerAliveInterval
Menetapkan interval waktu habis dalam hitungan detik setelahnya jika tidak ada data yang diterima dari server, ssh (1) akan mengirim pesan melalui saluran terenkripsi untuk meminta tanggapan dari server. Standarnya adalah 0, menunjukkan bahwa pesan-pesan ini tidak akan dikirim ke server.

Jadi, jika Anda menetapkan ServerAliveIntervalke 5, sshakan terputus secara otomatis jika jaringan terkelupas selama 15 detik.

Barmar
sumber
Untuk mematahkan sesi SSH dengan paksa, saya menekan ~.(atau Enter pertama, lalu ~.) yang terdiri dari: karakter pelarian ~dan perintah untuk memutus sesi.
imz - Ivan Zakharyaschev
@ imz - IvanZakharyaschev Itu mengasumsikan Anda dapat mengatakan bahwa koneksi terputus. Menggunakan keepalive SSH akan mendeteksi kegagalan secara otomatis.
Barmar
Kedengarannya sangat berguna, terima kasih, saya pasti akan mencobanya lain kali saya berada di "zona terkelupas".
Max Williams
@Barmar Ya, benar. Saya juga sudah memikirkan masalah menentukan apakah koneksi benar-benar terputus, atau saya menekan sesuatu secara tidak sengaja dapat mengirim kunci-kunci ini ke sisi yang jauh ... Dan saya tidak tahu solusi yang baik.
imz - Ivan Zakharyaschev
2

Dalam kondisi yang sama, saya cenderung menggunakan eshellTRAMP (over ssh) di dalam Emacs. TRAMP menangani penyambungan kembali bila perlu tanpa menyebabkan banyak masalah bagi saya memberikan perintah yang diinginkan untuk shell jarak jauh.

Namun, eshell tidak sebagus terminal, yaitu untuk menjalankan perintah yang melakukan sesuatu yang istimewa dengan terminal, atau yang berjalan untuk periode waktu yang signifikan secara terus-menerus (secara bertahap) mencetak sesuatu.

Pada dasarnya, cukup mudah untuk mulai menggunakannya di Emacs dengan TRAMP:

M-x eshell
cd /user@host:
imz - Ivan Zakharyaschev
sumber
1

Penolakan

Jika koneksi SSH Anda tidak bertahan dari pemadaman jaringan singkat, maka ada sesuatu yang terjadi yang tidak memungkinkan sshdan TCP melakukan hal normal mereka.

Lihat di bawah untuk detailnya. Bagaimanapun:

Solusi Tanpa-Dependensi Tercepat dan Terkotor

Buat skrip shell seperti ini:

#!/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"

Ini hanya akan menjalankan loop bodoh-sederhana yang terus berusaha terhubung sshdan dilampirkan screen. Lewati host atau apa pun yang biasanya Anda berikan pada sshpermohonan Anda sebagai argumen baris perintah.

Sambungan ulang hanya didasarkan pada apakah SSH melaporkan kesalahan dengan koneksi, yang berarti ia tidak memiliki kecerdasan untuk mendeteksi kesalahan non-SSH seperti "Anda benar-benar tidak mengaktifkan WiFI" atau apa pun, tetapi itu mungkin tidak masalah untuk kamu.

Saya berasumsi Anda memiliki ssh-agentatau kunci SSH tanpa-frasa sandi yang akan memungkinkan koneksi kembali berfungsi tanpa masukan tambahan dari Anda.

Akan ada kondisi perlombaan kecil di mana jika Anda menekan ^Cpada fraksi yang tepat yang tidak dapat dilihat manusia sedetik pun selama penyambungan kembali, Anda bisa berakhir dengan membunuh skrip alih-alih meneruskannya ^Cke terminal klien, jadi jika Anda mencurigai koneksi hang jangan tumbuk ^Cterlalu bersemangat.

Solusi Perangkat Lunak Tambahan Sederhana

Anda dapat mencoba program autossh , yang seharusnya tersedia di repositori paket Ubuntu Anda.

Jika Anda perlu membangun dari sumber atau mengauditnya, ini adalah program C tunggal yang mengkompilasi tanpa pustaka tambahan sebagai dependensi, tampaknya memiliki lebih banyak intelijen tentang memeriksa keaktifan koneksi daripada retasan saya di atas, dan juga dikirimkan dengan rscreenperintah skrip yang mudah yang otomatis -terhadap screen.

Detail

Bagaimana sshbiasanya pulih

Hanya untuk memverifikasi, karena saya tidak suka mengatakan sesuatu tanpa memeriksa diri saya sendiri, saya melakukan sedikit tes sebelum menjawab:

Saya menggunakan WiFi dengan perangkat Linux, membuat koneksi SSH ke perangkat lain di LAN saya, memverifikasi bahwa saya memiliki sshkoneksi yang berfungsi ke ujung lainnya (dapat menjalankan perintah, dll), kemudian pada klien memutus WiFi (menyebabkan antarmuka untuk tidak dikonfigurasikan: tidak ada lagi alamat IP), mengetikkan lebih banyak karakter ke dalam sesi ssh (tentu saja tidak ada respons), dan kemudian terhubung kembali ke WiFi saya - koneksi ulang sebenarnya gagal setidaknya sekali karena sinyal buruk dan faktor lainnya , kemudian akhirnya terhubung kembali: Saya menunggu sekitar lima detik hingga sshsesi pulih, tidak ada yang terjadi sehingga saya menekan satu tombol lagi, dan sshsesi segera menjadi hidup kembali, dengan semua kunci yang saya ketik selama pemutusan muncul di baris perintah.

Lihat, sshhanya menulis / membaca ke soket jaringan TCP sampai OS mengatakan ada sesuatu yang salah, dan TCP sebenarnya sangat toleran terhadap penurunan koneksi yang berkepanjangan.

Ditinggalkan ke perangkatnya sendiri dengan pengaturan kernel default, TCP stack di Linux dengan senang hati akan mentolerir koneksi yang benar-benar diam selama beberapa menit sebelum menyatakan koneksi mati dan melaporkan kesalahan ke ssh- pada saat akhirnya menyerah kita berbicara di stadion baseball itu. dari ~ 30 menit, atau setidaknya cukup lama untuk bertahan lebih lama dari cegukan koneksi yang berlangsung satu detik atau satu menit.

Di bawah penutup, Linux TCP stack secara bertahap mencoba kembali pesan dengan penundaan yang lebih lama, yang berarti bahwa pada saat koneksi Anda kembali, Anda mungkin melihat jeda tambahan sebelum sshsesi Anda tampaknya "hidup" lagi.

Mengapa ini terkadang rusak

Seringkali ada sesuatu yang secara aktif menyebabkan koneksi ditutup setelah beberapa periode tidak aktif secara signifikan lebih pendek daripada jumlah yang akan ditoleransi oleh TCP stack, dan kemudian gagal melaporkan status koneksi tersebut ke sshklien Anda .

Calon yang mungkin termasuk:

  1. Firewall atau NAT'ing router, yang harus menggunakan memori untuk mengingat setiap koneksi TCP langsung - sebagai optimasi dan beberapa mitigasi terhadap serangan DOS, mereka kadang-kadang hanya akan melupakan koneksi Anda, dan kemudian secara diam-diam mengabaikan paket konsekuen untuk itu, karena paket di tengah koneksi ketika Anda tidak ingat koneksi yang ada terlihat tidak valid.

  2. Firewall / router berperilaku lebih baik akan menyuntikkan paket TCP RST, yang biasanya bermanifestasi sebagai connection reset by peerpesan kesalahan, tetapi paket reset adalah api-dan-lupa, jadi jika koneksi ke klien Anda masih mengalami masalah pada saat itu dan menjatuhkan Reset paket juga, klien Anda akan berpikir koneksi masih hidup.

  3. Server itu sendiri mungkin memiliki kebijakan firewall untuk secara diam-diam menjatuhkan paket yang tidak terduga, yang akan memutus upaya koneksi kembali klien setiap kali server menganggap koneksi ditutup tetapi klien tidak: klien Anda terus berusaha melanjutkan koneksi, tetapi server hanya mengabaikannya karena tidak ada koneksi langsung ke mana paket-paket ini berada dalam keadaan firewall server.

    Karena Anda menjalankan Linux, hati-hati periksa server Anda iptables/ ip6tables(atau nftjika Anda menggunakan hal-hal baru) untuk apa yang Anda izinkan vs menjatuhkan. Sangat umum untuk memperbolehkan paket baru / mapan / terkait pada port TCP SSH, tetapi bukan yang "tidak valid" - jika Anda secara diam-diam menghapus semua yang tidak diizinkan, pengaturan umum ini dapat menyebabkan pembekuan semacam ini setelah masalah koneksi singkat .

  4. Server SSH Anda sendiri mungkin dikonfigurasikan untuk menutup koneksi setelah beberapa saat tidak aktif, menggunakan salah satu opsi OpenSSH untuk paket kenang-kenangan klien TCP atau SSH. Dengan sendirinya ini tidak akan menyebabkan hang tidak terbatas, tetapi dapat menempatkan Anda di salah satu negara yang dijelaskan di atas.

  5. Mungkin saja Anda tidak memberikan cukup waktu untuk "melepas" sendiri setelah Anda masuk ke keadaan di mana sshsesi Anda ditutup.

mtraceur
sumber