Bagaimana cara menjaga agar terowongan SSH tetap terbuka?


235

Saya menggunakan terowongan SSH dari kantor untuk berkeliling di berbagai firewall idola (tidak apa-apa dengan bos saya :)). Masalahnya adalah, setelah beberapa saat koneksi ssh biasanya hang, dan terowongan terputus.

Jika saya setidaknya bisa memantau terowongan secara otomatis, saya bisa memulai kembali terowongan ketika hang, tetapi saya bahkan belum menemukan cara untuk melakukannya.

Poin bonus untuk orang yang bisa memberi tahu saya cara mencegah koneksi ssh saya menggantung, tentu saja!


Apakah terowonganmu mati karena tidak aktif? Aku punya masalah ini ketika tunneling port dari ponsel saya sehingga saya akhirnya berakhir pemijahan perintah boneka pada sambungan untuk membuatnya "hidup" dengan menggunakan watchperintah seperti: watch -n1 60 echo "wiiiii". Tunnel tidak akan mati kecuali jaringan rusak atau Anda tidak menggunakannya.
erm3nda

Jawaban:


281

Sepertinya Anda perlu autossh . Ini akan memonitor terowongan ssh dan memulai kembali sesuai kebutuhan. Kami telah menggunakannya selama beberapa tahun dan tampaknya berfungsi dengan baik.

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

Lebih detail tentang parameter -M di sini


2
+1 untuk autossh, ia melakukan apa yang tertulis di kaleng. Saya percaya bagian dari fungsinya juga adalah untuk mengirim paket gaya hidup untuk mencegah segala jenis timeout.
akent

30
Bisakah Anda memasukkan contoh terowongan menggunakan autosshdalam jawabannya?
Ehtesh Choudhury

5
autossh -f -nNT -i ~/keypair.pem -R 2000:localhost:22 username@myoutsidebox.com Anda mungkin memperhatikan bahwa saya mengatur ini menggunakan -nNT yang tidak membuat terminal jarak jauh sehingga saya bisa meletakkan autossh di latar belakang, dan opsi -i untuk SSH untuk menggunakan file .pem. Jika Anda ingin menjaga koneksi tetap terbuka sepanjang waktu, saya pasti akan merekomendasikan pengaturan tambahan.
juckele

2
Untuk apa nilainya, sepertinya lebih baik mengabaikan -Mparameter: bugs.debian.org/cgi-bin/bugreport.cgi?bug=351162
rinogo

2
Saya melakukan ini untuk membuatnya coba lagi pada perubahan jaringan, itu berfungsi dengan baik untuk saya: autossh -M 0 -o "ServerAliveInterval 10" -o "ServerAliveCountMax 2" -L 9999: localhost: 19999 server@example.com
Luke Stanley

39

Semua firewall stateful melupakan koneksi setelah tidak melihat paket untuk koneksi itu untuk beberapa waktu (untuk mencegah tabel state menjadi penuh koneksi di mana kedua ujungnya mati tanpa menutup koneksi). Sebagian besar implementasi TCP akan mengirim paket keepalive setelah waktu yang lama tanpa mendengar dari pihak lain (2 jam adalah nilai umum). Namun, jika ada firewall stateful yang lupa tentang koneksi sebelum paket keepalive dapat dikirim, koneksi yang awet tapi lama akan mati.

Jika itu masalahnya, solusinya adalah mencegah koneksi menjadi idle. OpenSSH memiliki opsi yang disebut ServerAliveInterval yang dapat digunakan untuk mencegah koneksi menjadi terlalu lama (sebagai bonus, itu akan mendeteksi kapan rekannya mati lebih cepat bahkan jika koneksi idle).


Interval yang ditentukan adalah dalam hitungan detik, sehingga Anda dapat memberikan beberapa fine tuning. Jika firewall stateful Anda memiliki batas waktu idle 5 menit, maka 60 atau 120 detik sudah cukup untuk membuat koneksi tetap terbuka. Ini adalah salah satu cara saya menjaga sesi ssh saya melalui router rumah saya terbuka.
Darren Hall

Terima kasih, ini membantu. Tetapi perhatikan (dari jawaban dengan peringkat lebih rendah di sini, superuser.com/a/146641/115515 ) bahwa jika Anda menentukan ServerAliveInterval dan bukan ServerAliveCountMax, Anda mungkin menemukan ssh sengaja memutuskan sambungan lebih cepat dari yang Anda inginkan.
metamatt

