Dovecot ile Sanal Kullanıcı Yönetimi

Mail sunucusu yönetiminde en sık karşılaşılan ihtiyaçlardan biri, sistem kullanıcısı oluşturmadan e-posta hesabı açabilmektir. Bir müşteri için 50 farklı domain’de yüzlerce mailbox yönetiyorsanız, her biri için Linux kullanıcısı açmak hem güvenlik açısından hem de yönetim kolaylığı açısından ciddi sorunlar doğurur. İşte tam bu noktada Dovecot’un sanal kullanıcı (virtual user) sistemi devreye girer. Bu yazıda Dovecot ile sanal kullanıcı yönetimini, gerçek dünya senaryolarıyla birlikte adım adım ele alacağız.

Sanal Kullanıcı Nedir, Neden Kullanılır?

Dovecot varsayılan kurulumunda sistem kullanıcılarını okur. Yani /etc/passwd dosyasındaki kullanıcılar üzerinden kimlik doğrulaması yapar. Bu yaklaşım küçük, tek domainli kurulumlar için işe yarasa da ölçeklenebilir değildir.

Sanal kullanıcı yaklaşımında ise e-posta hesapları:

  • Sistemde gerçek bir Linux kullanıcısına karşılık gelmez
  • Bir veritabanında (MySQL, PostgreSQL, LDAP) veya düz metin dosyalarında saklanır
  • Tüm sanal kullanıcılar dosya sisteminde tek bir sistem kullanıcısının (genellikle vmail) altında çalışır
  • Domain bazlı izolasyon çok daha kolay sağlanır

Bu yaklaşım özellikle şu senaryolarda şarttır:

  • Hosting sağlayıcıları: Onlarca farklı müşteri için mail yönetimi
  • Çoklu domain kurulumları: [email protected] ve [email protected] aynı sunucuda, birbirinden izole
  • Otomatik hesap oluşturma: API veya panel üzerinden dinamik hesap açma
  • Güvenlik gereksinimleri: Mail kullanıcılarının sunucuya SSH erişimi olmamalı

Temel Kavramlar ve Mimari

Dovecot sanal kullanıcı sisteminde üç temel bileşen birbirleriyle konuşur:

Passdb (Password Database): Kimlik doğrulamadan sorumludur. Kullanıcı adı ve parola burada doğrulanır.

Userdb (User Database): Başarılı kimlik doğrulamasının ardından kullanıcının home dizini, UID/GID bilgileri ve özel ayarları buradan alınır.

Auth mekanizması: PLAIN, LOGIN, CRAM-MD5 gibi protokollerle istemci ile sunucu arasındaki iletişimi yönetir.

Tüm bu bileşenler dosya bazlı (passwd-file, shadow), SQL tabanlı (MySQL, PostgreSQL) veya LDAP tabanlı olabilir. Bu yazıda hem dosya bazlı hem de MySQL tabanlı yapılandırmayı göstereceğiz.

Gerekli Hazırlıklar

Önce vmail sistem kullanıcısını ve dizin yapısını oluşturalım. Bu kullanıcı tüm sanal kullanıcıların mailbox’larına sahip olacak:

# vmail grubu ve kullanıcısı oluştur
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/mail/vmail -s /sbin/nologin

# Mail dizinini oluştur ve sahipliği ver
mkdir -p /var/mail/vmail
chown -R vmail:vmail /var/mail/vmail
chmod 770 /var/mail/vmail

# Dovecot'un paketini kontrol et
dovecot --version

Dovecot kurulu değilse:

# Debian/Ubuntu
apt install dovecot-core dovecot-imapd dovecot-pop3d dovecot-mysql

# RHEL/CentOS/Rocky Linux
dnf install dovecot dovecot-mysql

Dosya Tabanlı Sanal Kullanıcı Yapılandırması

Küçük kurulumlar için dosya tabanlı yaklaşım oldukça pratiktir. Yönetimi basittir, veritabanı bağımlılığı yoktur, 50-100 kullanıcıya kadar rahatlıkla kullanılabilir.

passwd-file Formatı

Dovecot, kendi passwd-file formatını kullanır. Bu format standart /etc/passwd dosyasına benzer:

# /etc/dovecot/users dosyasını oluştur
# Format: kullanıcı:parola:uid:gid:gecos:home:shell:extra_fields

cat > /etc/dovecot/users << 'EOF'
[email protected]:{PLAIN}gizliparola123:5000:5000::/var/mail/vmail/firma.com/ali::userdb_quota_rule=*:storage=1G
[email protected]:{SHA512-CRYPT}$6$rounds=5000$...hashedpassword...:5000:5000::/var/mail/vmail/firma.com/ayse::
[email protected]:{PLAIN}parola456:5000:5000::/var/mail/vmail/baska.com/info::
EOF

