Uzaktan sunucu yönetiminin en can sıkıcı anlarından biri şudur: Bir servise erişmen lazım, ama o servis dışarıya kapalı. Firewall kuralları seni blokluyor, VPN ayarlamak için zaman yok, ya da sadece geçici bir çözüme ihtiyacın var. İşte tam bu noktada SSH tünelleme devreye giriyor ve hayatını kurtarıyor. SSH’ı sadece uzak sunucuya bağlanmak için kullananlar, bu aracın ne kadar güçlü olduğunun farkında bile değil. Bu yazıda SSH tünellemenin tüm inceliklerini, gerçek dünya senaryolarıyla birlikte ele alacağız.
SSH Tünelleme Nedir?
SSH tünelleme, ağ trafiğini şifreli bir SSH bağlantısı üzerinden yönlendirme işlemidir. Temel olarak iki nokta arasında güvenli bir “tünel” oluşturursun ve bu tünelden geçen tüm trafik SSH’ın şifreleme katmanıyla korunur. Üç farklı tünel türü vardır:
- Local Port Forwarding (Yerel Port Yönlendirme): Uzak sunucudaki bir porta yerel makinenden erişim
- Remote Port Forwarding (Uzak Port Yönlendirme): Yerel makinendeki bir porta uzak sunucudan erişim
- Dynamic Port Forwarding (Dinamik Port Yönlendirme): SOCKS proxy oluşturma
Her birinin farklı kullanım senaryoları var ve hangisini ne zaman kullanacağını bilmek gerçekten önemli.
Yerel Port Yönlendirme (Local Port Forwarding)
En sık kullanılan tünel türü budur. Mantığı şu: Uzak sunucuda çalışan ama dışarıya açık olmayan bir servise yerel makinenden erişmek istiyorsun.
Temel sözdizimi şöyle:
ssh -L [yerel_port]:[hedef_host]:[hedef_port] [kullanici]@[ssh_sunucu]
Pratik Senaryo 1: Uzak Veritabanına Güvenli Erişim
Diyelim ki production sunucunda MySQL çalışıyor ve güvenlik gereği 3306 portu dışarıya kapalı. Ama sen yerel makinendeki MySQL Workbench ile bağlanmak istiyorsun.
ssh -L 3307:localhost:3306 [email protected]
Bu komutla yerel makinende 3307 portunu dinlemeye alıyorsun. MySQL Workbench’i açıp localhost:3307 adresine bağlandığında, trafik SSH tüneli üzerinden production sunucusundaki 3306 portuna yönlendiriliyor. Production sunucusu sana sanki kendi localhost’undan bağlanıyormuşsun gibi davranıyor.
Pratik Senaryo 2: İç Ağdaki Bir Servise Erişim
Daha ilginç bir senaryo: Bir jump host (atlama sunucusu) üzerinden iç ağdaki başka bir sunucuya erişmek istiyorsun. Yani tünel doğrudan SSH sunucusunun localhostuna değil, o sunucunun erişebildiği başka bir adrese gidiyor.
ssh -L 8080:ic-sunucu.internal:80 [email protected]
Bu komutta ic-sunucu.internal kısmı, jump-host.sirketim.com‘un çözümleyebildiği bir adres. Senin makinenden bu adrese direkt erişim yok, ama jump host üzerinden erişim var. Yerel 8080 portuna bağlandığında trafik jump host üzerinden iç ağdaki web sunucusuna ulaşıyor.
Arka Planda Çalıştırma
Her seferinde terminal penceresini açık tutmak zorunda değilsin. -N ve -f parametreleriyle tüneli arka plana atabilirsin:
ssh -L 3307:localhost:3306 -N -f [email protected]
-N: Uzak komut çalıştırma, sadece port yönlendirme yap -f: SSH’ı arka plana al
Bu komut çalıştıktan sonra terminal serbest kalır, tünel arka planda çalışmaya devam eder. Tüneli kapatmak için process’i bulup öldürmen gerekir:
ps aux | grep ssh
kill [PID]
Ya da daha temiz bir yöntem:
ssh -L 3307:localhost:3306 -N -f -o ExitOnForwardFailure=yes [email protected]
-o ExitOnForwardFailure=yes: Port yönlendirme başarısız olursa SSH hemen çıksın
Uzak Port Yönlendirme (Remote Port Forwarding)
Bu, yerel yönlendirmenin tam tersidir. Kendi yerel makinesindeki bir servisi, SSH ile bağlandığın uzak sunucu üzerinden erişilebilir yapmak istiyorsun. Özellikle NAT arkasında olduğunda veya firewall geçemediğinde çok işe yarıyor.
ssh -R [uzak_port]:[yerel_host]:[yerel_port] [kullanici]@[ssh_sunucu]
Pratik Senaryo 3: Geliştirme Ortamını Dışarıya Açma
Klasik durum: Yerel makinende bir web uygulaması geliştiriyorsun, müşteriye göstermek istiyorsun ama makinen internete doğrudan açık değil. Bir VPS’in var ve bunu köprü olarak kullanabilirsin:
ssh -R 8080:localhost:3000 [email protected]
Şimdi vps.sirketim.com:8080 adresine giren biri, senin yerel makinesinde 3000 portunda çalışan uygulamayı görecek. Müşteriye sadece bu URL’i veriyorsun.
Önemli bir not: Uzak port yönlendirmenin dışarıya açılması için uzak sunucudaki sshd_config dosyasında şu ayarın olması gerekiyor:
# /etc/ssh/sshd_config
GatewayPorts yes
Bu ayar olmadan yönlendirme sadece uzak sunucunun kendi localhost’unda çalışır, dışarıdan erişilemez.
Pratik Senaryo 4: Ters SSH Tüneli ile Erişilemeyen Sunucuya Bağlanma
Bu senaryo gerçekten hayat kurtarıcı: NAT arkasında olan veya firewall nedeniyle dışarıdan SSH yapamadığın bir sunucu var. Ama o sunucu dışarıya bağlantı kurabiliyor. Önce o sunucudan bizim erişilebilir bir sunucuya ters tünel kuruyoruz:
# NAT arkasındaki sunucuda çalıştır
ssh -R 2222:localhost:22 [email protected] -N -f
Artık eriselebilir-sunucu.com üzerinden NAT arkasındaki sunucuya bağlanabilirsin:
# Erişilebilir sunucudan çalıştır
ssh -p 2222 localhost
Bu yöntem özellikle uzak lokasyonlardaki sunuculara, kiosk sistemlere veya müşteri sitelerindeki makinelere erişmek için harika çalışıyor.
Dinamik Port Yönlendirme (SOCKS Proxy)
Dinamik yönlendirme, öncekilerden farklı olarak tek bir port için değil, tüm trafik için bir SOCKS proxy oluşturuyor. SSH bağlantısı, gelen trafik nereye gitmek istiyorsa oraya yönlendiriyor.
ssh -D [yerel_port] [kullanici]@[ssh_sunucu]
Pratik Senaryo 5: Güvensiz Ağda Güvenli Browsing
Kafe, havalimanı gibi güvensiz WiFi ağlarında browsing yapacaksın:
ssh -D 1080 -N -f [email protected]
Sonra tarayıcını localhost:1080 üzerinden SOCKS5 proxy kullanacak şekilde ayarlıyorsun. Firefox’ta bunu about:preferences > Network Settings bölümünden yapabilirsin. Tüm browser trafiğin artık SSH tüneli üzerinden geçiyor.
Komut satırında curl veya başka araçları proxy üzerinden kullanmak için:
curl --socks5 localhost:1080 http://hedef-site.com
Ya da proxychains aracıyla herhangi bir programı proxy üzerinden çalıştırabilirsin:
# /etc/proxychains.conf dosyasına ekle:
# socks5 127.0.0.1 1080
proxychains firefox
SSH Config Dosyasıyla Tünelleri Kalıcı Hale Getirme
Her seferinde uzun komutlar yazmak yerine, ~/.ssh/config dosyasına tünel ayarlarını kaydedebilirsin. Bu gerçekten işleri kolaylaştırıyor.
# ~/.ssh/config
Host prod-db-tunnel
HostName production.sirketim.com
User admin
LocalForward 3307 localhost:3306
ServerAliveInterval 60
ServerAliveCountMax 3
Host dev-expose
HostName vps.sirketim.com
User root
RemoteForward 8080 localhost:3000
ServerAliveInterval 30
Artık sadece şunu yazman yeterli:
ssh prod-db-tunnel
ServerAliveInterval: Her 60 saniyede bir keepalive paketi gönder ServerAliveCountMax: 3 başarısız keepalive sonrası bağlantıyı kes
Bu keepalive ayarları çok önemli. Uzun süreli tünellerde bağlantı kopukluğu yaşamamak için mutlaka ekle.
AutoSSH ile Kalıcı Tüneller
SSH tünelleri bazen düşebilir. Network kesilmesi, sunucu yeniden başlatma, timeout gibi durumlar olabilir. Production ortamında otomatik yeniden bağlanan tüneller istiyorsan autossh kullanmalısın.
# Ubuntu/Debian
apt install autossh
# CentOS/RHEL
yum install autossh
Kullanımı SSH ile neredeyse aynı:
autossh -M 20000 -L 3307:localhost:3306 -N [email protected]
-M 20000: autossh’un bağlantı sağlığını kontrol etmek için kullanacağı monitoring portu
Systemd servis olarak çalıştırmak için bir unit dosyası oluşturabilirsin:
# /etc/systemd/system/ssh-tunnel-db.service
[Unit]
Description=SSH Tunnel - Production DB
After=network.target
[Service]
User=deploy
ExecStart=/usr/bin/autossh -M 20000 -N
-L 3307:localhost:3306
-o "ServerAliveInterval=30"
-o "ServerAliveCountMax=3"
-o "ExitOnForwardFailure=yes"
-i /home/deploy/.ssh/id_rsa
[email protected]
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
systemctl enable ssh-tunnel-db
systemctl start ssh-tunnel-db
systemctl status ssh-tunnel-db
Artık sistem yeniden başlasa bile tünel otomatik olarak kurulacak.
Çoklu Port Yönlendirme
Tek bir SSH bağlantısında birden fazla port yönlendirebilirsin. Bunun için -L parametresini tekrarlayabilirsin:
ssh -L 3307:localhost:3306
-L 6380:localhost:6379
-L 9200:localhost:9200
-N -f [email protected]
Bu komutla aynı anda MySQL (3306->3307), Redis (6379->6380) ve Elasticsearch (9200->9200) tünellerini açıyorsun. Tek bağlantı, üç farklı servis.
Güvenlik Konuları
SSH tünelleme güçlü ama dikkatli kullanılması gereken bir araç. Birkaç önemli nokta:
Tünel Açık Olan Portları Kontrol Et
# Açık tünelleri görmek için
ss -tlnp | grep ssh
# Ya da netstat ile
netstat -tlnp | grep ssh
GatewayPorts Ayarına Dikkat Et
Uzak port yönlendirmede GatewayPorts yes ayarı, yönlendirilen portun tüm arayüzlerden erişilebilir olmasını sağlar. Bu bazen güvenlik riski oluşturabilir. Daha kısıtlı bir yaklaşım için:
# sshd_config'de
GatewayPorts clientspecified
Bu ayarla, istemci hangi IP’de dinleneceğini belirtebilir:
ssh -R 0.0.0.0:8080:localhost:3000 [email protected]
Tünel İzinlerini Kısıtlama
Eğer bir kullanıcıya sadece tünel izni vermek istiyorsan, shell erişimi vermeden bunu yapabilirsin:
# authorized_keys dosyasında
no-pty,no-X11-forwarding,command="/bin/false" ssh-rsa AAAA...
Ya da daha modern yaklaşım olarak Match bloğu kullanabilirsin:
# sshd_config
Match User tunnel-user
AllowTcpForwarding yes
X11Forwarding no
PermitTTY no
ForceCommand /bin/false
Tünel Sorunlarını Gidermek
Tünel çalışmıyor mu? Debug modunu aç:
ssh -v -L 3307:localhost:3306 -N [email protected]
Daha fazla detay için:
ssh -vvv -L 3307:localhost:3306 -N [email protected]
Sık karşılaşılan sorunlar ve çözümleri:
- “bind: Address already in use”: Yerel port zaten kullanımda. Farklı bir port numarası seç ya da eski tüneli öldür.
- “channel 3: open failed: connect failed”: Uzak tarafta hedef porta ulaşılamıyor. Servisin çalışıp çalışmadığını kontrol et.
- Bağlantı sürekli kopuyor:
ServerAliveIntervalveServerAliveCountMaxayarlarını ekle. - Port 22 firewall’da kapalı: SSH’ı 443 veya 80 portunda çalıştırabilir ya da bu portlara yönlendirebilirsin. Birçok şirket firewall’u 443’e izin veriyor.
ProxyJump ile Tünelleri Birleştirmek
Modern SSH’da birden fazla sunucu üzerinden geçmek için ProxyJump kullanabilirsin. Eskiden bunu tünellerle yaparlardı, ama artık daha temiz bir yol var:
ssh -J jump-host.com ic-sunucu.internal
Config dosyasında:
Host ic-sunucu
HostName ic-sunucu.internal
User admin
ProxyJump jump-host.com
Host ic-sunucu-tunnel
HostName ic-sunucu.internal
User admin
ProxyJump jump-host.com
LocalForward 5432 localhost:5432
Bu yöntemle iki hop üzerinden hem bağlanabilir hem de port yönlendirebilirsin.
Sonuç
SSH tünelleme, sysadmin araç kutusunun en değerli parçalarından biri. Güvenlik duvarları aşmak, geçici çözümler üretmek, güvensiz ağlarda güvenli iletişim sağlamak, production servislerine güvenli erişim, geliştirici ortamlarını dışarıya açmak gibi onlarca senaryoda işe yarıyor.
Özetle hangi tüneli ne zaman kullanacağını netleştirelim:
- Local (-L): Uzaktaki bir servise yerel erişim istiyorsun
- Remote (-R): Yerelindeki bir servisi uzaktan erişilebilir yapmak istiyorsun
- Dynamic (-D): Tüm trafiği proxy üzerinden yönlendirmek istiyorsun
Gerçek production ortamlarında autossh ve systemd kombinasyonunu şiddetle tavsiye ederim. El ile kurulan tüneller unutulur, düşer, sorun çıkarır. Servis olarak yönetilen tüneller ise kendiliğinden ayağa kalkar ve izlenebilir.
Son olarak, SSH tünellemeyi bir kural dışı çözüm olarak değil, düzgün tasarlanmış bir network mimarisinin parçası olarak kullan. Uzun vadeli çözümler için VPN, servis mesh veya proper firewall kuralları daha uygun olabilir. Ama acil durumlarda ve geçici çözümlerde SSH tünelleme tartışmasız en pratik seçenek.