Bir SSH tüneli nasıl güvenilir bir şekilde korunur?


234

İşten çeşitli SSCB tünelleri kullanarak çeşitli aptal güvenlik duvarlarını dolaşıyorum (patronum için sorun yok :)). Sorun, bir süre sonra ssh bağlantısı genellikle askıda kalıyor ve tünel kırılıyor.

En azından tüneli otomatik olarak izleyebilseydim, kilitlendiğinde tüneli yeniden başlatabilirdim, ama bunu yapmanın bir yolunu bile bulamadım.

Tabii ki, ssh bağlantımın asılı kalmasını nasıl önleyeceğimi söyleyebilecek olanlara bonus puanları!


Tünelin öldüğü için aktif değil mi? Telefonumdan bağlantı noktaları tünel yaparken bu sorunu yaşadım, bu yüzden nihayet şu watchkomutu kullanarak "canlı" hale getirmek için bağlantıya kukla komutlar çıkardım watch -n1 60 echo "wiiiii". Ağ kopmadığı veya kullanmadığınız sürece tünel ölmeyecek.
erm3nda

Yanıtlar:


280

Autossh'a ihtiyacınız var gibi . Bu bir ssh tüneli izler ve gerektiğinde yeniden başlatır. Birkaç yıldır kullandık ve iyi çalışıyor gibi görünüyor.

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

-M parametresi hakkında daha fazla ayrıntı burada


2
Autossh için +1, teneke ne diyorsa onu yapar. İşlevselliğinin bir parçasının da zaman aşımını önlemek için canlı tutma stil paketleri göndermek olduğuna inanıyorum.
akent

30
autosshCevabı kullanarak örnek tüneli koyabilir misin ?
Ehtesh Choudhury

5
autossh -f -nNT -i ~/keypair.pem -R 2000:localhost:22 username@myoutsidebox.com Bunu, uzak bir terminal oluşturmayan -nNT kullanarak arka plana autossh koyabildiğim ve SSH'nin bir .pem dosyası kullanması için -i seçeneğini kullandığımı fark edebilirsiniz. Bir bağlantıyı her zaman açık tutacaksanız, kesinlikle ilave kurulum yapmayı öneriyorum.
Juckele

2
O atlamak için tipik iyidir gibi bu değer ne için, görünüşe -M: parametreyi bugs.debian.org/cgi-bin/bugreport.cgi?bug=351162
rinogo

2
Bunu ağ değişiminde yeniden denemek için yaptım, benim için iyi çalışıyor: autossh -M 0 -o "ServerAliveInterval 10" - o "ServerAliveCountMax 2" -L 9999: localhost: 19999 server@example.com
Luke Stanley

39

Durum bilgisi olan tüm güvenlik duvarları, bir süre bu bağlantı için bir paket görmedikten sonra bağlantıyı unutur (durum tablolarının, her iki ucun bağlantıyı kapatmadan öldüğü bağlantılarla dolmasını önlemek için). Çoğu TCP uygulaması, diğer taraftan haber almadan uzun bir süre sonra bir kalıcı paket gönderir (2 saat ortak bir değerdir). Bununla birlikte, kalıcı paketler gönderilmeden önce bağlantıyı unutan durumsal bir güvenlik duvarı varsa, uzun ömürlü fakat boşta bir bağlantı kesilecektir.

Bu durumda, çözüm bağlantının boşta kalmasını önlemektir. OpenSSH, bağlantının çok uzun süre boşta kalmasını önlemek için kullanılabilecek ServerAliveInterval adlı bir seçeneğe sahiptir (bonus olarak, eş boşta olsa bile eşin ne zaman öldüğünü algılar).


Belirtilen aralık saniye cinsindendir, bu nedenle bazı ince ayarlar sağlayabilirsiniz. Durum bilgisi olan güvenlik duvarınız 5 dakikalık bir boşta kalma zaman aşımına sahipse, bağlantıyı açık tutmak için 60 veya 120 saniye yeterlidir. Bu benim ssh oturumlarımı ev yönlendiricim üzerinden açık tutmamın yollarından biri.
Darren Hall

Teşekkürler, bu yardımcı oldu. Ancak, (burada daha düşük dereceli bir cevaptan, superuser.com/a/146641/115515 ), eğer ServerAliveInterval belirtirseniz ve ServerAliveCountMax belirtmezseniz, ssh'yi istediğiniz zaman kasten kesip bulabileceğinizi unutmayın.
metamat

