Passa al contenuto principale

Basic Mailserver

1. Introduction

We want a mail server that:

  • Allows you to send email if you authenticate with a valid username and password, which are stored on an LDAP server.

  • If someone sends email to one of the mail domains supported by the server, the recipient address will be checked on the LDAP directory whether it is valid, before the mail is accepted.

  • The received emails are not stored locally, but are forwarded instead to an external email address that belongs to the user (and is recorded in the LDAP directory).

These are called "forward-only" or "no-mailbox" email accounts.

This kind of mail server could be useful for small organizations or companies. It allows them to have branded email addresses and to use their own mail server for sending emails. However it spares their users from having multiple email accounts, allowing them to receive all the emails in a single mailbox, on their preferred mail provider (for example gmail.com, mailbox.org, proton.me, etc).

At the same time, it relieves the postmaster of the organization from having to manage mailboxes and backups, scanning emails for viruses and spam, having to deal with legal issues (like GDPR), etc. These are not easy tasks and they can be done much more professionally from the dedicated email providers.

2. Requirements

2.1 Simple SMTP server

This mail server is based on the Simple and minimal SMTP server, so make sure to install and test it first.

Once you have it installed, you already have a "forward-only" mail server. To add a forwarding address (or alias):

  1. Add a line like this to config/virtual_alias_maps:

    dashamir.hoxha@user1.fs.al  dashohoxha@gmail.com
  2. Then update the virtual_alias_maps.db:

    ds exec postmap /host/config/virtual_alias_maps

    #or:
    #ds inject update.sh

2.2 LDAP server

The default setup of the Simple SMTP Server allows us to send emails only from the "trusted hosts" (whose IPs are listed on config/trusted_hosts). This prevents any spammers from abusing the mail server.

If some users need to send emails from anywhere (any random IP), they should be able to authenticate themselves to the SMTP server, for example with a username and password. The SMTP server should be able to check their username and password in a database (which may be an LDAP directory or a relational DB like MariaDB, PostgreSQL, etc.)

In our case we are going to use an OpenLDAP server for storing the needed user details (username, password and forward email).

3. Setup

3.1 Add data to LDAP

Let's populate LDAP with some data. We need app credentials, so that the mail server is allowed to check the data stored in LDAP. We also need a couple of user entities, that we can use for testing.

  1. First, let’s make sure that we have the organizational units apps and users:

    ds ou
    ds ou add apps
    ds ou add users
    ds ou ls
    ds search "(objectClass=organizationalUnit)"

    OU-s are like branches or subdirectories in LDAP. The unit apps is for the mail server and other applications that need to check the user data on LDAP. The unit users is for the user entities.

  2. Let's also add a couple of test users:

    ds user
    ds user add users test1@user1.fs.al dashohoxha@gmail.com pass123
    ds user add users test2@user1.fs.al dashohoxha@gmail.com
    ds set-passwd pass234 uid=test2@user1.fs.al,ou=users,dc=user1,dc=fs,dc=al
    ds user ls
    ds search "(objectClass=inetOrgPerson)"

    The users can change or recover their password with a web interface at https://ldap.user1.fs.al/

  3. Create app credentials for the SMTP server:

    ds app
    ds app add smtp pass-smtp
    ds app ls
    ds search "(objectClass=organizationalRole)"
  4. Let's also check that we are able to read data from the LDAP server, using the credentials of cn=smtp,ou=apps,dc=user1,dc=fs,dc=al:

    apt install ldap-utils

    ldapsearch -xLLL \
    -H ldap://ldap.user1.fs.al/ \
    -D cn=smtp,ou=apps,dc=user1,dc=fs,dc=al \
    -w pass-smtp \
    -b ou=users,dc=user1,dc=fs,dc=al \
    "(uid=test1@user1.fs.al)"

    ldapsearch -xLLL -ZZ \
    -H ldap://ldap.user1.fs.al/ \
    -D cn=smtp,ou=apps,dc=user1,dc=fs,dc=al \
    -w pass-smtp \
    -b ou=users,dc=user1,dc=fs,dc=al \
    "(uid=test1@user1.fs.al)" \
    uid mail

    Note: In case of any problem, add the option -d9 for debugging.

3.2 Enable LDAP authentication on the SMTP server

