Cloudflare ile Subdomain Yönetimi ve Wildcard DNS Kullanımı

Onlarca subdomain yönetmek zorunda kaldığınızda, DNS yapılandırmalarının ne kadar hızlı karmaşıklaşabileceğini anlarsınız. Her yeni servis için ayrı bir A kaydı oluşturmak, IP değişikliklerinde onlarca kaydı güncellemek, wildcard sertifika sorunlarıyla boğuşmak… Cloudflare’in DNS yönetim araçlarını iyi kullanmayı öğrendiğinizde bu işlemler hem daha hızlı hem de daha güvenli hale geliyor.

Bu yazıda Cloudflare üzerinde subdomain yönetimini, wildcard DNS kayıtlarını ve bunları gerçek dünya senaryolarında nasıl kullanacağınızı ele alacağız. Hem küçük projeler için hem de kurumsal düzeyde DNS yönetimi yapanlar için faydalı olacak pratik bilgiler paylaşacağım.

Cloudflare DNS’in Temel Yapısı

Cloudflare, DNS yönetimini birkaç farklı katmanda sunar. Standart DNS kayıtlarının yanı sıra proxy modu, page rules ve Workers gibi özellikler DNS yönetimiyle iç içe geçmiş durumda. Bu yüzden sadece kayıt ekleyip çıkarmaktan ibaret değil işin aslı.

Cloudflare API’si üzerinden DNS yönetimi yapmak, özellikle otomasyon ihtiyacınız olduğunda hayat kurtarıcı oluyor. API token oluştururken en az ayrıcalık prensibini uygulamanızı şiddetle tavsiye ederim. Zone bazlı, sadece DNS edit yetkisi olan token yeterli çoğu senaryo için.

# Cloudflare API token ile zone listesini çekme
curl -X GET "https://api.cloudflare.com/client/v4/zones" 
  -H "Authorization: Bearer YOUR_API_TOKEN" 
  -H "Content-Type: application/json" | jq '.result[] | {id: .id, name: .name}'

Zone ID’nizi öğrendikten sonra DNS kayıtlarını listeleyebilirsiniz:

# Belirli bir zone'daki tüm DNS kayıtlarını listele
ZONE_ID="your_zone_id_here"
API_TOKEN="your_api_token_here"

curl -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" 
  -H "Authorization: Bearer ${API_TOKEN}" 
  -H "Content-Type: application/json" | jq '.result[] | {name: .name, type: .type, content: .content, proxied: .proxied}'

Subdomain Kayıtları Oluşturma ve Yönetme

Tekil Subdomain Ekleme

En basit senaryo: yeni bir uygulama kurdunuz, ona bir subdomain lazım. Cloudflare arayüzünden yapabilirsiniz elbette ama API üzerinden yapmak log tutmak ve tekrarlanabilirlik açısından çok daha mantıklı.

# Yeni bir A kaydı oluşturma (proxy modunda)
ZONE_ID="your_zone_id_here"
API_TOKEN="your_api_token_here"

curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" 
  -H "Authorization: Bearer ${API_TOKEN}" 
  -H "Content-Type: application/json" 
  --data '{
    "type": "A",
    "name": "app.sirketiniz.com",
    "content": "192.168.1.100",
    "ttl": 1,
    "proxied": true
  }'

Burada "ttl": 1 Cloudflare’de “Auto” anlamına gelir. Proxy modu açıkken zaten Cloudflare’in TTL’si geçerli olduğu için bu değerin pek önemi yok aslında. Ama proxy kapalıysa anlamlı bir TTL değeri vermenizi öneririm, örneğin 300 (5 dakika) veya 3600 (1 saat).

Toplu Subdomain Yönetimi

Gerçek dünyada onlarca subdomain var ve bunları tek tek yönetmek mantıklı değil. Bir bash scripti ile işleri otomatikleştirebilirsiniz:

#!/bin/bash
# bulk_dns_add.sh - Toplu subdomain ekleme scripti

