Tüm eğitimler
TEKNİK RAPOR OPENSSL mTLS 2026

Sıfırdan mTLS Kurulumu
OpenSSL ile Uçtan Uca

Kendi Sertifika Otoritesini oluştur, sunucu ve istemci sertifikaları üret, karşılıklı TLS bağlantısı kur. Her komut, her parametre, her adım açıklamalı.

00Çalışma klasörü

Her şey izole bir klasörde olsun. Bitince silersin, makinen kirlenmez.

bash
mkdir mtls-demo
cd mtls-demo

01CA oluştur

CA'nın iki şeye ihtiyacı var: kendi gizli anahtarı ve kendi sertifikası. CA'nın sertifikası self-signed olacak (kendi kendini imzalayacak) çünkü en tepedeki otorite — üstünde imzalayacak kimse yok.

1a — CA'nın gizli anahtarını üret

bash
openssl genrsa -out ca.key 2048

2048 bitlik RSA anahtar çifti üretir, gizli anahtarı ca.key dosyasına yazar. Açık anahtar gizli anahtarın içinden matematiksel olarak türetilebildiği için ayrı bir dosyaya yazılmaz.

Kritik Güvenlik

ca.key ultra gizlidir. Bu dosya çalınırsa tüm sistem çöker — saldırgan istediği sertifikayı üretebilir. Gerçek bir CA'da bu dosya internetten kopuk bir makinede, hatta özel donanımda (HSM) tutulur.

1b — CA'nın self-signed sertifikasını oluştur

bash
openssl req -new -x509 -key ca.key -out ca.crt -days 3650 \
  -subj "/C=TR/ST=Istanbul/O=Benim CA'm/CN=Benim Root CA"
-newyeni bir sertifika talebi başlat
-x509CSR değil, doğrudan self-signed sertifika üret
-key ca.keyimzalamak için bu gizli anahtarı kullan
-out ca.crtsertifikayı bu dosyaya yaz
-days 365010 yıl geçerli olsun
-subjsertifika sahibinin bilgileri (interaktif sormasın diye)

Bu komut sonunda ca.crt'nin içinde: CA'nın açık anahtarı + CA bilgileri + CA'nın kendi gizli anahtarıyla yaptığı imza var. Self-signed olduğu için Issuer ve Subject aynı.

1c — Sertifikayı incele (isteğe bağlı)

bash
openssl x509 -in ca.crt -noout -text

Çıktıda Issuer ve Subject alanlarının aynı olduğunu göreceksin — bu self-signed olmanın tanımı.

02Sunucu sertifikası

Üç adım: gizli anahtarı üret, CSR oluştur, CA'ya imzalat. Bu, gerçek dünyada bir web sitesi için sertifika almanın birebir aynısı — sadece CA olarak Let's Encrypt yerine kendi CA'mızı kullanıyoruz.

2a — Sunucunun gizli anahtarını üret

bash
openssl genrsa -out server.key 2048

Bu anahtar sunucuda kalacak, hiçbir yere gitmeyecek. CA bile bunu görmeyecek.

2b — Sunucu için CSR oluştur

bash
openssl req -new -key server.key -out server.csr \
  -subj "/C=TR/ST=Istanbul/O=Benim Sirketim/CN=localhost"

Burada -x509 yok — bu sefer CSR üretiyoruz, sertifika değil. CSR'ın içinde: sunucu bilgileri + sunucunun açık anahtarı + sunucunun kendi gizli anahtarıyla yaptığı imza. CN=localhost yazdık çünkü yerel makinada test edeceğiz.

2c — Uzantı config dosyası oluştur

Modern istemciler SAN (Subject Alternative Name) olmadan sertifikayı kabul etmez. Bir config dosyası lazım:

bash
cat > server_ext.cnf << 'EOF'
subjectAltName = DNS:localhost, IP:127.0.0.1
extendedKeyUsage = serverAuth
EOF
subjectAltNamesertifikanın hangi host'lar için geçerli olduğunu söyler. Modern istemciler CN alanına değil, buraya bakar.
extendedKeyUsageserverAuth = bu sertifika sadece sunucu kimlik doğrulamasında kullanılabilir.

2d — CSR'ı CA ile imzala

bash
openssl x509 -req -in server.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out server.crt -days 365 \
  -extfile server_ext.cnf
-reqgirdi bir CSR'dır
-CA ca.crtimzalayıcının sertifikası
-CAkey ca.keyimzalayıcının gizli anahtarı (imza bununla atılacak)
-CAcreateserialseri numarası sayacı (ca.srl) oluştur
-extfileyukarıdaki uzantıları sertifikaya ekle
Ne oluyor

