Exim Routing ve Transport Yapılandırması

Mail sunucusu yönetiminin en karmaşık parçalarından biri, gelen ve giden postaların doğru şekilde yönlendirilmesi ve teslim edilmesidir. Exim’in routing ve transport mimarisi, bu işlemleri son derece esnek bir şekilde yapılandırmanıza olanak tanır. Ancak bu esneklik beraberinde öğrenme eğrisi de getiriyor. Bu yazıda Exim’in routing ve transport yapısını gerçek dünya senaryolarıyla birlikte ele alacağız.

Exim’in Routing ve Transport Mantığı

Exim, bir e-posta aldığında onu işlemek için belirli bir pipeline izler. Önce ACL (Access Control List) kuralları çalışır, ardından mesaj kuyruğa alınır ve router’lar devreye girer. Router’lar mesajın nereye gideceğini belirler. Transport ise mesajın oraya nasıl iletileceğini tanımlar.

Temel akış şu şekildedir:

  • Routers: Alıcı adresini analiz eder ve mesajın teslim yöntemini seçer
  • Transports: Seçilen yöntemle mesajı fiziksel olarak teslim eder
  • Retry rules: Teslim başarısız olursa ne zaman tekrar deneneceğini belirler
  • Rewrite rules: Adres dönüşüm kurallarını uygular

Exim konfigürasyon dosyası genellikle /etc/exim4/exim4.conf veya /etc/exim/exim.conf yolunda bulunur. cPanel/WHM ortamlarında ise /etc/exim.conf kullanılır.

Router Yapılandırması

Router’lar sırayla işlenir ve her router belirli koşullar altında devreye girer. Bir router eşleşme sağladığında ve başarıyla tamamlandığında, sonraki router’lara geçilmez (aksi açıkça belirtilmediği sürece).

Temel Router Yapısı

# /etc/exim4/exim4.conf içindeki örnek router tanımı
begin routers

localuser:
  driver = accept
  check_local_user
  transport = local_delivery
  cannot_route_message = Kullanici bulunamadi

dnslookup:
  driver = dnslookup
  domains = ! +local_domains
  transport = remote_smtp
  ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
  no_more

Bu yapıda iki temel router görüyoruz. localuser router’ı yerel sistem kullanıcılarına posta teslim eder. dnslookup ise harici domainler için DNS MX kaydı sorgulaması yapar.

Smarthost Router Yapılandırması

Kurumsal ortamlarda çok sık karşılaştığım senaryo şu: Tüm giden postaları bir relay sunucusundan göndermek istiyorsunuz. Bunu smarthost router ile yapabilirsiniz.

# Smarthost üzerinden yönlendirme
smarthost:
  driver = manualroute
  domains = ! +local_domains
  transport = remote_smtp_smarthost
  route_list = * mail.relay.example.com byname
  host_find_failed = defer
  same_domain_copy_routing = yes
  no_more

driver = manualroute: DNS sorgusu yapmadan belirtilen sunucuya yönlendir demektir. route_list: Hangi domain için hangi host kullanılacağını belirtir. * tüm domainler anlamına gelir.

Domain Bazlı Yönlendirme

Farklı domainleri farklı mail sunucularına yönlendirmek gerektiğinde bunu route_list içinde tanımlayabilirsiniz:

# Belirli domainleri özel sunuculara yönlendir
domain_specific_route:
  driver = manualroute
  domains = partner1.com : partner2.org : subsidiary.net
  transport = remote_smtp
  route_list = partner1.com mail.partner1.com ; 
               partner2.org smtp.partner2.org ; 
               subsidiary.net 192.168.10.5
  no_more

Burada noktalı virgül ayracı her domain-host çiftini birbirinden ayırır. Bu yapıyı özellikle hybrid cloud ortamlarında, bazı domainler şirket içi bazıları bulutta barındırıldığında kullanıyorum.

Koşullu Routing: Condition Direktifi

Router’lara koşul eklemek oldukça güçlü senaryolar oluşturmanızı sağlar:

# Sadece belirli saatlerde veya koşullarda çalışan router
business_hours_route:
  driver = dnslookup
  domains = ! +local_domains
  condition = ${if and{ 
    {>{$tod_hours}{8}} 
    {<{$tod_hours}{18}} 
    }{yes}{no}}
  transport = remote_smtp
  no_more