4
@ metamatt, jawaban dengan peringkat lebih rendah yang Anda referensi memiliki peringkat lebih rendah karena alasan yang baik: ITU SALAH.
Lambart

24

Di mesin mac atau linux Anda sendiri konfigurasikan ssh Anda agar server ssh tetap hidup setiap 3 menit. Buka terminal dan buka .ssh Anda yang tak terlihat di rumah Anda:

cd ~/.ssh/ 

lalu buat file konfigurasi 1 baris dengan:

echo "ServerAliveInterval 180" >> config

Anda juga harus menambahkan:

ServerAliveCountMax xxxx (high number)

standarnya adalah 3 sehingga ServerAliveInterval 180 akan berhenti mengirim setelah 9 menit (3 dari interval 3 menit yang ditentukan oleh ServerAliveInterval).


2
Perhatikan bahwa perintah Anda tidak disarankan jika Anda sudah memiliki file konfigurasi. Menggunakan >> untuk redirection akan jauh lebih baik!
Peltier

mengapa ServerAliveInterval 180memberi kami 6 menit? intuisi membuat saya mencoba ini: 180/60 == 3. Jadi, apakah ServerAliveIntervalbekerja dalam kelipatan 30 detik?
nemesisfixx

@ mcnemesis: ServerAliveInterval 180 berarti 3 menit. ServerAliveCountMax default 3 berarti 3 interval tersebut, jadi 9 menit.
metamatt

2
Saya memilih jawaban ini karena terima kasih telah menyebutkan ServerAliveCountMax, dan apa yang terjadi jika Anda menentukan ServerAliveInterval tanpa ServerAliveCountMax. Tetapi seperti komentar sebelumnya, saya perhatikan perhitungan "akan berhenti mengirim setelah" salah, dan saya pikir jawaban ini akan lebih baik jika hanya memberikan informasi tentang opsi ini, tidak memberi tahu kami bagaimana menerapkannya dengan perintah cd dan gema .
metamatt

20
Downvoting karena tidak masuk akal untuk mengatur ServerAliveCountMax ke "angka tinggi". ServerAliveCountMax menentukan berapa kali ia akan mencoba mengirim pesan "keepalive" sebelum menyerah. Standarnya adalah 3, jadi dengan ServerAliveInterval 180, itu akan berhenti mengirim HANYA jika server TIDAK BERTANGGUNG JAWAB setelah 9 menit, dalam hal ini koneksi Anda mungkin benar dan benar-benar mati.
Lambart

22

Saya telah menggunakan skrip Bash berikut untuk terus memunculkan terowongan ssh baru ketika yang sebelumnya mati. Menggunakan skrip berguna ketika Anda tidak ingin atau tidak dapat menginstal paket tambahan atau menggunakan kompiler.

while true
do
  ssh <ssh_options> [user@]hostname
  sleep 15
done

Perhatikan bahwa ini memerlukan keyfile untuk membuat koneksi secara otomatis tetapi demikian juga halnya dengan autossh.


2
Anda harus menambahkan alasan apa pun bahwa Anda akan menggunakan skrip ini di atas autossh, atau hanya karena lebih mudah dengan cara ini?
Kyrias

4
Ini tidak akan membantu jika ssh sendiri membeku, bukan?
nafg

1
Ini membantu jika Anda tidak dapat menginstal hal-hal di server. autossh tidak diinstal sebelumnya dan birokrasi terkadang sangat tumpul.
quarkex

Ya, lebih disukai tidak harus menginstal sesuatu. Saya telah melakukannya dengan cara ini selama setahun sebagai satu-satunya cara saya untuk membuat mesin jarak jauh dapat diakses (bahkan mengatur crontab untuk menjalankannya saat reboot). Itu tidak pernah gagal, dan yang lebih penting, saya tahu mengapa itu tidak akan pernah gagal.
sudo

16

Systemd cocok untuk ini.

Buat file layanan yang /etc/systemd/system/sshtunnel.servicemengandung:

[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 user@otherserver

[Install]
WantedBy=multi-user.target

(Ubah perintah ssh agar sesuai)

  • ini akan berjalan sebagai pengguna sshtunneljadi pastikan pengguna itu ada terlebih dahulu
  • masalah systemctl enable sshtunneluntuk mengaturnya untuk mulai saat boot
  • masalah systemctl start sshtunneluntuk segera dimulai

Pembaruan Jan 2018 : beberapa distro (misalnya Fedora 27) dapat menggunakan kebijakan SELinux untuk mencegah penggunaan SSH dari systemd init, dalam hal ini kebijakan khusus perlu dibuat untuk memberikan pengecualian yang diperlukan.


2
Ini terlihat sangat mirip dengan intisari saya: gist.github.com/guettli/... Umpan balik diterima!
guettli

Sangat bagus untuk suatu systemdsistem. Jika seseorang menggunakan Restart=on-failuremaka secara manual membunuh klien SSH tidak akan menghasilkan restart-by-systemd sebagai klien SSH dengan keluar dengan sukses.
David Tonhofer

Jika Anda ingin memulai ssh dari skrip (bash) yang diberikan sebagai argumen, ExecStartmisalnya untuk membuat sshdaftar argumen, lakukan pemeriksaan dasar dll, kemudian panggil dari skrip seperti itu exec /bin/ssh -N .... Ini perintah saya: di exec /bin/ssh -N -oExitOnForwardFailure=Yes -oTCPKeepAlive=no -oServerAliveInterval=5 -oServerAliveCountMax=6 -i "${LOCAL_PRIVATE_KEY}" -L "${TUNNEL_INLET}:${TUNNEL_OUTLET}" "${REMOTE_USER}@${REMOTE_MACHINE}"mana TUNNEL_INLET="127.0.0.1:3307"danTUNNEL_OUTLET="127.0.0.1:3306"
David Tonhofer

10

Jelas terlihat bagi saya bahwa Anda semua salah menafsirkan ServerAliveCountMax. Saat saya memahami dokumen, ini adalah jumlah pesan server yang hidup yang tidak dapat dijawab tanpa koneksi diputus. Jadi dalam kasus seperti yang sedang kita bahas di sini, menetapkannya ke nilai tinggi hanya akan memastikan bahwa koneksi yang terputus tidak akan terdeteksi dan diakhiri!

Cukup mengatur ServerAliveInterval harus cukup untuk menyelesaikan masalah dengan firewall lupa tentang koneksi, dan meninggalkan ServerAliveCountMax rendah akan memungkinkan ujung yang berasal untuk melihat kegagalan dan berakhir jika koneksi gagal pula.

Yang Anda inginkan adalah, 1) agar koneksi tetap terbuka secara permanen dalam keadaan normal, 2) agar kegagalan koneksi terdeteksi dan sisi asal keluar saat gagal, dan 3) agar perintah ssh dikeluarkan kembali setiap kali keluar (bagaimana Anda melakukannya sangat bergantung pada platform, skrip "while true" yang disarankan oleh Jawa adalah satu arah, pada OS XI sebenarnya mengatur item launchd).


9

Selalu gunakan ServerAliveIntervalopsi SSH jika masalah terowongan dihasilkan oleh sesi NAT yang kedaluwarsa.

Selalu gunakan metode respawning jika konektivitas turun sepenuhnya, Anda memiliki setidaknya tiga opsi di sini:

  • program autossh
  • skrip bash ( while true do ssh ...; sleep 5; done) jangan menghapus perintah sleep, sshmungkin gagal dengan cepat dan Anda akan respawn terlalu banyak proses
  • /etc/inittab, untuk memiliki akses ke kotak yang dikirim dan diinstal di negara lain, di belakang NAT, tanpa penerusan port ke kotak, Anda dapat mengonfigurasinya untuk membuat terowongan ssh kembali kepada Anda:

    tun1:2345:respawn:/usr/bin/ssh -i /path/to/rsaKey -f -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip 'sleep 365d'
    
  • skrip pemula di Ubuntu, di mana /etc/inittabtidak tersedia:

    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 user@publicip
    post-stop script
        sleep 5
    end script
    

atau selalu gunakan kedua metode.


1
+1 untuk opsi sebaris jika Anda tidak menginginkannya untuk semua koneksi SSH Anda
user1146334

Anda menulis "jika konektivitas turun seluruhnya". Sekarang saya tidak mengerti, masalah apa yang diperbaiki autossh sendiri, dan apa yang tidak? Saya pikir, tentu saja, itu akan menjaga koneksi yang rusak, seperti mencabut kabel selama beberapa jam, tetapi mungkin tidak?
Mads Skjern

6

Saya memecahkan masalah ini dengan ini:

Sunting

~/.ssh/config

Dan tambahkan

ServerAliveInterval 15
ServerAliveCountMax 4

Menurut halaman manual untuk 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.

Setiap 15 detik sepertinya cukup sering melakukan ping ke server.
Lambart

