Blog > Mail > How to plug OpenSMTPD with OpenLDAP on Debian Buster

How to plug OpenSMTPD with OpenLDAP on Debian Buster

So you want to host your own mail server with opensmtpd, but you don't have time to understand everything going on? Here is an expeditious guide for doing just that.

In this guide I used OpenSMTPD 6.6.1 on Debian Buster.

Lets start by blindly copy-pasting this snippet to install the dependencies we will need:

sudo apt install opensmtpd libpam-ldap libnss-ldap

OpenSMTPD

OpenSMTPD has some LDAP support with the opensmtpd-extras package, but not enough for LDAP authentication. Someone opened a bug report stating that you can request some fields from the LDAP server, giving you access to the hashed user password, but that's it. You do not know which hash algorithm was used, and even if you did, OpenSMTPD will only use the one provided by crypt, so there is a good chance that comparing hashed passwords won't work. Later, an OpenSMTPD developer confirmed that there was no such thing as LDAP authentication in OpenSMTPD, but that one should rely on standard authentication mechanisms such as PAM or bsd_auth:

[...] OpenSMTPD authenticate using crypt(3) by default, which indeed will require credentials to be adapted for that function, but it does so through bsd_auth(3) on OpenBSD and may be configured to use pam(3) on other systems, so you may just delegate authentication to an ldap layer if you actually don't want the system's auth to take place.

This seems like the right approach to tackle this issue to me, if I were to authenticate against ldap, I'd use an ldap authenticator for bsd_auth(3) or pam(3).

Here is an example of a /etc/smtpd.conf file.

pki mail.mydomain.tld cert "/path/to/fullchain.pem"
pki mail.mydomain.tld key "/path/to/privkey.pem"
pki mail.mydomain.tld dhe auto

public_addr = "xxx.xxx.xxx.xxx"
listen on $public_addr port 465 smtps pki mail.mydomain.tld auth
listen on $public_addr port 587 tls-require pki mail.mydomain.tld auth

table ldap ldap:/etc/mail/ldap.conf

action dovecot lmtp "/var/run/dovecot/lmtp" userbase <ldap>
action "relay" relay

match from any for domain "mydomain.tld" action "dovecot"
match from any action "relay"

Note that the userbase parameter is not directly linked with user authentication. It actually defines the list of available recipients. Here is an example of /etc/mail/ldap.conf:

url                     ldap://ldap.mydomain.tld
username                cn=admin,dc=mydomain,dc=tld
password                MyAmazingPassword
basedn                  ou=Users,dc=mydomain,dc=tld

userinfo_filter         (&(objectClass=posixAccount)(uid=%s))
userinfo_attributes     uidNumber,gidNumber,homeDirectory

Without further configuration, the auth keyword in smtpd.conf tells OpenSMTPD to use PAM authentication. So this is what we should now configure.

PAM

According to its man page, PAM is a system of libraries that handle the authentication tasks of applications (services) on the system. In Debian, it mainly consists of a collection of configuration files in /etc/pam.d for programs that need a generic way to handle authentication, session management, etc. Each file is a set of rules for one program. Those rules generally use a pam_foobar.so file depending on the method used (unix, ldap etc.). The idea is to chain rules to define an authentication policy (e.g. try to authenticate against the unix backend, if that fails try against LDAP, then if that fails reject the user). By default, OpenSMTPD will look into the /etc/pam.d/smtpd file for its rules, so this is where we want to write some configuration. The pam_ldap.so module we are interested in is provided by the libpam-ldap package.

Here is an example of a /etc/pam.d/smtpd file.

#%PAM-1.0

account     [default=bad success=ok user_unknown=ignore] pam_ldap.so debug

auth        sufficient      pam_ldap.so debug
auth        required        pam_deny.so

Basically, this configuration tells PAM to rely on pam_ldap.so to manage user accounts and authentication. As you can see, there is not a lot of information in this file. The Debian documentation explains that this is because pam_ldap.so delegates everything to Name Service Switch. The debug keywords are used for verbosity, and can safely be removed.

NSS

The NSS is provided by the libnss-ldap package. It is a daemon that holds the LDAP configuration and caches the requests to the LDAP.

You can configure your ldap URI, your search DN and your bind credentials in /etc/nslcd.conf:

...
uri ldap://ldap.mydomain.tld

base ou=Users,dc=mydomain,dc=tld

binddn cn=admin,dc=mydomain,dc=tld
bindpw MyVerySecretPassphrase
...

SSHD

On debian Buster, enabling LDAP on it has a side effect: SSH sessions will try to authenticate against the LDAP via PAM, unless you switch UsePAM to no in /etc/ssh/sshd_config.

Debug your installation

To debug this installation, let's launch all those services manually and make them verbose:

Check the system authentication logs:

sudo tail --follow /var/log/auth.log | grep pam_ldap

Launch opensmtpd in verbose mode:

sudo systemctl stop opensmtpd
sudo /usr/sbin/smtpd -dv

Launch the NSS daemon in verbose mode:

sudo systemctl stop nslcd
sudo nslcd --debug

Check what is going on with your LDAP server:

sudo tail --follow /var/log/syslog | grep slapd