ZONE_ID="your_zone_id_here"
API_TOKEN="your_api_token_here"
TARGET_IP="10.20.30.40"
DOMAIN="sirketiniz.com"

# Eklenecek subdomainler listesi
SUBDOMAINS=("api" "admin" "dashboard" "docs" "status" "monitor" "mail")

add_dns_record() {
  local subdomain=$1
  local ip=$2
  local proxied=${3:-true}
  
  RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" 
    -H "Authorization: Bearer ${API_TOKEN}" 
    -H "Content-Type: application/json" 
    --data "{
      "type": "A",
      "name": "${subdomain}.${DOMAIN}",
      "content": "${ip}",
      "ttl": 1,
      "proxied": ${proxied}
    }")
  
  SUCCESS=$(echo $RESPONSE | jq -r '.success')
  
  if [ "$SUCCESS" = "true" ]; then
    echo "[OK] ${subdomain}.${DOMAIN} -> ${ip} eklendi"
  else
    ERROR=$(echo $RESPONSE | jq -r '.errors[0].message')
    echo "[HATA] ${subdomain}.${DOMAIN}: ${ERROR}"
  fi
}

for subdomain in "${SUBDOMAINS[@]}"; do
  add_dns_record "$subdomain" "$TARGET_IP"
  sleep 0.5  # Rate limiting için kısa bekleme
done

echo "Tüm kayıtlar işlendi."

Bu scripti cron’a ekleyip infrastructure provisioning sürecinizin bir parçası haline getirebilirsiniz. Terraform veya Ansible kullanıyorsanız Cloudflare provider’ı da var ama bazen bu kadar basit bir bash scripti yeterli oluyor.

Wildcard DNS Kayıtları

Wildcard DNS, *.sirketiniz.com şeklinde tanımlanan ve o domain altındaki tanımsız tüm subdomainlere yanıt veren kayıt tipidir. Özellikle multi-tenant SaaS uygulamalarında, development ortamlarında ve Kubernetes ingress yapılandırmalarında çok işe yarıyor.

Wildcard Kaydı Oluşturma

# Wildcard A kaydı oluşturma
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" 
  -H "Authorization: Bearer ${API_TOKEN}" 
  -H "Content-Type: application/json" 
  --data '{
    "type": "A",
    "name": "*.sirketiniz.com",
    "content": "192.168.1.200",
    "ttl": 300,
    "proxied": false
  }'

Dikkat etmeniz gereken önemli bir nokta: Cloudflare’de wildcard kayıtlar proxy modunda kullanılamaz (en azından Free ve Pro planlarda). Enterprise planlarda wildcard proxy desteği var ama bu büyük çoğunluk için geçerli bir çözüm değil. Bu yüzden yukarıdaki örnekte "proxied": false kullandım.

Wildcard ve Spesifik Kayıtların Önceliği

DNS’te wildcard kayıtlar, spesifik kayıtların varlığında devreye girmez. Yani app.sirketiniz.com için ayrıca A kaydı tanımladıysanız, wildcard bu kaydı ezmez. Bu aslında beklenen davranış ve genellikle istediğiniz şey de bu.

Şöyle düşünün: Wildcard ile *.sirketiniz.com‘u bir load balancer’a yönlendirdiniz. Ama mail.sirketiniz.com için ayrı bir MX ve A kaydınız var. mail için spesifik kayıt devreye girer, diğer her şey wildcard’a düşer. Temiz ve yönetilebilir bir yapı.

Gerçek Dünya Senaryosu: Multi-Tenant SaaS

Diyelim ki her müşteriniz kendi subdomain’i üzerinden uygulamanıza erişiyor: musteri1.sirketiniz.com, musteri2.sirketiniz.com gibi. Her yeni müşteri için DNS kaydı oluşturmak yerine wildcard kullanabilirsiniz.

# Wildcard ile CNAME kaydı (kendi load balancer'ınıza yönlendirme)
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" 
  -H "Authorization: Bearer ${API_TOKEN}" 
  -H "Content-Type: application/json" 
  --data '{
    "type": "CNAME",
    "name": "*.app.sirketiniz.com",
    "content": "lb.sirketiniz.com",
    "ttl": 300,
    "proxied": false
  }'

