Mail sunucunuzu kurdunuz, her şey çalışıyor, ama zamanla kuyruklar büyümeye, teslim süreleri uzamaya başladı. Sabah işe geldiğinizde yüzlerce mail bekliyor, kullanıcılar şikayetçi ve siz de “bu Exim neden bu kadar yavaş?” diye soruyorsunuz. İşte bu yazıda tam olarak bu soruyu cevaplayacağız. Exim’in performans optimizasyonu, doğru yapılandırıldığında ciddi farklar yaratabilecek bir konu ve bu farkları somut örneklerle göstereceğim.
Exim Performans Sorunlarını Tanımak
Optimizasyona geçmeden önce neyi optimize ettiğimizi anlamak lazım. Exim performans sorunları genellikle birkaç kategoriye giriyor:
- Kuyruk birikimi: Mailler gönderilemeyip kuyrukta bekliyor
- Yavaş teslim: Mailler gidebiliyor ama çok uzun sürüyor
- Yüksek CPU kullanımı: Exim süreçleri sistemi boğuyor
- Bellek sorunları: Her bağlantı için açılan süreçler RAM’i tüketiyor
- DNS gecikmeleri: Her mail için yapılan DNS sorguları darboğaz yaratıyor
Önce mevcut durumu görmek için birkaç komut çalıştıralım:
# Kuyruk boyutunu görüntüle
exim -bpc
# Kuyruktaki mailleri listele
exim -bp | head -50
# Aktif Exim süreçlerini say
ps aux | grep exim | wc -l
# Son 100 log satırını filtrele
tail -100 /var/log/exim4/mainlog | grep -E "(defer|reject|panic)"
# Exim istatistiklerini görüntüle
eximstats /var/log/exim4/mainlog | head -50
Bu komutların çıktılarına bakarak hangi kategoride sorun yaşadığınızı anlayabilirsiniz. Kuyruk 1000’in üzerindeyse ciddi bir sorun var demektir.
Ana Yapılandırma Dosyasını Optimize Etmek
Exim’in ana yapılandırma dosyası genellikle /etc/exim4/exim4.conf veya Debian tabanlı sistemlerde /etc/exim4/conf.d/ dizini altında parçalı halde bulunur. Temel performans parametrelerini buradan yönetiyoruz.
Bağlantı ve Süreç Limitleri
# /etc/exim4/exim4.conf veya ilgili conf dosyasına eklenecekler
# Eş zamanlı maksimum bağlantı sayısı (varsayılan 20, yüklü sunucularda artırın)
smtp_accept_max = 100
# IP başına maksimum eş zamanlı bağlantı
smtp_accept_max_per_host = 5
# Bağlantı kurulamadığında aynı host için bekleme süresi (saniye)
smtp_connect_backoff_limit = 3
# Bir kerede kuyruktan işlenecek mesaj sayısı
queue_run_max = 50
# Kuyruk kontrol periyodu (dakika cinsinden)
queue_interval = 15m
# Maksimum mesaj boyutu (25MB)
message_size_limit = 26214400
smtp_accept_max değerini artırırken dikkatli olun. Her SMTP bağlantısı bir Exim süreci oluşturuyor ve bu süreçlerin her biri bellek tüketiyor. Sunucunuzun RAM’ine göre bu değeri belirleyin. Genel kural olarak her Exim süreci yaklaşık 5-10MB bellek kullanıyor.
Zaman Aşımı Değerlerini Ayarlamak
Varsayılan zaman aşımı değerleri bazen çok uzun olabiliyor. Özellikle dışarıya mail gönderirken yanıt vermeyen sunucular bağlantıları uzun süre meşgul tutuyor:
# SMTP komutları için zaman aşımı
timeout_connect = 5m
timeout_helo = 5m
timeout_mail = 5m
timeout_rcpt = 5m
timeout_data = 10m
# Bağlantı denemeleri arasındaki süre
retry_interval = 15m
# Bir mesajın en fazla ne kadar kuyrukta kalacağı
timeout_frozen_after = 7d
ignore_bounce_errors_after = 2d
Gerçek dünya senaryosu: Bir müşterimizin sunucusunda teslim edilemeyen mesajlar 4-5 günlük zaman aşımı beklentisiyle kuyrukta binlerceydi ve yeni mailler gecikiyordu. timeout_frozen_after = 2d yaparak ve ignore_bounce_errors_after = 1d ayarlayarak kuyruğu temizledik, sorun çözüldü.
DNS Optimizasyonu
Mail sunucularında en büyük darboğazlardan biri DNS çözümlemesidir. Her gelen ve giden mail için DNS sorguları yapılıyor. Bu sorguları hızlandırmak ciddi performans kazancı sağlıyor.
Yerel DNS Cache Kurulumu
# Unbound veya dnsmasq kurarak yerel DNS cache aktif edin
apt-get install unbound # Debian/Ubuntu
yum install unbound # CentOS/RHEL
# /etc/unbound/unbound.conf temel ayarları
server:
interface: 127.0.0.1
port: 53
cache-max-ttl: 86400
cache-min-ttl: 300
num-threads: 4
msg-cache-size: 64m
rrset-cache-size: 128m
# Unbound'u başlat
systemctl enable unbound
systemctl start unbound
Exim’i yerel DNS sunucusunu kullanacak şekilde yapılandırın:
# exim4.conf içinde
dns_servers = 127.0.0.1
# Alternatif olarak /etc/resolv.conf'ta
nameserver 127.0.0.1
DNS önbelleği olmadan çalışan bir sunucuda her mail teslimi 200-500ms DNS gecikmesiyle başlıyordu. Yerel cache kurulumundan sonra bu süre 1-5ms’ye düştü.
Veritabanı ve ACL Optimizasyonu
Exim’in ACL (Access Control List) kontrollerini verimli yazmak büyük önem taşıyor. Kötü yazılmış ACL kuralları her bağlantıda gereksiz işlem yapılmasına neden olur.
SQLite veya MySQL ile Verimli Lookup
# Kara liste ve beyaz liste sorguları için SQLite kullanımı
# /etc/exim4/exim4.conf ACL bölümü
acl_smtp_rcpt = acl_check_rcpt
begin acl
acl_check_rcpt:
# Önce beyaz listeyi kontrol et (hızlı lookup)
accept condition = ${lookup sqlite {/etc/exim/whitelist.db}
{SELECT count(*) FROM whitelist WHERE email='${quote_sqlite:$sender_address}'}
{${if eq{$value}{0}{no}{yes}}}}
# Kara liste kontrolü
deny condition = ${lookup sqlite {/etc/exim/blacklist.db}
{SELECT count(*) FROM blacklist WHERE ip='${quote_sqlite:$sender_host_address}'}
{${if eq{$value}{0}{no}{yes}}}}
message = Your IP is blacklisted
accept
ACL optimizasyonunda dikkat edilmesi gereken önemli noktalar:
- En hızlı kontrolleri önce yapın: IP bazlı kontroller domain bazlı kontrollerden hızlıdır
- DNSBL sorgularını sonlara bırakın: Her DNSBL sorgusu bir DNS lookup demektir
- Koşul kısaltma (short-circuit): Önceki kural kabul ettiyse sonraki kuralları çalıştırmayın
Paralel Mail Gönderimi ve Kuyruk Yönetimi
Exim’in kuyruk işleme mekanizmasını iyi anlamak optimizasyonun temelidir.
Kuyruk Runner Yapılandırması
# exim4.conf içinde
# Eş zamanlı kuyruk runner sayısı
queue_run_max = 5
# Kuyruk tarama sıklığı
# Her 15 dakikada bir otomatik tarama
queue_interval = 15m
# Belirli bir domain için maksimum eş zamanlı bağlantı
# transport_max_parallel büyük kitlesel gönderimler için önemli
Transport seviyesinde paralel bağlantıları yapılandırmak:
begin transports
remote_smtp:
driver = smtp
hosts_try_auth = *
# Aynı hedefe maksimum eş zamanlı bağlantı
multi_domain
# Bağlantı havuzu kullan
connection_max_messages = 500
# TLS ayarları
tls_verify_certificates = /etc/ssl/certs/ca-certificates.crt
# Bağlantı zaman aşımı
connect_timeout = 30s
connection_max_messages parametresi kritik! Bir SMTP bağlantısı kurulduktan sonra aynı bağlantı üzerinden kaç mail göndereceğinizi belirliyor. Varsayılan değer 1 ise her mail için yeni bağlantı kurulur, bu da ciddi gecikmelere yol açar. 500 gibi yüksek bir değer aynı hedefe çok sayıda mail gönderirken büyük performans artışı sağlar.
Manuel Kuyruk Yönetimi
Kuyrukta biriken mailleri yönetmek için pratik komutlar:
# Belirli bir domaindeki tüm mailleri yeniden dene
exim -Rrf example.com
# Dondurulmuş mailleri sil
exim -bp | grep frozen | awk '{print $3}' | xargs exim -Mrm
# 24 saatten eski mailleri listele
exiqgrep -o 86400 -i | xargs exim -Mrm
# Belirli bir alıcıya giden tüm mailleri bul ve sil
exiqgrep -r "[email protected]" -i | xargs exim -Mrm
# Kuyruk istatistikleri
exim -bp | exiqsumm
Gerçek dünya senaryosu: Bir spam atağından sonra kuyrukta 50.000 mail biriktiydi. Yukarıdaki exiqgrep komutlarıyla önce sahte alıcılara giden mailleri temizledik, sonra gerçek mailleri önceliklendirdik. İşlem 20 dakika sürdü, manuel yapılsaydı saatler alırdı.
Spool Dizini ve Dosya Sistemi Optimizasyonu
Exim her mail için spool dizininde dosyalar oluşturuyor. Bu dizinin performansı mail işleme hızını doğrudan etkiliyor.
# Spool dizinini kontrol et
ls -la /var/spool/exim4/
du -sh /var/spool/exim4/input/
# Spool dizini için ayrı partition veya tmpfs kullanımı
# /etc/fstab'a ekle (düşük trafikli test ortamları için)
tmpfs /var/spool/exim4/input tmpfs defaults,size=512m 0 0
# Üretim ortamı için ext4 mount seçenekleri
# /etc/fstab'da mevcut satırı düzenle
/dev/sdb1 /var/spool/exim4 ext4 defaults,noatime,nodiratime,data=writeback 0 2
noatime seçeneği özellikle önemli. Her dosyaya erişimde erişim zamanını güncellemek gereksiz disk yazma işlemi oluşturuyor. Bunu devre dışı bırakmak disk I/O’yu azaltıyor.
Spool dizini için bölümlü yapılandırma:
# exim4.conf içinde
# Hash direktifleri ile spool dizini bölümlemeleri
# Büyük hacimli sunucularda binlerce dosya tek dizinde olmamalı
spool_directory = /var/spool/exim4
# Exim otomatik olarak input/msglog alt dizinlerini kullanır
# Bu dizinleri ayrı disklere almak için symlink kullanabilirsiniz
mv /var/spool/exim4/input /mnt/fast-disk/exim-input
ln -s /mnt/fast-disk/exim-input /var/spool/exim4/input
TLS ve Şifreleme Optimizasyonu
Modern mail sunucularında TLS zorunlu hale geldi ama yanlış yapılandırılmış TLS ciddi performans maliyeti çıkarabiliyor.
# exim4.conf TLS yapılandırması
tls_advertise_hosts = *
tls_certificate = /etc/letsencrypt/live/mail.example.com/fullchain.pem
tls_privatekey = /etc/letsencrypt/live/mail.example.com/privkey.pem
# TLS session cache (bağlantı kurulum süresini azaltır)
tls_sessioncache_dbfile = /tmp/exim-tls-session-db
tls_sessioncache_timeout = 3600
# Güvenli ama performanslı cipher listesi
tls_require_ciphers = ECDHE+AESGCM:DHE+AESGCM:ECDHE+AES256:DHE+AES256:!aNULL:!MD5:!RC4
# OpenSSL için ek seçenekler
openssl_options = +no_sslv2 +no_sslv3 +no_compression
TLS session cache özellikle önemli. Aynı istemciden tekrarlayan bağlantılarda tam TLS el sıkışması yerine session resume kullanılıyor ve bu bağlantı kurulum süresini yarıya indiriyor.
Log Yönetimi ve İzleme
Performans optimizasyonu sürekli bir süreç. Düzenli izleme yapmadan neyin işe yaradığını bilemezsiniz.
#!/bin/bash
# exim-monitor.sh - Basit Exim izleme scripti
QUEUE_SIZE=$(exim -bpc)
FROZEN=$(exim -bp | grep frozen | wc -l)
ACTIVE_PROCS=$(ps aux | grep 'exim' | grep -v grep | wc -l)
LOG_FILE="/var/log/exim-perf.log"
echo "$(date '+%Y-%m-%d %H:%M:%S') | Queue: $QUEUE_SIZE | Frozen: $FROZEN | Procs: $ACTIVE_PROCS" >> $LOG_FILE
# Eşik değerleri aşıldığında uyarı gönder
if [ "$QUEUE_SIZE" -gt 1000 ]; then
echo "UYARI: Exim kuyruğu 1000 mesajı aştı! Mevcut: $QUEUE_SIZE" |
mail -s "Exim Kuyruk Uyarisi" [email protected]
fi
if [ "$FROZEN" -gt 100 ]; then
echo "UYARI: $FROZEN adet dondurulmuş mesaj var!" |
mail -s "Exim Frozen Mail Uyarisi" [email protected]
fi
Bu scripti crontab’a ekleyin:
# crontab -e ile ekle
*/5 * * * * /usr/local/bin/exim-monitor.sh
Log seviyesini performans izleme için düzenlemek:
# exim4.conf içinde
# Temel performans metriklerini logla
log_selector = +smtp_confirmation +smtp_connection +queue_time
+deliver_time +tls_peerdn -queue_run
# Log döndürme için logrotate yapılandırması
# /etc/logrotate.d/exim4
/var/log/exim4/mainlog {
daily
missingok
rotate 14
compress
delaycompress
notifempty
sharedscripts
postrotate
invoke-rc.d exim4 reload > /dev/null 2>&1 || true
endscript
}
Rate Limiting ve Anti-Spam Önlemleri Performans Dengeleri
Spam kontrolü önemli ama aşırı kontrol performansı düşürüyor. Doğru dengeyi bulmak kritik.
# Hız sınırlama ile kötü niyetli gönderimler azaltılır
# Aynı zamanda meşru trafiği de etkilememeli
acl_smtp_connect:
# IP başına dakikada 10'dan fazla bağlantıya izin verme
defer ratelimit = 10 / 1m / strict / per_conn
message = Cok fazla baglanti denemesi. Lutfen bekleyin.
log_message = Rate limited: $sender_host_address
# Greylisting için basit bir yapı
# Not: Greylisting meşru mailleri de geciktirir, dikkatli kullanın
defer message = Gecici hata, lutfen tekrar deneyin
!hosts = : @[] : /etc/exim4/whitelist_hosts
condition = ${if !def:acl_c_greylisted {yes}{no}}
accept
Greylisting hakkında önemli not: Greylisting spam’i azaltmak için etkili bir yöntem ama aynı zamanda meşru mailleri 5-30 dakika geciktiriyor. Yüksek trafikli ortamlarda beyaz listeye alınmış IP’ler için devre dışı bırakmak daha mantıklı.
Bellek ve Sistem Kaynakları Optimizasyonu
# /etc/default/exim4 - Exim başlatma parametreleri
QUEUERUNNER='combined'
QUEUEINTERVAL='15'
SMTPLISTENEROPTIONS=''
# Sistem limitlerini artır
# /etc/security/limits.conf
exim soft nofile 65536
exim hard nofile 65536
exim soft nproc 1024
exim hard nproc 2048
# Kernel parametreleri
# /etc/sysctl.conf
net.core.somaxconn = 1024
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_tw_reuse = 1
# Değişiklikleri uygula
sysctl -p
nofile limiti özellikle önemli. Exim her mail bağlantısı için dosya tanımlayıcı açıyor. Varsayılan limit 1024 olan sistemlerde yoğun trafikte “too many open files” hatası alırsınız.
Pratik Sorun Giderme Senaryoları
Senaryo 1: Sabah İşe Geldiniz, 5000 Mail Kuyrukta
# Durumu hızlıca değerlendir
exim -bp | exiqsumm
# Hangi domainlere teslim edilemiyor?
exim -bp | grep '<' | awk '{print $4}' | sort | uniq -c | sort -rn | head -20
# O domainlerin DNS sorununu kontrol et
dig MX problematic-domain.com
# Ulaşılamayan domainlere giden mailleri geçici olarak askıya al
exiqgrep -r "@problematic-domain.com" -i | xargs exim -Mf
# Kalan mailleri yeniden dene
exim -qff
Senaryo 2: CPU Kullanımı Sürekli Yüksek
# Hangi Exim süreci ne yapıyor?
ps aux --sort=-%cpu | grep exim | head -10
# Exim içinden aktif işlemleri gör
exiwhat
# ACL'de loop veya yavaş lookup var mı?
tail -f /var/log/exim4/mainlog | grep -E "ACL|lookup"
# Debug modunda test mesajı gönder
exim -d -v [email protected] <<< "Test mesaji"
Sonuç
Exim performans optimizasyonu tek seferlik yapılan bir iş değil, sürekli gözlem ve ince ayar gerektiren bir süreç. Burada anlattıklarımı öncelik sırasıyla özetleyeyim:
- Önce ölçün: Neyi optimize ettiğinizi bilmeden değişiklik yapmayın, yukarıdaki izleme scriptlerini kurun
- DNS cache: En hızlı kazanç buradan geliyor, ilk yapacağınız iş olsun
- Zaman aşımı değerleri: Varsayılanlar genellikle çok uzun, kendi trafiğinize göre ayarlayın
- Kuyruk yönetimi: Düzenli temizlik yapın, dondurulmuş mailleri biriktirmeyin
- Sistem limitleri: nofile ve nproc limitlerini artırın, kernel parametrelerini ayarlayın
- TLS session cache: Tekrarlayan bağlantılarda ciddi zaman kazandırıyor
- ACL optimizasyonu: Hızlı kontrolleri önce, yavaş DNS sorgularını sonra yapın
Tüm bu değişikliklerden sonra production ortamında test etmeyi unutmayın. Her değişikliği exim -bV ile syntax kontrolünden geçirin ve bir değişikliğin etkisini görmek için en az 24-48 saat bekleyin. Performans optimizasyonu sabır isteyen bir iş, ama doğru yapıldığında sonuçlar gerçekten tatmin edici oluyor.