DEV Community

Cover image for Integrating a local mail server into my LDAP lab
Shoban Chiddarth
Shoban Chiddarth

Posted on

Integrating a local mail server into my LDAP lab

Introduction

This is the second stage of my OpenLDAP home lab. I set up a mail server to work with existing LDAP configuration.

Pre-Requisites

  1. VM Intercommunication setup
  2. Pi-hole
  3. Local TLS for HTTPS
  4. OpenLDAP Home Lab

Setup Process

Mail Server Install

In the existing setup, I cloned another debian server VM, gave it static IP 192.168.57.7, set its hostname to mail-server.acme.internal and then added the DNS record in Pi-hole. Then I went ahead and installed the required packages for postfix and dovecot to work with LDAP.

sudo apt install -y postfix postfix-ldap dovecot-core dovecot-imapd dovecot-ldap dovecot-lmtpd
Enter fullscreen mode Exit fullscreen mode

Then I chose "Internet Site" in the postfix install prompt asking about which type of mail server to install and set the domain to acme.internal.

Postfix Config

I edited /etc/postfix/main.cf to have this configuration:

myhostname = mail-server.acme.internal
mydomain = acme.internal
mydestination = $myhostname, $mydomain, localhost
mynetworks = 192.168.57.0/24 127.0.0.0/8
inet_interfaces = all
mailbox_transport = lmtp:unix:private/dovecot-lmtp
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
local_recipient_maps = ldap:/etc/postfix/ldap-recipients.cf
Enter fullscreen mode Exit fullscreen mode

mailbox_transport hands mail delivery off to Dovecot via LMTP. The smtpd_sasl_* settings let Postfix use Dovecot for SMTP authentication. local_recipient_maps tells Postfix to look up valid recipients in LDAP instead of the local user table - without this, Postfix rejects mail to LDAP users with "User unknown in local recipient table".

I created /etc/postfix/ldap-recipients.cf for the recipient lookup:

server_host = ldaps://ldap-server.acme.internal
bind = yes
bind_dn = cn=sssd,ou=service-accounts,dc=acme,dc=internal
bind_pw = SSSDPass123
search_base = ou=users,dc=acme,dc=internal
query_filter = (&(objectClass=posixAccount)(mail=%s))
result_attribute = mail
Enter fullscreen mode Exit fullscreen mode

Then reloaded Postfix:

sudo systemctl reload postfix
Enter fullscreen mode Exit fullscreen mode

Local CA Config on Mail Server

I copied rootCA.pem that I created earlier to this server and trusted it.

debian@mail-server:~/acme-certs$ ls
rootCA.pem
debian@mail-server:~/acme-certs$ sudo cp rootCA.pem /usr/local/share/ca-certificates/acme-rootCA.crt
[sudo] password for debian: 
debian@mail-server:~/acme-certs$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
rehash: warning: skipping ca-certificates.crt, it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
debian@mail-server:~/acme-certs$ 
Enter fullscreen mode Exit fullscreen mode

Dovecot TLS Config

I generated a TLS cert for mail-server.acme.internal using mkcert and copied it to the server:

sudo cp mail-server.acme.internal.pem /etc/dovecot/private/mail-server.crt
sudo cp mail-server.acme.internal-key.pem /etc/dovecot/private/mail-server.key
sudo chown root:dovecot /etc/dovecot/private/mail-server.key
sudo chmod 640 /etc/dovecot/private/mail-server.key
Enter fullscreen mode Exit fullscreen mode

Then updated /etc/dovecot/conf.d/10-ssl.conf:

ssl_server_cert_file = /etc/dovecot/private/mail-server.crt
ssl_server_key_file = /etc/dovecot/private/mail-server.key
Enter fullscreen mode Exit fullscreen mode

Dovecot LDAP Config

I changed dovecot auth settings to use LDAP auth instead of system auth by editing /etc/dovecot/conf.d/10-auth.conf - commented out auth-system.conf.ext and uncommented auth-ldap.conf.ext.

debian@mail-server:~/acme-certs$ cat /etc/dovecot/conf.d/10-auth.conf | grep "include auth"
#!include auth-deny.conf.ext
#!include auth-master.conf.ext
#!include auth-oauth2.conf.ext
#!include auth-system.conf.ext
#!include auth-sql.conf.ext
!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-static.conf.ext
Enter fullscreen mode Exit fullscreen mode

Dovecot 2.4 changed the config syntax from older versions, so the standard examples online did not work. After checking the example config the package ships with, I set /etc/dovecot/conf.d/auth-ldap.conf.ext to:

ldap_uris = ldaps://ldap-server.acme.internal
ldap_auth_dn = cn=sssd,ou=service-accounts,dc=acme,dc=internal
ldap_auth_dn_password = SSSDPass123
ldap_base = ou=users,dc=acme,dc=internal