Bu yapıda lb.sirketiniz.com için ayrıca bir A kaydı tanımlamanız gerekiyor elbette. Nginx veya HAProxy tarafında da server_name *.app.sirketiniz.com ile wildcard virtual host tanımlarsınız.

# Nginx wildcard virtual host örneği
server {
    listen 443 ssl;
    server_name ~^(?P<tenant>[^.]+).app.sirketiniz.com$;
    
    ssl_certificate /etc/ssl/certs/wildcard.sirketiniz.com.crt;
    ssl_certificate_key /etc/ssl/private/wildcard.sirketiniz.com.key;
    
    location / {
        proxy_pass http://backend_app;
        proxy_set_header X-Tenant-ID $tenant;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Nginx’in yakaladığı $tenant değişkenini backend’e header olarak iletiyorsunuz. Backend uygulamanız bu header’a bakarak hangi müşterinin verilerine erişeceğini anlıyor. Basit ve etkili.

Let’s Encrypt ile Wildcard SSL Sertifikaları

Wildcard DNS kullandığınızda SSL sertifikası meselesi biraz farklı ele alınması gerekiyor. Let’s Encrypt wildcard sertifikalar için DNS-01 challenge kullanıyor. Cloudflare API’si ile bu süreci otomatikleştirebilirsiniz.

Certbot ile Cloudflare DNS plugin kullanarak wildcard sertifika almak için:

# Cloudflare API credentials dosyası oluşturma
cat > ~/.secrets/certbot/cloudflare.ini << 'EOF'
# Cloudflare API token (DNS edit yetkili)
dns_cloudflare_api_token = your_api_token_here
EOF

chmod 600 ~/.secrets/certbot/cloudflare.ini

# Wildcard sertifika alma
certbot certonly 
  --dns-cloudflare 
  --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini 
  -d "sirketiniz.com" 
  -d "*.sirketiniz.com" 
  --preferred-challenges dns-01 
  --server https://acme-v02.api.letsencrypt.org/directory

Sertifika yenileme de aynı şekilde otomatik çalışıyor. Cron veya systemd timer ile certbot renew komutu çalıştırıldığında Cloudflare API’si üzerinden DNS kaydı otomatik oluşturuluyor, doğrulama yapılıyor ve silinyor.

Cloudflare Workers ile Dinamik Subdomain Yönlendirmesi

Daha ileri bir senaryo: Wildcard DNS ile gelen istekleri farklı backend’lere yönlendirmek için Cloudflare Workers kullanabilirsiniz. Bu özellikle edge’de basit routing mantığı koymak istediğinizde işe yarıyor.

// Cloudflare Worker - Dinamik subdomain routing
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  const url = new URL(request.url)
  const hostname = url.hostname
  
  // Subdomain'i çıkar
  const parts = hostname.split('.')
  const subdomain = parts[0]
  
  // Backend mapping (gerçekte KV store veya external API'den alınabilir)
  const backendMap = {
    'api': 'https://api-backend.internal.sirketiniz.com',
    'admin': 'https://admin-backend.internal.sirketiniz.com',
    'legacy': 'https://old-system.internal.sirketiniz.com'
  }
  
  const targetBackend = backendMap[subdomain]
  
  if (!targetBackend) {
    return new Response('Subdomain bulunamadı', { status: 404 })
  }
  
  const newUrl = targetBackend + url.pathname + url.search
  
  return fetch(newUrl, {
    method: request.method,
    headers: request.headers,
    body: request.body
  })
}

Bu Worker’ı wildcard route ile eşleştirirseniz (.sirketiniz.com/) tüm subdomain trafiğini tek bir Worker üzerinden yönetebilirsiniz. Proxy mode açık olduğu için Cloudflare’in CDN ve güvenlik özellikleri de devreye giriyor.

DNS Değişikliklerini İzleme ve Audit Log

Production ortamında DNS değişikliklerini takip etmek kritik. Cloudflare Audit Log özelliği bu konuda yardımcı oluyor ama bunu düzenli olarak çekip kendi log sistemlerinize aktarmanız gerekiyor.

#!/bin/bash
# dns_audit_check.sh - Son DNS değişikliklerini kontrol et

ACCOUNT_ID="your_account_id_here"
API_TOKEN="your_api_token_here"
HOURS_AGO=24

# Son 24 saatteki DNS değişikliklerini çek
SINCE=$(date -u -d "${HOURS_AGO} hours ago" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || 
        date -u -v-${HOURS_AGO}H +"%Y-%m-%dT%H:%M:%SZ")

curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/audit_logs?action.type=rec.add&action.type=rec.set&action.type=rec.delete&since=${SINCE}" 
  -H "Authorization: Bearer ${API_TOKEN}" 
  -H "Content-Type: application/json" | 
  jq -r '.result[] | "(.when) | (.actor.email) | (.action.type) | (.metadata.zone_name)"' | 
  sort

Bu scripti günlük olarak çalıştırıp çıktısını email veya Slack’e gönderebilirsiniz. Beklenmedik bir DNS değişikliği olduğunda hemen haberdar olursunuz.

Sık Yapılan Hatalar ve Dikkat Edilmesi Gerekenler

Proxy modu ile wildcard karışıklığı: Daha önce bahsettiğim gibi wildcard kayıtlar Free/Pro planlarda proxy edilemiyor. Ama wildcard A kaydı proxy olmadan, spesifik subdomainler proxy ile çalışabilir. Bu karma yapı genellikle makul bir çözüm.

TTL değerleri: Büyük bir değişiklik yapmadan önce (örneğin IP migrasyonu) TTL’yi düşürün. En az 2 * eski_TTL kadar bekleyin, değişikliği yapın, sonra TTL’yi tekrar yükseltin. Bu basit adım DNS kaynaklı kesintilerin büyük çoğunluğunu önler.

CNAME flattening: Cloudflare apex domain için CNAME kullanamazsınız (RFC gereği) ama Cloudflare kendi “CNAME flattening” özelliği ile bunu mümkün kılıyor. sirketiniz.com için CNAME benzeri bir davranış istiyorsanız Cloudflare arayüzünde bunu yapabilirsiniz, API’de ise normal CNAME formatında girip Cloudflare otomatik hallediyor.

Rate limiting: Cloudflare API’de dakikada 1200 istek limiti var. Toplu işlemlerde sleep ekleyin, yoksa 429 hataları alırsınız. Yukarıdaki bulk script’te sleep 0.5 tam bu yüzden var.

Silme işlemlerinde dikkat: DNS kaydı silmek API üzerinden çok kolay, geri almak o kadar kolay değil. Özellikle production ortamında silme işlemlerini manuel onay gerektiren bir sürece bağlamanızı öneririm. Terraform state kullanıyorsanız bu konuda doğal bir koruma mekanizması var.

Cloudflare API ile DNS Yedekleme

Tüm DNS kayıtlarınızı düzenli olarak yedeklemek iyi bir alışkanlık. Yanlışlıkla bir kaydı silerseniz veya hesabınıza yetkisiz erişim olursa hızlıca geri dönebilirsiniz.

#!/bin/bash
# dns_backup.sh - Tüm zone'ların DNS kayıtlarını yedekle

ACCOUNT_ID="your_account_id_here"
API_TOKEN="your_api_token_here"
BACKUP_DIR="/var/backups/cloudflare-dns"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p "${BACKUP_DIR}"

# Tüm zone'ları listele
ZONES=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?per_page=50" 
  -H "Authorization: Bearer ${API_TOKEN}" 
  -H "Content-Type: application/json" | jq -r '.result[] | "(.id):(.name)"')

