sshuttle ile Şeffaf SSH Proxy ve VPN Alternatifi Kullanımı

Kurumsal ağlarda çalışan herkes şunu bilir: bazen en basit çözüm, en zekice çözümdür. VPN sunucusu kurmak, sertifika yönetimiyle boğuşmak, iptables kurallarını ayarlamak… Bunların hiçbirine gerek kalmadan, elinizin altındaki SSH erişimiyle tam anlamıyla bir tünel kurabilirsiniz. İşte sshuttle tam da bu iş için var ve benim gibi “minimum kurulum, maksimum verimlilik” prensibini benimseyenler için gerçek bir nimet.

sshuttle Nedir ve Neden Önemli?

sshuttle kendini “poor man’s VPN” olarak tanımlar, yani “yoksulun VPN’i”. Ama bu tanım biraz haksızlık ediyor aslında. Çünkü sshuttle, klasik VPN çözümlerinin sunduğu şeylerin büyük çoğunluğunu, çok daha az karmaşıklıkla sunuyor.

Nasıl çalıştığını anlamak önemli. Klasik SSH port yönlendirme (-L ya da -D flag’leri) uygulama bazında çalışır; her uygulamayı ayrı ayrı proxy üzerinden yönlendirmeniz gerekir. SOCKS proxy kurduğunuzda tarayıcıyı ayarlarsınız, ama DNS hala yerel çözümleyiciden geçer, ping çalışmaz, bazı uygulamalar proxy’i desteklemez.

sshuttle ise işi tamamen farklı bir seviyede çözer. Yerel makinenizde iptables (ya da macOS’ta pf) kuralları oluşturur ve belirttiğiniz IP bloklarına giden trafiği şeffaf biçimde SSH tüneli üzerinden yönlendirir. Uygulamaların bundan haberi olmaz. curl, wget, psql, redis-cli, ne kullanırsanız kullanın, hepsi tünelden geçer.

Uzak tarafta ise tek gereken şey Python 3 kurulu bir SSH sunucusu. OpenVPN gibi root yetkisiyle bir daemon başlatmanıza gerek yok. WireGuard için kernel modülü yüklemeniz gerekmiyor. Sadece SSH erişiminiz olsun, gerisini sshuttle halleder.

Kurulum

Yerel makinenize kurmanız yeterli, uzak sunucuda hiçbir şey kurmanıza gerek yok.

Ubuntu/Debian:

sudo apt update && sudo apt install sshuttle

RHEL/CentOS/Fedora:

sudo dnf install sshuttle
# veya eski sistemlerde
sudo yum install sshuttle

macOS (Homebrew):

brew install sshuttle

pip ile (en güncel versiyon için):

pip3 install sshuttle

Kurulum sonrası versiyonu kontrol edin:

sshuttle --version

Temel Kullanım

En basit senaryo: Bir jump host ya da bastion sunucunuz var, ve o sunucunun erişebildiği iç ağa ulaşmak istiyorsunuz.

sshuttle -r [email protected] 10.0.0.0/8

Bu komut şunu yapar: 10.0.0.0/8 bloğuna giden tüm trafiği sunucu.example.com üzerinden tüneller. Komut çalıştığında yerel şifrenizi (sudo için) ve SSH şifrenizi sorar, sonra arka planda bekler. Ctrl+C ile kapatırsınız.

Birden fazla subnet belirtebilirsiniz:

sshuttle -r [email protected] 10.0.0.0/8 192.168.1.0/24 172.16.0.0/12

Tüm trafiği tünellemek istiyorsanız (dikkatli kullanın):

sshuttle -r [email protected] 0.0.0.0/0

DNS Sorununu Çözmek

sshuttle’ın en güçlü özelliklerinden biri DNS yönetimi. Sadece IP yönlendirmesi yapıp DNS’i yerel bırakırsanız, iç ağ hostname’leri çözümlenemez. --dns parametresi bu sorunu çözer:

sshuttle -r [email protected] --dns 10.0.0.0/8

Bu bayrakla birlikte DNS sorguları da tünel üzerinden gönderilir. Artık ping uygulama-sunucu.ic-ag.local gibi hostname’lere erişebilirsiniz.

Daha ince bir kontrol istiyorsanız, hangi DNS sunucusunun kullanılacağını belirtebilirsiniz:

sshuttle -r [email protected] --dns --to-ns 10.0.0.1 10.0.0.0/8