# Dosya izinlerini ayarla (sadece dovecot okusun)
chown root:dovecot /etc/dovecot/users
chmod 640 /etc/dovecot/users

Parola hash’i üretmek için:

# SHA512-CRYPT hash üret
doveadm pw -s SHA512-CRYPT -p "kullanicinin_parolasi"

# Çıktı örneği:
# {SHA512-CRYPT}$6$rounds=5000$tuz$hashedpassword...

# Bcrypt kullanmak istersen (daha güvenli)
doveadm pw -s BLF-CRYPT -p "kullanicinin_parolasi"

Dovecot Yapılandırması: auth-passwdfile.conf.ext

# /etc/dovecot/conf.d/auth-passwdfile.conf.ext
passdb {
  driver = passwd-file
  args = scheme=SHA512-CRYPT /etc/dovecot/users
}

userdb {
  driver = passwd-file
  args = /etc/dovecot/users
  default_fields = uid=vmail gid=vmail home=/var/mail/vmail/%d/%n
}

10-auth.conf dosyasında ilgili include satırını aktifleştir:

# /etc/dovecot/conf.d/10-auth.conf içinde şu satırı bul ve # işaretini kaldır:
!include auth-passwdfile.conf.ext

# Sistem kullanıcısı auth'u devre dışı bırak (eğer açıksa)
# !include auth-system.conf.ext  # Bu satırı yorum satırına al

MySQL Tabanlı Sanal Kullanıcı Yapılandırması

Büyük ölçekli kurulumlar için MySQL/MariaDB çok daha uygun. Özellikle Postfix Admin, ISPConfig veya kendi yazdığınız bir panelle entegrasyon yapıyorsanız bu yaklaşım şart.

Veritabanı Şeması

mysql -u root -p << 'EOF'
CREATE DATABASE mailserver CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'mailuser'@'localhost' IDENTIFIED BY 'mailpassword';
GRANT SELECT ON mailserver.* TO 'mailuser'@'localhost';
FLUSH PRIVILEGES;

USE mailserver;

CREATE TABLE virtual_domains (
  id INT NOT NULL AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  PRIMARY KEY (id)
);

CREATE TABLE virtual_users (
  id INT NOT NULL AUTO_INCREMENT,
  domain_id INT NOT NULL,
  email VARCHAR(100) NOT NULL UNIQUE,
  password VARCHAR(150) NOT NULL,
  quota_bytes BIGINT DEFAULT 1073741824,
  active TINYINT DEFAULT 1,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
);

-- Örnek veri ekle
INSERT INTO virtual_domains (name) VALUES ('firma.com'), ('baska.com');
INSERT INTO virtual_users (domain_id, email, password) VALUES
  (1, '[email protected]', CONCAT('{SHA512-CRYPT}', ENCRYPT('parola123', CONCAT('$6$', MD5(RAND()))))),
  (1, '[email protected]', '{PLAIN}testparola'),
  (2, '[email protected]', '{PLAIN}parola456');
EOF

Dovecot MySQL Yapılandırması

# /etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=mailpassword

# Parolaları hash olarak sakla, Dovecot karşılaştırsın
default_pass_scheme = SHA512-CRYPT

# Kimlik doğrulama sorgusu
password_query = 
  SELECT email AS username, password 
  FROM virtual_users 
  WHERE email = '%u' AND active = 1

# Kullanıcı bilgileri sorgusu
user_query = 
  SELECT 
    'vmail' AS uid, 
    'vmail' AS gid, 
    CONCAT('/var/mail/vmail/', SUBSTRING_INDEX(email,'@',-1), '/', SUBSTRING_INDEX(email,'@',1)) AS home, 
    CONCAT('*:bytes=', quota_bytes) AS quota_rule 
  FROM virtual_users 
  WHERE email = '%u' AND active = 1

# Dovecot iterate (doveadm user listesi için)
iterate_query = SELECT email AS username FROM virtual_users WHERE active = 1

auth-sql.conf.ext dosyasını yapılandır:

# /etc/dovecot/conf.d/auth-sql.conf.ext
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

userdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

Mailbox Dizin Yapısı

10-mail.conf dosyasında mailbox konumunu belirle:

# /etc/dovecot/conf.d/10-mail.conf
mail_home = /var/mail/vmail/%d/%n
mail_location = maildir:/var/mail/vmail/%d/%n/Maildir

# Namespace tanımla
namespace inbox {
  inbox = yes
  separator = /
  mailbox Drafts {
    auto = subscribe
    special_use = Drafts
  }
  mailbox Junk {
    auto = subscribe
    special_use = Junk
  }
  mailbox Sent {
    auto = subscribe
    special_use = Sent
  }
  mailbox Trash {
    auto = subscribe
    special_use = Trash
  }
}

