Postfix ile tek sunucuda onlarca alan adı: virtual_mailbox_domains'i doğru kurmak
Çoğu "çoklu alan adı" rehberi Postfix'in üç alan sınıfını birbirine karıştırdığı için sessizce "User unknown" ya da mail loop üretir. Tek Postfix örneğinde onlarca alanı gerçek posta kutularıyla barındırmanın doğru yolunu, alan sınıflandırma mantığından MySQL arka ucuna kadar operasyonel bir rehberle kuruyoruz.
EvilMail Team9 Temmuz 202614 dk okuma
Tek bir VPS'te evilmail.pro ve evilmail.cloud'un yanına 20 müşteri alanı daha koymak istiyorsun. Her yeni alan için ayrı bir Postfix örneği açmak saçma; hepsi aynı 25/587 portunu, aynı kuyruğu, aynı TLS sertifikasını paylaşabilir. Sorun teknik değil, taksonomik: Postfix bir alanı hangi listede gördüğüne göre bambaşka davranır. Kırık yapılandırmaların çoğu alanı yanlış kovaya koymaktan doğar; sonuç da ya "User unknown" ya da mesajın kendine geri dönmesidir.
Bu yazı üç şeyi netleştiriyor: Postfix'in alanları hangi sınıflara ayırdığı, her alan için posta kutusu haritalarını ölçeklenebilir biçimde nasıl yöneteceğin ve dosya tabanlı başlangıçtan mysql: arka ucuna geçiş. Tümü 10+ alanlık üretim ölçeği düşünülerek.
Postfix bir alanı nasıl sınıflandırır (ve neden hayati)
Postfix'te bir teslim alanı üç sınıftan yalnızca birine ait olabilir:
`mydestination` — yerel teslim. Adres /etc/passwd + /etc/aliases üzerinden local(8)
Postfix Çoklu Alan Adı Barındırma: virtual_mailbox_domains Rehberi — EvilMail Blog
transportuyla teslim edilir. Geleneksel Unix kullanıcıları içindir; sanal barındırmada burada yalnızca
localhost
kalmalı.
`virtual_alias_domains` — sadece yönlendirme. Bu alanın kendi posta kutusu yoktur; her adres virtual_alias_maps ile başka bir hedefe genişletilir. [email protected] → [email protected] gibi.
`virtual_mailbox_domains` — gerçek posta kutuları. Adres virtual_mailbox_maps ile bir maildir yoluna eşlenir ve virtual_transport (tipik olarak Dovecot LMTP) üzerinden teslim edilir. Çoklu barındırmanın omurgası budur.
Altın kural: bir alan aynı anda birden fazla sınıfta olamaz. Olursa teslim belirsizleşir. En sık tuzak şudur: mydestination içinde varsayılan olarak $mydomain durur, sen de aynı alanı virtual_mailbox_domains'e eklersin. Artık iki liste de o alanı sahipleniyor; hangisinin kazanacağı yapılandırma sırasına kalır ve bir gün sessizce bounce üretir.
Teslim akışı şöyle işler: smtpd gelen RCPT TO'yu alır, trivial-rewrite adresi çözümler, ardından alanın hangi listede olduğuna bakılır. virtual_alias_maps her zaman önce genişletme yapar; yani bir alias varsa adres daha mailbox sorgusuna gelmeden yeniden yazılır.
Sınıflandırmayı elle denetlemenin en hızlı yolu üç listeyi yan yana yazdırmaktır:
virtual_uid_maps/virtual_gid_maps'in static:5000 olması, tüm maildir'lerin 5000:5000 sahipliğinde olacağı anlamına gelir; bu Dovecot'un vmail kullanıcısıyla eşleşmeli. virtual_mailbox_limit = 0 posta kutusu başına boyut sınırını kaldırır; kotayı Dovecot tarafında yönetmek daha esnektir.
/etc/postfix/vmailbox dosyasının formatı basit, ama bir detay ölümcül:
Sağdaki yolun sonundaki eğik çizgi maildir demektir. Çizgiyi unutursan Postfix bunu tek bir mbox dosyası olarak yorumlar; Dovecot maildir beklerken teslimatlar sessizce kaybolur. virtual_mailbox_base ile birleşince gerçek yol /var/mail/vhosts/evilmail.pro/info/ olur.
Alias dosyası /etc/postfix/virtual da rol adreslerini ve catch-all'ı taşır:
@evilmail.pro catch-all'dır: eşleşmeyen tüm adresleri info@ kutusuna düşürür. Catch-all'a dikkat — spam mıknatısıdır, ama posta kutusu olmayan bir alanı toplarken pratiktir.
Her düzenlemeden sonra hash veritabanını yeniden derlemek zorunludur, yoksa Postfix eski .db'yi okur:
Aslında hash tablosunu güncellerken tek gereken postmap'tir — Postfix .db'yi her sorguda taze okur — ama main.cf'i değiştirdiysen reload şart; restart gereksiz. Değişikliği canlı sorguyla doğrula:
Çıktı boşsa adres maps'te yok demektir ve o adrese gelen her mesaj "User unknown in virtual mailbox table" ile bounce olur.
Her alan için ayrı posta kutusu haritası yönetmek
Tek bir dev vmailbox dosyası 20 alanda çöker. Birleştirme çatışmaları çıkar, bir müşteriye kendi dosyasını düzenleme yetkisi devredemezsin ve her küçük değişiklik tüm dosyayı riske atar. Postfix'in az bilinen bir özelliği bunu çözer: virtual_mailbox_mapsbirden çok tabloyu sırayla sorgular.
Artık her alanın kendi dosyası var. Postfix bir adres için tabloları soldan sağa gezer, ilk eşleşmede durur. Yeni alan eklemek bir provisioning adımına indirgenir:
virtual_alias_maps'i ayrı tut. Alias'lar rol adresleri (postmaster@, abuse@) ve catch-all için mantıksal olarak farklı bir katmandır; posta kutusu haritalarıyla karıştırmak teşhisi zorlaştırır. Ve tüm bu postmap kaynak dosyalarını git ile versiyonla — .db üretilmiştir, ama düz metin kaynaklar yedeklenebilen ve denetlenebilen tek gerçektir.
MySQL arka ucu: 10+ alanda gerçek ölçek
Dosya tabanlı yaklaşımın tavanı bellidir: her değişiklikte postmap + reload, ve yapılandırmanın kontrol panelinle senkron olmaması. 10 alanı geçtiğinde mysql: arka ucuna geç. Kazanç net: reload gerektirmez (Postfix her sorguda DB'yi okur) ve aynı tablolar hem Postfix'in routing'i hem Dovecot'un auth/teslimi tarafından okunur — tek doğruluk kaynağı.
evilmail'in mailserver DB'si tam olarak bu şemayı kullanır:
mysql-virtual-mailbox-domains.cf bir alanın barındırılıp barındırılmadığını yanıtlar:
ini
user = mailuser
password = your_strong_db_password
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'
Diğer iki dosya aynı bağlantı bloğunu paylaşır, sadece query değişir:
sql
-- mysql-virtual-mailbox-maps.cf
query = SELECT 1 FROM virtual_users WHERE email='%s'
-- mysql-virtual-alias-maps.cf
query = SELECT destination FROM virtual_aliases WHERE source='%s'
%s Postfix'in aradığı adres/alanla değiştirilir. Mailbox-domains ve mailbox-maps sorgularının SELECT 1 döndürmesi yeterli — Postfix için anlamlı olan tek şey "kayıt var mı yok mu" bilgisidir. Alias sorgusu ise gerçek destination değerini döndürmeli, çünkü adres o hedefe yeniden yazılacak.
.cf dosyalarının izinlerini kısıtla; DB parolası içerirler:
Sorgu doğrulaması dosya tabanlıyla aynı mantıkta, sadece hedef değişir:
bash
postmap -q evilmail.pro mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
# 1 → alan barındırılıyor
postmap -q [email protected] mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
# 1 → posta kutusu var
Dovecot'u aynı DB'ye bağlamak, kullanıcı bir kez virtual_users'a eklendiğinde hem Postfix'in onu teslim alanı olarak tanıması hem de kullanıcının IMAP ile giriş yapabilmesi demektir. Bu yüzden virtual_transport için Postfix'in yerleşik virtual teslimini değil Dovecot LMTP'yi tercih et: sieve filtreleri, kota uygulaması ve indeksleme ancak teslimi Dovecot yaptığında çalışır.
Kırılma noktaları ve teşhis
Log'daki hata mesajı alanın yanlış kovada olduğunu doğrudan söyler. Eşleştirme tablosu:
`User unknown in virtual mailbox table` — alan virtual_mailbox_domains'te doğru, ama kullanıcı virtual_mailbox_maps'te yok. postmap -q ile maps'i sorgula; DB arka ucundaysa virtual_users'a kayıt ekle.
`User unknown in local recipient table` — alan yanlışlıkla mydestination'da. postconf mydestination çalıştır, alanı (veya $mydomain'i) oradan çıkar.
`mail for X loops back to myself` — alan hiçbir listede değil. Postfix onu ne yerel ne sanal sayıyor, MX kendini gösterdiği için mesaj geri döner. Alanı virtual_mailbox_domains'e ekle.
Çakışma uyarısı (do not list domain X in ... and ...) — aynı alan iki sınıfta. Postfix bunu bazen başlangıçta uyarır, bazen sessizce yanlış davranır.
Canlı teşhis için mail log'unu teslim durumuna göre süz:
postfix/lmtp satırları Dovecot'a teslim edildiğini, postfix/virtual satırları yerleşik sanal teslimi gösterir. LMTP kullanıyorsan virtual satırı görmemelisin — görüyorsan virtual_transport yanlış. reject_unlisted_recipient'i smtpd_recipient_restrictions içinde tutmak, var olmayan alıcıları SMTP aşamasında reddettirir; böylece kuyruğa girip sonra bounce üretmezler ve backscatter'dan kaçınırsın.
Üretim kontrol listesi
postconf mydestination virtual_mailbox_domains virtual_alias_domains çıktısında kesişim boş mu — üç listede aynı alan yok.
Her barındırılan alan için postmaster@ ve abuse@ rol adresleri tanımlı mı (RFC 2142 gereği ve deliverability için).
Yeni alan provisioning'inin dört adımı tamam mı: DNS MX 10 mail.evilmail.pro + PTR (203.0.113.10 → mail.evilmail.pro) + postmap/reload (ya da DB kaydı) + gerçek test mesajı.
message_size_limit (örn. 50MB) ve virtual_mailbox_limit ölçeğinle uyumlu mu; kotayı Dovecot mu Postfix mi yönetiyor netleşti mi.
SPF/DKIM/DMARC her alan için ayrı mı: v=spf1 mx -all, her alana kendi default._domainkey.<domain> DKIM anahtarı (ortak anahtar deliverability'yi böler), v=DMARC1; p=quarantine; rua=.... Tek PTR tüm alanlarca paylaşılır — HELO banner'ı mail.evilmail.pro olduğu için sorun değil, ama FCrDNS'in tutması şart.
Yedek: mailserver DB dump'ı veya postmap kaynak dosyaları git'te versiyonlanıyor mu — .db'ler türetilmiştir, düz metin/DB gerçektir.
3+ alanda hâlâ hash: mi kullanıyorsun — mysql:'ye geç; reload'suz güncelleme ve panelle senkron kazanırsın.