We need to uncomment the LDAP_ variables on settings.sh, and remake the container.

  1. Go to the directory of the SMTP server:

    cd /var/ds/smtp.user1.fs.al/
  2. Edit settings.sh and uncomment the LDAP settings, giving them proper values, like these:

    LDAP_SERVER_HOST="ldap.user1.fs.al"
    LDAP_SEARCH_BASE="ou=users,dc=user1,dc=fs,dc=al"
    LDAP_BIND_DN="cn=smtp,ou=apps,dc=user1,dc=fs,dc=al"
    LDAP_BIND_PW="pass-smtp"
  3. Re-make the container:

    ds make

When the LDAP_ settings are available, the scripts will setup some additional configurations that instruct the SMTP server to lookup on the given LDAP server, or to authenticate users there, when needed.

4. Testing

Add users

The instructions in this section assume that these test users exist on the LDAP database:

  • (test1@user1.fs.al, pass123)
  • (test2@user1.fs.al, pass234)

They can be added like this:

cd /var/ds/ldap.user1.fs.al/

ds ou add users

ds user add users test1@user1.fs.al dashohoxha@gmail.com pass123
ds user add users test2@user1.fs.al dashohoxha@gmail.com pass234
ds user ls

For a quick automated test of the basic functionality of the server try: ds test2

4.1 Test the LDAP queries

cat config/smtpd_sender_login_maps.ldap
cat config/virtual_alias_maps.ldap

ds shell

postconf -f virtual_alias_maps
postconf -f smtpd_sender_login_maps

postmap -q test1@user1.fs.al \
ldap:/host/config/virtual_alias_maps.ldap
postmap -q test1@user1.fs.al \
ldap:/host/config/smtpd_sender_login_maps.ldap
suggerimento

If the postmap queries don't return the expected result, append the line debuglevel = -1 on smtpd_sender_login_maps.ldap and virtual_alias_maps.ldap and try to identify the problem.

You can also try with ldapsearch, like this:

### on the host, outside the container
apt install ldap-utils
ldapsearch -x -LLL -ZZ \
-H ldap://ldap.user1.fs.al/ \
-D cn=smtp,ou=apps,dc=user1,dc=fs,dc=al \
-w pass-smtp \
-b ou=users,dc=user1,dc=fs,dc=al \
"(uid=test1@user1.fs.al)"

4.2 Test SASL authentication

ds shell
cat /etc/saslauthd.conf
cat /etc/postfix/sasl/smtpd.conf
cat /etc/default/saslauthd | grep MECHANISMS
systemctl status saslauthd
testsaslauthd \
-f /var/spool/postfix/var/run/saslauthd/mux \
-u test1 -r user1.fs.al -p pass123
postconf smtpd_sasl_auth_enable

4.3 Test sending and forwarding emails

These test commands are supposed to run on a computer other than the server, which has a public IP that is NOT on the list of trusted hosts (config/trusted_hosts). While running them, it may be useful to check the logs on the mail server, on a separate tab/terminal:

cd /var/ds/smtp.user1.fs.al/
ds exec tail /var/log/mail.log -f

4.3.1 Try to send message without authentication

Send a test message from test1@user1.fs.al to a gmail account:

swaks --server smtp.user1.fs.al \
--from test1@user1.fs.al \
--to dashohoxha@gmail.com

swaks --server smtp.user1.fs.al \
--from test1@user1.fs.al \
--to dashohoxha@gmail.com

We are trying it twice. The first time you try to send an email from a new client the service is automatically refused (in order to confuse spam bots). The second time the connection is accepted, however it fails because the sender is not authenticated.

important

The test above should fail (sending email without authentication).

If it succeeds, make sure that your public IP is not on config/trusted_hosts.

If you modify this file you should also run ds inject update.sh.

suggerimento

If you fail a few times, eventually you may get an error message Connection refused, like this:

=== Trying smtp.user1.fs.al:25...
*** Error connecting to smtp.user1.fs.al:25:
*** IO::Socket::INET6: connect: Connection refused

The reason is fail2ban that runs inside the SMTP container. If a client fails several times, it blocks its IP on the firewall. This is a temporary block, but if you want to continue testing, you can unblock it like this:

ds shell

fail2ban-client status postfix
fail2ban-client set postfix unbanip 188.245.242.143
fail2ban-client status postfix

4.3.2 Send a message with authentication

