Integrasi LDAP dengan postfix dan dovecot
Integrasi Postfix + Dovecot + OpenLDAP
Virtual users via LDAP — Debian 12 · LKS ITNSA Ready
✓ Tested & Working
result_attribute = mail
Virtual Users
Konsep & Arsitektur
Tiga komponen bekerja bersama: Postfix terima dan route email, Dovecot simpan email dan handle login, OpenLDAP jadi database sentral user. Semua user bersifat virtual — tidak punya akun Linux di /etc/passwd.
Email Masuk
→
Postfix
→ query LDAP (validasi field mail) →
Dovecot LDA
→
/home/budi@example.com/Maildir/
Login IMAP → Dovecot → auth LDAP → buka /home/budi@example.com/Maildir/
Login IMAP → Dovecot → auth LDAP → buka /home/budi@example.com/Maildir/
Penyebab error umum: Domain
example.com ada di mydestination sekaligus di virtual_mailbox_domains. Postfix akan anggap email ke domain itu sebagai local delivery → cari user di /etc/passwd → unknown user. Solusi: domain hanya boleh ada di salah satu.Bagian 1 — Postfix
1 /etc/postfix/main.cf
/etc/postfix/main.cf
# FQDN server — Fully Qualified Domain Name # Digunakan sebagai identitas server saat handshake SMTP myhostname = mail.example.com # mydestination = daftar domain yang di-deliver sebagai LOCAL user (/etc/passwd) # KRUSIAL: example.com TIDAK boleh ada di sini # Kalau ada, Postfix cari budi di /etc/passwd → unknown user error mydestination = $myhostname, localhost.$mydomain, localhost # Domain yang di-handle sebagai virtual mailbox # Dipisah dari mydestination agar Postfix tahu ini virtual, bukan local virtual_mailbox_domains = example.com # Postfix tanya ke LDAP: "apakah user tujuan email ini ada?" # Format "ldap:/path/ke/file.cf" = konfigurasi query ada di file terpisah virtual_mailbox_maps = ldap:/etc/postfix/ldap-users.cf # Setelah email divalidasi, teruskan ke Dovecot untuk disimpan secara fisik # "dovecot" merujuk ke nama transport yang didefinisikan di master.cf virtual_transport = dovecot # SASL — Simple Authentication and Security Layer # Postfix delegasikan proses verifikasi password ke Dovecot via unix socket # smtpd_sasl_type = dovecot → pakai implementasi SASL milik Dovecot, bukan Cyrus smtpd_sasl_type = dovecot # Path socket relatif terhadap /var/spool/postfix/ # WAJIB relatif di Debian karena Postfix berjalan dalam chroot # Chroot = Postfix terisolasi, root filesystem-nya adalah /var/spool/postfix/ # Kalau pakai absolute path, socket tidak ditemukan smtpd_sasl_path = private/auth # Aktifkan SASL authentication di Postfix smtpd_sasl_auth_enable = yes # noanonymous = tolak siapa pun yang coba auth tanpa identity smtpd_sasl_security_options = noanonymous # Aturan relay: # permit_mynetworks = izinkan dari jaringan lokal # permit_sasl_authenticated = izinkan user yang sudah login via SASL # reject_unauth_destination = tolak semua yang lain smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
2 /etc/postfix/ldap-users.cf
File ini dibuat manual (tidak ada by default). Isi dan strukturnya bisa dilihat via man 5 ldap_table.
/etc/postfix/ldap-users.cf
# Alamat server LDAP server_host = ldap://127.0.0.1 # Titik awal pencarian di pohon direktori LDAP # "dc=example,dc=com" = representasi domain example.com dalam format LDAP search_base = dc=example,dc=com # Bind = login ke LDAP server sebelum bisa query # bind_dn = akun service khusus Postfix, bukan akun email biasa bind = yes bind_dn = cn=postfix,dc=example,dc=com bind_pw = passwordPostfix # Query filter = kondisi pencarian di LDAP # %s = alamat email LENGKAP tujuan (budi@example.com) # Berbeda dari %u yang hanya username pendek # Cari entry LDAP yang field "mail"-nya cocok dengan tujuan email query_filter = (mail=%s) # Field LDAP yang dikembalikan sebagai hasil query # Nilai field "mail" = budi@example.com result_attribute = mail # Format path mailbox yang dikirim ke Postfix # %s diganti dengan nilai result_attribute (budi@example.com) # Hasil akhir: "budi@example.com/" # Postfix akan deliver email ke path ini secara langsung result_format = %s/Maildir domain = example.com
Karena
virtual_mailbox_base dihapus, Postfix pakai nilai dari result_format sebagai path absolut. Pastikan path /home/budi@example.com/ benar-benar ada dan sudah di-chown ke mail:mail.3 /etc/postfix/master.cf
/etc/postfix/master.cf — tambahkan di baris paling bawah
# Mendefinisikan transport bernama "dovecot" # Ini yang dipanggil oleh "virtual_transport = dovecot" di main.cf # # "pipe" = Postfix pipe email ke program eksternal (dovecot-lda) # flags=DRhu: # D = tambahkan header Delivered-To # R = tambahkan Return-Path header # h = hostname case-insensitive # u = username case-insensitive # user=mail:mail = jalankan dovecot-lda sebagai user mail, group mail # Format user:group — eksplisit agar tidak ambiguous # # -f ${sender} = envelope sender (From address) # -d ${recipient} = tujuan pengiriman dalam format FULL address (budi@example.com) # Dovecot LDA pakai nilai ini untuk userdb lookup # Harus full address agar sinkron dengan user_filter (mail=%u) di Dovecot dovecot unix - n n - - pipe flags=DRhu user=mail:mail argv=/usr/lib/dovecot/dovecot-lda -f ${sender} -d ${recipient}
Bagian 2 — Dovecot
4 /etc/dovecot/conf.d/10-auth.conf
10-auth.conf — edit baris berikut
# Nonaktifkan autentikasi sistem lokal (/etc/passwd) # Tanda "!" di depan = disable/exclude file ini # Semua user ada di LDAP, bukan di Linux #!include auth-system.conf.ext # Aktifkan autentikasi LDAP !include auth-ldap.conf.ext # Mekanisme auth yang diizinkan # plain = kirim password as-is (aman kalau pakai TLS) # login = kompatibilitas dengan email client lama (Outlook, dll) auth_mechanisms = plain login
5 /etc/dovecot/conf.d/auth-ldap.conf.ext
auth-ldap.conf.ext
# passdb = database untuk verifikasi password # driver = ldap → cek password ke OpenLDAP # args → tunjuk ke file detail koneksi LDAP passdb { driver = ldap args = /etc/dovecot/dovecot-ldap.conf.ext } # userdb = database untuk informasi filesystem user (home dir, UID, GID) # driver = static → semua virtual user dipetakan ke nilai yang sama (statis) # # uid=8, gid=8 = paksa semua virtual user pakai identitas sistem "mail" # UID 8 = user "mail" di Debian — user sistem khusus untuk proses email # Ini mencegah permission denied saat Dovecot akses folder # # home=/home/%u → %u = full address (budi@example.com) # Hasil: /home/budi@example.com — sinkron dengan path di ldap-users.cf userdb { driver = static args = uid=8 gid=8 home=/home/%u }
6 /etc/dovecot/dovecot-ldap.conf.ext
dovecot-ldap.conf.ext
# Alamat server LDAP hosts = 127.0.0.1 # DN dan password untuk bind (login) ke LDAP # Akun service khusus Dovecot — bukan user email dn = cn=dovecot,dc=example,dc=com dnpass = passwordDovecot # Titik awal pencarian di pohon direktori LDAP base = dc=example,dc=com # Filter untuk mencari entry user saat login # %u = full address (budi@example.com) karena -d ${recipient} di master.cf # Cari entry LDAP yang field "mail"-nya cocok user_filter = (mail=%u) # Mapping field LDAP → atribut Dovecot untuk verifikasi password # userPassword (field LDAP) → password (yang dicek Dovecot) pass_attrs = userPassword=password # Paksa UID dan GID ke 8 terlepas dari nilai di LDAP # "=" di depan = override, bukan mapping dari field LDAP # Mencegah permission denied saat akses Maildir user_attrs = =uid=8,=gid=8 # Filter untuk verifikasi password — compound filter (dua kondisi) # & = AND: kedua kondisi harus terpenuhi # objectClass=inetOrgPerson = entry harus bertipe inetOrgPerson # mail=%u = field mail harus cocok dengan user yang login # Lebih aman dari filter tunggal karena mencegah false positive pass_filter = (&(objectClass=inetOrgPerson)(mail=%u))
7 /etc/dovecot/conf.d/10-mail.conf
10-mail.conf
# Format dan lokasi penyimpanan email tiap user # maildir: = format Maildir (satu file per email, recommended) # /home/%u = path fisik, %u = budi@example.com # Hasil: /home/budi@example.com/ — sinkron dengan result_format di ldap-users.cf # TIDAK ada /Maildir di belakang — konsisten dengan result_format = %s/Maildir mail_location = maildir:/home/%u/Maildir # Dovecot default tolak user dengan UID di bawah 1000 (dianggap akun sistem) # Diubah ke 8 agar user "mail" (UID 8) bisa dipakai sebagai virtual user # Tanpa ini: Dovecot throw "user not found" meski LDAP auth sudah sukses first_valid_uid = 8
8 /etc/dovecot/conf.d/10-master.conf
10-master.conf — tambahkan/edit dua blok ini
# Buka socket agar Postfix bisa minta validasi SASL ke Dovecot # Path relatif terhadap /var/spool/postfix/ (chroot Postfix) # mode = 0660 → hanya owner dan group yang bisa akses # user = postfix, group = mail → Postfix bisa tulis, Dovecot bisa baca service auth { unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = mail } } # Fix permission untuk stats-writer socket # Dovecot LDA berjalan sebagai user "mail" (UID 8) # Tanpa ini: LDA gagal akses stats-writer → error saat delivery # user = dovecot → owner socket adalah proses dovecot utama # group = mail → proses LDA (yang jalan sebagai mail) bisa akses service stats { unix_listener stats-writer { mode = 0660 user = dovecot group = mail } }
Bagian 3 — Persiapan Maildir
Virtual user tidak punya home directory otomatis — harus dibuat manual. Nama folder pakai full address karena %u = budi@example.com.
bash
# Buat struktur Maildir untuk tiap user # Format Maildir wajib punya tiga subfolder: new, cur, tmp # new/ = email baru belum dibaca # cur/ = email yang sudah pernah dibuka (dipindah IMAP client dari new/) # tmp/ = email sedang dalam proses ditulis (atomic write, prevent corruption) # Tanda "" di sekeliling path karena ada karakter @ di nama folder mkdir -p "/home/budi@example.com/"{new,cur,tmp} mkdir -p "/home/boaz@example.com/"{new,cur,tmp} # Ubah kepemilikan ke user "mail" (UID 8) dan group "mail" (GID 8) # -R = recursive, berlaku ke semua subfolder # Harus sinkron dengan uid=8 gid=8 di auth-ldap.conf.ext chown -R mail:mail "/home/budi@example.com" "/home/boaz@example.com" # Set permission 700 = hanya owner (mail) yang bisa akses # Mencegah user atau proses lain membaca isi mailbox chmod -R 700 "/home/budi@example.com" "/home/boaz@example.com"
Nama folder mengandung karakter
@ — selalu gunakan tanda kutip " saat referensi path ini di command line, contoh: ls "/home/budi@example.com/"Bagian 4 — Verifikasi
bash
# Restart kedua service systemctl restart postfix dovecot systemctl status postfix dovecot # Test LDAP query dari Postfix # Harus return: budi@example.com/ postmap -q budi@example.com ldap:/etc/postfix/ldap-users.cf # Cek konfigurasi Dovecot — tidak boleh ada error dovecot -n # Monitor log real-time saat kirim email test tail -f /var/log/mail.log # Test SMTP manual via telnet telnet localhost 25 EHLO test MAIL FROM:<test@example.com> RCPT TO:<budi@example.com> DATA Subject: Test LDAP . QUIT
Summary Perubahan dari Versi Sebelumnya
| File | Parameter | Lama → Baru | Alasan |
|---|---|---|---|
main.cf |
virtual_mailbox_base | /home → dihapus | Path sudah absolut dari result_format |
ldap-users.cf |
query_filter | (uid=%u) → (mail=%s) | Query pakai field mail, %s = full address |
ldap-users.cf |
result_format | %s/Maildir/ → %s/ | Sinkron dengan mail_location tanpa /Maildir |
master.cf |
argv dovecot pipe | -d ${user}@${nexthop} → -d ${recipient} | Lebih simpel, langsung pakai full envelope recipient |
master.cf |
user flag | user=mail → user=mail:mail | Eksplisit user dan group |
10-mail.conf |
mail_location | maildir:/home/%u/Maildir → maildir:/home/%u/Maildir | Sinkron dengan result_format = %s/Maildir |
dovecot-ldap.conf.ext |
user_filter | (uid=%n) → (mail=%u) | %u = full address sekarang, cari by field mail |
dovecot-ldap.conf.ext |
pass_filter | (objectClass=inetOrgPerson) → (&(objectClass=...)(mail=%u)) | Compound filter, lebih presisi |
10-master.conf |
service stats | tidak ada → stats-writer fix | Fix permission Dovecot LDA ke stats socket |
| Maildir path | nama folder | /home/budi/ → /home/budi@example.com/ | Sinkron dengan %u = full address |
Checklist kompetisi: mydestination tidak mengandung domain email · postmap -q return path yang benar · Maildir dibuat dengan nama domain lengkap · chown dan chmod sudah dijalankan · stats-writer fix ada di 10-master.conf
Keren bang ...
ReplyDelete