Postfix smtpd Restriction Sıralaması: Erken ve Ucuz Reddetme Sanatı
Çoğu Postfix rehberi devasa bir restriction listesini kopyala-yapıştır olarak verir ama iki gerçeği hiç anlatmaz: kurallar soldan sağa değerlendirilir ve smtpd_delay_reject her şeyi RCPT TO anında toplar. Bu iki gerçeği bilmeyen sysadmin ya spam sızdırır, ya meşru postayı bloklar, ya da her bağlantıda boşuna DNS yakar. Doğru sıralama bir stil tercihi değil; hem güvenlik hem performans meselesidir.
EvilMail Team24 Temmuz 202611 dk okuma
Elinizde internetten kopyalanmış 40 satırlık bir smtpd_recipient_restrictions bloğu var. Çalışıyor gibi görünüyor: spam düşük, meşru posta geliyor. Ama bu blok muhtemelen iki şeyi aynı anda yapıyor: kimliği doğrulanmış müşterileriniz için bile Spamhaus'a DNS sorgusu atıyor ve içine gizlenmiş yanlış sıralanmış bir kural yüzünden ya bir gün açık relay'e dönüşecek ya da meşru bir göndereni sessizce 550'liyor.
Postfix'te restriction sıralaması estetik bir tercih değildir. Postfix her listeyi soldan sağa tarar ve ilk kesin kararda durur. Bu tek cümle, hem güvenlik açıklarının hem de gereksiz DNS trafiğinin kaynağıdır. Aşağıda sıralamanın gerçekte nasıl çalıştığını, herkesin kaçırdığı smtpd_delay_reject ayrıntısını, kuralları maliyetlerine göre nasıl dizeceğinizi ve ağır işi postscreen'e devrederek smtpd'yi nasıl neredeyse boşta bırakacağınızı göreceğiz.
Sıralama gerçekte nasıl çalışır: soldan sağa, ilk karar kazanır
) her biri bir listedir. Postfix bu listeyi baştan tarar ve her kuralın döndürdüğü üç sonuçtan birine bakar:
PERMIT (OK) → dur, kalan kuralları atla, bağlantıya izin ver.
REJECT → dur, kalan kuralları atla, reddet.
DUNNO → karar yok, bir sonraki kurala geç.
Kritik nokta: OK ile REJECT arasındaki tek fark yön değil, çünkü ikisi de listenin geri kalanını atlar. Bunun iki doğrudan sonucu var.
Birincisi güvenlik. Bir permit_* kuralını çok erken koyarsanız, ondan sonra gelen tüm reddetme kuralları o bağlantı için hiç çalışmaz. Klasik felaket, reject_unauth_destination'ı bir permit'ten sonraya koymaktır: o permit'e takılan istemci için relay kontrolü hiç işlemez ve sunucunuz açık relay olur.
İkincisi performans. Pahalı bir kuralı (örneğin bir RBL sorgusu) listenin başına koyarsanız, o kurala kadar hiçbir permit kısa devre yapmadığı için her meşru bağlantı da o DNS bedelini öder. Kendi ağınızdan gelen posta bile Spamhaus'a sorgu attırır.
Doğru sıralamanın iki hedefi buradan çıkar: reddetme kurallarını hiçbir permit'in atlayamayacağı yere koymak ve pahalı kuralları, ucuz permit'lerin çoktan kısa devre yaptığı listenin sonuna itmek.
Herkesin kaçırdığı ayrıntı: smtpd_delay_reject
Sezgisel beklenti şudur: smtpd_helo_restrictions HELO komutunda çalışır, smtpd_sender_restrictions MAIL FROM'da çalışır. Yanlış. Varsayılan olan smtpd_delay_reject = yes bu davranışı tamamen değiştirir.
delay_reject açıkken Postfix, client, helo ve sender sınıflarının değerlendirmesini protokolün ilgili anında yapmaz; hepsini RCPT TO komutuna kadar erteler ve orada birlikte değerlendirir. Bu bir hata değil, bilinçli ve iyi bir varsayılan:
Reddetme kararı verildiğinde artık istemcinin kim olduğunu, gönderen ve alıcıyı da biliyorsunuz. Log satırınız eksiksiz olur.
Bazı bozuk istemciler erken bir 5xx görünce bağlantıyı düzgün kapatmaz veya agresifçe yeniden dener; RCPT'e kadar beklemek bunu yumuşatır.
Pratik sonuç ince ama önemli: sınıflar arasında "hangisi önce değerlendirilir" tartışması çoğu zaman görünürde önemsizdir, çünkü client/helo/sender kuralları zaten RCPT anında birlikte patlar. Asıl kritik olan, her sınıfın kendi içindeki sıralamadır. Bir permit_sasl_authenticated'ı smtpd_recipient_restrictions'ın başına koyduğunuzda, o listedeki geri kalan her şey (RBL'ler dahil) o oturum için atlanır.
Bunu smtpd_helo_required = yes ile tamamlayın; HELO/EHLO'yu zorunlu kılmadan HELO tabanlı kurallarınızın çoğu boşa döner.
smtpd_relay_restrictions (Postfix 2.10+) tarihsel olarak kritiktir. Eskiden relay kontrolü reject_unauth_destination ile smtpd_recipient_restrictions içine gömülüydü; insanlar o listeyi düzenlerken kuralı yanlışlıkla bir permit'in arkasına atıp açık relay yaratıyordu. Postfix ekibi tam bu yüzden relay kararını ayrı, kendinden güvenli bir sınıfa taşıdı. Bugün relay güvenliğini burada tutun; recipient_restrictions'ı spam politikanız için kullanın.
Relay kararı artık yalnızca smtpd_relay_restrictions'ta; recipient_restrictions'a reject_unauth_destination'ı ikinci kez koymuyoruz. Ayrıca her listenin ilk iki satırı permit_mynetworks ve permit_sasl_authenticated: kendi ağınız ve kimliği doğrulanmış müşterileriniz daha ilk adımda kısa devre yapar, altındaki hiçbir DNS/RBL kuralı onlar için çalışmaz.
Ucuzdan pahalıya: kuralları maliyetine göre dizin
Bir liste içindeki sıralamanın altın kuralı: önce bedava yerel kontroller, en sonda pahalı DNS kontrolleri. Maliyet merdiveni şöyle:
Yerel / sıfır maliyet:permit_mynetworks, permit_sasl_authenticated — bellek içi kontrol, ağ yok.
Sözdizimi / DNS'siz:reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_invalid_helo_hostname — sadece string ayrıştırır.
Relay kapısı:reject_unauth_destination — yerel, ama güvenlik için erken olmalı (bu yüzden ayrı sınıfta).
Forward-DNS:reject_unknown_sender_domain, reject_unknown_recipient_domain — bir A/MX sorgusu.
Reverse-DNS:reject_unknown_reverse_client_hostname — bir PTR sorgusu.
RBL/RHSBL:reject_rbl_client, reject_rhsbl_sender — en pahalı, harici servise bağımlı, kotalı sorgular.
Bu diziliş sadece CPU tasarrufu değil; aynı zamanda gizlilik ve dayanıklılık. Kimliği doğrulanmış her müşteri için Spamhaus'a sorgu atarsanız, hem müşteri IP bilgisini üçüncü tarafa sızdırır hem de DQS sorgu kotanızı boşa yakarsınız. permit_sasl_authenticated en başta olduğu için o sorgu hiç yapılmaz.
postscreen: savaş smtpd'den önce kazanılır
Modern bir MX'te ağır işi smtpd değil, postscreen yapar. postscreen, istemci 220 banner'ını görmeden önce devreye girer: ağırlıklı bir DNSBL sorgusu çalıştırır, pregreet testi yapar (banner'dan önce konuşan istemcileri yakalar) ve protokol ihlallerine bakar. Botların büyük çoğunluğu smtpd'ye hiç ulaşmadan burada elenir; dolayısıyla smtpd'deki pahalı RBL kurallarınız neredeyse hiç ateşlenmez.
Ağırlıklı skorun mantığı: her liste bir puan ekler, toplam postscreen_dnsbl_threshold'u aşmadıkça istemci reddedilmez. zen'in ağırlığı 3 olduğu için tek başına eşiği geçer (Spamhaus'a güveniyorsanız), ama daha oynak listelere 2 verip yalnız başlarına karar vermelerini engellersiniz.
RBL kontrollerini postscreen'e taşıdığınızda aynı listeleri smtpd_recipient_restrictions'ta da tutmak çift sorgu demektir: postscreen zaten elediği için smtpd'dekiler ya gereksiz tekrar yapar ya da hiç ateşlenmez. İkisini de tutacaksanız en azından farklı listeler seçin.
2026 uyarısı: Spamhaus'un anahtarsız ücretsiz public mirror'ı (ör. doğrudan zen.spamhaus.org sorguları) emekliye ayrıldı. Artık ücretsiz kişisel kullanım için bile Data Query Service (DQS) anahtarı zorunlu ve sorgu formatı {key}.zen.dq.spamhaus.net. Eski anahtarsız sorgular NXDOMAIN veya hata döner, yani hiçbir şeyi bloklamaz. Bu tehlikeli bir sessiz başarısızlık: filtreniz çalışıyor sanırsınız ama aslında tüm spam'i geçiriyordur. Loglarınızda düz zen.spamhaus.org görüyorsanız hemen DQS anahtarına geçin.
HELO ve reverse-DNS kontrollerinin ince farkları
Bu iki çift, üretimde en çok yanlış-pozitif üreten kurallardır; farklarını bilmek meşru posta ile spam arasındaki çizgidir.
Reverse-DNS:
reject_unknown_reverse_client_hostname — yalnızca istemci IP'sinin bir PTR kaydı olmasını ister. Güvenli, üretimde tercih edilen. Çoğu meşru MX'in PTR'si vardır.
reject_unknown_client_hostname — hem PTR hem de o isme geri dönen eşleşen bir A/forward kaydı ister. Agresif. DNS'i özensiz kurulmuş ama tamamen meşru gönderenleri bloklar. Yalnızca ne yaptığınızı biliyorsanız ve loglarla doğruladıysanız kullanın.
HELO:
reject_invalid_helo_hostname + reject_non_fqdn_helo_hostname — pratikte sıfıra yakın yanlış-pozitif. HELO'da düpedüz bozuk veya eksik isim verenleri yakalar. Gönül rahatlığıyla açın.
reject_unknown_helo_hostname — HELO adının DNS'te çözülmesini ister. Yanlış-pozitif üretir: birçok meşru host HELO'da çözülmeyen bir iç isim verir. Dikkatli kullanın, önce warn_if_reject ile ölçün.
Reject kodu tuzağı:reject_unknown_reverse_client_hostname'in döndürdüğü kod unknown_client_reject_code'a bağlıdır ve bu varsayılan 450'dir; yani kalıcı değil, geçici deferral. İstemci tekrar dener. Kalıcı reddetmek istiyorsanız bilinçli olarak unknown_client_reject_code = 550 ayarlamanız gerekir, ama bunu önce loglarla doğrulamadan yapmayın; 550 geri dönüşü olmayan bir karardır.
Kırmadan devreye alma: warn_if_reject ve loglar
Yeni bir reddetme kuralını canlıda doğrudan açmak amatör işidir. Postfix güvenli test araçları verir.
Herhangi bir reddetme kuralının önüne warn_if_reject ekleyin; kural reddetmez, sadece "reddedecektim" satırı loglar:
48 saat gerçek trafikle çalıştırıp logda kaç meşru gönderenin takıldığına bakın. Temizse warn_if_reject'i kaldırırsınız.
Daha geniş bir güvenlik ağı soft_bounce = yes: tüm 5xx reddetmeleri geçici 4xx'e çevrilir, yani hiçbir posta kalıcı olarak kaybolmaz. Yeni bir yapılandırmayı ilk kez açarken idealdir; test bitince kaldırın.
Doğrulama komutları:
bash
# Aktif (varsayılandan farklı) ayarları gör
postconf -n | grep -E 'restrictions|delay_reject|helo_required'
# Bir access map'i test et
postmap -q "[email protected]" hash:/etc/postfix/sender_access
# Canlı reddetmeleri izle
journalctl -u postfix --since "10 min ago" | grep NOQUEUE
Tipik bir reddetme satırı şöyle görünür:
text
NOQUEUE: reject: RCPT from unknown[203.0.113.9]: 554 5.7.1
Service unavailable; Client host [203.0.113.9] blocked using
zen.dq.spamhaus.net; from=<[email protected]> to=<[email protected]> proto=ESMTP
from= ve to='nun aynı satırda görünmesi tam olarak smtpd_delay_reject'in armağanıdır: client kuralı RCPT'e ertelendiği için Postfix reddederken tüm bağlamı biliyor.
Devreye alma checklist'i
postconf -n | grep delay_reject → smtpd_delay_reject = yes (veya hiç ayarlı değil, ki varsayılan yes) olduğunu teyit et.
Her restriction listesinde permit_mynetworks ve permit_sasl_authenticated en başta, kısa devre yapıyor mu?
Relay kararı ayrı smtpd_relay_restrictions'ta ve reject_unauth_destination hiçbir permit'ten sonra değil mi? (Açık relay testi: swaks --to [email protected] --server sizin-mx başkasının domainine relay edilmemeli.)
RBL/RHSBL kuralları listenin en sonunda mı, ucuz yerel kontroller önlerinde mi?
postscreen ağırlıklı skorla (postscreen_dnsbl_threshold >= 2) çalışıyor, tek liste tek başına bloklamıyor mu?
Reject kodları bilinçli mi? Geçici (450) mi yoksa kalıcı (550) mı istediğinizi gerçekten seçtiniz mi?
Yeni her kural warn_if_reject ile 48 saat gözlendi mi?
postscreen ile smtpd'deki RBL'ler aynı listeye çift sorgu yapmıyor mu?
Sıralama görünmez bir güvenlik katmanıdır: doğru olduğunda kimse fark etmez, yanlış olduğunda ya bir sabah kara listelerde uyanırsınız ya da müşteri "postam gitmiyor" diye yazar. Beş dakika ayırıp postconf -n çıktınızı bu checklist'e karşı okuyun; büyük olasılıkla bir permit'in arkasında saklanan bir sürprizle karşılaşacaksınız.