DMARC kaydınıza rua=mailto: satırını eklediniz ve ertesi sabah gelen kutunuzda google.com!ornek.com.tr!1786838400!1786924799.xml.gz gibi tuhaf isimli sıkıştırılmış dosyalar birikmeye başladı. Açtınız, içinden yüzlerce satırlık bir XML çıktı ve ilk tepkiniz büyük ihtimalle "bunu kim okuyacak" oldu.
Okumaya değer, çünkü bu dosyalar alan adınız adına dünyada kim mail gönderiyorsa hepsinin listesidir. Unuttuğunuz bir CRM, muhasebe programının SMTP ayarı, eski bir sunucudaki cron betiği ve gerçekten sizi taklit eden birileri — hepsi aynı tabloda. p=none'dan p=reject'e geçerken kendi maillerinizi çöpe atmamanızı sağlayan tek nesnel veri kaynağı da budur.
Bu yazıda bir toplu raporun XML'ini satır satır açacağız: source_ip kimdir, count neyi sayar, disposition ile policy_evaluated arasındaki fark nedir ve en önemlisi — bir gönderici neden spf=pass aldığı hâlde DMARC'tan kalır. Sonunda elinizde meşru göndericileri tanıma ve politikayı kademeli sıkılaştırma için çalışan bir planınız olacak.
DMARC Toplu Raporu Nedir, Kim Gönderir#
DMARC kaydınızdaki rua etiketi, alıcı sunuculara "alan adım adına gelen mailleri özetleyip bana yolla" der. Bu özetler toplu rapor (aggregate report) olarak bilinir ve genellikle 24 saatlik pencereler hâlinde, günde bir kez gönderilir.
_dmarc.ornek.com.tr. 3600 IN TXT "v=DMARC1; p=none; rua=mailto:[email protected]; adkim=r; aspf=r"
Rapor gönderen tarafta önemli bir gerçek var: herkes rapor göndermez. Google, Microsoft, Yahoo, Mail.ru, Comcast ve birkaç büyük operatör düzenli gönderir. Türkiye'deki pek çok kurumsal mail sunucusu ve küçük hosting sağlayıcısı hiç göndermez. Dolayısıyla raporlar trafiğinizin tamamını değil, rapor gönderen alıcılara giden kısmını kapsar. Bu, verinin işe yaramadığı anlamına gelmez; sadece "raporda görünmüyorsa yok" diye düşünmemeniz gerekir.
ruf etiketi ise ayrı bir şeydir: tek tek başarısız mesajların örneklerini içeren adli (forensic) rapordur. Kişisel veri barındırdığı için Google dâhil çoğu sağlayıcı hiç göndermez; pratikte üzerine plan kurulmaz. İşin tamamı rua ile döner.
Dosya adı da bilgi taşır ve şu kalıptadır: raporlayan!alanadi!baslangic!bitis[!benzersiz].xml.gz. Baştaki google.com raporu gönderen sunucudur, ortadaki iki uzun sayı ise Unix zaman damgasıdır.
# Zaman damgalarını okunabilir tarihe çevir
date -u -d @1786838400 # pencerenin başlangıcı
date -u -d @1786924799 # pencerenin bitişi
# Dosyayı aç
gunzip google.com\!ornek.com.tr\!1786838400\!1786924799.xml.gz
xmllint --format google.com\!ornek.com.tr\!1786838400\!1786924799.xml | less
Bazı sağlayıcılar .gz yerine .zip gönderir; o durumda unzip kullanın. xmllint yoksa Debian/Ubuntu'da apt install libxml2-utils ile gelir.
XML'in İskeleti: Dört Ana Blok#
Her toplu rapor dört bölümden oluşur. Önce iskeleti tanıyalım, sonra içlerini dolduracağız:
| Blok | İçerdiği bilgi |
|---|---|
<report_metadata> | Raporu kim gönderdi, hangi tarih aralığı, rapor kimliği |
<policy_published> | Raporu gönderen sunucunun DNS'te gördüğü DMARC kaydınız |
<record> | Her benzersiz gönderen IP için bir blok; asıl veri buradadır |
<auth_results> | O IP için SPF ve DKIM'in ham sonuçları |
<policy_published> bloğu sıklıkla atlanır ama çok işe yarar: kaydınızda bir yazım hatası varsa ya da yaptığınız değişiklik henüz yayılmamışsa, alıcının gerçekte ne gördüğünü buradan doğrularsınız. Kendi DNS'inizde gördüğünüzle rapordaki değer farklıysa sorun politikanızda değil, yayılmadadır.
Bir Kaydı Satır Satır Okumak#
İşte gerçekçi bir raporun ilk <record> bloğu. Bu, Google Workspace üzerinden çalışanlarınızın attığı normal maillere ait:
<record>
<row>
<source_ip>209.85.220.41</source_ip>
<count>184</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>pass</dkim>
<spf>pass</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>ornek.com.tr</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>ornek.com.tr</domain>
<selector>google</selector>
<result>pass</result>
</dkim>
<spf>
<domain>ornek.com.tr</domain>
<scope>mfrom</scope>
<result>pass</result>
</spf>
</auth_results>
</record>
Alanları tek tek çözelim:
source_ip— mesajı alıcı sunucuya teslim eden IP adresi. Bu, mailin ilk çıktığı yer değil, son adımı yapan sunucudur; yönlendirme varsa aradaki sunucu görünür.count— o pencerede aynı IP'den, aynı doğrulama sonucuyla gelen mesaj sayısı. Yani rapor mesaj başına değil, gruplanmış gelir. 184 mesaj tek satırda özetlenmiştir.disposition— alıcının mesaja fiilen ne yaptığı:none,quarantineveyareject. Bu, sizin politikanızın uygulanmış hâlidir.policy_evaluatediçindekidkimvespf— hizalama dâhil DMARC değerlendirmesinin sonucu. Kritik alan budur.auth_resultsiçindeki sonuçlar — hizalamadan bağımsız, ham SPF ve DKIM sonucu.
Bu son iki maddenin farkı, DMARC raporlarını okumanın tamamıdır. Bir sonraki bölüm tam olarak bunun üzerine.
En Kritik Ayrım: spf=pass Ama policy_evaluated spf=fail#
Aşağıdaki blok, "SendGrid'den mail atıyorum, SPF'te include var, neden DMARC'tan kalıyor" sorusunun cevabıdır:
<record>
<row>
<source_ip>167.89.118.24</source_ip>
<count>1420</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>ornek.com.tr</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>sendgrid.net</domain>
<selector>s1</selector>
<result>pass</result>
</dkim>
<spf>
<domain>em1234.sendgrid.net</domain>
<scope>mfrom</scope>
<result>pass</result>
</spf>
</auth_results>
</record>
Dikkat edin: auth_results içinde her ikisi de pass. SPF geçmiş, DKIM imzası geçerli. Buna rağmen policy_evaluated her ikisi için de fail diyor ve 1420 mesaj risk altında.
Sebep hizalama (alignment). DMARC yalnızca "SPF geçti mi" diye sormaz; "geçen SPF, kullanıcının gördüğü gönderen adresiyle aynı alan adına mı ait" diye sorar:
- SPF hizalaması, zarftaki
MAIL FROMalan adını (em1234.sendgrid.net)From:başlığındaki alan adıyla (ornek.com.tr) karşılaştırır. Farklı → hizalama yok. - DKIM hizalaması, imzadaki
d=değerini (sendgrid.net)From:alan adıyla karşılaştırır. Farklı → hizalama yok.
Yani SendGrid maili teknik olarak kusursuz imzalamış, ama kendi adına imzalamış. DMARC açısından bu, "başkası sizin adınızı kullanıyor" ile aynı görünür.
Hizalamanın iki modu vardır:
| Mod | Etiket | Kural | Örnek |
|---|---|---|---|
| Gevşek (varsayılan) | adkim=r / aspf=r | Kurumsal alan adı eşleşmesi yeter | bulten.ornek.com.tr ↔ ornek.com.tr geçer |
| Katı | adkim=s / aspf=s | Alan adları birebir aynı olmalı | bulten.ornek.com.tr ↔ ornek.com.tr kalır |
Çözüm, sağlayıcı panelinde kimlik doğrulamalı alan adı (authenticated domain / sender authentication) kurmaktır. SendGrid'de bunu yaptığınızda size CNAME kayıtları verir; ekledikten sonra d= değeri sendgrid.net yerine ornek.com.tr olur ve DKIM hizalanır. Aynı mantık Mailchimp, HubSpot, Zoho ve Brevo için de geçerlidir. DKIM tarafında bir şey tutmuyorsa DKIM doğrulaması başarısız yazısındaki tanı adımları işinizi görür.
Şunu da not edin: DMARC'ın geçmesi için ikisinin de hizalanması gerekmez. SPF veya DKIM'den yalnızca biri hem geçerse hem hizalanırsa DMARC pass olur. Bu yüzden hizalanmış DKIM tek başına yeterli bir hedeftir ve yönlendirmeye dayanıklı olduğu için daha da değerlidir.
Raporlardaki Gönderenleri Sınıflandırmak#
Elinizde onlarca satır varken tek tek incelemek yerine, her source_ip değerini üç kutudan birine atın:
1. Tanıdığınız ve hizalanmış olanlar. policy_evaluated en az birinde pass. Yapacak bir şey yok, izlemeye devam edin.
2. Tanıdığınız ama hizalanmayan olanlar. auth_results yeşil, policy_evaluated kırmızı. Yukarıdaki SendGrid örneği. Bunlar p=reject'e geçtiğinizde kendi mailleriniz olduğu için asıl işiniz bunlardır — hepsini panelde alan adı doğrulaması yaparak düzeltin.
3. Tanımadığınız olanlar. IP'yi çözmeden karar vermeyin:
# IP kime ait
whois 45.83.220.17 | grep -iE "orgname|netname|country|descr"
# Ters DNS ne diyor
dig -x 45.83.220.17 +short
Ters DNS mail.muhasebeprogrami.com.tr gibi bir şey döndürüyorsa bu bir spoofing değil, unutulmuş meşru bir gönderendir. Tamamen ilgisiz bir ülkedeki barındırma sağlayıcısına çıkıyor ve doğrulamaların hepsi fail ise, muhtemelen alan adınızı taklit eden bir kampanyaya bakıyorsunuz — e-posta spoofing önleme yazısı bu tarafın ayrıntısını içerir.
Üçüncü grubu değerlendirirken bir tuzağa dikkat: düşük count değerleri genellikle gürültüdür. Günde 2-3 mesajlık, tek seferlik IP'ler çoğu zaman yönlendirilmiş bir mesaj ya da bir tarama denemesidir. Önceliğinizi count değeri yüksek olanlara verin.
Pratikte raporlarda karşınıza çıkacak gönderici tipleri neredeyse her kurumda aynıdır:
| Rapordaki görüntü | Muhtemel kaynak | Yapılacak |
|---|---|---|
d= sağlayıcı alan adı, SPF alan adı emXXXX.* | Pazarlama/işlem maili servisi | Panelde alan adı doğrulaması yap |
| Ters DNS kendi sunucunuza çıkıyor, DKIM yok | Sunucudaki uygulama/cron maili | Sunucuya DKIM imzalama ekle |
Google/Microsoft IP'si, hepsi pass | Kurumsal posta kutuları | Dokunma |
Tek seferlik, düşük count, fail | Yönlendirme veya tarama | Gürültü, izlemeye al |
Yüksek count, tümü fail, alakasız ülke | Taklit kampanyası | Politikayı sıkılaştır |
İkinci satır özellikle sinsidir: web sitenizdeki iletişim formu ya da fatura üreten bir betik, hosting sunucusundan doğrudan mail atıyorsa SPF geçebilir ama DKIM imzası hiç yoktur. Bu maillerin varlığını fark etmenin en kolay yolu raporlardır. SPF, DKIM ve DMARC üçlüsünün nasıl kurulduğunu e-posta kimlik doğrulama rehberinde adım adım bulabilirsiniz.
Yönlendirme ve Mailing List Satırlarını Tanımak#
Raporlarda hiçbir şey yapmadığınız hâlde fail dönen satırlar görürsünüz ve bunlar çoğu zaman sizin hatanız değildir. Bir kullanıcı kurumsal adresini kişisel Gmail'ine yönlettiğinde, mesajı ileten sunucu sizin SPF listenizde olmadığı için SPF hizalaması kaçınılmaz olarak kalır.
DMARCbis ile birlikte raporlarda bu durumu açıklayan reason elemanı daha yaygın kullanılır:
<policy_evaluated>
<disposition>none</disposition>
<dkim>pass</dkim>
<spf>fail</spf>
<reason>
<type>forwarded</type>
<comment>message was forwarded by an intermediary</comment>
</reason>
</policy_evaluated>
Burada DKIM pass olduğu için DMARC yine geçmiştir. Zaten yönlendirmeye karşı asıl savunma budur: DKIM imzası mesajın içeriğine bağlıdır ve yolda değiştirilmediği sürece hayatta kalır; SPF ise IP'ye bağlı olduğu için ilk atlamada kopar. Bu yüzden p=reject'e geçmeden önce DKIM'i mutlaka kurmuş ve hizalamış olmalısınız.
Mailing list yazılımları (Mailman, Google Groups) konu satırına [Liste] etiketi ekleyip alt bilgi yapıştırdığında DKIM imzası da kırılır. reason tipi mailing_list olarak gelir. Bu satırların sayısı azsa görmezden gelin; kurumsal bir listeniz varsa listeyi From: başlığını kendi adına yeniden yazacak şekilde (ARC veya from-rewriting) yapılandırın.
Raporları Elle Değil, Toplu Özetleyerek Okumak#
Günde beş rapor gelirken elle okunur; kırk rapor gelirken okunmaz. Tüm dosyaları tek bir özet tabloya indirmek için xmllint ile şu döngü yeterlidir:
#!/usr/bin/env bash
# dmarc-ozet.sh — klasördeki tüm raporları IP bazında özetler
for f in *.xml.gz *.zip; do
[ -e "$f" ] || continue
case "$f" in
*.gz) zcat "$f" ;;
*.zip) unzip -p "$f" ;;
esac > /tmp/rapor.xml
xmllint --xpath '//record' /tmp/rapor.xml 2>/dev/null |
sed 's|</record>|</record>\n|g' |
while read -r kayit; do
[ -z "$kayit" ] && continue
ip=$(echo "$kayit" | grep -oP '(?<=<source_ip>)[^<]+')
adet=$(echo "$kayit" | grep -oP '(?<=<count>)[^<]+')
spf=$(echo "$kayit" | grep -oPm1 '(?<=<spf>)[a-z]+(?=</spf>)')
dkim=$(echo "$kayit" | grep -oPm1 '(?<=<dkim>)[a-z]+(?=</dkim>)')
echo -e "${adet}\t${ip}\tspf=${spf}\tdkim=${dkim}"
done
done | sort -rn | head -30
Çıktı, en çok mesaj gönderen IP'den başlayarak sıralanmış bir liste verir:
1420 167.89.118.24 spf=fail dkim=fail
184 209.85.220.41 spf=pass dkim=pass
96 185.62.190.11 spf=pass dkim=pass
7 45.83.220.17 spf=fail dkim=fail
Bu dört satır bir kurumun tüm mail durumunu özetler: SendGrid düzeltilmeli, Google ve kendi sunucusu sağlam, son satır ise incelenecek gürültü. grep -P desteklenmeyen sistemlerde (macOS) grep -oE ile eşdeğerini yazabilir ya da doğrudan bir rapor analiz servisine yükleyebilirsiniz — ücretsiz seçenekler XML'i tarayıcıda çözer ve dosyayı sunucularına göndermez.
Kayıtlarınızın DNS tarafını doğrularken dig ve nslookup kullanımı yazısı, _dmarc kaydının gerçekten yayıldığını kontrol etmek için işinize yarar.
p=none'dan reject'e Kademeli Geçiş Planı#
Rapor okumanın amacı bu geçiştir. Acele etmeyin: hizalanmamış tek bir meşru gönderici, p=reject'e geçtiğiniz gün fatura maillerinizi sessizce yok eder.
p=noneile en az 4 hafta bekleyin. Aylık çalışan sistemler (bordro, dönem sonu faturaları) ancak bu pencerede görünür. İki hafta çoğu zaman yetersizdir.- Envanteri kapatın. Raporlardaki her
source_ipiçin "bu kim" sorusunun cevabı yazılı olsun. Cevaplanmamış tek satır kalmasın. - Hizalamayı düzeltin. Her sağlayıcı panelinde alan adı doğrulaması yapın, verilen CNAME/TXT kayıtlarını ekleyin ve raporlarda
policy_evaluateddeğerinin yeşile döndüğünü teyit edin. Panelin "verified" demesi yetmez, rapor kanıttır. - Alt alan adlarını ayırın. Bültenleri
bulten., uygulama bildirimlerinibildirim.altına taşımak hem SPF bütçesini rahatlatır hem de riski bölümlere ayırır. p=quarantine'e geçin ve iki hafta izleyin.dispositionalanındaquarantinegörmeye başlarsanız, hangi göndericinin karantinaya düştüğünü kontrol edin.p=reject'e geçin. Önce alt alan adları içinsp=reject, sonra ana alan adı.
Toplu mail gönderiyorsanız bu geçiş artık isteğe bağlı da değil: Google ve Yahoo, günde beş binin üzerinde mesaj gönderenler için DMARC'ı zorunlu tuttu. Eşiklerin ayrıntısı için gönderici kuralları yazımıza bakabilirsiniz.
Mayıs 2026'da yayımlanan DMARCbis (RFC 9989, 9990, 9991) bu yolculukta iki şeyi değiştirdi. Birincisi, kademeli geçiş için kullanılan pct etiketi kaldırıldı; çalışma grubu, uygulamaların 0 ve 100 dışındaki değerleri tutarsız yorumladığını tespit etti. Yerine t=y "test modu" geldi: p=reject; t=y yazdığınızda alıcılar reddetmek yerine karantinaya alır.
; Test modunda reject — reddetmez, karantinaya alır
_dmarc.ornek.com.tr. 3600 IN TXT "v=DMARC1; p=reject; t=y; sp=reject; np=reject; rua=mailto:[email protected]"
İkincisi, np etiketi eklendi: var olmayan alt alan adlarına uygulanacak politikayı ayrı belirler. Saldırganlar sıklıkla fatura.ornek.com.tr gibi hiç tanımlanmamış alt alanları taklit ettiği için np=reject ucuz ve etkili bir korumadır. Rapor tarafında ise <np>, <testing> ve <discovery_method> elemanları eklendi, DKIM sonucunun raporlanması zorunlu hâle geldi. Mevcut v=DMARC1 kayıtlarınız geçerliliğini koruyor; pct, rf ve ri etiketlerini bir sonraki düzenlemede temizlemeniz yeterli.
Harici Adrese Rapor Göndertirken Atlanan Adım#
Raporları kendi alan adınız dışındaki bir adrese (örneğin bir analiz servisine) yönlendiriyorsanız, tek başına rua=mailto: yazmak yetmez. Standart, rapor almak istenen alan adının bu izni açıkça vermesini şart koşar; aksi hâlde biri sizin alan adınızı kullanarak üçüncü taraflara rapor yağdırabilirdi.
İzin, hedef alan adında şu TXT kaydıyla verilir:
ornek.com.tr._report._dmarc.raporservisi.com. IN TXT "v=DMARC1"
Bu kaydı genellikle servis sağlayıcı kendi tarafında hazırlar, ama eksikse hiç rapor almazsınız ve hiçbir hata mesajı görmezsiniz. Kendi alan adınıza gönderiyorsanız ([email protected]) böyle bir kayda ihtiyaç yoktur. Bir haftadır tek rapor gelmiyorsa kontrol edilecek ilk yer burasıdır; ikinci yer ise rua adresinin gerçekten var olan ve mail kabul eden bir kutu olup olmadığıdır.
Sıkça Sorulan Sorular#
DMARC raporları neden hiç gelmiyor?#
Üç neden yaygındır. Kayıtta yazım hatası olabilir; dig TXT _dmarc.alanadiniz ile kaydın yayıldığını doğrulayın. Rapor adresi başka bir alan adındaysa hedef tarafta alanadiniz._report._dmarc.hedef.com TXT kaydı gerekir, yoksa raporlar sessizce düşer. Son olarak alan adınızdan rapor gönderen sağlayıcılara hiç mail gitmiyorsa rapor da üretilmez.
auth_results'ta spf=pass yazıyor ama DMARC neden fail?#
Çünkü DMARC yalnızca SPF'in geçmesini değil, geçen SPF'in From: başlığındaki alan adıyla hizalanmasını da ister. Bir pazarlama aracı kendi zarf alan adıyla (em1234.sendgrid.net) gönderiyorsa SPF geçer ama hizalama kalır. Çözüm, sağlayıcının panelinde alan adı doğrulaması yapıp verilen kayıtları DNS'e eklemektir.
DMARC'ın geçmesi için hem SPF hem DKIM mi geçmeli?#
Hayır. İkisinden birinin hem geçmesi hem hizalanması yeterlidir. Pratikte hizalanmış DKIM'i öncelikli hedef yapmak daha iyidir, çünkü DKIM mesajın kendisine bağlıdır ve yönlendirmelerde hayatta kalır. SPF ise gönderen IP'ye bağlı olduğu için mesaj bir kez iletildiğinde kopar.
p=none politikası alan adımı koruyor mu?#
Hayır, p=none yalnızca gözlem modudur; başarısız mesajlara hiçbir şey yapılmaz, sadece raporlanır. Koruma p=quarantine ile başlar, gerçek koruma p=reject ile gelir. none bir hedef değil, geçiş aşamasıdır — envanterinizi tamamlayıp hizalama sorunlarını çözdükten sonra ilerlemelisiniz.
Raporda tanımadığım bir IP gördüm, saldırı altında mıyım?#
Hemen değil. Önce whois ve dig -x ile IP'yi çözün; sıklıkla unutulmuş bir muhasebe programı, form eklentisi veya eski sunucu çıkar. Gerçek taklit girişimlerinde tüm doğrulamalar fail olur, IP alakasız bir ülkeye aittir ve mesaj sayısı düzensizdir. Günde birkaç mesajlık satırlar genellikle yönlendirme kaynaklı gürültüdür.
pct etiketini hâlâ kullanabilir miyim?#
Kayıtta bırakmanız bir hataya yol açmaz, ancak DMARCbis ile kaldırıldığı için giderek daha az uygulama dikkate alır. Kademeli geçiş için yeni yöntem t=y test modudur: p=reject; t=y yazdığınızda alıcılar reddetmek yerine karantina uygular. Bir sonraki DNS düzenlemenizde pct, rf ve ri etiketlerini kaldırıp t kullanmaya geçmeniz yeterli.