# VIP kullanıcılar için öncelikli router
vip_sender_route:
  driver = dnslookup
  domains = ! +local_domains
  senders = [email protected] : [email protected] : [email protected]
  transport = remote_smtp_priority
  no_more

Transport Yapılandırması

Transport, mesajın gerçekten nasıl teslim edileceğini tanımlar. En yaygın kullandığım transport türleri şunlardır:

  • smtp: Uzak sunucuya SMTP ile teslim
  • local_delivery: Lokal dosya sistemine teslim (mailbox)
  • pipe: Bir programa pipe ederek teslim
  • appendfile: Dosyaya ekleme

SMTP Transport Yapılandırması

begin transports

remote_smtp:
  driver = smtp
  message_size_limit = ${if > {$max_received_linelength}{998}{1}{0}}
  hosts_avoid_tls = <; 0.0.0.0/0
  
remote_smtp_smarthost:
  driver = smtp
  hosts = mail.relay.example.com
  port = 587
  hosts_require_auth = mail.relay.example.com
  hosts_require_tls = mail.relay.example.com
  tls_verify_certificates = /etc/ssl/certs/ca-certificates.crt

hosts_require_auth: Belirtilen host’a bağlanırken kimlik doğrulama zorunlu. hosts_require_tls: TLS şifreleme zorunlu. Bu iki direktifi production ortamlarda mutlaka kullanın.

TLS ile Güvenli SMTP Transport

# TLS zorunlu, modern cipher suite'lerle güvenli transport
remote_smtp_tls:
  driver = smtp
  port = 465
  hosts_require_tls = *
  tls_verify_certificates = /etc/ssl/certs/ca-certificates.crt
  tls_require_ciphers = ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:
                        ECDH+AES128:DH+AES:!aNULL:!MD5:!DSS
  tls_try_verify_hosts = *
  dnssec_request_domains = *

Özellikle finans sektörü müşterilerinde bu konfigürasyonu kullanıyorum. DNSSEC ve zorunlu TLS ile man-in-the-middle saldırılarına karşı ciddi bir koruma sağlanmış oluyor.

Local Delivery Transport

# Yerel kullanıcıya Maildir formatında teslim
local_delivery:
  driver = appendfile
  directory = $home/Maildir
  maildir_format = true
  delivery_date_add
  envelope_to_add
  return_path_add
  group = mail
  mode = 0660
  mode_fail_narrower = false

# Mbox formatında teslim (eski sistemler için)
local_mbox:
  driver = appendfile
  file = /var/mail/$local_part
  delivery_date_add
  envelope_to_add
  return_path_add
  group = mail
  mode = 0660

Maildir formatı dosya kilitleme sorunları yaşamadığı için modern sistemlerde kesinlikle tercih edilmeli. Özellikle yüksek trafikli sunucularda mbox’ın kilitleme sorunları can sıkıcı olabiliyor.

Pipe Transport: Filtreleme ve İşleme

Postaları işlemek için bir programa yönlendirmeniz gerektiğinde pipe transport kullanırsınız. SpamAssassin veya özel işleme scriptleri için idealdir:

# SpamAssassin ile spam kontrolü için pipe transport
spamcheck_transport:
  driver = pipe
  command = /usr/bin/spamc -u $local_part
  use_bsmtp = true
  transport_filter = /usr/sbin/exim4 -oMr spam-scanned -bS
  home_directory = /tmp
  current_directory = /tmp
  user = mail
  group = mail
  log_output = true
  return_fail_output = true
  message_prefix =
  message_suffix =

Gerçek Dünya Senaryoları

Senaryo 1: Çoklu Domain, Çoklu Backend

Bir hosting ortamında yüz farklı domainle çalışıyorsunuz. Bazı domainler kendi mail sunucularına sahip, bazıları sizin sunucunuzda barındırılıyor.

# Harici domain listesi için dosya bazlı router
external_domains_router:
  driver = manualroute
  domains = lsearch;/etc/exim4/external_domains.list
  transport = remote_smtp
  route_list = lsearch;/etc/exim4/domain_routes.list
  no_more