4
@metamatt, referansta olduğunuz düşük dereceli cevap, iyi bir sebepten dolayı düşük dereceli: IT IS WRONG.
Lambart

24

Kendi mac veya linux makinenizde ssh sunucunuzu her 3 dakikada bir sunucunun ssh olmasını sağlayın. Bir terminal açın ve evinizde görünmez .ssh'nize gidin:

cd ~/.ssh/ 

sonra 1 satırlı config dosyası oluşturun:

echo "ServerAliveInterval 180" >> config

ayrıca eklemelisiniz:

ServerAliveCountMax xxxx (high number)

varsayılan değer 3'dür, bu nedenle ServerAliveInterval 180, 9 dakika sonra göndermeyi durduracaktır (ServerAliveInterval tarafından belirtilen 3 dakikalık aralığın 3'ü).


2
Zaten bir config dosyanız varsa komutunuzun önerilmediğini unutmayın. Yönlendirme için >> kullanmak çok daha iyi olurdu!
Peltier

neden ServerAliveInterval 180bize 6 dakika veriyor? sezgi ben de denemek yapar: 180/60 == 3. Peki, ServerAliveInterval30 saniyenin katlarında çalışıyor mu?
nemesisfixx

@mcnemesis: ServerAliveInterval 180, 3 dakika anlamına gelir. ServerAliveCountMax varsayılan 3, bu aralıkların 3'ü, yani 9 dakika anlamına gelir.
metamat

2
Bu cevabı ben oyluyorum, çünkü ServerAliveCountMax'ten bahsettiğiniz için teşekkürler ve ServerAliveCountMax olmadan ServerAliveInterval belirtirseniz ne olur? Ancak önceki yorumlar gibi, "sonra göndermeyi durduracak" ifadesinin yanlış olduğunu fark ettim ve bu seçenekle ilgili bilgi verdiyse bu cevabın daha iyi hizmet edeceğini düşünüyorum, bize cd ve yankı komutları ile nasıl uygulanacağımızı söylemiyoruz. .
metamat

20
DownA oylama, çünkü ServerAliveCountMax'i "yüksek sayı" olarak ayarlamanın bir anlamı yoktur. ServerAliveCountMax, pes etmeden önce "keepalive" mesajını kaç kez göndermeye çalışacağını belirler. Varsayılan değer 3'dür, bu nedenle ServerAliveInterval 180 ile, 9 dakika sonra sunucu YANIT VERMEYEN SADECE göndermeyi durdurur, bu durumda bağlantınız muhtemelen iyi ve gerçekten ölüdür.
Lambart

22

Birincisi öldüğünde yeni ssh tünellerinin ortaya çıkmasını sağlamak için aşağıdaki Bash komut dosyasını kullandım. Komut dosyası kullanmak istemediğinizde veya ek paketler kuramadığınızda veya derleyici kullanamadığınızda kullanışlıdır.

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

Bunun, bağlantıyı otomatik olarak kurmak için bir anahtar dosya gerektirdiğini, ancak autossh için de geçerli olduğunu unutmayın.


2
Bu betiği autossh üzerinde kullanmanız için herhangi bir sebep eklemelisiniz, yoksa bu şekilde mi kolaylaşıyor?
kyrias

4
Bu ssh kendiliğinden donarsa yardımcı olmaz, değil mi?
nafg

1
Sunucuya bir şey yükleyemezseniz yardımcı olur. autossh önceden yüklenmiş olarak gelmiyor ve bürokrasi bazen çok geniş oluyor.
quarkex

Evet, bir şeyler yüklemek zorunda değilsiniz tercih edilir. Uzak bir makineyi erişilebilir kılmak için tek yolum olarak, bir yıl boyunca bu şekilde yapıyorum (yeniden başlatma sırasında çalıştırmak için crontab bile ayarladım). Asla başarısız olmaz ve daha da önemlisi, neden asla başarısız olmayacağını biliyorum.
sudo

16

Systemd bunun için idealdir.

Aşağıdakileri /etc/systemd/system/sshtunnel.serviceiçeren bir servis dosyası oluşturun:

[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

(Ssh komutunu uyacak şekilde değiştirin)

  • bu kullanıcı olarak çalışır, sshtunnelbu yüzden önce kullanıcının var olduğundan emin olun
  • systemctl enable sshtunnelönyükleme sırasında başlayacak şekilde ayarlama sorunu
  • systemctl start sshtunnelhemen başlamak sorunu

Jan 2018 Güncellemesi : bazı dağıtımlar (örneğin, Fedora 27), SSH'nin sistem girişinden kullanılmasını önlemek için SELinux politikasını kullanabilir, bu durumda gerekli istisnaları sağlamak için özel bir politika oluşturulması gerekecektir.


2
Bu benim özüme çok benziyor: gist.github.com/guettli/… Geribildirim bekliyoruz!
guettli

Bir systemdsistem için mükemmel . Eğer biri kullanırsa Restart=on-failure, SSH istemcisini manuel olarak öldürmek, başarıyla çıkılan SSH istemcisi olarak sistem tarafından yeniden başlatmaya neden olmaz.
David Tonhofer

Ssh'yi ExecStartörneğin sshargüman listesini oluşturmak için argüman olarak verilen bir (bash) betiğinden başlatmak istiyorsanız , temel kontrolleri vb. Yapın ve ardından betiğinden çağırınız exec /bin/ssh -N .... İşte 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}"TUNNEL_INLET="127.0.0.1:3307"TUNNEL_OUTLET="127.0.0.1:3306"
emrim

10

Bana öyle geliyor ki, hepiniz ServerAliveCountMax’i yanlış yorumluyorsunuz. Belgeleri anladığım kadarıyla, bağlantı kesilmeden cevapsız kalabilen sunucu canlı mesaj sayısıdır. Bu yüzden burada tartıştığımız gibi durumlarda, bunu yüksek bir değere ayarlamak sadece asılı bir bağlantının algılanmamasını ve sonlandırılmamasını sağlayacaktır!

Basitçe ServerAliveInterval ayarının, bağlantıyı unutan bir güvenlik duvarı ile sorunu çözmek için yeterli olması gerekir ve ServerAliveCountMax'ı düşük bırakmak, kaynak bağlantının yine başarısız olması durumunda kaynak sonun fark etmesine ve sonlandırılmasına izin verecektir.

İstediğiniz şey şu: 1) normal şartlar altında bağlantının sürekli açık kalması için, 2) bağlantı hatası tespit edilebilecek ve kaynak tarafın arızada çıkacağı, 3) ssh komutunun her seferinde yeniden yayınlanması için çıkın (nasıl yaptığınız platforma bağımlı, Jawa'nın önerdiği "gerçek olsa" betiği bir yoludur, aslında OS XI'de bir fırlatma öğesi hazırlamıştır).


9

ServerAliveIntervalTünel sorunlarının süresi dolan NAT oturumları tarafından oluşturulmuş olması durumunda, her zaman SSH seçeneğini kullanın .

Bağlantının tamamen kesilmesi durumunda her zaman bir yeniden doğuş yöntemi kullanın, burada en az üç seçeneğiniz vardır:

  • autossh programı
  • bash script ( while true do ssh ...; sleep 5; done) uyku komutunu kaldırmaz, sshhızlı bir şekilde başarısız olabilir ve çok fazla işlemi yeniden resmediniz
  • /etc/inittab, başka bir ülkeye gönderilen ve kurulan bir kutuya, NAT'ın arkasına, kutuya bağlantı noktası iletmeden erişebilmek için, size geri bir ssh tüneli oluşturacak şekilde yapılandırabilirsiniz:

    tun1:2345:respawn:/usr/bin/ssh -i /path/to/rsaKey -f -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip 'sleep 365d'
    
  • Ubuntu'da başlatma komut dosyası, /etc/inittabuygun değil:

    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
    

veya her zaman iki yöntemi de kullanın.


1
Tüm SSH bağlantılarınızda istemiyorsanız, inline seçeneği için +1
user1146334

"Bağlantının tamamen düşmesi durumunda" yazıyorsunuz. Şimdi anlamıyorum, autossh hangi sorunları çözüyor ve ne anlama geliyor? Elbette, birkaç saat boyunca kabloyu çıkarmak gibi herhangi bir kopuk bağlantıyı halledeceğini düşündüm, ama belki de değil?
Mads Skjern

6

Bu sorunu bununla çözdüm:

Düzenle

~/.ssh/config

Ve Ekle

ServerAliveInterval 15
ServerAliveCountMax 4

Ssh_config için man sayfasına göre :

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.

Her 15 saniyede bir, sunucuya ping yapmak oldukça sık görünüyor.
Lambart

