- SSH tünelleme, güvenli bir SSH bağlantısı üzerinden TCP trafiği taşıyarak eski protokolleri şifrelemek, yönetim panellerine erişmek ve NAT arkasındaki sunuculara bağlanmak gibi kısıtlı yolları güvenli biçimde açmak için kullanılır
- Sunucu tarafında
AllowTcpForwarding yes gerekir; loopback olmayan bir arayüzde port açmak için GatewayPorts yes ayarı ve SSH sunucusunun yeniden başlatılması gerekir
ssh -J, ssh -L, ssh -R, ssh -D sırasıyla jump host, yerel yönlendirme, uzak yönlendirme ve SOCKS5 tabanlı dinamik yönlendirmeden sorumludur
- Tüneli arka planda tutmak için
ssh -fN kullanılır; kopma algılama ise ClientAliveInterval ve ClientAliveCountMax gibi heartbeat ayarlarıyla düzenlenir
- SSH tünelleme UDP’yi doğrudan desteklemez ve TCP-over-TCP’de gecikme ile bant genişliği sorunları oluşabilir; bu yüzden VPN alternatifi olmaktan çok belirli TCP yollarını açan bir araca daha yakındır
SSH tünellemenin kullanıldığı durumlar
- SSH tünelleme ve port yönlendirme, TCP trafiğini bir SSH bağlantısı üzerinden istemciden sunucuya veya sunucudan istemciye iletir
- TCP portları ve UNIX soketleri kullanılabilir, ancak örnekler TCP portları odaklıdır
- Başlıca kullanım biçimleri güvenlik, sorun giderme ve bağlantı etrafında toplanır
- Güvenlik
- FTP gibi güvenli olmayan bağlantıları veya eski protokolleri şifreler
- Açık anahtar kimlik doğrulamasına dayalı SSH tüneliyle web yönetim paneline erişir
- 80/443 gibi ek portları dışa açmadan yalnızca 22 numaralı portu açmayı sağlar
- Sorun giderme
- Güvenlik duvarlarını veya içerik filtrelerini aşar
- Farklı bir ağ rotası seçer
- Bağlantı
- NAT arkasındaki sunucuya erişir
- Bir jump host üzerinden internetten iç sunucuya girer
- Yerel portu internete açar
Port yönlendirmeden önce kontrol edilecek ayarlar
- Örneklerdeki seçenekler ortama göre birleştirilerek yapılandırılabilir
bind_address belirtilmezse varsayılan değer localhost olur
- Yerel ve uzak kullanıcıların ilgili makinelerde port açma yetkisi olmalıdır
0-1024 arası portlar, özel bir ayar yoksa root yetkisi gerektirir
- Diğer portlar normal kullanıcılar tarafından da ayarlanabilir
- İstemci ve ağ güvenlik duvarları da yönlendirme yoluna uygun şekilde açık olmalıdır
- SSH sunucusunda port yönlendirme etkin olmalıdır
AllowTcpForwarding yes
- Çoğu durumda varsayılan olarak etkin olsa da sunucu ayarlarının kontrol edilmesi gerekir
- Bir portu
127.0.0.1 dışındaki bir arayüze yönlendirmek için SSH sunucusunda GatewayPorts etkinleştirilir
GatewayPorts yes
- Ayardan sonra SSH sunucu servisi yeniden başlatılmalıdır
SSH jump host ve çok aşamalı tünel
ssh -J, bir veya daha fazla host üzerinden geçerek uzak host’a şeffaf biçimde bağlanmak için kullanılır
ssh -J user@REMOTE-MACHINE:22 -p 22 user@10.99.99.1
- Varsayılan port
22 kullanılırken port gösterimi atlanabilir
- REMOTE-MACHINE jump host olarak kullanıldığında bağlantı şu şekilde doğrulanır
[user@REMOTE-MACHINE]$ ss | grep -i ssh
tcp ESTAB 0 0 167.135.173.108:ssh 192.160.140.207:45960
tcp ESTAB 0 0 10.99.99.2:49770 10.99.99.1:ssh
- Örnek adreslerin rolleri şöyledir
167.135.173.108: REMOTE-MACHINE’in genel IP’si
192.160.140.207: LOCAL-MACHINE’in genel IP’si
10.99.99.2: REMOTE-MACHINE’in iç IP’si
10.99.99.1: REMOTE-WEBAPP’in iç IP’si
- Birden fazla jump host kullanırken virgülle ayrılır
ssh -J user@REMOTE-MACHINE:22,user@ANOTHER-REMOTE-MACHINE:22 -p 22 user@10.99.99.1
Yerel port yönlendirme
- Yerel port yönlendirme
ssh -L seçeneğini kullanır
- İlk örnek, LOCAL-MACHINE üzerindeki
10.10.10.1:8001 adresini REMOTE-MACHINE üzerindeki localhost:8000 adresine iletir
ssh -L 10.10.10.1:8001:localhost:8000 user@REMOTE-MACHINE
- REMOTE-MACHINE üzerinde yalnızca
127.0.0.1 adresine bind edilmiş web sunucusunun erişim günlüğü şöyle görünür
127.0.0.1 - - [30/Dec/2022 18:05:15] "GET / HTTP/1.1" 200
- Bu istek LOCAL-MACHINE’den başlatılır
- İkinci örnek, yerel
8001 portunu REMOTE-MACHINE üzerinden 10.99.99.1:8000 adresine iletir
ssh -L 8001:10.99.99.1:8000 user@REMOTE-MACHINE
- REMOTE-WEBAPP’in web sunucusu erişim günlüğünde istek REMOTE-MACHINE’in iç IP’sinden gelmiş olarak kalır
10.99.99.2 - - [30/Dec/2022 21:28:42] "GET / HTTP/1.1" 200
Uzak port yönlendirme
- Uzak port yönlendirme
ssh -R seçeneğini kullanır
- Örnek, REMOTE-MACHINE üzerindeki
8000 portunu yerel taraftaki localhost:8001 veya 10.10.10.2:8001 adresine iletir
ssh -R 8000:localhost:8001 user@REMOTE-MACHINE
ssh -R 8000:10.10.10.2:8001 user@REMOTE-MACHINE
- Belirli bir uzak arayüz olan
10.99.99.2:8000 üzerinde dinleyecek şekilde de ayarlanabilir
ssh -R 10.99.99.2:8000:10.10.10.2:8001 user@REMOTE-MACHINE
- Loopback arayüzü dışında bir yerde dinlemek için SSH sunucusunda
GatewayPorts yes etkin olmalıdır
Dinamik port yönlendirme ve SOCKS5
- Birden fazla port iletilirken SSH SOCKS protokolünü kullanır
- SOCKS şeffaf bir proxy protokolüdür ve SSH en yeni sürüm olan SOCKS5’i kullanır
- SOCKS5 sunucusunun varsayılan portu RFC 1928 içinde tanımlanan
1080’dir
- İstemcinin uygulama katmanında veya OS katmanında SOCKS proxy kullanacak şekilde ayarlanması gerekir
ssh -D örneği 10.10.10.1:5555 üzerinde bir SOCKS proxy açar
ssh -D 10.10.10.1:5555 user@REMOTE-MACHINE
- LOCAL istemcisinde bağlantı rotası
curl ile test edilebilir
curl -L -x socks5://10.10.10.1:5555 brrl.net/ip
- Doğru çalışırsa REMOTE-MACHINE’in genel IP’si döndürülür
SSH TUN/TAP tünelleme
-w bayrağıyla çift yönlü tünel oluşturulabilir
- Arayüzler önceden oluşturulmuş olmalıdır
- Bu yöntem için test edilmediğine dair bir caveat kalır
-w local_tun[:remote_tun]
Arka planda çalıştırma ve kapatma
- Tüneli yerel yöntemle arka planda çalıştırmak için
-fN kullanılır
-f: Arka planda çalıştırma
-N: Kabuk açmaz
ssh -fN -L 8001:127.0.0.1:8000 user@REMOTE-MACHINE
- Bunun dışında
screen veya başka araçlar kullanılabilir
- Arka planda çalışan SSH için süreç bulunur ve PID ile sonlandırılır
user@pleasejustwork:~$ ps -ef | grep ssh
[...]
user 19255 1 0 11:40 ? 00:00:00 ssh -fN -L 8001:127.0.0.1:8000 user@REMOTE-MACHINE
[...]
kill 19255
SSH bağlantısını sürdürme ve yeniden bağlanma
- SSH bağlantısını canlı tutmanın çeşitli yolları vardır
- Zaman aşımı işleme için heartbeat seçenekleri istemcide, sunucuda veya her ikisinde ayarlanabilir
ClientAliveInterval, bağlantıyı sürdürmek için her n saniyede bir istek gönderir
ClientAliveInterval 15
ClientAliveCountMax, karşı taraftan yanıt alınamadıktan sonra bağlantıyı sonlandırmadan önce gönderilecek heartbeat isteği sayısıdır
ClientAliveCountMax 3
3 varsayılan değerdir; 0 olarak ayarlanırsa bağlantı sonlandırma devre dışı bırakılır
- Örnek ayarda yanıt yoksa bağlantı yaklaşık 45 saniye sonra kesilir
- Bağlantı sonlandıktan sonra yeniden bağlanmak için
autossh, betikler, cronjob vb. kullanılabilir
Sınırlamalar ve güvenlik açısından dikkat edilmesi gerekenler
-
UDP
- SSH, doğru şifre çözme için güvenilir aktarıma dayanır
- UDP güvenilirlik sağlamadığı için SSH tünellerinde desteklenmez ve önerilmez
- UDP over SSH tunneling ele alan bir yöntem vardır, ancak test edilmediğine dair bir caveat bulunur
-
TCP-over-TCP
- Ek yük nedeniyle bant genişliği düşer ve gecikme artar
- Paket kaybı veya yüksek gecikme olan bağlantılarda TCP meltdown yaşanabilir
- TCP over TCP ile ilgili yazıya bakılabilir
- OpenVPN-over-TCP bir süre kullanıldığında bant genişliği UDP’ye göre daha düşüktü, ancak kararlı çalıştı; sonuçlar yapılandırmaya büyük ölçüde bağlıdır
-
VPN alternatifi olarak kullanıldığında sınırlamalar
- SSH tünelleme VPN gibi kullanılabilir, ancak daha iyi performans için VPN daha uygundur
-
Güvenlik riskleri
- Bu özelliğe ihtiyaç yoksa devre dışı bırakılması önerilir
- Saldırganlar SSH tünelleme ve port yönlendirmeyi kullanarak güvenlik duvarlarını ve diğer güvenlik önlemlerini aşabilir
-
Referans belgeler
1 yorum
Hacker News yorumları
2024'te SSH komutlarını uzun uzun elle yazmak yerine
~/.ssh/configiçinde LocalForward, RemoteForward, ProxyJump tanımlamak daha iyiBirden fazla ara SSH bağlantısından geçilmesi gereken uzak sunuculara
ssh,scp,rsyncile erişirken ciddi zaman kazandırıyorÖrneğin
jump-host-1,jump-host-2,jump-host-3zinciriniProxyJumpile kuruptarget-servera bir takma adla bağlanabilirsinizLocalForward 0.0.0.0:8080 0.0.0.0:80, uzaktaki 80 numaralı portu yereldeki 8080'e yönlendirir;RemoteForward 0.0.0.0:9022 0.0.0.0:22ise uzak tarafta 9022'ye gelen SSH isteklerini yereldeki 22 numaralı porta iletirLocalForwardveRemoteForwardiçinde soldaki hedef sunucu, sağdaki ise yereldir; ayrıcalocalhostya da127.0.0.1yerine0.0.0.0kullanılması yönünde bir ipucu da varssh_configipucu paylaşacak olursam, evde ya da kendi barındırdığınız VPN içindeyken her cihaza doğrudan SSH ile bağlanıp, dışarıdayken jump host üzerinden otomatik dallanan bir yapı kullanışlı oluyorMatch host *.example.org exec "getent ahosts router.example.org | grep -q ^10.0.0.1"gibi bir yöntemle önce yönlendirici adresinden ev/VPN durumunu algılayıp,arpile MAC adresi beklenen değerle eşleşmiyorsaProxyJump jump.example.orgkullanılmasını sağlayabilirsinizSıra önemli; önce VPN/ev ağı algılanmalı, sonra dışarıdaysanız jump host uygulanmalı
Kısa süreli bir VPS açıp SSH'ı SOCKS proxy olarak kullanarak bölgesel kısıtlamaları aşmak ya da başka bir takıma kısa süre yardım ederken normalde erişmediğiniz bir sunucuya bir kez girmeniz gerektiğinde komut satırı seçenekleri daha iyi olabilir
0.0.0.0kullanmak riskli olabilirTüm ağ arayüzlerinde port açabilir ve özellikle uzak sunucuda güvenlik duvarı yoksa bir şeyi tüm internete açık hale getirebilir
Sık kullanılan tünelleme ya da port yönlendirme için yapılandırma dosyası iyidir ama tek seferlik veya seyrek işler için komut satırı seçenekleri daha iyi olabilir
Tek kullanıcı/çok makine senaryosuna uyan, ayrı bir sunucuyu sürekli açık tutmayı gerektirmeyen ve GitHub benzeri bir yerden yapılandırma çekebilen GitOps benzeri bir çözüm arıyorum
bash/fishişlevleri oluşturdumUnutursam, belgelediğim işlev tanımlarına bakmam yeterli oluyor
Çalıştığım saçma kurumsal ortamda SSH tünelleme vazgeçilmez
Erişim izni almak, port açtırmak ya da güvenlik duvarı/VPN istisnası elde etmek bazen bürokrasi yüzünden haftalar sürüyor
Bu yazı
-Dseçeneğinden bahsediyor ama gücünü yeterince açıklamıyorssh -D 8888 someserverçalıştırıp tarayıcının SOCKS proxy ayarınılocalhost:8888yaparsanız, tüm tarayıcı trafiğisomeserverüzerinden yönlendirilirFirefox bunu hâlâ sistem varsayılanlarını değiştirmeden yapabildiği için çok kullanışlı
Ama şirkete girince IP izin listeleri yüzünden internetteki rastgele sunuculara SSH bağlantısı bile kuramıyordum; o kadar bunaldım ki HTTP tüneli kurup kontrol ettiğim bir sunucuyu izin listesine ekletmenin yollarını araştırdım, sonra da sonunda iş değiştirdim
Bu tür kısıtlamaların bir nedeni vardır ve bunları aşmaya çalışmak, kurum süreçlerine ve güvenlik uzmanlığına saygısızlık ve onları önemsememe olarak görülebilir
Erişim almak haftalar ya da aylar sürüyorsa beklemeniz gerekir; gizli bilgilere bir arka kapı açmanın ya da güvenliği zayıflatmanın sorumluluğunu üstlenmek istemezsiniz
Sabah 3'te yaptığım en dağınık SSH tünelleme işi, üç veri merkezi arasında bağlantı kurmaktı
Aynı metro bölgede bulunan üç tesis internette üst ağa bağlıydı ama garip yönlendirme politikaları yüzünden A yalnızca B'ye, B de yalnızca C'ye bağlanabiliyordu
Sonunda A'daki veriyi B üzerinden C'ye taşımak için rsync + SSH tüneli + anahtarlar + yönlendirme hileleri karışımı bir çözüm kurmak zorunda kaldım; sipariş formülü gibi komutları birkaç kez düzelttikten sonra her şeyin tek seferde çalıştığını görmek sihir gibiydi
Bugün dönüp bakınca nasıl yapılacağı çok açık geliyor ama o zamanlar acemiydim; bu büyük bir başarıydı ve senkronizasyonun bittiğini doğruladığımdaki heyecanı hâlâ hatırlıyorum
~/.ssh/configve ProxyJump ile A, B, C, D, E gibi kaç adım olursa olsun fiilen sıçrayarak ilerleyebilirsinizGörselleştirmenin ayrıntıları güzel
Özellikle ağ tarafında, daha düşük seviyeli bağlantılarda trafiği görsel olarak ifade eden çok daha fazla araç olmasını isterdim
Elbette bunlar sadece statik kavram gösterimleri; çoğu ağ üreticisi de bir tür trafik görselleştirmesi sunuyor ama genelde tekil metrikler ya da grafikler düzeyinde kalıyor
Linux sunucunuz ya da IoT cihazınız güvenlik duvarının arkasındaysa ve sabit IP'si yoksa ama SSH ile erişmek istiyorsanız, https://sshreach.me gibi bir tünelleme hizmeti kullanabilirsiniz
Birkaç yıldır tünellemeyi epey kullandım ama
-Jseçeneğini bilmiyordumBirkaç ayda bir tünel gerektiğinde her seferinde 30 dakika uğraşmak yerine, tüneli sizin yerinize kuran görsel bir araç olsaydı keşke
TCP-over-TCP'nin ek yükü artırarak aktarım hızını düşürebileceği, gecikmeyi yükseltebileceği ve paket kaybı ya da uydu ağı gibi gecikmesi yüksek bağlantılarda TCP meltdown'a yol açabileceğine dair bir açıklama var
Ancak SSH tünelinde, TAP/TUN kullanılmadığı sürece pratikte bu bir sorun olmuyor
Çünkü SSH, TCP akışını açıp iletiyor
Yine de birden çok kanal kullanıldığında head-of-line blocking nedeniyle performans düşebilir
Yaklaşık 15 yıl önce üniversite ağındaki güvenlik duvarını aşmak için SSH tünellemeyi öğrendim ve varsayılan portu 443 olarak değiştirmem gerekiyordu
O zamandan beri de bunu sadece güvenlik duvarını aşmak için değil, çok daha çeşitli amaçlarla kullanmaya devam ediyorum
sshuttlekullanırsanız tünelleme çok daha kolay olursshuttle -r user@host 10.0.0.0/8gibi kullanıldığında10/8aralığı otomatik olarak tünellenir ve fiilen SSH üzerinde bir VPN gibi çalışırSSH'nin kendisinde bir yönlendirme özelliği olup olmadığını merak ediyorum
Örneğin A, B'ye SSH ile bağlanmaya çalıştığında B'nin "C'ye bağlan" demesi ve A'nın saydam biçimde doğrudan C'ye bağlanması, böylece B'nin artık ana veri yolunda kalmaması gibi bir işlev var mı diye soruyorum
Benim güvenlik duvarım/yönlendiricim DHCP option 67'yi düzgün iletmiyor ve her zaman kendi adresini gönderiyordu; bu yüzden ilgili porttaki PXE önyükleme trafiği yönlendirici IP'sine gittiğinde bunun gerçek PXE önyükleme sunucusuna yönlenmesi için sanal IP/kurallar tanımlamam gerekti
Öyle değilse sıçrama özelliği kullanılabilir:
ssh -J B CB'nin yol üzerinde olması gerekmiyor ve C'ye doğrudan bağlanılabiliyorsa zaten doğrudan C'ye bağlanmak gerekir; bu mümkün değilse B zaten bir atlama noktası olarak işin içinde olmak zorundadır
Sorunu biraz daha ayrıntılı anlatırsanız daha uygun bir çözüm bulunabilir
Bir ölçüde gömülü bir host söz konusuysa DNS'in “yönlendirme” işini üstlenmesi sağlanabilir, ancak bu durumda host key fingerprint doğrulamasını kendiniz yapmanız gerekir