Mail sunucusu yönetiminde en çok zaman kaybettiğimiz konuların başında performans sorunları geliyor. Postfix çalışıyor, mailler gönderiliyor, her şey “tamam” gibi görünüyor ama bir yerde bir şeyler yavaş. Queue’da biriken mailler, geciken deliverylar, artan load average… Bu yazıda Postfix performansını gerçek dünya senaryoları üzerinden nasıl optimize edeceğimizi konuşacağız.
Mevcut Durumu Anlamak
Optimizasyona başlamadan önce neyi optimize ettiğimizi bilmemiz lazım. Körü körüne parametre değiştirmek bazen işleri daha da kötüye götürür. Önce mevcut durumu ölçelim.
Queue Durumunu İncelemek
# Genel queue özeti
postqueue -p | tail -n 1
# Queue'daki mail sayısı ve boyutu
postqueue -p | grep -c "^[A-F0-9]"
# Deferred mailleri listele
postqueue -p | grep "Deferred"
# Queue içindeki bir mailin detaylarına bak
postqueue -p | head -20
postcat -q MAILID
postqueue -p çıktısının son satırı size şu anda kaç mail olduğunu ve toplam boyutu verir. Eğer bu sayı sürekli artıyorsa, bir şeyler yanlış gidiyor demektir.
Mail Log Analizi
# Son 1 saatin mail istatistikleri
grep "$(date '+%b %e %H')" /var/log/mail.log | grep "status=" |
awk '{print $NF}' | sort | uniq -c | sort -rn
# En çok mail gönderen domain'leri bul
grep "from=<" /var/log/mail.log |
grep -oP 'from=<[^>]+>' | sort | uniq -c | sort -rn | head -20
# Bounce oranını hesapla
grep "status=bounced" /var/log/mail.log | wc -l
grep "status=sent" /var/log/mail.log | wc -l
# Ortalama delivery süresini kontrol et
grep "status=sent" /var/log/mail.log |
grep -oP 'delay=K[0-9.]+' |
awk '{sum+=$1; count++} END {print "Ortalama delay:", sum/count, "saniye"}'
Bu komutlar size gerçek tablo çizer. Bounce oranı yüksekse DNS veya blacklist sorunu olabilir. Ortalama delay yüksekse teslim tarafında bir tıkanma var demektir.
Sistem Kaynaklarını Kontrol Etmek
# Postfix process'lerini gör
ps aux | grep postfix | grep -v grep
# Postfix'in kullandığı file descriptor sayısı
lsof -u postfix | wc -l
# Network bağlantılarını kontrol et
ss -tnp | grep master | awk '{print $1}' | sort | uniq -c
# Disk I/O durumu (queue dizini için)
iostat -x 1 5 | grep -E "Device|$(df /var/spool/postfix | tail -1 | awk '{print $1}' | sed 's|/dev/||')"
main.cf Temel Performans Parametreleri
Postfix’in kalbi main.cf dosyasıdır. Buradaki parametreler doğru ayarlanmadığında en güçlü sunucu bile yavaş kalır.
Process Limitleri
# /etc/postfix/main.cf
# Eş zamanlı çalışacak maksimum process sayısı
# Genellikle CPU çekirdeği sayısı x 2 iyi başlangıç noktasıdır
default_process_limit = 100
# Bir domain'e eş zamanlı açılabilecek maksimum bağlantı
smtp_destination_concurrency_limit = 20
# Bir domain'e dakikada gönderilebilecek maksimum mesaj
smtp_destination_rate_delay = 0
# Recipient başına maksimum mesaj
smtp_extra_recipient_limit = 10
# SMTP client timeout değerleri (çok düşük = erken kopma, çok yüksek = kaynak israfı)
smtp_connect_timeout = 30s
smtp_data_init_timeout = 120s
smtp_data_done_timeout = 600s
smtp_quit_timeout = 5s
Bu değerler orta ölçekli bir mail sunucusu için başlangıç noktası. Günde 100.000 üzerinde mail gönderen sunucularda default_process_limit değerini artırmak gerekebilir ama önce CPU ve memory kullanımını izleyin.
Queue Yönetimi
# Deferred maillerin tekrar deneme süresi
minimal_backoff_time = 300s
maximal_backoff_time = 4000s
maximal_queue_lifetime = 5d
bounce_queue_lifetime = 5d
# Queue'dan okuma hızı
qmgr_message_active_limit = 20000
qmgr_message_recipient_limit = 20000
qmgr_message_recipient_minimum = 10
# Queue dosya sistemi için
hash_queue_depth = 2
hash_queue_names = deferred, defer
hash_queue_depth parametresi çok kritik. Varsayılan değer 1’dir ve büyük queue’larda ciddi filesystem performans sorunlarına yol açar. 2 veya 3 yaparak queue dizinini alt klasörlere dağıtırsınız, bu da readdir() çağrılarını dramatik şekilde hızlandırır.
Memory ve I/O Optimizasyonu
# In-memory queue cache
# Bu değeri RAM'in %10-15'i olarak ayarlayın
qmgr_caches = 1
# SMTP server'ın bellekte tutacağı bağlantı bilgisi
smtp_connection_cache_on_demand = yes
smtp_connection_cache_destinations =
smtp_connection_reuse_time_limit = 300s
# Header ve body check'leri için maksimum boyut
header_size_limit = 102400
message_size_limit = 52428800
# MIME encoding sınırları
mime_boundary_length_limit = 2048
mime_nesting_limit = 100
master.cf Optimizasyonu
main.cf genel ayarları yaparken, master.cf her servisin kaç process ile çalışacağını belirler. Burası çoğu sysadmin’in göz ardı ettiği ama kritik öneme sahip bir yer.
# /etc/postfix/master.cf
# Servis tipi private unpriv chroot wakeup maxproc command
smtp inet n - n - - smtpd
-o smtpd_client_connection_rate_limit=100
-o smtpd_client_message_rate_limit=100
# Outbound SMTP için ayrı bir servis (yük dengeleme için)
smtp unix - - n - 10 smtp
# Yerel teslimat
local unix - n n - - local
# Cleanup servisi - paralel çalışma için artır
cleanup unix n - n - 0 cleanup
# Queue manager - sadece bir tane olmalı
qmgr unix n - n 300 1 qmgr
# Deferred queue için retry
retry unix - - n - - error
# Pipe servisi (procmail, maildrop gibi programlar için)
# maxproc değerini sunucunuza göre ayarlayın
maildrop unix - n n - - pipe
flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
maxproc değeri olan 0, sınırsız process anlamına gelir. Çoğu servis için bu tehlikeli. smtp için 10-20 arası değer genellikle yeterlidir ve sistem kaynaklarını korur.
SMTP Bağlantı Optimizasyonu
TLS Performansı
TLS her mail bağlantısında CPU kullanır. Bunu optimize etmek ciddi performans kazancı sağlar.
# TLS session cache - aynı sunucuya tekrar bağlanırken handshake atlanır
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_session_cache_timeout = 3600s
# TLS güvenlik seviyesi (may = mümkünse TLS kullan, encrypt = zorunlu)
smtp_tls_security_level = may
smtpd_tls_security_level = may
# Daha hızlı cipher'ları tercih et
smtp_tls_ciphers = medium
smtpd_tls_ciphers = medium
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
# ECDSA sertifika kullanıyorsanız (RSA'dan daha hızlı)
smtpd_tls_cert_file = /etc/ssl/certs/mail.ecdsa.crt
smtpd_tls_key_file = /etc/ssl/private/mail.ecdsa.key
# TLS session ticket'ları etkinleştir
tls_ssl_options = NO_COMPRESSION, NO_RENEGOTIATION
TLS session cache olmadan her bağlantı tam bir handshake yapıyor. Yoğun sunucularda bu CPU kullanımını %20-30 artırabilir. Cache aktif olduğunda aynı sunucuya giden bağlantılar önceki session bilgisini kullanır.
DNS Performansı
Mail gönderimi sırasında en çok zaman kaybettiğiniz yer DNS çözümleme. Her MX lookup birkaç milisaniyeden birkaç saniyeye kadar sürebilir.
# /etc/postfix/main.cf
# Yerel DNS cache kullanmak için
smtp_dns_resolver_options = res_defnames, res_dnsrch
# DNS timeout değerleri
smtp_dns_support_level = dnssec
# Postfix'in kendi DNS cache'i (Postfix 3.0+)
# Bu özellik için smtpd_proxy_timeout yetersizse ayrı resolver kurun
Postfix kendi DNS cache’ini tutmaz. Bu yüzden sistemde unbound veya dnsmasq gibi bir local DNS resolver çalıştırmak büyük fark yaratır.
# unbound kurulumu ve Postfix için ayarlama
apt-get install unbound # Debian/Ubuntu
yum install unbound # CentOS/RHEL
# /etc/unbound/unbound.conf içine ekle
server:
cache-size: 64m
prefetch: yes
num-threads: 2
# /etc/resolv.conf
nameserver 127.0.0.1
options timeout:2 attempts:3
Local resolver kurduğunuzda mail delivery süresinin %10-15 kısaldığını görebilirsiniz. Özellikle çok sayıda farklı domain’e mail gönderen sistemlerde bu etki daha belirgindir.
Gerçek Dünya Senaryosu: Kalabalık Queue Sorunu
Bir e-ticaret sitesi için mail sunucusu yönetiyorsunuz. Kampanya saatlerinde sipariş onayları, kargo bildirimleri ve promosyon mailleri aynı anda gönderiliyor. Queue dolup taşıyor ve müşteriler maillerini almakta gecikme yaşıyor.
#!/bin/bash
# queue_monitor.sh - Queue'yu izle ve uyar
THRESHOLD=5000
QUEUE_COUNT=$(postqueue -p | grep -c "^[A-F0-9]" 2>/dev/null || echo 0)
DEFERRED_COUNT=$(postqueue -p | grep -c "Deferred" 2>/dev/null || echo 0)
if [ "$QUEUE_COUNT" -gt "$THRESHOLD" ]; then
echo "UYARI: Queue $QUEUE_COUNT mail iceriyor!" |
mail -s "Postfix Queue Alarmı - $(hostname)" [email protected]
# Otomatik flush - deferred mailleri hemen tekrar dene
if [ "$DEFERRED_COUNT" -gt 1000 ]; then
postqueue -f
echo "$(date): Deferred queue flush edildi. Deferred sayisi: $DEFERRED_COUNT" >> /var/log/postfix_queue.log
fi
fi
Bu senaryoda ek olarak main.cf‘e şunları ekliyoruz:
# Transaksiyonel mailler için öncelik sistemi
# Sipariş onayları (yüksek öncelik) vs bültenler (düşük öncelik)
# Yüksek öncelikli mailler için ayrı transport
# /etc/postfix/transport
transaksiyonel.sirket.com smtp:[mail1.sirket.com]:25
bulten.sirket.com smtp:[mail2.sirket.com]:25
# main.cf'e ekle
transport_maps = hash:/etc/postfix/transport
# transport tablosunu derle
postmap /etc/postfix/transport
postfix reload
Postfix ile Veritabanı Entegrasyonu Performansı
Büyük sistemlerde virtual domain ve kullanıcı bilgileri MySQL veya PostgreSQL’de tutulur. Bu sorguların yavaşlaması tüm mail akışını etkiler.
# /etc/postfix/mysql-virtual-domains.cf
user = postfix
password = guclu_sifre
hosts = 127.0.0.1
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
# Bağlantı pool'u için (Postfix doğrudan desteklemez ama ProxySQL kullanılabilir)
# main.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf
# Lookup cache (Postfix 2.9+)
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual-domains.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual-alias-maps.cf
proxy: ön eki kritik. Bu Postfix’in proxymap servisini kullanmasını sağlar ve veritabanı bağlantılarını merkezi olarak yönetir. Her smtp process ayrı bağlantı açmak yerine proxymap üzerinden ortak bağlantıları kullanır. Yoğun sistemlerde veritabanı bağlantı sayısını %70’e kadar düşürebilir.
Postscreen ile Spam Filtresi Optimizasyonu
Gereksiz mailleri erken engellemek kaynakları korur ve gerçek maillerin daha hızlı işlenmesini sağlar.
# /etc/postfix/main.cf - postscreen ayarları
postscreen_access_list = permit_mynetworks,
cidr:/etc/postfix/postscreen_access.cidr
# Greylist ile bağlantı sayısını azalt
postscreen_greet_action = enforce
postscreen_dnsbl_action = enforce
postscreen_dnsbl_sites =
zen.spamhaus.org*3,
bl.spamcop.net*2,
b.barracudacentral.org*2
postscreen_dnsbl_threshold = 3
postscreen_dnsbl_whitelist_threshold = -1
# Whitelist için
postscreen_whitelist_interfaces = static:all
# Cache ayarları - tekrar bağlanan temiz IP'ler hemen geçsin
postscreen_cache_map = btree:$data_directory/postscreen_cache
postscreen_cache_retention_time = 7d
postscreen_cache_cleanup_interval = 12h
# /etc/postfix/master.cf değişikliği
smtp inet n - n - 1 postscreen
smtpd pass - - n - - smtpd
dnsblog unix - - n - 0 dnsblog
tlsproxy unix - - n - 0 tlsproxy
Postscreen aktif olduğunda sunucuya bağlanan IP’lerin büyük çoğunluğu gerçek SMTP sunucusu olmayan botlar. Bunları erkenden engellemek smtpd process’lerine ulaşmadan onları geri çevirir. Test ortamında postscreen’i _action = warn modunda çalıştırıp logları incelemenizi öneririm, direkt enforce’a geçmeden önce.
Logging ve Monitoring
Performans optimizasyonunun sonuçlarını görmek için doğru monitoring şart.
#!/bin/bash
# postfix_stats.sh - Her saat çalıştırılacak istatistik toplayıcı
LOG_FILE="/var/log/mail.log"
STATS_FILE="/var/log/postfix_hourly_stats.log"
HOUR=$(date '+%Y-%m-%d %H:00')
SENT=$(grep "status=sent" $LOG_FILE | grep "$(date '+%b %e %H')" | wc -l)
DEFERRED=$(grep "status=deferred" $LOG_FILE | grep "$(date '+%b %e %H')" | wc -l)
BOUNCED=$(grep "status=bounced" $LOG_FILE | grep "$(date '+%b %e %H')" | wc -l)
QUEUE=$(postqueue -p | grep -c "^[A-F0-9]" 2>/dev/null || echo 0)
AVG_DELAY=$(grep "status=sent" $LOG_FILE | grep "$(date '+%b %e %H')" |
grep -oP 'delay=K[0-9.]+' |
awk '{sum+=$1; count++} END {if(count>0) print sum/count; else print 0}')
echo "$HOUR | Sent: $SENT | Deferred: $DEFERRED | Bounced: $BOUNCED | Queue: $QUEUE | Avg Delay: ${AVG_DELAY}s" >> $STATS_FILE
Bu scripti cron’a ekleyin:
# /etc/cron.d/postfix-stats
0 * * * * root /usr/local/bin/postfix_stats.sh
Sık Yapılan Hatalar ve Çözümleri
Hata 1: too many errors after DATA mesajları
Genellikle content filter veya milter gecikmesinden kaynaklanır. smtpd_timeout değerini artırın:
smtpd_timeout = 300s
smtpd_data_restrictions = reject_unauth_pipelining
Hata 2: connection timed out ile dolu log
Hedef sunucular yanıt vermiyorsa gereksiz bekleme yerine daha agresif timeout kullanın:
smtp_connect_timeout = 15s
smtp_helo_timeout = 30s
smtp_mail_timeout = 30s
smtp_rcpt_timeout = 30s
Hata 3: Queue sürekli büyüyor ama flush çalışmıyor
# Aktif kilitli mesajları temizle
find /var/spool/postfix/deferred -type f -mtime +5 -delete
find /var/spool/postfix/defer -type f -mtime +5 -delete
postfix reload
# Tek bir domain'e giden mailleri sil (spam durumunda)
postqueue -p | grep '@hedef-domain.com' |
awk '{print $1}' | tr -d '*!' |
postsuper -d -
Sonuç
Postfix performans optimizasyonu tek seferlik bir iş değil, sürekli devam eden bir süreç. Önce ölçün, sonra değiştirin, tekrar ölçün. Kör ayar değişikliği yapmak yerine log analizi ve monitoring verilerine dayanarak karar alın.
Özetlemek gerekirse en kritik noktalar şunlar:
- hash_queue_depth değerini 2 yapın, büyük queue’larda ciddi fark yaratır
- proxy: ön ekini veritabanı lookup’larında kullanın, bağlantı sayısını dramatik düşürür
- Yerel DNS resolver kurun, her mail gönderiminde DNS lookup maliyetini azaltır
- postscreen aktif edin, sahte SMTP clientları ana servise ulaşmadan engellenir
- TLS session cache ekleyin, CPU kullanımını belirgin şekilde azaltır
- Queue monitoring scriptlerini cron’a alın, sorunları büyümeden yakalarsınız
Her mail sunucusunun iş yükü farklı. Bu yazıdaki değerler iyi bir başlangıç noktası ama sunucunuzu izleyerek kendi optimal değerlerinizi bulmanız gerekir. Yüksek trafikli sistemlerde postfix check ve postconf -n komutlarıyla mevcut ayarlarınızı düzenli gözden geçirin.