Buradaki değişkenler:

  • %d: Domain kısmı (firma.com)
  • %n: Kullanıcı adı kısmı (ali)
  • %u: Tam e-posta adresi ([email protected])

Kota Yönetimi

Sanal kullanıcılar için kota yönetimi 10-quota.conf üzerinden yapılır:

# /etc/dovecot/conf.d/90-quota.conf
plugin {
  quota = maildir:User quota
  quota_rule = *:storage=1G
  # Kullanıcı bazlı kota SQL'den geliyorsa quota_rule userdb'den override eder

  # Uyarı eşikleri
  quota_warning = storage=90%% quota-warning 90 %u
  quota_warning2 = storage=75%% quota-warning 75 %u
}

# Kota aşım bildirimi için script
service quota-warning {
  executable = script /usr/local/bin/quota-warning.sh
  user = dovecot
  unix_listener quota-warning {
    user = vmail
  }
}

Kota uyarı scripti:

#!/bin/bash
# /usr/local/bin/quota-warning.sh

PERCENT=$1
USER=$2

cat << EOF | sendmail -f [email protected] "$USER"
From: Mail Sistemi <[email protected]>
To: $USER
Subject: Posta kutunuz %$PERCENT dolu

Merhaba,

Posta kutunuz kapasitesinin %$PERCENT'ini kullanmaktadir.
Lutfen eski e-postalari silmeyi veya arsivlemeyi dusunun.

Sistem Yoneticisi
EOF

Kullanıcı Yönetimi: doveadm Araçları

doveadm komutu günlük yönetim işleri için vazgeçilmez. Kullanıcı listesi, mailbox işlemleri, kimlik doğrulama testi gibi her şeyi buradan yapabilirsin:

# Tüm sanal kullanıcıları listele
doveadm user '*'

# Belirli bir kullanıcının ayarlarını görüntüle
doveadm user [email protected]

# Kullanıcı kimlik doğrulamasını test et
doveadm auth test [email protected] "parolası"

# Kullanıcının kota durumunu göster
doveadm quota get -u [email protected]

# Kullanıcının aktif bağlantılarını listele
doveadm who -u [email protected]

# Bir kullanıcının tüm bağlantılarını kes
doveadm kick [email protected]

# Mailbox istatistikleri
doveadm mailbox list -u [email protected]

# Yeni mailbox klasörü oluştur
doveadm mailbox create -u [email protected] Arsiv/2024

# Kullanıcının maildir'ini fiziksel olarak oluştur
doveadm mailbox subscribe -u [email protected] INBOX

Gerçek Dünya Senaryosu: Toplu Kullanıcı Migrasyonu

Bir müşteriyi eski mail sunucusundan taşıdığını düşün. Mevcut kullanıcıları toplu olarak MySQL’e import etmen gerekiyor:

#!/bin/bash
# /usr/local/bin/import-mailaccounts.sh
# CSV formatı: email,password,quota_mb

MYSQL_CMD="mysql -u root -p'rootpass' mailserver"
CSV_FILE="$1"

while IFS=',' read -r email password quota_mb; do
  # Boş satırları ve başlık satırını atla
  [[ -z "$email" || "$email" == "email" ]] && continue

  domain=$(echo "$email" | cut -d'@' -f2)
  quota_bytes=$((quota_mb * 1048576))

  # Domain yoksa ekle
  domain_id=$(echo "SELECT id FROM virtual_domains WHERE name='$domain';" | $MYSQL_CMD -sN)
  if [[ -z "$domain_id" ]]; then
    echo "INSERT INTO virtual_domains (name) VALUES ('$domain');" | $MYSQL_CMD
    domain_id=$(echo "SELECT LAST_INSERT_ID();" | $MYSQL_CMD -sN)
    echo "Domain eklendi: $domain (ID: $domain_id)"
  fi

  # Parolayı hash'le
  hashed=$(doveadm pw -s SHA512-CRYPT -p "$password")

  # Kullanıcıyı ekle (varsa atla)
  echo "INSERT IGNORE INTO virtual_users (domain_id, email, password, quota_bytes) 
    VALUES ($domain_id, '$email', '$hashed', $quota_bytes);" | $MYSQL_CMD

  # Maildir'i oluştur
  mail_path="/var/mail/vmail/$domain/$(echo "$email" | cut -d'@' -f1)"
  mkdir -p "$mail_path/Maildir"
  chown -R vmail:vmail "$mail_path"

  echo "Kullanıcı eklendi: $email (Kota: ${quota_mb}MB)"

done < "$CSV_FILE"

echo "Import tamamlandı."

Kullanımı:

# CSV dosyası örneği (users.csv):
# [email protected],parola123,1024
# [email protected],parola456,2048

chmod +x /usr/local/bin/import-mailaccounts.sh
/usr/local/bin/import-mailaccounts.sh users.csv

Güvenlik Hususları