local_domains_router:
  driver = accept
  domains = lsearch;/etc/exim4/local_domains.list
  local_parts = lsearch;/etc/exim4/local_addresses.list
  transport = local_delivery

/etc/exim4/domain_routes.list dosyası şu şekilde görünür:

# domain_routes.list
domain1.com     mail.domain1.com
domain2.org     10.0.1.50
domain3.net     mx.provider.com byname

Bu yapıyı birden fazla ISP için mail yönetimi yapan bir ortamda kullandım. Yüzlerce domain’in routing’ini tek bir dosya üzerinden yönetmek büyük kolaylık sağlıyor.

Senaryo 2: Bounce Yönetimi ve DSN Konfigürasyonu

Delivery Status Notification’ları düzgün yönetmek, özellikle bulk mail gönderen ortamlarda kritiktir:

# Bounce mesajlarını özel adrese yönlendir
begin routers

bounce_handler:
  driver = accept
  senders = :
  local_parts = bounce-handler
  domains = +local_domains
  transport = bounce_processing_pipe
  
begin transports

bounce_processing_pipe:
  driver = pipe
  command = /usr/local/bin/process_bounce.py
  user = mailhandler
  group = mail
  log_output = true

Bu router, envelope from adresi boş olan (bounce mesajları) ve [email protected] adresine gelen mesajları yakalar ve işleme scriptine yönlendirir. E-posta pazarlama platformlarında suppression list yönetimi için hayat kurtarıcı bir yapı.

Senaryo 3: Rate Limiting ile Spam Kontrolü

Giden spam’i engellemek için router seviyesinde kontrol ekleyebilirsiniz:

# Kullanıcı bazlı rate limiting router
rate_limited_smtp:
  driver = dnslookup
  domains = ! +local_domains
  ratelimit = 100 / 1h / strict / $sender_address
  transport = remote_smtp
  no_more
# exim4.conf içinde global rate limit ayarı
RATELIMIT_PER_USER = 100
RATELIMIT_WINDOW = 1h

begin routers
outgoing_ratelimit:
  driver = dnslookup
  domains = ! +local_domains
  condition = ${if ratelimit{$sender_address}{RATELIMIT_PER_USER/RATELIMIT_WINDOW/strict/per_addr}{no}{yes}}
  transport = remote_smtp
  no_more

Retry Kuralları

Router ve transport yapısını tamamlamak için retry kurallarını da anlamak gerekiyor. Teslim başarısız olduğunda Exim ne yapacak?

begin retry

# Genel retry kuralı
# Format: address error retries
*   *   F,2h,15m; G,16h,1h,1.5; F,4d,6h

# Belirli bir domain için özel retry
gmail.com   *   F,1h,10m; F,8h,2h

# 4xx geçici hatalar için agresif retry
*   4??   F,30m,5m; F,4h,30m; F,24h,2h

# Bağlantı reddinde daha uzun bekle
*   connection_refused   F,30m,10m; F,4h,1h; F,5d,4h

Retry kurallarının formatını açıklayalım:

  • F,2h,15m: 2 saat boyunca 15 dakikada bir dene (Fixed interval)
  • G,16h,1h,1.5: 16 saat boyunca, 1 saatten başlayıp 1.5 çarpanıyla artan aralıklarla dene (Geometric)

Logging ve Debugging

Konfigürasyonunuzu test ederken ve sorun giderirken şu komutları sık kullanıyorum:

# Routing testini simüle et (mesaj göndermeden)
exim -bt [email protected]

# Detaylı routing debug çıktısı
exim -d+routing -bt [email protected]

# Belirli bir mesajın routing'ini test et
exim -d -bh 192.168.1.100

# Konfigürasyon dosyasını kontrol et
exim -bV

# Mail kuyruğunu görüntüle
exim -bp

# Belirli bir mesajı yeniden dene
exim -M message-id

# Transport log'larını canlı izle
tail -f /var/log/exim4/mainlog | grep -E "router|transport"
# Exim konfigürasyonunu syntax kontrolü ile test et
exim -C /etc/exim4/exim4.conf -bV