SSH Anahtar Yönetimi ve Gelişmiş Bağlantı Seçenekleri

Parola yerine SSH anahtarı kullanmak (ki her zaman böyle olmalı):

sshuttle -r [email protected] -e 'ssh -i ~/.ssh/sirket_key' 10.0.0.0/8

Standart dışı bir SSH portu kullanıyorsanız:

sshuttle -r [email protected]:2222 10.0.0.0/8

SSH config dosyasını kullanmak en temiz yöntem. ~/.ssh/config dosyanıza şunu ekleyin:

Host bastion
    HostName bastion.sirket.com
    User kullanici
    IdentityFile ~/.ssh/sirket_key
    ServerAliveInterval 30
    ServerAliveCountMax 3

Sonra sshuttle’ı bu alias ile çalıştırın:

sshuttle -r bastion 10.0.0.0/8

Çok daha temiz, değil mi?

Gerçek Dünya Senaryosu 1: Uzak Veri Tabanına Erişim

Diyelim ki production ortamınızda PostgreSQL sunucusu sadece iç ağdan erişilebilir. db.ic-ag.local adresinde çalışıyor, portu 5432. Normalde SSH tüneli kurarsınız:

ssh -L 5432:db.ic-ag.local:5432 [email protected]

Sonra psql -h localhost -p 5432 bağlanırsınız. Bu çalışır, ama zahmetlidir. Her farklı servis için ayrı tünel açmanız gerekir. Bir de şunu hayal edin: aynı anda üç farklı servise, beş farklı porta bağlanmanız gerekiyor.

sshuttle ile:

sshuttle -r bastion --dns 10.0.0.0/8

Artık direkt olarak:

psql -h db.ic-ag.local -U dbkullanici production_db

Hiçbir port yönlendirmesi yok. Monitoring araçlarınız, uygulama connection string’leriniz olduğu gibi çalışır.

Gerçek Dünya Senaryosu 2: Çoklu Atlama (Jump Host Zincirleri)

Bazı kurumsal ağlarda güvenlik katmanları var. Önce bir bastion’a, oradan iç ağa, oradan daha kısıtlı bir segmente geçmeniz gerekiyor. sshuttle bunu da kaldırır.

SSH config’inizi şöyle düzenleyin:

Host bastion
    HostName bastion.sirket.com
    User kullanici
    IdentityFile ~/.ssh/sirket_key

Host ic-sunucu
    HostName 10.0.1.5
    User kullanici
    ProxyJump bastion
    IdentityFile ~/.ssh/sirket_key

Şimdi sshuttle’ı ic-sunucu üzerinden çalıştırın ve daha kısıtlı ağa ulaşın:

sshuttle -r ic-sunucu 172.16.0.0/16

sshuttle SSH’ın ProxyJump mekanizmasını kullandığı için bu zincir şeffaf biçimde çalışır.

Arka Planda Çalıştırma ve Daemon Modu

Geliştirme sırasında tüneli sürekli açık tutmak isteyebilirsiniz. Daemon modunda çalıştırın:

sshuttle --daemon --pidfile=/tmp/sshuttle.pid -r bastion 10.0.0.0/8

Durdurmak için:

kill $(cat /tmp/sshuttle.pid)

Ya da daha temiz bir wrapper script yazın. Ben bu scripti ~/.local/bin/tun-ac ve tun-kapat olarak kaydediyorum:

#!/bin/bash
# tun-ac
sshuttle 
    --daemon 
    --pidfile=/tmp/sirket-tun.pid 
    --dns 
    -r bastion 
    10.0.0.0/8 
    192.168.100.0/24 
    && echo "Tunel aktif" 
    || echo "Tunel baslatilamadi"
#!/bin/bash
# tun-kapat
if [ -f /tmp/sirket-tun.pid ]; then
    kill $(cat /tmp/sirket-tun.pid)
    rm /tmp/sirket-tun.pid
    echo "Tunel kapatildi"
else
    echo "Aktif tunel bulunamadi"
fi

Bağlantı Sürdürülebilirliği: autossh ile Kombinasyon

Uzun süreli kullanımlarda bağlantı kopabilir. autossh ile sshuttle’ı birleştirirseniz otomatik yeniden bağlanma elde edersiniz:

autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" 
    -f -N [email protected] 
    & sshuttle -r bastion 10.0.0.0/8