for ZONE_INFO in $ZONES; do
  ZONE_ID=$(echo $ZONE_INFO | cut -d: -f1)
  ZONE_NAME=$(echo $ZONE_INFO | cut -d: -f2)
  
  BACKUP_FILE="${BACKUP_DIR}/${ZONE_NAME}_${DATE}.json"
  
  curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?per_page=500" 
    -H "Authorization: Bearer ${API_TOKEN}" 
    -H "Content-Type: application/json" > "${BACKUP_FILE}"
  
  RECORD_COUNT=$(jq '.result | length' "${BACKUP_FILE}")
  echo "[${DATE}] ${ZONE_NAME}: ${RECORD_COUNT} kayıt yedeklendi -> ${BACKUP_FILE}"
done

# 30 günden eski yedekleri sil
find "${BACKUP_DIR}" -name "*.json" -mtime +30 -delete
echo "Eski yedekler temizlendi."

Bu scripti cron’a ekleyin ve yedekleri farklı bir konuma (S3, başka bir sunucu vb.) kopyalamayı unutmayın.

Terraform ile Cloudflare DNS Yönetimi

Eğer infrastructure-as-code kullanıyorsanız Cloudflare Terraform provider harika bir seçenek. DNS kayıtlarınız da kod haline geldiğinde değişiklikler review edilebilir, versiyonlanabilir ve geri alınabilir oluyor.