swaks --server smtp.user1.fs.al \
--from test1@user1.fs.al \
--to dashohoxha@gmail.com \
--auth-user test1@user1.fs.al \
--auth-password pass123

[. . .]
*** Host did not advertise authentication
[. . .]

The message Host did not advertise authentication indicates that the SMTP server does not accept authentication on the port 25. Let's try with the ports 587 and 465:

swaks --server smtp.user1.fs.al:587 \
--from test1@user1.fs.al \
--to dashohoxha@gmail.com \
--auth-user test1@user1.fs.al \
--auth-password pass123

[. . .]
<- 235 2.7.0 Authentication successful
[. . .]


swaks --server smtp.user1.fs.al:465 \
--from test1@user1.fs.al \
--to dashohoxha@gmail.com \
--auth-user test1@user1.fs.al \
--auth-password pass123

[. . .]
<- 235 2.7.0 Authentication successful
[. . .]

It should succeed, if the password is correct.

important

Notice that as username we are using the whole email address (test1@user1.fs.al) instead of the uid (test1).

4.3.3 Send a message from the wrong address

Let's try to send a message from the same user as before, but with --from test2@user1.fs.al:

swaks --server smtp.user1.fs.al \
--from test2@user1.fs.al \
--to dashohoxha@gmail.com \
--auth-user test1@user1.fs.al \
--auth-password pass123

[. . .]
<- 235 2.7.0 Authentication successful
[. . .]
<** 553 5.7.1 <test2@user1.fs.al>: Sender address rejected:
not owned by user test1@user1.fs.al
[. . .]

This --from address does not belong to the authenticated user, so the server refuses to send the mail.

4.3.4 Test forwarding emails

Let's send an email from test1 to test2. It should be forwarded to the external email address of test2:

swaks --server smtp.user1.fs.al \
--auth-user test1@user1.fs.al \
--auth-password pass123 \
--from test1@user1.fs.al \
--to test2@user1.fs.al

Try also to send an email from an external email address to test1@user1.fs.al and test2@user1.fs.al.

5. Using

5.1 Create account

The forward-only email address assumes that you already have a primary email account (on the provider of your choice) where the incoming emails are forwarded. We can create it like this:

  1. Add a new user entity on the LDAP server:

    cd /var/ds/ldap.user1.fs.al/
    ds user add users \
    dashamir.hoxha@user1.fs.al \
    dashohoxha@gmail.com \
    pass1234
  2. Go to https://ldap.user1.fs.al/ and make sure that you can reset the password. Users can either change the password, if they know the current one (pass1234), or reset the password with the help of the primary email address (dashohoxha@gmail.com).

5.2 Receive messages

All the emails that are sent to the forward-only email address (dashamir.hoxha@user1.fs.al) will end up in the inbox of the primary email account (dashohoxha@gmail.com).

suggerimento

To be more organized, I use filtering to automatically move all the emails that come to dashamir.hoxha@user1.fs.al to their own folder.

5.3 Send messages

So far so good, but what if you want to send emails from your forward-only email address, or to reply to an incoming message?

The answer lies on the SMTP settings of your mail client. Ideally, you should use a mail client that supports multiple SMTP servers, or at least multiple email accounts (one for the primary address, and one for the forward-only one). Thunderbird, for example, is a suitable email client.

The setup on Thunderbird would be like this:

  1. First of all, make sure to add in Thunderbird an account for the primary email address. (Probably you already have it.)

  2. Add also an additional SMTP server, with settings like this:

    • Description: dashamir.hoxha@user1.fs.al
      (it can actually be anything).
    • Server Name: smtp.user1.fs.al
    • Port: 587
    • Connection security: STARTTLS
    • Authentication method: Normal password
    • User Name: dashamir.hoxha@user1.fs.al
  3. On the settings of the primary account, add an additional identity, with the forward-only email address (dashamir.hoxha@user1.fs.al).

  4. Make sure that the "Sending Mail Server SMTP" for this new identity is the SMTP server created above.

  5. On the settings of this new identity, also make sure that the sent emails are saved on the local "Sent" directory, and archived emails on the local "Archive" directory. Do the same for "Drafts" and "Templates".

    (Probably you have to create these local directories first.)

  6. When you send a new email (or reply to an email) switch the identity to the one for dashamir.hoxha@user1.fs.al.

This video shows how to do it

6. References