Birden Fazla Posta Sunucusunun Loglarını Merkezîleştirmek: rsyslog RELP ve journald ile Uçtan Uca Teslimat İzi
Dört ayrı /var/log/mail.log'a SSH'lamayı bırak. Postfix ve Dovecot loglarını rsyslog RELP + TLS ile tek bir toplayıcıda birleştir, Message-ID korelasyonuyla bir mektubun MX'ten alıcı MTA'nın 250/550 yanıtına kadar tüm yolculuğunu tek sorguda gör.
EvilMail Team31 Temmuz 202611 dk okuma
Bir alıcı "mailiniz gelmedi" dediğinde başlayan telaşı bilirsin: MX1'e SSH, grep boş; MX2'ye SSH, orada da yok; smarthost'a bak, queue-ID değişmiş, izi kaybettin. Üç ayrı /var/log/mail.log arasında sekmeler açık, timestamp'leri kafanda hizalamaya çalışıyorsun. Filon ikiden fazla sunucuya çıktığı anda bu yöntem çöker.
Çözüm romantik değil ama işe yarıyor: bütün posta sunucularının mail loglarını tek bir toplayıcıya taşımak, öyle ki bir Message-ID'yi tek yerde grepleyip mektubun MX'ten filtreye, smarthost'a ve alıcı MTA'nın verdiği 250/550 yanıtına kadar bütün yolculuğunu saniyeler içinde okuyabilesin. Bunu doğru yapmanın yolu UDP syslog değil — RELP + TLS. Nedenini ve tam config'i aşağıda anlatıyorum.
Sorun: filo büyüdükçe log dağınıklaşıyor
Tek bir mesaj, gönderim mimarinde en az üç sürece dokunur: alıcı MX'in smtpd'si, içerik filtresi (Rspamd/amavis), sonra smarthost'un smtp client'ı. Her relay hop'unda Postfix'in queue-ID'si değişir — MX1'de
Merkezî Mail Logları: rsyslog RELP + journald ile Tek Zaman Çizelgesi — EvilMail Blog
A1B2C3D4
olan mesaj smarthost'ta
E5F6A7B8
olur. Değişmeyen tek şey
Message-ID
'dir. Host başına
grep
yaptığında bu ipi her sunucuda yeniden yakalamak zorunda kalırsın; tek bir kayıp hop bütün izi koparır.
Merkezîleştirmenin somut kazanımları:
Uçtan uca teslimat izi: Tek sorguyla mesajın hangi sunucuda takıldığını, greylisting'e mi yoksa RBL reddine mi çarptığını görürsün.
Sunucu çökse bile log durur: Disk dolduğunda ya da makine kernel panic verdiğinde, o ana kadarki loglar zaten toplayıcıda olur. Olay sonrası analizde en çok ihtiyaç duyduğun loglar tam da kaybolan makinededir.
Uyumluluk ve saklama: KVKK/GDPR kapsamında envelope from/to ve istemci IP'si kişisel veridir; saklama süresini tek yerden politikaya bağlamak, her makinede ayrı logrotate ayarı kovalamaktan iyidir.
Desen görünürlüğü: Bounce oranları, greylisting gecikmeleri ve RBL red sebepleri ancak tüm filodan gelen log aynı yerde toplanınca desen olarak ortaya çıkar. Tek sunucudaki gürültü, filo ölçeğinde anlamlı bir sinyaldir.
Mimari: rsyslog RELP mi, journal-remote mı?
İki geçerli yol var. Karar, filonun homojenliğine ve hedefine bağlı.
Yol 1 — rsyslog RELP: Her mail sunucusunda rsyslog client (omrelp) → merkezî rsyslog server (imrelp), TLS ile. Postfix zaten syslog'a yazdığı için ekosistem burada oturmuştur. Heterojen filo (Debian + AlmaLinux karışık) ve Graylog/Loki hedefi varsa doğru seçim budur.
Yol 2 — systemd-journal-remote:systemd-journal-upload → systemd-journal-remote, HTTPS 19532 üzerinden. Binary journal'ı ve _SYSTEMD_UNIT, PRIORITY gibi structured field'ları korur. Saf systemd filosu işletiyorsan ve toplayıcıda journalctl ile sorgulamak istiyorsan mantıklı.
Protokol seçiminde asıl mesele taşıma katmanı. UDP (514) yük altında sessizce paket düşürür — logun en kritik olduğu an (sunucu boğulmuşken) tam da logu kaybettiğin andır. Plain TCP (`imtcp`) kernel buffer'a yazıldıktan sonra iletim başarısız olursa fark etmez; uygulama seviyesinde onay yoktur. RELP ise uygulama seviyesinde ACK + retransmit yapar: toplayıcı satırı diske yazdığını teyit etmeden client onu kuyruktan silmez. Mail loglaması için pazarlık konusu değil.
Toplayıcıyı kurmak (merkezî rsyslog server)
Debian/Ubuntu'da apt install rsyslog-relp rsyslog-gnutls, RHEL/AlmaLinux'ta dnf install rsyslog-relp rsyslog-gnutls. TLS için sunucu sertifikası, private key ve client'ları imzalayan bir CA'ya ihtiyacın var.
imrelp modülünü TLS ile dinlet ve gelen logu host + program bazında ayrı dosyaya yaz:
tls.authMode="name" + permittedPeer kritik: yalnızca sertifika CN'i (ya da SAN'ı) listede olan sunucular log gönderebilir. maxDataSize tek bir devasa satırın diski patlatmasını engeller. Firewall'da 2514/tcp'yi yalnızca mail sunucularının IP'lerine aç:
bash
iptables -A INPUT -p tcp --dport 2514 -s 203.0.113.10 -j ACCEPT
iptables -A INPUT -p tcp --dport 2514 -j DROP
logrotate ile disk kontrolü — tarih bazlı değil host bazlı dizin döndürüyoruz:
En sık yapılan hata: logu yalnızca toplayıcıya göndermek. Toplayıcı bakıma girdiğinde ya da ağ koptuğunda o sunucuda hiçbir iz kalmaz. Çift yaz şart — hem lokal /var/log/mail.log, hem omrelp:
rsyslog
# /etc/rsyslog.d/60-relp-forward.conf
module(load="omrelp")
# 1) Lokal kopya her zaman kalsın
mail.* /var/log/mail.log
# 2) Toplayıcıya disk-assisted queue ile ilet
action(type="omrelp"
target="logserver.evilmail.pro"
port="2514"
tls="on"
tls.caCert="/etc/rsyslog.d/tls/ca.pem"
tls.myCert="/etc/rsyslog.d/tls/mx1-cert.pem"
tls.myPrivKey="/etc/rsyslog.d/tls/mx1-key.pem"
tls.authMode="name"
tls.permittedPeer=["logserver.evilmail.pro"]
queue.type="LinkedList"
queue.filename="relp_fwd"
queue.maxDiskSpace="1g"
queue.saveOnShutdown="on"
action.resumeRetryCount="-1")
Buradaki disk-assisted queue ayarları dayanıklılığın bel kemiğidir. queue.type="LinkedList" + queue.filename toplayıcı erişilemezken logu diskte biriktirir; action.resumeRetryCount="-1" sonsuza kadar yeniden dener; queue.saveOnShutdown="on" reboot'ta kuyruğu kaybetmez. Bu satırlar olmadan toplayıcı 30 saniye düşse o pencerelik log buharlaşır. queue.maxDiskSpace="1g" ise kuyruğun kendi diskini doldurmasını sınırlar.
journald köprüsü: gerektiğinde
Postfix hâlâ syslog'a yazdığı için yukarıdaki akış onu doğal olarak yakalar. Ama Dovecot ve Rspamd systemd unit olarak çalışır ve _SYSTEMD_UNIT, PRIORITY, SYSLOG_IDENTIFIER gibi structured field'lar üretir. Bu alanları kaybetmeden taşımanın iki yolu var:
A) Aynı RELP hattına köprüle. rsyslog'un imjournal modülüyle journal'ı okuyup mevcut omrelp action'ına besle. Tek boru hattı, tek toplayıcı, tek sorgu yüzeyi — heterojen filoda tercih edilen yöntem:
B) Saf journal zinciri.systemd-journal-upload ile binary journal'ı doğrudan systemd-journal-remote'a (HTTPS 19532) gönder. Structured field'lar sonuna kadar korunur ve toplayıcıda journalctl -D /var/log/journal/remote ile sorgularsın. Filon baştan sona systemd ise ve rsyslog'a hiç dokunmak istemiyorsan bu yol daha temizdir. Karışık filoda ise iki farklı sorgu arayüzü (dosya + journal) yönetmek zorunda kalırsın; genelde A daha az sürtünme yaratır.
Korelasyon: dağınık logu tek zaman çizelgesine dizmek
Asıl değer burada. Toplayıcıda bütün loglar var ama onları anlamlı bir zaman çizelgesine dizmen gerekir. Anahtar satır postfix/cleanup:
Bu satır bir hop'un queue-ID'sini sabit Message-ID'ye bağlar — altın anahtar. Uçtan uca izi çıkarmak için önce Message-ID'den queue-ID'leri bul, sonra her queue-ID'nin bütün satırlarını zaman sırasına diz:
bash
# 1) Message-ID hangi sunucuda hangi queue-ID almış?
grep -r 'message-id=<[email protected]>' /var/log/remote/*/postfix.log
# 2) Bulunan queue-ID'lerin tüm hop satırlarını zaman sırasına diz
grep -h -E ' (A1B2C3D4|E5F6A7B8):' /var/log/remote/*/postfix.log | sort -k1,3
Bounce olduysa satır status=bounced ve bir DSN kodu taşır: 5.1.1 alıcı yok, 4.2.2 kota dolu (geçici), 5.7.1 policy reddi. Bu kodu doğru okumak, "mailimiz gitmiyor" şikayetinin gerçekte greylisting mi (4.x, tekrar denenecek) yoksa kalıcı red mi (5.x) olduğunu anında söyler.
Bir uyarı: NTP/chrony şart. Sunucular arası saat kayması 1 saniyeyi geçerse birleşik zaman çizelgesi yalan söyler — smarthost'un satırı MX'in satırından önce görünür ve sebep-sonuç ters döner. chronyc tracking ile her makinede senkronu doğrula.
Saklama, boyut ve gürültü kontrolü
Orta yoğunluklu bir MX günde kabaca 200–500 MB ham mail log üretir. Verbose açıksa bu 3–5 katına çıkar; prod'da Dovecot mail_debug=yes ve auth_verbose=yes kesinlikle kapalı olsun — bir teslimat sorununu ararken geçici açar, işin bitince geri kaparsın. Rspamd log seviyesini de info'da tut, debug'da değil. imrelp tarafında rate limit koyarak bir sunucunun log fırtınasının toplayıcıyı boğmasını engelle.
Neyin asla loglanmaması gerektiği en az bunlar kadar önemli: parola, tam mesaj gövdesi, SASL kimlik doğrulama sırrı. SASL kullanıcı adı (kim gönderdi) meşru bir alandır ama şifre değildir. Envelope from/to ve istemci IP'si KVKK/GDPR kapsamında kişisel veridir; saklama süresini (yukarıda 90 gün) hukuk politikana bağla, keyfi seçme.
Downstream'e (Loki/Graylog) taşıyacaksan toplayıcıdan şu label'ları çıkar: host, program, queue_id, message_id, dsn, client_ip. Bu altı label'la her teslimat sorusunu tek bir sorguya çevirirsin.
Doğrulama ve pratik kontrol listesi
Kurduktan sonra gerçekten çalıştığını kanıtla. Bir test maili gönder, Message-ID'sini not al, toplayıcıda ara ve her üç sunucunun da satırının geldiğini gör. Sonra dayanıklılığı test et: toplayıcıyı durdur, birkaç mail geçir, toplayıcıyı geri aç ve client'ın disk kuyruğunu flush ettiğini doğrula.
bash
# TLS handshake gerçekten kuruluyor mu?
tcpdump -ni eth0 port 2514
# Toplayıcı kapalıyken client kuyruğu birikiyor mu?
ls -lh /var/spool/rsyslog/relp_fwd*
Devreye almadan önceki kontrol listesi:
TLS doğrulama açık — tls.authMode="name" + permittedPeer her iki tarafta da tanımlı.
Çift yaz açık — istemcide lokal /var/log/mail.log action'ı korunuyor.
Disk-assisted queue açık — queue.filename, queue.saveOnShutdown="on", action.resumeRetryCount="-1".
chrony senkron — chronyc tracking tüm sunucularda <1 sn offset.
Firewall daraltılmış — 2514/tcp yalnızca mail sunucu IP'lerine açık, gerisi DROP.
Bu düzeni bir kez kurduğunda, "mail gelmedi" telefonu artık dört sekmelik bir SSH turnesi değil, tek bir grep'lik iş olur — ve deliverability desenleri (RBL redleri, greylisting gecikmeleri, bounce kümeleri) filo genelinde ilk kez görünür hale gelir.