Daha sağlam bir yaklaşım için systemd servisi yazabilirsiniz. /etc/systemd/system/sirket-tun.service:

[Unit]
Description=Sirket IC Ag Tuneli
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=kullanici_adi
ExecStart=/usr/bin/sshuttle -r bastion 10.0.0.0/8 --dns
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable sirket-tun
sudo systemctl start sirket-tun
sudo systemctl status sirket-tun

Bu sayede sistem yeniden başladığında tünel otomatik olarak kurulur.

Belirli Adresleri Tünelden Hariç Tutmak

Bazen tüm iç ağı tünellemek istemezsiniz. Belirli subnetleri hariç tutmak için -x (exclude) parametresini kullanın:

sshuttle -r bastion 10.0.0.0/8 -x 10.0.99.0/24

Bu özellikle işe yarayan bir senaryo: Şirket ağının tamamını tünellerken, yavaş ya da sorunlu bir subnet’i bypass etmek. Ya da bir monitoring sistemini yerel ağdan erişilebilir tutarken geri kalanı tünellemek.

Aynı anda hem dahil edip hem hariç tutma:

sshuttle -r bastion 
    0.0.0.0/0 
    -x 192.168.0.0/16 
    -x 10.10.0.0/24

Burada tüm trafiği tünellerken iki subnet’i yerel ağdan geçirmeye devam ediyoruz.

Verbose Mod ve Hata Ayıklama

Bir şeyler ters gittiğinde ne olduğunu anlamak için:

sshuttle -r bastion 10.0.0.0/8 -v

Daha ayrıntılı çıktı için:

sshuttle -r bastion 10.0.0.0/8 -vv

Verbose modda hangi paketlerin tünelleneceğini, iptables kurallarının nasıl oluşturulduğunu görebilirsiniz. Bir bağlantı neden çalışmıyor diye bakarken bu çıktı çok değerli.

Yerel tarafta hangi iptables kurallarının oluşturulduğunu görmek için ayrı bir terminal açıp:

sudo iptables -t nat -L -n -v

sshuttle’ın oluşturduğu zincirleri (sshuttle- ile başlayanları) göreceksiniz.

Gerçek Dünya Senaryosu 3: Geliştirici Makinelerinde Staging Ortamı Erişimi

Bir yazılım ekibini düşünün. Staging ortamı kurumsal ağın içinde, geliştiricilerin kısmı ofiste değil, evden çalışıyor. Her geliştirici için OpenVPN hesabı açmak, sertifika dağıtmak, sorunları çözmek ciddi bir iş yükü.

Alternatif: Geliştiricilere bastion sunucusuna SSH erişimi verin ve şu scripti dağıtın:

#!/bin/bash
# staging-connect.sh
set -e

BASTION="bastion.sirket.com"
STAGING_NET="10.20.0.0/16"
DNS_OPT="--dns"
PID_FILE="$HOME/.staging-tun.pid"

case "$1" in
    baslat)
        if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
            echo "Tunel zaten aktif (PID: $(cat $PID_FILE))"
            exit 0
        fi
        echo "Staging tuneli baslatiliyor..."
        sshuttle --daemon 
            --pidfile="$PID_FILE" 
            $DNS_OPT 
            -r "$BASTION" 
            "$STAGING_NET"
        echo "Tunel aktif. 'staging-connect.sh durdur' ile kapatabilirsiniz."
        ;;
    durdur)
        if [ -f "$PID_FILE" ]; then
            kill $(cat "$PID_FILE") && rm "$PID_FILE"
            echo "Tunel durduruldu."
        else
            echo "Aktif tunel bulunamadi."
        fi
        ;;
    durum)
        if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
            echo "Tunel aktif (PID: $(cat $PID_FILE))"
        else
            echo "Tunel aktif degil."
        fi
        ;;
    *)
        echo "Kullanim: $0 {baslat|durdur|durum}"
        exit 1
        ;;
esac

Bu script ile geliştirici ./staging-connect.sh baslat diyerek saniyeler içinde iç ağa bağlanır, işi bitince ./staging-connect.sh durdur ile kapatır.

macOS’ta Özel Durumlar

macOS’ta sshuttle, iptables yerine pf (Packet Filter) kullanır. Genel kullanım aynı, ancak bazı nüanslar var.