# cloudflare_dns.tf

terraform {
  required_providers {
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 4.0"
    }
  }
}

provider "cloudflare" {
  api_token = var.cloudflare_api_token
}

variable "zone_id" {
  description = "Cloudflare Zone ID"
  type        = string
}

# Ana uygulama
resource "cloudflare_record" "app" {
  zone_id = var.zone_id
  name    = "app"
  value   = "192.168.1.100"
  type    = "A"
  proxied = true
}

# Wildcard kaydı
resource "cloudflare_record" "wildcard" {
  zone_id = var.zone_id
  name    = "*"
  value   = "192.168.1.200"
  type    = "A"
  proxied = false
  ttl     = 300
}

# Tenant subdomainleri (örnek)
locals {
  tenants = ["musteri1", "musteri2", "musteri3"]
}

resource "cloudflare_record" "tenant_records" {
  for_each = toset(local.tenants)
  
  zone_id = var.zone_id
  name    = "${each.value}.app"
  value   = "lb.sirketiniz.com"
  type    = "CNAME"
  proxied = false
  ttl     = 300
}

terraform plan çalıştırdığınızda hangi DNS kayıtlarının ekleneceğini, değişeceğini veya silineceğini görebilirsiniz. Bu şeffaflık production DNS değişikliklerinde çok değerli.

Sonuç

Cloudflare ile subdomain ve wildcard DNS yönetimi, doğru araçları ve yaklaşımı kullandığınızda oldukça sistematik ve güvenli hale gelebiliyor. API üzerinden otomasyon, Terraform ile IaC, düzenli yedekleme ve audit log takibi gibi pratikler bir araya geldiğinde DNS yönetimi artık dertli bir konu olmaktan çıkıyor.

Özetlemek gerekirse en önemli noktalar şunlar: Wildcard DNS proxy modundan önce limitleri anlayın, büyük değişiklikler öncesinde TTL’yi düşürün, her değişikliği API veya IaC üzerinden yapıp loglamaya çalışın, düzenli yedekleme alın ve least privilege prensibini API token’larınızda uygulayın.

Multi-tenant uygulama yönetiyorsanız wildcard DNS plus Nginx regex matching kombinasyonu gerçekten güçlü bir yapı sunuyor. Kubernetes kullanıyorsanız cert-manager ile Cloudflare webhook’u entegre etmeye de bakmanızı öneririm, wildcard sertifika yönetimi de tamamen otomatik hale geliyor.

DNS değişiklikleri basit görünse de production’da hatalı bir yapılandırma ciddi erişim sorunlarına yol açabiliyor. O yüzden test ortamında deneyin, değişiklikleri küçük adımlarla yapın ve her zaman geri dönüş planınız olsun.

Bir yanıt yazın

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