@Lambart tetapi jika koneksi benar-benar rapuh dan sering drop koneksi, setidaknya mendeteksi koneksi mati dan memberikan kesempatan untuk mencoba lagi sebelumnya.
binki

4

ExitOnForwardFailure yesadalah tambahan yang bagus untuk saran lainnya. Jika terhubung tetapi tidak dapat membuat port forwarding sama tidak berguna bagi Anda seolah-olah tidak terhubung sama sekali.


Ini ide yang sangat bagus. Bahkan autossh tidak ada gunanya jika koneksi sebelumnya dianggap lebih awal di sisi jarak jauh daripada di host lokal, karena dalam hal ini host lokal akan mencoba untuk terhubung lagi, tetapi penerusan tidak dapat dibuat karena port masih terbuka.
Raúl Salinas-Monteagudo

1

Saya memiliki kebutuhan untuk mempertahankan terowongan SSH jangka panjang. Solusi saya berjalan dari server Linux, dan itu hanya program C kecil yang merespons ssh menggunakan otentikasi berbasis kunci.

Saya tidak yakin tentang penggantungan, tetapi terowongan saya mati karena batas waktu.

Saya ingin memberikan kode untuk respawner, tetapi saya tidak bisa menemukannya sekarang.


1

sementara ada alat-alat seperti autossh yang membantu memulai kembali sesi ssh ... yang menurut saya sangat berguna adalah menjalankan perintah 'layar'. Hal ini memungkinkan Anda untuk MENGUMPULKAN sesi ssh Anda bahkan setelah Anda memutuskan sambungan. Terutama berguna jika koneksi Anda tidak dapat diandalkan seperti seharusnya.

... jangan lupa untuk menandai ini adalah jawaban yang 'benar' jika itu membantu Anda k! ;-)


7
... tapi pertanyaannya adalah tentang bagaimana menjaga terowongan SSH terbuka, bukan hanya sesi terminal. Layarnya luar biasa!
akent

Saya sudah menggunakan layar, tetapi itu tidak menyelesaikan masalah saya: - / Terima kasih atas jawaban Anda.
Peltier

1

Sedikit peretasan, tapi saya suka menggunakan layar untuk menyimpan ini. Saat ini saya memiliki remote forward yang telah berjalan selama berminggu-minggu.

Contoh, mulai secara lokal:

screen
ssh -R ......

Ketika remote forward diterapkan, dan Anda memiliki shell di komputer remote:

screen
Ctrl + a + d

Anda sekarang memiliki penerusan jarak jauh tanpa gangguan. Caranya adalah dengan menjalankan layar di kedua ujungnya


1

Baru-baru ini memiliki masalah ini sendiri, karena solusi ini mengharuskan Anda memasukkan kembali kata sandi setiap kali jika Anda menggunakan kata sandi masuk, saya menggunakan sshpass dalam satu lingkaran bersama dengan prompt teks untuk menghindari kata sandi dalam file batch.

Saya pikir saya akan membagikan solusi saya pada thead ini jika ada orang lain yang memiliki masalah yang sama:

#!/bin/bash
read -s -p "Password: " pass
while true
do
    sshpass -p "$pass" ssh user@address -p port
    sleep 1
done

0

Saya memiliki masalah serupa dengan ISP saya sebelumnya. Bagi saya itu sama dengan koneksi tcp, mengunjungi situs web atau mengirim surat.

Solusinya adalah mengkonfigurasi koneksi VPN melalui UDP (saya menggunakan OpenVPN). Koneksi ini lebih toleran terhadap apa pun yang menyebabkan pemutusan. Kemudian Anda dapat menjalankan layanan apa pun melalui koneksi ini.

Mungkin masih ada masalah dengan koneksi tetapi karena terowongan akan lebih toleran setiap sesi ssh akan merasakan penahanan singkat daripada terputus.

Untuk melakukan ini, Anda akan memerlukan layanan VPN online yang dapat Anda siapkan di server Anda sendiri.


0

Karena autosshtidak memenuhi kebutuhan kami (ada kesalahan jika tidak dapat terhubung ke server pada upaya pertama), kami telah menulis aplikasi bash murni: https://github.com/aktos-io/link- dengan-server

Ini menciptakan terowongan terbalik untuk port sshd NODE (22) di server secara default. Jika Anda perlu melakukan tindakan lain (seperti meneruskan port tambahan, mengirim surat saat koneksi, dll ...) Anda dapat menempatkan skrip on-connectdan on-disconnectfolder Anda.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.