CSR'daki imza önce doğrulanır (CSR'daki açık anahtarla) — "bu CSR gerçekten gizli anahtar sahibinden gelmiş mi". Sonra yeni sertifika oluşturulur: CSR'dan gelen bilgiler + eklenen uzantılar + CA'nın gizli anahtarıyla yeni imza.

03İstemci sertifikası

Süreç tamamen aynı, tek fark extendedKeyUsage = clientAuth olması. Normal TLS'te bu adım yok — mTLS'i mTLS yapan şey bu.

3a — İstemci gizli anahtarı ve CSR

bash
openssl genrsa -out client.key 2048

openssl req -new -key client.key -out client.csr \
  -subj "/C=TR/ST=Istanbul/O=Benim Sirketim/CN=ali-musteri"

CN=ali-musteri — istemcinin kim olduğunu belirten bir isim. Gerçek hayatta bu bir kullanıcı adı, servis adı veya cihaz ID'si olabilir.

3b — İstemci için config dosyası

bash
cat > client_ext.cnf << 'EOF'
extendedKeyUsage = clientAuth
EOF

İstemci sertifikasında SAN gerekmiyor çünkü istemci bir host değil — ona bağlanan olmayacak. Sadece clientAuth damgası yeterli.

3c — CSR'ı CA ile imzala

bash
openssl x509 -req -in client.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out client.crt -days 365 \
  -extfile client_ext.cnf

04Dosyaların özeti

Şu an elimizde 8 dosya var. Hangisi gizli, hangisi paylaşılabilir, hangisi nerede durmalı?

DosyaNeNerede Durmalı
ca.keyCA gizli anahtarıULTRA GİZLİ — sadece CA'da
ca.crtCA sertifikasıHerkese verilir (güven kökü)
server.keySunucu gizli anahtarıSunucuda, hiç çıkmaz
server.csrSunucu CSR'ıİşi bitti, silinebilir
server.crtSunucu sertifikasıSunucuya konulur, herkese gösterilir
client.keyİstemci gizli anahtarıİstemcide, hiç çıkmaz
client.csrİstemci CSR'ıİşi bitti, silinebilir
client.crtİstemci sertifikasıİstemciye konulur, sunucuya gösterilir

Hatırlatma: .key uzantılı hiçbir dosya ağa gitmez, başka makineye kopyalanmaz, e-postayla gönderilmez. .crt uzantılı dosyalar ise zaten herkese gösterilmek için var.

05mTLS sunucusunu başlat

Birinci terminalde bu komutu çalıştır ve açık bırak. Sunucu 4433 portunu dinleyecek.

terminal 1 — sunucu
openssl s_server \
  -accept 4433 \
  -cert server.crt \
  -key server.key \
  -CAfile ca.crt \
  -Verify 1 \
  -www
-accept 44334433 portunu dinle
-cert server.crtsunucunun kendi sertifikası (istemciye gönderilecek)
-key server.keysunucunun gizli anahtarı (handshake için)
-CAfile ca.crtistemci sertifikasını bu CA ile doğrula
-Verify 1istemci sertifika göstermek ZORUNDA (mTLS anahtar parametresi)
-wwwbağlanan istemciye basit bir HTTP yanıtı döndür
Büyük V vs Küçük v

-Verify (büyük V) zorunlu demektir — sertifika yoksa bağlantı reddedilir. -verify (küçük v) opsiyonel demektir — istemci sertifika gösterirse doğrularım, göstermezse de bağlanırım. mTLS için büyük V lazım.

06Test senaryoları

İkinci terminalde bu testleri sırayla dene. Her testten sonra bağlantıyı kapatmak için Ctrl+C.

Test 1 — Doğru sertifikayla (BAŞARILI olmalı)

terminal 2 — istemci
echo "GET / HTTP/1.0" | openssl s_client \
  -connect localhost:4433 \
  -cert client.crt \
  -key client.key \
  -CAfile ca.crt \
  -quiet
Beklenen

✓ Bağlantı kurulur, sunucudan HTML yanıtı gelir. Karşılıklı doğrulama başarılı.

Test 2 — Sertifikasız (BAŞARISIZ olmalı)

terminal 2 — istemci
openssl s_client \
  -connect localhost:4433 \
  -CAfile ca.crt
Beklenen

tlsv13 alert certificate required veya peer did not return a certificate hatası. Sunucu "sen sertifika göstermek zorundasın" diyor.

Test 3 — Başka bir CA'dan sertifikayla (BAŞARISIZ olmalı)

Önce sahte bir CA ve onunla imzalı bir istemci sertifikası üret:

bash — sahte ca oluştur
# Sahte CA
openssl genrsa -out fake-ca.key 2048
openssl req -new -x509 -key fake-ca.key -out fake-ca.crt -days 365 \
  -subj "/CN=Sahte CA"

# Sahte CA ile imzalı istemci
openssl genrsa -out fake-client.key 2048
openssl req -new -key fake-client.key -out fake-client.csr \
  -subj "/CN=sahte-musteri"
openssl x509 -req -in fake-client.csr \
  -CA fake-ca.crt -CAkey fake-ca.key -CAcreateserial \
  -out fake-client.crt -days 365 \
  -extfile client_ext.cnf

Şimdi bu sahte sertifikayla bağlanmayı dene:

terminal 2 — istemci
openssl s_client \
  -connect localhost:4433 \
  -cert fake-client.crt \
  -key fake-client.key \
  -CAfile ca.crt
Beklenen

tlsv1 alert unknown ca hatası. Sunucu "bu sertifikayı imzalayan CA benim güven listemde yok" diyor. Çünkü sunucu -CAfile ca.crt ile başladı, sadece o CA'ya güveniyor. fake-ca.crt orada yok.

07Handshake'te ne oluyor

Test 1 çalıştığında ağ üzerinde ne gidip geldi? mTLS'e özgü adımlar sarı ile işaretli.

 1. İstemci ClientHello gönderir
    → client_random, cipher suite listesi, TLS versiyonu

 2. Sunucu ServerHello gönderir
    → server_random, seçilen cipher suite

 3. Sunucu kendi sertifikasını gönderir (server.crt)
    → içinde sunucunun açık anahtarı

 4. Sunucu CertificateRequest gönderir              ← mTLS EK ADIMI
    → "senin de sertifikanı istiyorum"
    → hangi CA'lardan imzalı olması gerektiğini söyler

 5. Sunucu ServerHelloDone gönderir

 6. İstemci sunucu sertifikasını doğrular:
    → server.crt'yi ca.crt ile doğrular
    → imza tutuyor mu? ✓
    → süre geçerli mi? ✓
    → hostname SAN'da var mı? ✓

 7. İstemci kendi sertifikasını gönderir (client.crt)   ← mTLS EK ADIMI

 8. İstemci ClientKeyExchange gönderir
    → pre-master secret'i sunucunun açık anahtarıyla
      şifreleyip yollar

 9. İstemci CertificateVerify gönderir                  ← mTLS EK ADIMI
    → şimdiye kadarki handshake mesajlarının hash'ini
      kendi gizli anahtarıyla imzalar
    → "sertifikadaki açık anahtarın eşi olan gizli
       anahtar gerçekten bende" kanıtı

10. Sunucu istemci sertifikasını doğrular:
    → client.crt'yi ca.crt ile doğrular
    → imza tutuyor mu? ✓
    → CertificateVerify imzası tutuyor mu? ✓
    → extendedKeyUsage = clientAuth var mı? ✓

11. Her iki taraf session key türetir
12. Finished mesajları
13. Şifreli uygulama verisi akmaya başlar
Neden CertificateVerify kritik

Bu adım olmasa, biri başkasının sertifikasını (public bilgi olduğu için) çalıp "bak ben oyum" diyebilirdi. CertificateVerify, istemcinin gerçekten o sertifikanın eşi olan gizli anahtara sahip olduğunu matematiksel olarak kanıtlar — çünkü o imzayı sadece gizli anahtarın sahibi üretebilir.

08Kim kimi doğruluyor

mTLS'te -CAfile hem sunucu hem istemci tarafında var ama anlamları farklı.

TarafNeyi DoğruluyorHangi Dosyayla
İstemciSunucunun sertifikasınıca.crt (istemci tarafında)
Sunucuİstemcinin sertifikasınıca.crt (sunucu tarafında)

Bizim örneğimizde aynı CA her ikisini imzaladı, o yüzden aynı ca.crt kullanılıyor. Gerçekte iki farklı CA olabilir — mesela şirket içi CA istemcileri imzalar, Let's Encrypt sunucuyu imzalar. O zaman sunucu -CAfile sirket-ca.crt, istemci -CAfile letsencrypt-ca.crt kullanır.

Tek cümlede mTLS

Normal TLS'te sadece sunucu kendini kanıtlar, istemci anonim kalır. mTLS'te iki taraf da sertifika gösterir ve gizli anahtarlarına sahip olduklarını kanıtlar — yani iki taraf da birbirinin gerçekten iddia ettiği kişi/servis olduğundan matematiksel olarak emin olur.