macOS’ta --method=tproxy desteklenmez, bunun yerine varsayılan metod olan nat kullanılır. Çoğu durumda ekstra bir şey yapmanıza gerek yok, sshuttle kendisi halleder. Ama bazen pf ile ilgili izin sorunları çıkabilir:

sudo sshuttle -r bastion 10.0.0.0/8 --dns

macOS’ta özellikle Monterey ve sonrasında pf kuralları için sudo şart. Bunu script’e gömmek yerine, macOS kullanıcılarına sudoers’a şu satırı eklemelerini önerin:

kullanici_adi ALL=(ALL) NOPASSWD: /usr/bin/sshuttle

Performans ve Sınırlamalar

sshuttle mükemmel bir araç, ama her araç gibi sınırları var. Bunları bilmeden kullanmak hayal kırıklığına yol açabilir.

UDP desteği sınırlıdır. sshuttle öncelikle TCP trafiğini tüneller. DNS sorgularını tünelleyebilir (UDP üzerinden), ama genel UDP trafiği için --method=tproxy gerekir ve bu yalnızca Linux’ta çalışır. Yani VoIP, video konferans trafikleri sshuttle üzerinden tam anlamıyla geçmeyebilir.

ICMP (ping) varsayılanda tünellenmez. ping 10.0.0.5 çalışmayabilir, ama curl http://10.0.0.5 çalışır. Bu kafa karıştırıcı olabilir. Bağlantı var ama ping gönderemiyor gibi görünebilir.

Bant genişliği: Tüm trafik SSH üzerinden şifrelenerek geçtiği için CPU kullanımı artar. Yüksek bantgenişliği gerektiren işlemler (büyük dosya transferleri, video streaming) için dedicated VPN çözümlerine göre daha yavaş olabilir.

Kernel tproxy metodu: En güçlü özellikler için:

sudo sshuttle -r bastion --method=tproxy 10.0.0.0/8

Bu metod UDP dahil tüm trafiği tüneller, ama root gerektirir ve yalnızca Linux’ta çalışır.

sshuttle ile Güvenlik Değerlendirmesi

sshuttle kullandığınızda güvenlik açısından şunları göz önünde bulundurun:

Trafik SSH ile şifrelenir, bu iyi. Ama yerel makinenizde iptables kuralları oluşturulur, yani sshuttle’ın root yetkisine ihtiyacı var. Bu gerekliliği minimize etmek için sudoers konfigürasyonunu dikkatli yapın.

Bastion sunucunuz bir proxy görevi gördüğü için, bu sunucu üzerinden geçen tüm trafik loglara düşebilir. Kurumsal ortamlarda bu beklenen bir davranış, ama farkında olun.

Son olarak, hangi subnetleri tünellediğinize dikkat edin. 0.0.0.0/0 ile tüm trafiği tünellemek, kişisel trafiğinizin de kurumsal bastion üzerinden geçmesi anlamına gelir. İş makinalarında, politikaya bağlı olarak, bu sorun yaratabilir.

Sonuç

sshuttle benim araç çantamda köşeye kaldırılmış ekipmanlardan değil, haftalık hatta günlük kullandığım bir araç. Özellikle şu üç durumda vazgeçilmez:

Geçici iç ağ erişimi gerektiğinde, tam teşekküllü VPN kurmak overkill olur. Birkaç geliştiriciyi ya da sysadmin’i hızlıca iç ağa bağlamak gerektiğinde, sshuttle’ı ayaklandırmak on dakika sürer, OpenVPN sunucusu kurmak ise yarım gün.

Çok katmanlı ağ topolojilerinde, jump host zincirlerini SSH config ile yöneterek sshuttle’ı çalıştırmak, her aşamada ayrı port yönlendirmesi yapmaktan çok daha temiz bir deneyim sunar.

Geliştirici erişimi standartlaştırmada, bir script yazıp tüm ekibe dağıtmak; VPN istemcisi kurma, sertifika yönetimi, lisans sorunları gibi dertlerden kurtarır.

Tabii ki üretim trafiği için, yüksek erişilebilirlik gerektiren durumlar için ya da tüm şirketin bağlandığı merkezi bir çözüm için WireGuard ya da OpenVPN gibi araçlar daha uygun. Ama “işimi hızlıca halledeyim, fazla zaman kaybetmeyeyim” dediğinizde, SSH erişiminiz varsa sshuttle’dan daha hızlı bir çözüm bulmak zordur.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir