Mail sunucusu yönetiminde en sık karşılaşılan ihtiyaçlardan biri, farklı alıcılar veya domain’ler için e-postaları farklı yollardan iletmektir. Postfix’in transport maps özelliği tam olarak bu iş için var. Bir e-postanın nereye, nasıl ve hangi protokol üzerinden iletileceğini granüler seviyede kontrol edebilirsiniz. Bu yazıda transport maps’i sıfırdan yapılandıracak, gerçek dünya senaryolarına bakacak ve olası sorunlarla nasıl başa çıkacağınızı anlatacağım.
Transport Maps Nedir ve Neden Kullanılır?
Postfix, bir e-postayı teslim etmeden önce bir dizi karar mekanizmasından geçirir. Bu mekanizmalardan biri de transport tablosudur. Transport maps sayesinde Postfix’e şunu söyleyebilirsiniz: “Bu domain’den gelen mailler şu SMTP sunucusuna gitsin”, “Şu kullanıcının maili yerel olarak teslim edilsin” ya da “Bu domain’e gelen mailler bir relay üzerinden geçsin.”
Bunu neden yapmak istersiniz? Birkaç somut senaryo düşünelim:
- Şirketinizin bir bölümü farklı bir mail sistemine taşındı, ama DNS henüz güncellenmedi. İlgili domain’in maillerini yeni sunucuya yönlendirmeniz gerekiyor.
- Bazı domainlerin maillerini bir spam filtre servisi üzerinden geçirmek istiyorsunuz.
- Test ortamınızdaki maillerin production’a karışmaması için belirli adresleri local delivery’e zorlamak istiyorsunuz.
- ISP’nizin 25. portu blokladığı için belirli mailler için 587 portunu kullanmanız gerekiyor.
Transport maps, tüm bu senaryolarda tek bir yapılandırma dosyasıyla çözüm sunar.
Transport Maps’in Temel Yapısı
Transport tablosu, sol tarafta eşleştirme deseni ve sağ tarafta transport tanımından oluşur. Format şöyle:
# /etc/postfix/transport
# Format: pattern transport:nexthop
example.com smtp:[mail.example.com]:25
test.local local:
criticalmail.org smtp:[relay.provider.com]:587
Sol taraftaki pattern şunlar olabilir:
- Tam domain adı:
example.com– Sadece bu domain için geçerli - Alt domain wildcard:
.example.com– example.com’un tüm subdomain’leri için - Tam e-posta adresi:
[email protected]– Sadece bu adres için - Boş string ya da catch-all: Diğer tüm eşleşmeler için
Sağ taraftaki transport:nexthop ifadesinde ise:
- smtp: Standart SMTP ile ilet
- lmtp: Local Mail Transfer Protocol
- local: Yerel teslim
- virtual: Virtual mailbox teslimi
- discard: Maili sessizce at
- error: Hata döndür ve maili reddet
- relay: Relay üzerinden gönder
Köşeli parantez kullanımı çok önemli bir detay: [mail.example.com] şeklinde köşeli parantez kullanırsanız Postfix MX kaydına bakmaz, doğrudan o host’a bağlanır. Köşeli parantez kullanmazsanız Postfix önce MX kaydını sorgular.
Temel Kurulum ve İlk Yapılandırma
Önce Postfix’in kurulu olduğundan emin olalım:
# Debian/Ubuntu
sudo apt update && sudo apt install postfix
# RHEL/CentOS/Rocky Linux
sudo dnf install postfix
# Postfix versiyonunu kontrol et
postconf mail_version
Transport dosyasını oluşturalım:
sudo nano /etc/postfix/transport
Basit bir yapılandırmayla başlayalım:
# /etc/postfix/transport
# Bu domain'in maillerini direkt SMTP ile ilet, MX'e bakma
example.com smtp:[mail.example.com]:25
# Bu domain'i relay üzerinden gönder
partner.org smtp:[smarthost.isp.com]:587
# Test domain'ini local teslime zorla
test.internal local:
# Bu adres için hata döndür
[email protected] error:Mailiniz kabul edilmedi
# Alt domainlerin hepsini bir relay'e yönlendir
.corporate.net smtp:[internal-relay.corp.net]:25
Dosyayı kaydettikten sonra Postfix’in okuyabileceği binary formata çevirmeniz gerekiyor:
sudo postmap /etc/postfix/transport
Bu komut /etc/postfix/transport.db dosyasını oluşturur. Her transport dosyasını değiştirdiğinizde bu komutu çalıştırmanız şart.
Şimdi main.cf dosyasına transport_maps direktifini ekleyin:
sudo postconf -e 'transport_maps = hash:/etc/postfix/transport'
Ya da doğrudan /etc/postfix/main.cf dosyasına ekleyebilirsiniz:
transport_maps = hash:/etc/postfix/transport
Son olarak Postfix’i yeniden yükleyin:
sudo systemctl reload postfix
Birden Fazla Transport Dosyası Kullanmak
Büyük ortamlarda tek bir dosyayı yönetmek karmaşık hale gelebilir. Postfix birden fazla transport dosyasını destekler:
# main.cf
transport_maps = hash:/etc/postfix/transport,
hash:/etc/postfix/transport-relay,
hash:/etc/postfix/transport-local
Bu durumda Postfix listedeki dosyaları sırayla arar ve ilk eşleşmeyi kullanır. Öncelik sıralaması önemlidir.
# /etc/postfix/transport-relay
# ISP relay gerektiren domainler
heavyfiles.com smtp:[relay.bigfiles.isp.com]:587
newsletter.net smtp:[bulk-relay.provider.com]:25
# /etc/postfix/transport-local
# Yerel teslim zorunlu domainler
internal.company local:
dev.company local:
Her dosyayı oluşturduktan sonra postmap’i çalıştırmayı unutmayın:
sudo postmap /etc/postfix/transport-relay
sudo postmap /etc/postfix/transport-local
sudo systemctl reload postfix
Gerçek Dünya Senaryosu 1: Mail Migrasyonu Sırasında Yönlendirme
Diyelim ki şirketiniz eski mail sunucusundan (oldmail.company.com) yeni bir platforma (newmail.company.com) geçiyor. DNS değişikliği yapılmadan önce yeni sunucuya trafik yönlendirmeniz gerekiyor.
# /etc/postfix/transport
# Yeni platforma taşınan departmanların mailleri
it.company.com smtp:[newmail.company.com]:25
hr.company.com smtp:[newmail.company.com]:25
finance.company.com smtp:[newmail.company.com]:25
# Henüz taşınmamış domainler eski sunucuya gitsin
legacy.company.com smtp:[oldmail.company.com]:25
# Genel şirket maili yeni sunucuya
company.com smtp:[newmail.company.com]:25
Bu senaryoda migration tamamlandıkça ilgili satırları tablodan kaldırabilir ve DNS’i güncellediğinizde transport kuralına gerek kalmaz.
Gerçek Dünya Senaryosu 2: TLS Zorunluluğu ile Güvenli İletim
Bazı ortamlarda belirli domainlere TLS şifrelemesi zorunlu tutularak mail gönderilmesi gerekir. Bu durumda transport maps ile birlikte smtp_tls_policy_maps veya özel bir transport tanımı kullanabilirsiniz.
master.cf dosyasına özel bir transport servisi ekleyin:
sudo nano /etc/postfix/master.cf
# /etc/postfix/master.cf
# TLS zorunlu SMTP transport
tlssmtp unix - - n - - smtp
-o smtp_tls_security_level=encrypt
-o smtp_tls_CAfile=/etc/ssl/certs/ca-certificates.crt
-o smtp_tls_note_starttls_offer=yes
Sonra transport dosyanızda bu servisi kullanın:
# /etc/postfix/transport
bank.com tlssmtp:[mail.bank.com]:25
secure-partner.org tlssmtp:[smtp.secure-partner.org]:587
Bu sayede belirtilen domainlere gönderilen mailler TLS olmadan iletilmez, bağlantı TLS’i desteklemiyorsa mail teslim edilmez ve kuyrukta bekler.
Gerçek Dünya Senaryosu 3: Null Delivery ve Test Ortamları
Test ortamlarında çok kritik bir ihtiyaç var: gerçek kullanıcılara test maili gitmesini engellemek. Transport maps ile bunu kolayca yapabilirsiniz:
# /etc/postfix/transport
# Tüm mailler discard edilsin (sessizce silinsin)
* discard:
# Sadece test adresleri local teslim alsın
test.internal local:
Ya da daha spesifik bir yaklaşım:
# /etc/postfix/transport
# Harici domainlere gidecek mailler local log'a düşsün
gmail.com discard:Test ortami - mail gonderilmedi
yahoo.com discard:Test ortami - mail gonderilmedi
hotmail.com discard:Test ortami - mail gonderilmedi
# Internal domainler normal gitsin
company.com smtp:[mail.company.com]:25
discard transport’u, Postfix’e maili başarıyla teslim etmiş gibi davranmasını söyler ama mail hiçbir yere gitmez. Gönderici başarı raporu alır. error transport’u ise göndericiye hata döndürür.
Gerçek Dünya Senaryosu 4: Yük Dağılımı için Birden Fazla Relay
Yüksek hacimli mail gönderimlerinde tek bir relay tıkanabilir. Transport maps ile farklı domainleri farklı relay’lere yönlendirebilirsiniz:
# /etc/postfix/transport
# Büyük hacimli newsletter domainleri relay1'e
newsletter-heavy.com smtp:[relay1.mailservice.com]:25
bulk-sender.net smtp:[relay1.mailservice.com]:25
# Normal iş maili relay2'ye
business-normal.com smtp:[relay2.mailservice.com]:587
# Kritik transactional mailler direkt gitsin
transactional.app smtp:[dedicated-relay.mailservice.com]:587
Transport Maps ile LDAP Entegrasyonu
Büyük kurumsal ortamlarda transport kararları LDAP’tan alınabilir. Bu, transport kurallarını merkezi olarak yönetmenizi sağlar:
# main.cf
transport_maps = ldap:/etc/postfix/transport-ldap.cf, hash:/etc/postfix/transport
# /etc/postfix/transport-ldap.cf
server_host = ldap.company.com
server_port = 389
bind = yes
bind_dn = cn=postfix,ou=services,dc=company,dc=com
bind_pw = gizlisifre
search_base = ou=domains,dc=company,dc=com
query_filter = (mailDomain=%s)
result_attribute = mailTransport
LDAP entegrasyonu ile bir domain eklediğinizde ya da transport kuralını değiştirdiğinizde Postfix’i reload etmenize gerek kalmaz.
Sorun Giderme ve Debug
Transport maps ile ilgili sorunları tespit etmek için birkaç araç vardır.
Önce transport tablosunda bir adresin nasıl çözümlendiğini test edin:
# Belirli bir domain için transport lookup yap
postmap -q example.com hash:/etc/postfix/transport
# E-posta adresi için lookup
postmap -q [email protected] hash:/etc/postfix/transport
# Eğer sonuç dönmezse eşleşme yok demektir
Mail kuyruğunu inceleyin:
# Kuyruktaki tüm mailler
mailq
# Ya da postqueue ile
postqueue -p
# Belirli bir maili zorla gönder
postqueue -i QUEUE_ID
# Tüm kuyruğu temizle (dikkatli!)
postsuper -d ALL
Postfix loglarına bakın:
# Gerçek zamanlı log takibi
sudo tail -f /var/log/mail.log
# Belirli bir domain için filtrele
sudo grep "example.com" /var/log/mail.log | tail -50
# Transport ile ilgili loglar
sudo grep "transport" /var/log/mail.log | tail -20
Postfix’in yapılandırmasını test edin:
# Sözdizimi hatalarını kontrol et
sudo postfix check
# Aktif yapılandırmayı göster
postconf transport_maps
# Tüm non-default değerleri listele
postconf -n
Verbose modda transport lookup debug edebilirsiniz:
# Debug seviyesini geçici olarak artır
sudo postconf -e 'debug_peer_list = example.com'
sudo postconf -e 'debug_peer_level = 3'
sudo systemctl reload postfix
# Logları takip et
sudo tail -f /var/log/mail.log
# Testi bitirince debug'ı kapat
sudo postconf -e 'debug_peer_list ='
sudo postconf -e 'debug_peer_level = 2'
sudo systemctl reload postfix
Yaygın Hatalar ve Çözümleri
postmap çalıştırmayı unutmak: Transport dosyasını değiştirip postmap çalıştırmazsanız değişiklikler geçerli olmaz. Bu en sık yapılan hatadır. Her değişiklikten sonra şu sırayı takip edin:
sudo postmap /etc/postfix/transport
sudo systemctl reload postfix
# Değişikliğin geçerli olup olmadığını doğrula
postmap -q "hedef-domain.com" hash:/etc/postfix/transport
Köşeli parantez kullanımı: smtp:mail.example.com:25 ile smtp:[mail.example.com]:25 arasındaki fark kritiktir. İlkinde Postfix MX kaydına bakar, ikincisinde doğrudan bağlanır. Çoğu durumda direkt host belirtmek istiyorsanız köşeli parantez kullanmalısınız.
Boşluk yerine tab kullanımı: Transport dosyalarında pattern ile transport arasında tab veya boşluk kullanabilirsiniz ama tutarlı olun. Karma kullanım bazen beklenmedik sorunlara yol açabilir.
Dosya izinleri: Transport dosyası ve db dosyası Postfix tarafından okunabilir olmalıdır:
sudo chown root:postfix /etc/postfix/transport
sudo chown root:postfix /etc/postfix/transport.db
sudo chmod 640 /etc/postfix/transport
sudo chmod 640 /etc/postfix/transport.db
Transport Maps ile Güvenlik Düşünceleri
Transport maps güçlü bir araçtır ama yanlış yapılandırılırsa open relay sorunu yaratabilir. Şunlara dikkat edin:
relay_domainsdirektifini sadece relay yapmanız gereken domainleri kapsayacak şekilde ayarlayın- Transport tablosunda wildcard kullanırken dikkatli olun
smtpd_relay_restrictionsvesmtpd_recipient_restrictionsdirektiflerini transport maps ile birlikte doğru yapılandırın
Güvenli bir temel yapılandırma örneği:
# /etc/postfix/main.cf
relay_domains = $mydestination, hash:/etc/postfix/relay_domains
transport_maps = hash:/etc/postfix/transport
smtpd_relay_restrictions = permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination
Değişiklikleri Otomatize Etmek
Production ortamında transport tablosunu elle yönetmek hataya açıktır. Basit bir script ile süreci otomatize edebilirsiniz:
#!/bin/bash
# /usr/local/bin/update-postfix-transport.sh
TRANSPORT_FILE="/etc/postfix/transport"
BACKUP_DIR="/etc/postfix/backups"
DATE=$(date +%Y%m%d_%H%M%S)
# Backup al
mkdir -p $BACKUP_DIR
cp $TRANSPORT_FILE $BACKUP_DIR/transport_$DATE
# Yeni kuralı ekle
echo "$1 $2" >> $TRANSPORT_FILE
# postmap çalıştır
postmap $TRANSPORT_FILE
# Postfix'i reload et
systemctl reload postfix
echo "Transport kuralı eklendi: $1 -> $2"
echo "Postfix reload edildi."
# Doğrulama
postmap -q "$1" hash:$TRANSPORT_FILE
Script’i çalıştırılabilir hale getirin:
sudo chmod +x /usr/local/bin/update-postfix-transport.sh
# Kullanımı
sudo /usr/local/bin/update-postfix-transport.sh "yenidomain.com" "smtp:[relay.example.com]:25"
Sonuç
Postfix transport maps, mail routing üzerinde tam kontrol sağlayan vazgeçilmez bir araçtır. İster migration süreçlerinde geçici yönlendirme yapın, ister kalıcı relay yapılandırmaları oluşturun, ister test ortamlarında mail trafiğini izole edin; transport maps her durumda esnek bir çözüm sunar.
Kritik noktalara bir daha bakalım: Transport dosyasını her değiştirdiğinizde postmap çalıştırmayı unutmayın. Köşeli parantez kullanımının MX sorgusu davranışını etkilediğini aklınızda tutun. Birden fazla transport dosyası kullanırken öncelik sırasına dikkat edin. Sorun yaşadığınızda postmap -q ile lookup testleri yapın ve mail.log’u detaylıca inceleyin.
Transport maps’i doğru yapılandırdıktan sonra mail routing sorunlarının büyük çoğunluğunu tek bir dosyadan yönetebilirsiniz. Bu, özellikle karmaşık kurumsal mail altyapılarında operasyonel yükü ciddi ölçüde azaltır.