Sanal kullanıcı sisteminde dikkat edilmesi gereken güvenlik noktaları:

SSL/TLS zorunluluğu: Kimlik doğrulama bilgileri açık metin gitmemeli. 10-ssl.conf dosyasında:

ssl = required
ssl_cert = </etc/letsencrypt/live/mail.firma.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.firma.com/privkey.pem
ssl_min_protocol = TLSv1.2
ssl_cipher_list = EECDH+AESGCM:EDH+AESGCM

Brute-force koruması: 10-auth.conf dosyasında:

# Başarısız deneme limiti
auth_failure_delay = 2s
# 10 başarısız denemede 60 saniyelik bekleme (fail2ban ile birlikte kullan)

MySQL bağlantısı için izinler: Mail kullanıcısına sadece SELECT yetkisi ver, asla INSERT/UPDATE/DELETE verme. Veritabanı işlemleri her zaman ayrı bir admin kullanıcısı üzerinden yapılmalı.

Dosya izinleri: dovecot-sql.conf.ext içinde veritabanı parolası var. Bu dosyanın izinlerini mutlaka kısıtla:

chown root:dovecot /etc/dovecot/dovecot-sql.conf.ext
chmod 640 /etc/dovecot/dovecot-sql.conf.ext

Hata Ayıklama ve Log Yönetimi

Bir şeyler ters gittiğinde debug modunu aç:

# Geçici olarak debug loglamayı aç
# /etc/dovecot/conf.d/10-logging.conf
auth_debug = yes
auth_debug_passwords = yes  # SADECE test ortamında!
auth_verbose = yes
mail_debug = yes

# Dovecot'u yeniden başlat
systemctl restart dovecot

# Logları takip et
journalctl -u dovecot -f

# veya
tail -f /var/log/mail.log | grep dovecot

# Kimlik doğrulama sorunlarını manuel test et
doveadm auth test [email protected] yanlisparola
doveadm auth test [email protected] dogruparola

# SQL sorgunuzu test edin
doveadm -Dv auth test [email protected] dogruparola 2>&1 | grep -E "(sql|query|SELECT)"

Sık karşılaşılan sorunlar ve çözümleri:

  • “User not found”: user_query SQL’inin döndürdüğü sonucu doveadm -Dv auth test ile kontrol et
  • “Permission denied” hataları: /var/mail/vmail dizininin sahipliğini ve vmail kullanıcı UID/GID’ini doğrula
  • “Wrong authentication credentials”: default_pass_scheme ile veritabanındaki hash formatının uyuştuğundan emin ol
  • SSL hatası: Sertifika dosyalarının dovecot tarafından okunabilir olduğunu kontrol et (chown root:dovecot /etc/letsencrypt/live/...)

Postfix Entegrasyonu

Dovecot sanal kullanıcıları genellikle Postfix ile birlikte çalışır. Postfix’in de aynı MySQL tablosunu kullanması gerekir. main.cf dosyasına eklenecek temel ayarlar:

# /etc/postfix/main.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_transport = lmtp:unix:private/dovecot-lmtp

# /etc/postfix/mysql-virtual-mailbox-domains.cf
user = mailuser
password = mailpassword
hosts = 127.0.0.1
dbname = mailserver
query = SELECT name FROM virtual_domains WHERE name='%s'

Dovecot LMTP servisini aktifleştir:

# /etc/dovecot/conf.d/20-lmtp.conf
protocol lmtp {
  postmaster_address = [email protected]
  mail_plugins = $mail_plugins sieve
}

# master.cf'de LMTP socket tanımla
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}

Sonuç

Dovecot ile sanal kullanıcı yönetimi, küçük bir dosya tabanlı kurulumdan başlayıp yüz binlerce kullanıcıyı barındıran büyük ölçekli bir mail altyapısına kadar genişletilebilir. Temel prensipler her durumda aynı: fiziksel sistem kullanıcılarından bağımsız bir kimlik doğrulama katmanı, tek bir vmail kullanıcısı altında izole mailbox’lar ve merkezi yönetim için bir veritabanı.

Küçük bir hosting ortamı için dosya tabanlı passwd-file yeterli olacaktır. Ancak dinamik hesap yönetimi, panel entegrasyonu veya yoğun kullanım söz konusuysa MySQL/PostgreSQL ile SQL tabanlı yapıya geçmek şart. Üstüne bir de Postfix + Dovecot + Rspamd üçlüsünü düzgün kurguladığında, ticari mail sistemlerine taş çıkartan, tamamen kontrol altında bir altyapıya sahip olursun.

Sonraki adım olarak Sieve filtrelerini ve ManageSieve servisini incelemeyi öneririm. Sanal kullanıcıların kendi filtrelerini webmail üzerinden yönetebilmesi, destek yükünü ciddi ölçüde azaltır.

Yorum yapın