İç ağda bir servis ayağa kaldırıyorsun, HTTPS lazım ama Let’s Encrypt kullanamıyorsun çünkü domain public değil. Ya da test ortamında bir şeyler denemek istiyorsun ve sertifika satın almak saçma gelecek. İşte tam bu noktalarda self-signed sertifikalar hayat kurtarıcı oluyor. Tabii “tarayıcı uyarısı veriyor, güvensiz” diye düşünebilirsin ama doğru kullanım senaryosunda self-signed sertifika hem pratik hem de yeterince güvenli bir çözüm.
Bu yazıda OpenSSL ile self-signed sertifika oluşturmayı, farklı kullanım senaryolarını ve production dışı ortamlarda bu sertifikaları nasıl yöneteceğini ele alacağız.
Self-Signed Sertifika Nedir ve Ne Zaman Kullanılır
Normal bir SSL sertifikası bir Certificate Authority (CA) tarafından imzalanır. Tarayıcılar ve işletim sistemleri bu CA’lara güvenir, dolayısıyla sertifikaya da güvenir. Self-signed sertifikada ise sertifikayı sen imzılıyorsun, yani hem sertifikayı oluşturan hem de imzılayan sensin. Hiçbir harici otorite devreye girmiyor.
Self-signed sertifika kullanmanın mantıklı olduğu durumlar:
- İç ağ servisleri: Sadece şirket içinden erişilen admin panelleri, monitoring araçları, internal API’ler
- Development ve test ortamları: Localhost ya da staging sunucularında HTTPS testi
- Kendi CA’ını oluşturma: Self-signed root CA oluşturup bunu tüm sistemlere dağıtmak (bu en sağlıklı yaklaşım)
- Kubernetes ve konteyner ortamları: Cluster içi servisler arası şifreli iletişim
- CI/CD pipeline’ları: Otomatik test süreçlerinde sertifika doğrulamasının sorun çıkardığı durumlar
Self-signed sertifika kullanmamanın gerektiği yerler de var: Public facing web siteleri, müşteri erişimli portaller veya mobil uygulamalarla iletişim kuran API’ler bunların başında geliyor.
OpenSSL ile Temel Self-Signed Sertifika Oluşturma
En basit yöntemle başlayalım. Tek komutla hem private key hem de sertifika oluşturabilirsin:
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt
-days 365 -nodes
-subj "/C=TR/ST=Istanbul/L=Istanbul/O=TestCorp/OU=IT/CN=myserver.local"
Bu komuttaki parametreler:
- -x509: X.509 formatında sertifika üret
- -newkey rsa:4096: 4096 bit RSA key pair oluştur
- -keyout server.key: Private key dosyasının adı
- -out server.crt: Sertifika dosyasının adı
- -days 365: Sertifikanın geçerlilik süresi
- -nodes: Private key’i şifrelemeden kaydet (no DES)
- -subj: Sertifika bilgileri (ülke, şehir, organizasyon, Common Name)
Oluşan dosyaları kontrol edelim:
# Sertifika detaylarını görüntüle
openssl x509 -in server.crt -text -noout
# Sertifikanın geçerlilik tarihlerini kontrol et
openssl x509 -in server.crt -dates -noout
# Private key'i doğrula
openssl rsa -in server.key -check
İki Aşamalı Yöntem: CSR ile Sertifika Oluşturma
Daha kontrollü bir yaklaşım için önce CSR (Certificate Signing Request) oluşturup sonra imzılamak daha iyi pratik:
# Önce private key oluştur
openssl genrsa -out server.key 4096
# CSR oluştur
openssl req -new -key server.key -out server.csr
-subj "/C=TR/ST=Istanbul/L=Istanbul/O=TestCorp/CN=myserver.local"
# CSR'ı self-signed olarak imzıla
openssl x509 -req -in server.csr -signkey server.key
-out server.crt -days 365
Bu yöntem özellikle aynı key ile farklı sertifikalar üretmen gerektiğinde ya da CSR’ı bir CA’ya göndermeden önce test etmek istediğinde işe yarıyor.
SAN (Subject Alternative Names) ile Modern Sertifika
Eski yöntemde sadece CN (Common Name) kullanılıyordu. Ama modern tarayıcılar ve araçlar artık SAN alanını zorunlu tutuyor. CN’ye bakılmıyor bile. Eğer SAN olmadan sertifika oluşturursan Chrome ve Firefox bunu reddedecek. Doğru yol şu:
# OpenSSL konfigürasyon dosyası oluştur
cat > san.cnf << 'EOF'
[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn
x509_extensions = v3_req
[dn]
C = TR
ST = Istanbul
L = Istanbul
O = TestCorp
OU = IT
CN = myserver.local
[v3_req]
subjectAltName = @alt_names
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[alt_names]
DNS.1 = myserver.local
DNS.2 = myserver
DNS.3 = localhost
IP.1 = 192.168.1.100
IP.2 = 127.0.0.1
EOF
# SAN'lı sertifikayı oluştur
openssl req -x509 -newkey rsa:4096
-keyout server.key
-out server.crt
-days 365
-nodes
-config san.cnf
Bu konfigürasyonla hem DNS adları hem de IP adresleri için geçerli bir sertifika oluşturmuş oluyorsun. Özellikle IP adresiyle erişilen iç ağ servislerinde IP.x satırları kritik.
Kendi CA’ını Oluşturma (En İyi Yaklaşım)
Self-signed sertifikanın asıl güçlü kullanımı burada. Her sertifika için tek tek sisteme “güven” eklemek yerine, kendi internal CA’ını oluşturup bunu bir kez sistemlere tanıtıyorsun. Sonrasında bu CA ile imzıladığın tüm sertifikalara otomatik güveniliyor.
# Root CA key ve sertifikasını oluştur
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes
-key ca.key
-sha256
-days 3650
-out ca.crt
-subj "/C=TR/ST=Istanbul/O=TestCorp Internal CA/CN=TestCorp Root CA"
Şimdi bu CA ile sunucu sertifikası imzılayalım:
# Sunucu için key ve CSR oluştur
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr
-subj "/C=TR/ST=Istanbul/O=TestCorp/CN=myserver.local"
# SAN extension dosyası
cat > server_ext.cnf << 'EOF'
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = myserver.local
DNS.2 = *.myserver.local
IP.1 = 192.168.1.100
EOF
# CA ile imzıla
openssl x509 -req
-in server.csr
-CA ca.crt
-CAkey ca.key
-CAcreateserial
-out server.crt
-days 365
-sha256
-extfile server_ext.cnf
Bu yaklaşımla wildcard sertifika da oluşturabiliyorsun (*.myserver.local), yani app.myserver.local, db.myserver.local gibi tüm subdomainler tek sertifikayla çalışıyor.
CA Sertifikasını Sistemlere Tanıtma
CA sertifikasını oluşturduktan sonra bunu sistemlere güvenilir CA olarak ekliyorsun. Artık bu CA tarafından imzılanan tüm sertifikalara güvenilecek.
Ubuntu/Debian:
# CA sertifikasını kopyala
sudo cp ca.crt /usr/local/share/ca-certificates/testcorp-ca.crt
# CA store'unu güncelle
sudo update-ca-certificates
# Doğrulama
ls /etc/ssl/certs/ | grep testcorp
RHEL/CentOS/Rocky:
sudo cp ca.crt /etc/pki/ca-trust/source/anchors/testcorp-ca.crt
sudo update-ca-trust extract
Windows (PowerShell):
# PowerShell ile
Import-Certificate -FilePath "ca.crt" -CertStoreLocation Cert:LocalMachineRoot
# Ya da certutil ile
certutil -addstore "Root" ca.crt
Tarayıcılar için ayrıca ayar gerekebiliyor. Firefox kendi sertifika store’unu kullandığı için sistem store’undan bağımsız. about:preferences#privacy üzerinden Authorities bölümünde CA sertifikasını import edebilirsin.
Nginx ile Self-Signed Sertifika Kullanımı
Sertifikaları oluşturduktan sonra Nginx konfigürasyonuna eklemek oldukça basit:
# Sertifika dosyalarını uygun yere kopyala
sudo mkdir -p /etc/nginx/ssl
sudo cp server.crt /etc/nginx/ssl/
sudo cp server.key /etc/nginx/ssl/
sudo chmod 600 /etc/nginx/ssl/server.key
# Nginx konfigürasyonu
cat > /etc/nginx/sites-available/myapp << 'EOF'
server {
listen 443 ssl;
server_name myserver.local;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name myserver.local;
return 301 https://$host$request_uri;
}
EOF
sudo nginx -t && sudo systemctl reload nginx
Sertifika Doğrulama ve Sorun Giderme
Sertifikanı deploy ettikten sonra düzgün çalışıp çalışmadığını test etmek için:
# Uzak sunucunun sertifikasını kontrol et
openssl s_client -connect myserver.local:443 -showcerts
# Sertifika zincirini doğrula
openssl verify -CAfile ca.crt server.crt
# Sertifikanın son kullanma tarihini script ile kontrol et
CERT_FILE="server.crt"
EXPIRY_DATE=$(openssl x509 -in $CERT_FILE -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
if [ $DAYS_LEFT -lt 30 ]; then
echo "UYARI: Sertifikanin son kullanma tarihine $DAYS_LEFT gun kaldi!"
else
echo "Sertifika gecerli, $DAYS_LEFT gun kaldi."
fi
Gerçek Dünya Senaryosu: Kubernetes Internal Servisler
Kubernetes cluster içinde pod’lar arası iletişimi şifrelemek istediğinde, her servis için sertifika üretip secret olarak saklayabilirsin:
# Her mikroservis için sertifika oluştur
for SERVICE in api-service auth-service db-proxy; do
# Key oluştur
openssl genrsa -out ${SERVICE}.key 2048
# CSR oluştur
openssl req -new -key ${SERVICE}.key -out ${SERVICE}.csr
-subj "/CN=${SERVICE}/O=cluster.local"
# CA ile imzıla
openssl x509 -req
-in ${SERVICE}.csr
-CA ca.crt
-CAkey ca.key
-CAcreateserial
-out ${SERVICE}.crt
-days 365
-sha256
# Kubernetes secret oluştur
kubectl create secret tls ${SERVICE}-tls
--cert=${SERVICE}.crt
--key=${SERVICE}.key
-n production
echo "${SERVICE} icin sertifika ve secret olusturuldu"
done
Bu yaklaşım özellikle service mesh kullanmadığın ama yine de mTLS (mutual TLS) istediğin durumlarda işe yarıyor.
Gerçek Dünya Senaryosu: Development Ortamı Otomasyonu
Ekibin her geliştirici kendi local ortamında HTTPS ile test etmek istediğinde, bir script ile süreci otomatikleştirebilirsin:
#!/bin/bash
# setup-dev-certs.sh - Geliştirici local ortamı için sertifika kurulumu
DOMAIN="dev.local"
DAYS=730
CERT_DIR="$HOME/.dev-certs"
mkdir -p $CERT_DIR
echo "==> Root CA olusturuluyor..."
openssl genrsa -out $CERT_DIR/ca.key 4096 2>/dev/null
openssl req -x509 -new -nodes
-key $CERT_DIR/ca.key
-sha256 -days 3650
-out $CERT_DIR/ca.crt
-subj "/CN=Dev Root CA/O=Development" 2>/dev/null
echo "==> Gelistirici sertifikasi olusturuluyor..."
openssl genrsa -out $CERT_DIR/dev.key 4096 2>/dev/null
cat > $CERT_DIR/dev.cnf << EOF
[req]
prompt = no
distinguished_name = dn
x509_extensions = v3_req
[dn]
CN = $DOMAIN
[v3_req]
subjectAltName = @alt_names
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[alt_names]
DNS.1 = $DOMAIN
DNS.2 = *.$DOMAIN
DNS.3 = localhost
IP.1 = 127.0.0.1
EOF
openssl req -new -key $CERT_DIR/dev.key
-out $CERT_DIR/dev.csr
-config $CERT_DIR/dev.cnf 2>/dev/null
openssl x509 -req
-in $CERT_DIR/dev.csr
-CA $CERT_DIR/ca.crt
-CAkey $CERT_DIR/ca.key
-CAcreateserial
-out $CERT_DIR/dev.crt
-days $DAYS
-sha256
-extfile $CERT_DIR/dev.cnf
-extensions v3_req 2>/dev/null
echo "==> CA sisteme ekleniyor..."
if command -v update-ca-certificates &> /dev/null; then
sudo cp $CERT_DIR/ca.crt /usr/local/share/ca-certificates/dev-root-ca.crt
sudo update-ca-certificates
elif command -v update-ca-trust &> /dev/null; then
sudo cp $CERT_DIR/ca.crt /etc/pki/ca-trust/source/anchors/dev-root-ca.crt
sudo update-ca-trust extract
fi
echo ""
echo "Sertifikalar hazir: $CERT_DIR"
echo "CRT: $CERT_DIR/dev.crt"
echo "KEY: $CERT_DIR/dev.key"
echo ""
echo "Nginx icin:"
echo " ssl_certificate $CERT_DIR/dev.crt;"
echo " ssl_certificate_key $CERT_DIR/dev.key;"
Sertifika Yenileme ve Otomatik Takip
Self-signed sertifikaların en büyük handikabı unutulmaları. Bir sertifikayı oluşturup kuruyorsun, 365 gün sonra servis çöküyor, stres yaşıyorsun. Bunun için basit bir cron job ile takip sistemi kurabilirsin:
#!/bin/bash
# cert-check.sh - /etc/cron.weekly/ altına koy
CERTS_TO_CHECK=(
"/etc/nginx/ssl/server.crt"
"/etc/ssl/internal/api.crt"
"/home/app/.dev-certs/dev.crt"
)
WARN_DAYS=30
ALERT_EMAIL="[email protected]"
for CERT in "${CERTS_TO_CHECK[@]}"; do
if [ ! -f "$CERT" ]; then
echo "HATA: $CERT bulunamadi" | mail -s "Sertifika Eksik" $ALERT_EMAIL
continue
fi
EXPIRY=$(openssl x509 -in "$CERT" -noout -enddate 2>/dev/null | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s 2>/dev/null)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
if [ "$DAYS_LEFT" -lt "$WARN_DAYS" ]; then
MESSAGE="Sertifika: $CERTnKalan gun: $DAYS_LEFTnSon kullanma: $EXPIRY"
echo -e "$MESSAGE" | mail -s "UYARI: Sertifika yenilenmeli" $ALERT_EMAIL
echo "UYARI: $CERT - $DAYS_LEFT gun kaldi"
else
echo "OK: $CERT - $DAYS_LEFT gun kaldi"
fi
done
Güvenlik Notları ve En İyi Pratikler
Self-signed sertifika kullanırken dikkat etmen gereken bazı önemli noktalar var:
- Private key izinleri: Key dosyası asla 644 olmamalı.
chmod 600 server.keyve sahibi root ya da ilgili servis kullanıcısı olmalı. - CA key’ini koru: Eğer internal CA oluşturuyorsan, CA’nın private key’i çok kritik. Bunu offline bir ortamda saklamayı düşün, sadece yeni sertifika imzılarken kullan.
- Kısa süreli sertifikalar: 365 gün yerine 90 gün kullanmak, rotasyon alışkanlığı kazandırır ve potansiyel risk penceresini daraltır.
- Algoritma seçimi: RSA 2048 hala kabul edilebilir ama RSA 4096 ya da ECDSA P-256 tercih et. ECDSA hem daha hızlı hem de daha küçük key boyutuyla güvenli.
- SHA-256 veya üstü: MD5 veya SHA-1 ile imzılama artık güvenli kabul edilmiyor, her zaman
-sha256kullan. - Wildcard sertifika dikkatli kullan:
*.sirket.localgibi wildcard sertifikalar pratikte kullanışlı ama bir key compromise durumunda tüm subdomainler etkileniyor.
Sonuç
Self-signed sertifikalar, doğru kullanıldığında iç ağ güvenliğinin önemli bir parçası haline gelebiliyor. Önemli olan nerede kullandığını bilmek: public facing servislerde değil, internal servislerde, dev ortamlarında ve cluster içi iletişimde anlamlı bir çözüm.
Kendi internal CA’ını oluşturup bunu sistemlere bir kez tanıtmak, uzun vadede en temiz yaklaşım. Böylece her yeni servis için sertifika eklediğinde ekstra güven tanımlama işi yapmak zorunda kalmıyorsun. Otomatik sertifika takibi ve yenileme scriptleri de eklenince, self-signed sertifika yönetimi gerçekten eforla orantılı bir iş haline geliyor.
Son olarak şunu da söyleyeyim: eğer public DNS’te bir domain’in varsa ve Let’s Encrypt kullanabilecek durumdaysan, self-signed yerine her zaman onu tercih et. Ama bunu yapamadığın durumlarda bu yazıdaki yöntemler seni fazlasıyla idare ettirir.