# Routing kararlarını detaylı gör
exim -d+all -bt [email protected] 2>&1 | grep -E "router|transport|deliver"

Adres Rewrite Kuralları

Transport öncesinde adresleri dönüştürmeniz gerekebilir. Örneğin, eski domain adından yeni domain adına geçiş yapıyorsunuz:

begin rewrite

# Eski domain'den yeni domain'e rewrite
*@eski-domain.com    ${local_part}@yeni-domain.com    FfrsTt

# Harici görünüm için rewrite (gönderen adresi düzeltme)
*@internal.company.com    ${local_part}@company.com    FfrsTt

# Postmaster adresini yönetici'ye yönlendir
postmaster@*    [email protected]    FfrsTt

Rewrite flag’lerinin anlamları:

  • F: From header’ını rewrite et
  • f: Envelope from’u rewrite et
  • T: To header’ını rewrite et
  • t: Envelope to’yu rewrite et
  • r: Reply-To header’ını rewrite et
  • s: Sender header’ını rewrite et

Performans Optimizasyonu

Yüksek trafikli ortamlarda transport konfigürasyonunda dikkat etmeniz gereken bazı parametreler var:

# Paralel bağlantı sayısını optimize et
remote_smtp:
  driver = smtp
  hosts_try_fastopen = *
  connection_max_messages = 500
  helo_name = mail.sirketiniz.com
  
# Bağlantı başına maksimum mesaj sayısı
smtp_accept_max = 150
smtp_accept_max_per_host = 10
smtp_accept_queue_per_connection = 10

# Queue runner ayarları
queue_run_max = 5
remote_max_parallel = 10
# Büyük sunucular için gelişmiş ayarlar
# /etc/exim4/exim4.conf içine ekleyin

# SMTP bağlantı zaman aşımı
smtp_connect_timeout = 30s
smtp_write_timeout = 5m

# Paralel delivery worker sayısı  
deliver_queue_load_max = 10
queue_smtp_domains = *

# DNS cache optimizasyonu
dns_again_means_nonexist = ! .
dns_check_names_pattern = ^(([-a-z0-9]+.)+[a-z]{2,}.?)$

Yaygın Sorunlar ve Çözümleri

Freeze olan mesajlar: Exim bazen mesajları freeze eder. Toplu unfreeze için:

# Tüm frozen mesajları unfreeze et
exiqgrep -z -i | xargs exim -Mt

# Freeze olan ve bounce olan mesajları sil
exiqgrep -z -i | xargs exim -Mrm

Relay denied hatası: Router’larınızda domain listesi yanlış yapılandırılmış olabilir. exim -bt komutuyla routing kararını test edin.

TLS handshake hataları: hosts_avoid_tls veya hosts_require_tls direktiflerini kontrol edin. Modern Exim versiyonlarında TLS 1.0/1.1 varsayılan olarak devre dışı bırakılmıştır.

Yüksek kuyruk derinliği: exim -bp | exiqsumm komutuyla kuyruk özetini görüntüleyin. Sorunlu domain’leri tespit edip geçici olarak transport_home_directory ve connection_max_messages değerlerini ayarlayın.

Sonuç

Exim’in routing ve transport mimarisi, ilk bakışta karmaşık görünse de mantığını kavradıktan sonra son derece güçlü ve esnek bir yapı sunuyor. Önemli noktalara bakacak olursak:

  • Router’lar sırayla işlenir, ilk eşleşen router kazanır. Router sıralamanıza dikkat edin
  • Transport konfigürasyonunda TLS ve kimlik doğrulamayı ihmal etmeyin
  • Retry kurallarını domain’in özelliğine göre özelleştirin
  • Logging ve exim -bt komutu sorun gidermede en değerli araçlarınız
  • Yüksek trafikli ortamlarda paralel bağlantı ve kuyruk ayarlarını mutlaka optimize edin

Production’da değişiklik yapmadan önce her zaman exim -C yeni_conf.conf -bV ile syntax kontrolü yapın ve exim -d+routing -bt [email protected] ile routing kararlarını simüle edin. Mail sunucusu yanlış yapılandırması hem iş sürekliliğini hem de domain reputation’ı doğrudan etkileyen bir konudur.

Yorum yapın