passdb ldap {
  ldap_filter = (&(objectClass=posixAccount)(uid=%{user}))
  ldap_bind = yes
}

userdb ldap {
  ldap_filter = (&(objectClass=posixAccount)(uid=%{user}))
  fields {
    uid = vmail
    gid = vmail
    home = /var/mail/vhosts/%{user | username}
  }
}
Enter fullscreen mode Exit fullscreen mode

This reuses the same read-only service account from the LDAP lab. ldap_bind = yes means Dovecot verifies passwords by actually binding to LDAP as the user rather than fetching and comparing the hash. The userdb block maps all mail storage to a dedicated vmail system user instead of running as the LDAP user's UID.

Note: ldap_auth_dn_password is stored in plaintext, but /etc/dovecot/conf.d/auth-ldap.conf.ext is owned by root and not readable by other users.

Dovecot Mail Storage and Postfix Integration

Since LDAP users don't have home directories on the mail server, I created a dedicated vmail system user to own all mailboxes and set up a central mail storage directory:

sudo adduser --system --no-create-home --group vmail
sudo mkdir -p /var/mail/vhosts
sudo chown -R vmail:vmail /var/mail/vhosts
sudo chmod 770 /var/mail/vhosts
Enter fullscreen mode Exit fullscreen mode

I updated /etc/dovecot/conf.d/10-mail.conf to use this path:

mail_driver = maildir
mail_home = /var/mail/vhosts/%{user | username}
mail_path = %{home}/Maildir
first_valid_uid = 100
Enter fullscreen mode Exit fullscreen mode

Then I configured the LMTP and auth unix sockets in /etc/dovecot/conf.d/10-master.conf so Postfix can hand off incoming mail to Dovecot and use Dovecot for SMTP authentication.

In the service lmtp block:

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}
Enter fullscreen mode Exit fullscreen mode

In the service auth block:

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}
Enter fullscreen mode Exit fullscreen mode

Then restarted Dovecot:

sudo systemctl restart dovecot
Enter fullscreen mode Exit fullscreen mode

Verification

Sending mail

I sent a test mail from jsmith to adoe over SMTP from a desktop VM on the same network:

debian@debian:~/acme-certs$ curl -v --url "smtp://mail-server.acme.internal:25" \
  --mail-from "jsmith@acme.internal" \
  --mail-rcpt "adoe@acme.internal" \
  --upload-file - <<EOF
From: jsmith@acme.internal
To: adoe@acme.internal
Subject: Test from jsmith

Hello Alice, this is John.
EOF
Enter fullscreen mode Exit fullscreen mode

Postfix accepted it and delivered it to Dovecot via LMTP:

250 2.0.0 Ok: queued as 98B624018B
Enter fullscreen mode Exit fullscreen mode

Verified the mail landed in adoe's mailbox on the server:

debian@mail-server:~$ sudo ls /var/mail/vhosts/adoe/Maildir/new/
1773903163.M693787P7845.mail-server.acme.internal,S=560,W=576
Enter fullscreen mode Exit fullscreen mode

Retrieving mail over IMAPS

I verified that adoe can authenticate and retrieve mail over IMAPS using their LDAP credentials:

debian@debian:~/acme-certs$ curl -v --url "imaps://mail-server.acme.internal/INBOX" \
  --user "adoe:Password456"
Enter fullscreen mode Exit fullscreen mode
* SSL certificate verify ok.
* Connected to mail-server.acme.internal (192.168.57.7) port 993
< A002 OK Logged in
< * LIST (\HasNoChildren) "." INBOX
< A003 OK List completed (0.001 + 0.000 secs).
Enter fullscreen mode Exit fullscreen mode

TLS handshake succeeded using the mkcert CA, LDAP authentication worked, and the INBOX is accessible.

Thunderbird Verification

Thunderbird has its own certificate store separate from the system trust store, so I had to manually import rootCA.pem into Thunderbird settings before it would trust the IMAPS connection.

adoe sends an email to jsmith

001

jsmith opens it

002

jsmith sends a reply email to adoe

003

adoe views the reply email

004

Conclusion

Postfix and Dovecot are now running as a mail server for acme.internal. Users defined in the OpenLDAP directory can send and receive mail using their LDAP credentials. Postfix looks up valid recipients in LDAP so it accepts mail for LDAP users. Dovecot authenticates over LDAPS using the same read-only service account from the LDAP lab and stores mail in a central directory owned by a dedicated vmail user. IMAP access is over TLS only.

This mail server will be used in the next part of this series as the SMTP backend for Keycloak notifications.

Top comments (0)