@Lambart, ancak bağlantı gerçekten kesikse ve sık sık bağlantıları keserse, en azından ölü bir bağlantıyı algılar ve daha önce yeniden deneme fırsatı verir.
binki

4

ExitOnForwardFailure yesdiğer önerilere iyi bir yardımcıdır. Bağlanır ancak bağlantı noktası yönlendirmeyi kuramazsa, hiç bağlantınız yokmuş gibi sizin için işe yaramaz.


Bu çok iyi bir fikir. Eğer önceki bağlantı uzak tarafta yerel ana bilgisayardan daha önce zaman aşımına uğramış olarak algılanırsa autossh bile işe yaramaz, çünkü bu durumda yerel ana bilgisayar tekrar bağlanmaya çalışacaktır, ancak bağlantı noktası açık olduğu için iletme kurulamaz.
Raúl Salinas-Monteagudo

1

Uzun süredir SSH tüneli tutmaya ihtiyacım vardı. Çözümüm bir Linux sunucusundan çalışıyordu ve ssh'yi anahtar tabanlı kimlik doğrulamasını kullanarak yeniden başlatan küçük bir C programı.

Asıldığından emin değilim, ama zaman aşımına uğrayan tüneller ölmüştü.

Yeniden doğuranın kodunu vermeyi çok isterdim ama şu anda bulamıyorum.


1

ssh oturumunu yeniden başlatmaya yardımcı olan autossh gibi araçlar varken ... gerçekten yararlı bulduğum şey 'screen' komutunu çalıştırmak. Bağlantıyı kestikten sonra bile ssh oturumlarına devam etmeni sağlar. Özellikle bağlantınız olması gerektiği kadar güvenilir değilse kullanışlıdır.

... eğer size yardım ederse, bunun 'doğru' cevap olduğunu işaretlemeyi unutmayın! ;-)


7
... ancak soru SSH tünellerini nasıl açık tutacağımızla ilgiliydi, sadece terminal oturumunu değil. Ekran olsa harika!
akent

Zaten ekranı kullanıyorum, ancak sorunumu çözmüyor: - / Cevabınız için teşekkürler.
Peltier

1

Biraz kesmek, ancak bunu korumak için ekranı kullanmak istiyorum. Şu anda haftalardır çalışan bir uzaktan ileri.

Yerel olarak başlayan örnek:

screen
ssh -R ......

Uzak iletme uygulandığında ve uzak bilgisayarda bir kabuk varsa:

screen
Ctrl + a + d

Artık kesintisiz bir uzaktan kumandaya sahipsiniz. Hile iki ucunda ekranı çalıştırmak için


1

Son zamanlarda bu sorunu kendim yaşadım, çünkü bu çözümler parola girişini kullanırsanız her seferinde parolayı tekrar girmenizi gerektiriyor çünkü sshpass komutunu toplu iş dosyasında parola bulundurmamak için metin istemiyle birlikte kullanıyorum.

Başkalarının da aynı sorunu yaşayabilmesi için çözümümü bu konuda paylaşacağımı düşündüm:

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

0

Önceki ISS'mde de benzer problemler yaşadım. Benim için tcp ile bağlantı kurmak, web sitelerini ziyaret etmek veya posta göndermek ile aynıydı.

Çözüm UDP üzerinden bir VPN bağlantısı yapılandırmaktı (OpenVPN kullanıyordum). Bu bağlantı, bağlantı kopmalarına neden olana daha toleranslıdır. Daha sonra bu bağlantı üzerinden herhangi bir servisi çalıştırabilirsiniz.

Bağlantıda hala sorunlar olabilir, ancak tünel daha toleranslı olacağından, herhangi bir ssh oturumu bağlantısı kesilmek yerine kısa bir bekletme hissedecektir.

Bunu yapmak için çevrimiçi olarak kendi sunucunuzda ayarlayabileceğiniz bir VPN servisine ihtiyacınız olacak.


0

Gibi autosshihtiyaçlarımızı (çok ilk denemesinde sunucuya bağlanamıyor eğer hata ile mevcut) uymayan, biz saf bash uygulaması yazdık: https://github.com/aktos-io/link- ile sunucu

Varsayılan olarak NODE'nin sshd portu (22) için sunucuda ters bir tünel oluşturur. Başka bir işlem yapmanız gerekirse (ek bağlantı noktaları iletme, bağlantıda posta gönderme vb.), Komut dosyalarınızı on-connectve on-disconnectklasörlerinizi yerleştirebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.