stunnel ile SSL/TLS Tüneli Oluşturma ve Şifresiz Servisleri Güvenli Hale Getirme
Eski bir Redis instance’ını internete açmak zorunda kaldığınızda ne hissedersiniz? Ben ilk kez o duruma düştüğümde, bir müşteri “Redis’e dışarıdan bağlanmam lazım ama şifreli olsun” dediğinde stunnel aklıma geldi. Çoğu servis kendi içinde TLS desteği sunmuyor ya da sunsa bile yapılandırması karmaşık oluyor. stunnel tam bu boşluğu dolduruyor: mevcut uygulamaya dokunmadan, önüne oturup SSL/TLS katmanı ekliyorsunuz.
stunnel Nedir ve Neden Kullanırız?
stunnel, TCP bağlantılarını şifrelemek için kullanılan, açık kaynaklı bir SSL/TLS proxy aracıdır. Uygulamanın kaynak koduna dokunmadan, ağ trafiğini şifrelenmiş bir tünelden geçirmenizi sağlar. Mantığı son derece basit: bir taraftan şifresiz bağlantı alır, diğer tarafa şifreli olarak iletir ya da tam tersi.
Neden bu kadar işe yarıyor? Çünkü gerçek dünyada her servis modern TLS desteğiyle gelmiyor. Eski SMTP sunucuları, Redis, Memcached, MySQL’in bazı eski sürümleri, hatta bazı endüstriyel protokoller TLS bilmiyor. Bu servisleri dışarıya açmanız gerektiğinde ya da iç ağda bile şifreleme istediğinizde stunnel devreye giriyor.
Kullanım alanları:
- Legacy uygulama güvenliği: TLS desteklemeyen eski uygulamaların önüne koyma
- Redis/Memcached şifreleme: Cache servislerini şifreli hale getirme
- SMTP/POP3/IMAP tünelleme: Eski mail servislerini güvenli hale getirme
- Veritabanı bağlantıları: MySQL, PostgreSQL için ek TLS katmanı
- Mikro servis iletişimi: İç ağdaki servisler arası şifreli kanal
Kurulum
Çoğu dağıtımda paket deposunda hazır geliyor.
# Debian/Ubuntu
sudo apt update && sudo apt install stunnel4 -y
# RHEL/CentOS/Rocky Linux
sudo dnf install stunnel -y
# Arch Linux
sudo pacman -S stunnel
# Versiyon kontrolü
stunnel -version
Kurulumdan sonra servisin durumunu kontrol edin:
# systemd üzerinde
sudo systemctl status stunnel4 # Debian/Ubuntu
sudo systemctl status stunnel # RHEL tabanlı
Sertifika Oluşturma
stunnel için bir sertifikaya ihtiyacınız var. Test ortamı için self-signed sertifika yeterli, production’da Let’s Encrypt veya kurumsal CA’dan alınan sertifika kullanın.
# Self-signed sertifika oluşturma (test için)
sudo openssl req -new -x509 -days 3650 -nodes
-out /etc/stunnel/stunnel.pem
-keyout /etc/stunnel/stunnel.pem
-subj "/C=TR/ST=Istanbul/L=Istanbul/O=MyCompany/CN=myserver.local"
# Dosya izinlerini kısıtlayın - private key dünyaya açık olmamalı
sudo chmod 600 /etc/stunnel/stunnel.pem
sudo chown root:root /etc/stunnel/stunnel.pem
Production ortamda sertifika ve private key ayrı dosyalarda tutulur:
# Sertifika ve key ayrı dosyalarda
sudo openssl req -newkey rsa:4096 -nodes
-keyout /etc/stunnel/server.key
-x509 -days 365
-out /etc/stunnel/server.crt
-subj "/C=TR/ST=Istanbul/L=Istanbul/O=MyCompany/CN=redis.mycompany.com"
sudo chmod 600 /etc/stunnel/server.key
sudo chmod 644 /etc/stunnel/server.crt
Temel Yapılandırma Dosyası
stunnel’in ana yapılandırma dosyası /etc/stunnel/stunnel.conf konumunda bulunur. Dosya yoksa oluşturmanız gerekiyor.
sudo nano /etc/stunnel/stunnel.conf
Temel bir yapılandırma şöyle görünür:
# Global ayarlar
pid = /var/run/stunnel4/stunnel.pid
output = /var/log/stunnel4/stunnel.log
# Güvenlik seviyesi
sslVersion = TLSv1.2
options = NO_SSLv2
options = NO_SSLv3
options = NO_TLSv1
options = NO_TLSv1.1
# Cipher suite - zayıf şifreleri devre dışı bırak
ciphers = HIGH:!aNULL:!MD5:!RC4
# Servis tanımı (örnek: Redis)
[redis-ssl]
accept = 0.0.0.0:6380
connect = 127.0.0.1:6379
cert = /etc/stunnel/server.crt
key = /etc/stunnel/server.key
Bu yapılandırmada stunnel, 6380 portunu dinliyor ve gelen şifreli bağlantıları yerel 6379 portundaki Redis’e yönlendiriyor. Dışarıdan bağlanan istemci TLS kullanıyor, Redis ise şifresiz localhost bağlantısı görüyor.
Gerçek Dünya Senaryosu 1: Redis’i Güvenli Hale Getirme
Diyelim ki bir uygulama sunucunuz var ve Redis’e başka bir sunucudan bağlanmanız gerekiyor. Redis kendi TLS desteğini 6.0’da aldı ama eski sürümler veya yapılandırma zahmetinden kaçınmak isteyenler için stunnel mükemmel bir çözüm.
Sunucu tarafı (Redis çalışan makine):
# /etc/stunnel/stunnel.conf - SUNUCU
pid = /var/run/stunnel4/stunnel.pid
output = /var/log/stunnel4/stunnel.log
# Sunucu modunda çalışıyoruz
[redis-server]
accept = 0.0.0.0:6380
connect = 127.0.0.1:6379
cert = /etc/stunnel/server.crt
key = /etc/stunnel/server.key
# İstemci sertifikası doğrulama (mutual TLS için)
# verify = 3
# CAfile = /etc/stunnel/ca.crt
İstemci tarafı (uygulamanın çalıştığı makine):
# /etc/stunnel/stunnel.conf - İSTEMCİ
pid = /var/run/stunnel4/stunnel.pid
output = /var/log/stunnel4/stunnel.log
# İstemci modunda çalışıyoruz
[redis-client]
client = yes
accept = 127.0.0.1:6379
connect = redis-server.mycompany.com:6380
CAfile = /etc/stunnel/server.crt
verify = 4
İstemci tarafında client = yes ayarı kritik. Bu sayede uygulama kodu değişmeden, sanki yerel Redis’e bağlanıyormuş gibi 127.0.0.1:6379 adresini kullanıyor. stunnel bu bağlantıyı alıp şifreleyerek uzak sunucuya iletiyor.
Servisi başlatın ve test edin:
# Servisi başlat
sudo systemctl enable stunnel4
sudo systemctl start stunnel4
# Log'u izle
sudo tail -f /var/log/stunnel4/stunnel.log
# İstemci tarafından Redis bağlantısını test et
redis-cli -h 127.0.0.1 -p 6379 ping
# Cevap: PONG
Gerçek Dünya Senaryosu 2: MySQL Bağlantısını Şifreleme
Bazı ekipler, MySQL’in dahili TLS yapılandırması yerine stunnel kullanmayı tercih ediyor. Özellikle eski MySQL sürümleri veya MariaDB kurulumlarında sertifika yönetimi karmaşık olabiliyor.
# /etc/stunnel/stunnel.conf - MySQL Sunucu Tarafı
[mysql-ssl]
accept = 0.0.0.0:3307
connect = 127.0.0.1:3306
cert = /etc/stunnel/mysql.crt
key = /etc/stunnel/mysql.key
# Bağlantı başına fork yerine thread kullan (performans)
# Bu global bir ayar
İstemci tarafında ise:
[mysql-client]
client = yes
accept = 127.0.0.1:3306
connect = db.mycompany.com:3307
CAfile = /etc/stunnel/mysql.crt
verify = 4
# Bağlantı zaman aşımı
TIMEOUTclose = 0
Bağlantıyı test etmek için:
# Normal mysql client ile test - istemci stunnel üzerinden şifreli bağlanır
mysql -h 127.0.0.1 -P 3306 -u myuser -p
# openssl ile SSL tünelini doğrudan test et
openssl s_client -connect db.mycompany.com:3307 -CAfile /etc/stunnel/mysql.crt
Gerçek Dünya Senaryosu 3: SMTP Tünelleme
Eski posta sunucuları veya bazı relay yapılandırmaları STARTTLS ya da SMTPS desteklemeyebilir. stunnel burada da devreye giriyor.
# SMTP için stunnel - sunucu tarafı
[smtps]
accept = 0.0.0.0:465
connect = 127.0.0.1:25
cert = /etc/stunnel/mail.crt
key = /etc/stunnel/mail.key
Postfix veya başka bir MTA’yı stunnel arkasına almak için bu yeterli. Dışarıdan 465 portuna şifreli bağlantı geliyor, stunnel onu çözerek yerel 25 portuna iletiyor.
Gelişmiş Yapılandırma Seçenekleri
stunnel’in bir kaç parametresi vardır ki doğru ayarlanmadığında ya güvenlik açığı oluşur ya da performans sorunuyla karşılaşırsınız.
Önemli global parametreler:
pid: stunnel’in PID dosyasının yoluoutput: Log dosyasının yolu; syslog içinsyslog = yeskullanılabilirdebug: Log seviyesi, 0-7 arası; production’da 4-5 yeterlicompression: zlib sıkıştırma; yüksek band genişliği senaryolarında kullanışlısocket: TCP socket seçenekleri;l:TCP_NODELAY=1latency’yi düşürür
Servis düzeyinde parametreler:
accept: Dinlenecek adres ve portconnect: Hedef adres ve portclient: İstemci modunu aktif edercert: Sertifika dosyasının yolukey: Private key dosyasının yoluCAfile: CA sertifikası; doğrulama içinverify: Sertifika doğrulama seviyesi; 0=yok, 1=isteğe bağlı, 2=zorunlu, 3=local CA, 4=ignore CNciphers: İzin verilen cipher suite listesisessionCacheSize: TLS session cache boyutu; yüksek bağlantı sayısında önemli
Yüksek yük altında performans için:
# /etc/stunnel/stunnel.conf - Performans odaklı ayarlar
# Global
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
sessionCacheSize = 1000
sessionCacheTimeout = 300
[redis-ssl]
accept = 0.0.0.0:6380
connect = 127.0.0.1:6379
cert = /etc/stunnel/server.crt
key = /etc/stunnel/server.key
ciphers = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
Mutual TLS (mTLS) Yapılandırması
Sadece sunucu değil, istemcinin de kimliğini doğrulamak istediğinizde mutual TLS kullanırsınız. Bu, özellikle mikro servis ortamlarında veya sadece belirli istemcilerin bağlanmasına izin vermek istediğinizde kritik.
Önce istemci sertifikası oluşturun:
# CA oluştur
openssl genrsa -out /etc/stunnel/ca.key 4096
openssl req -new -x509 -days 3650 -key /etc/stunnel/ca.key
-out /etc/stunnel/ca.crt
-subj "/C=TR/O=MyCompany CA/CN=MyCompany Internal CA"
# İstemci sertifikası oluştur ve CA ile imzala
openssl genrsa -out /etc/stunnel/client.key 2048
openssl req -new -key /etc/stunnel/client.key
-out /etc/stunnel/client.csr
-subj "/C=TR/O=MyCompany/CN=app-server-01"
openssl x509 -req -days 365
-in /etc/stunnel/client.csr
-CA /etc/stunnel/ca.crt
-CAkey /etc/stunnel/ca.key
-CAcreateserial
-out /etc/stunnel/client.crt
Sunucu yapılandırması:
[redis-mtls]
accept = 0.0.0.0:6380
connect = 127.0.0.1:6379
cert = /etc/stunnel/server.crt
key = /etc/stunnel/server.key
# mTLS için istemci doğrulama
CAfile = /etc/stunnel/ca.crt
verify = 3
İstemci yapılandırması:
[redis-client-mtls]
client = yes
accept = 127.0.0.1:6379
connect = redis.mycompany.com:6380
cert = /etc/stunnel/client.crt
key = /etc/stunnel/client.key
CAfile = /etc/stunnel/ca.crt
verify = 3
verify = 3 ile hem sunucu hem istemci sertifikaları kendi local CA’nız tarafından imzalanmış olmalı. Bu sayede rastgele bir istemci, geçerli bir sertifikası olmadan bağlanamıyor.
Sorun Giderme
stunnel sorunlarının büyük çoğunluğu ya sertifika problemi ya port çakışması ya da izin sorunudur. Log dosyası genellikle çok açıklayıcı oluyor.
# Log'u canlı izle
sudo tail -f /var/log/stunnel4/stunnel.log
# Debug modunda çalıştır (servisi durdur önce)
sudo systemctl stop stunnel4
sudo stunnel /etc/stunnel/stunnel.conf
# Port dinleniyor mu kontrol et
sudo ss -tlnp | grep stunnel
# Sertifika geçerliliğini kontrol et
openssl x509 -in /etc/stunnel/server.crt -text -noout | grep -E "Validity|Subject|Issuer"
# Tüneli manuel test et
openssl s_client -connect localhost:6380
-CAfile /etc/stunnel/server.crt
-cert /etc/stunnel/client.crt
-key /etc/stunnel/client.key
Yaygın hatalar ve çözümleri:
no certificate or private key specified:certvekeyparametrelerini kontrol edinVERIFY ERROR: unable to get local issuer certificate: CAfile yanlış ya da eksikbind: Address already in use: Port zaten kullanımda,ss -tlnpile kontrol edinPermission denied: Sertifika dosyası izinleri yanlış,chmod 600vechown rootuygulayınstunnel: LOG5[0]: stunnel 5.xx on... for Linux: Bu hata değil, versiyon bilgisi, paniğe gerek yok
Firewall ile Entegrasyon
stunnel yapılandırdıktan sonra firewall kurallarını güncellemeyi unutmayın. Eski port artık dışarıya açık olmamalı.
# UFW ile
sudo ufw allow 6380/tcp comment "Redis SSL via stunnel"
sudo ufw deny 6379/tcp comment "Redis direkt erisim engelle"
sudo ufw reload
# firewalld ile
sudo firewall-cmd --permanent --add-port=6380/tcp
sudo firewall-cmd --permanent --remove-port=6379/tcp
sudo firewall-cmd --reload
# iptables ile
sudo iptables -A INPUT -p tcp --dport 6380 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 6379 ! -s 127.0.0.1 -j DROP
Burada önemli bir nokta: 6379 portunu tamamen kapatmak yerine sadece localhost’tan kabul etmek daha doğru bir yaklaşım. Böylece Redis kendi sunucusundaki uygulamalar tarafından hala kullanılabilir, ama dışarıdan kimse direkt erişemez.
Systemd ile Otomatik Başlatma ve İzleme
Production ortamda stunnel’in sistem başlangıcında otomatik başlaması ve çökmesi halinde yeniden başlatılması gerekiyor.
# Servisi etkinleştir
sudo systemctl enable stunnel4
# Yeniden başlatma politikasını kontrol et
sudo systemctl show stunnel4 | grep -i restart
# Özel bir restart politikası için override oluştur
sudo mkdir -p /etc/systemd/system/stunnel4.service.d/
sudo tee /etc/systemd/system/stunnel4.service.d/restart.conf << 'EOF'
[Service]
Restart=always
RestartSec=5
EOF
sudo systemctl daemon-reload
sudo systemctl restart stunnel4
Servis sağlığını izlemek için basit bir script:
#!/bin/bash
# /usr/local/bin/check-stunnel.sh
SERVICE="stunnel4"
LOG="/var/log/stunnel-health.log"
if ! systemctl is-active --quiet $SERVICE; then
echo "$(date): $SERVICE down, restarting..." >> $LOG
systemctl restart $SERVICE
# Alarm gönder (opsiyonel)
# mail -s "stunnel restart edildi" [email protected] < /dev/null
else
echo "$(date): $SERVICE running OK" >> $LOG
fi
Bu scripti cron’a ekleyin:
# Her 5 dakikada kontrol
echo "*/5 * * * * root /usr/local/bin/check-stunnel.sh" | sudo tee /etc/cron.d/stunnel-health
Sonuç
stunnel, sysadmin’in araç kutusunda mutlaka olması gereken araçlardan biri. Özellikle legacy sistemlerle uğraşırken, her şeyi yeniden yazmak yerine mevcut servislerin önüne oturup güvenli iletişim sağlamak çok daha pragmatik bir yaklaşım.
Birkaç noktayı aklınızda tutun: Self-signed sertifika test için iyidir ama production’da mutlaka kurumsal CA veya Let’s Encrypt kullanın. Mutual TLS, servisler arası iletişimde ekstra bir güvenlik katmanı sağlıyor ve kurulum maliyeti düşük. Cipher suite’leri güncel tutun; TLSv1.0 ve TLSv1.1 artık güvensiz kabul ediliyor. Log’ları düzenli inceleyin; anormal bağlantı denemeleri güvenlik problemlerini erkenden fark etmenizi sağlıyor.
stunnel, sıfır uygulama değişikliğiyle ciddi bir güvenlik iyileştirmesi sunuyor. Bir Redis’i veya eski bir SMTP relay’ini şifrelemek için haftalar süren bir proje planlamak zorunda değilsiniz, birkaç saatlik bir çalışma yeterli.
