Cover V13, i02

Article

feb2004.tar

Installing Dovecot: A Secure IMAP Server

Lawrence Teo

Last year, I began looking around for an IMAP server to replace my aging UW IMAP server. Although UW IMAP has served me well, I wanted something newer that was designed with security in mind and was easier to configure. I found Dovecot, an open source IMAP server that advertises itself as "an IMAP and POP3 server for Linux/UNIX-like systems, written primarily with security in mind." I liked what I read, so I tried it. I have been running Dovecot for close to a year now, and it has served hundreds of thousands of email messages without a hitch.

Apart from its security-focused design, Dovecot is also packed with nifty features, despite its work-in-progress status. It's IPv6 ready. It's fast -- very fast. I don't have specific measures, but Dovecot's author Timo Sirainen mentions on the Web site that he has successfully tested it up to 367,000 emails. Dovecot runs on a wide range of operating systems, from the usual open source suspects (Linux and *BSD) to the big Unix varieties. It has complete support for the IMAP4rev1 standard, plus extensions for Web mail clients. When I looked at the source code, I was impressed by the quality of C code under the hood; the author definitely knows what he's doing. I'm confident that I've finally found an IMAP server that'll help me sleep better at night.

While I really like Dovecot, I found its documentation to be somewhat sketchy. This is the key reason why I decided to write this article -- I want to share what I've learned about installing Dovecot with you.

I installed Dovecot on an OpenBSD system; both Dovecot and OpenBSD have similar goals in security, which is extremely important for security-conscious administrators. In this article, I'll describe how to install Dovecot on a vanilla OpenBSD 3.3 system. Given the myriad of ways in which an IMAP server can be configured, I won't provide a complete HOWTO article; instead, I'll present a "how-I-did-it" approach, with pointers along the way so you'll know where to go if you need more information. My own IMAP needs are rather simple, so I'll show a somewhat minimal installation and configuration of Dovecot. This leaves a lot of room to play with more advanced configuration options.

Decisions

Before you install Dovecot, you'll need to make a few key decisions. For example, do you want to serve IMAPS in addition to IMAP? Where are the users' mailbox locations? Which mailbox format do you want to use: mbox or maildir? In my environment, I made the following decisions, which I'll describe along with my reasons:

  • IMAPS only -- Dovecot will serve IMAPS (IMAP over SSL) only, and not regular IMAP. This is because regular IMAP runs over plaintext, and I don't want my messages to be intercepted in transit.
  • OpenSSL only -- By default, Dovecot uses GNUTLS if it's found. Since OpenSSL comes stock with OpenBSD, I'll use OpenSSL instead.
  • No POP -- Although Dovecot supports POP, I won't be serving it, because I'm primarily interested in IMAP.
  • Non-standard IMAPS port -- The regular IMAPS port is 993. However, as an extra precaution, I'll use port 779, just to make things a little harder for portscanner-wielding attackers.
  • Mailbox locations -- A user's main inbox will be in $HOME/Mailbox, while the IMAP folders will be in the $HOME/mail/ directory. These locations could be elsewhere; this is just my preference. You'll need to make sure that your MTA delivers mail to your inbox location though, if the location is non-standard.
  • mbox format -- I chose mbox over maildir. Although maildir is much faster when additions and deletions are involved, I prefer having my mail in a small collection of folders, as opposed to an entire directory full of thousands of files (which would be the case if you use maildir). Plus, my server isn't a terribly busy mail server, so performance isn't too critical.

At the time of writing, the latest version of Dovecot is Dovecot 0.99.10, and the latest stable version of OpenBSD is OpenBSD 3.3. I will use these versions for this article; however, I should point out a few things that might have changed by the time you read this article.

OpenBSD 3.4 is in the works and not released yet, but it does contain a port for Dovecot. To make things more complicated, the Dovecot port in 3.4 has a number of patches that address a few bugs when running Dovecot in OpenBSD. These factors made it rather challenging to write this article.

Therefore, to make this article accessible to non-OpenBSD users, I will describe the generic way of compiling and installing it, which was how I did it, but I will leave notes here and there for future OpenBSD 3.4 administrators as well. Also, Dovecot is now available for the other BSD variants (FreeBSD and NetBSD) as well as Linux distributions like Debian and Red Hat. If you use their specific installation methods, bear in mind that the file locations (such as the configuration file and SSL certificate locations) may be different from those described here.

Installation

To begin, you'll need to download the source tarball from the Dovecot Web site:

http://dovecot.procontrol.fi/
At the time of writing, the source tarball's filename is dovecot-0.99.10.tar.gz. On the same download page, you'll find a PGP signature for the file. If you're truly security-conscious, you can verify the signature using PGP or an open source alternative like GnuPG.

Extract the tarball:

lteo:~$ tar zxvf http://dovecot.procontrol.fi/dovecot-0.99.10.tar.gz
lteo:~$ cd dovecot-0.99.10
Next, you must decide what the relevant configure options should be. Invoking ./configure --help provides a useful help screen. If you want more details on each option, check the INSTALL file in the source distribution. For my environment, I used the following configure options:

./configure --without-pam --without-shadow             \
            --without-vpopmail --localstatedir=/var    \
            --with-ssldir=/etc/ssl --with-ssl=openssl  \
            --sysconfdir=/etc
This will build Dovecot without Pluggable Authentication Modules (PAM) (which OpenBSD does not support), Shadow password, and Vpopmail support. Next, it'll put local state information (such as SSL parameters and Dovecot's Unix socket file) in /var and specify that the SSL certificates live in /etc/ssl. The --with-ssl=openssl option makes Dovecot use OpenSSL instead of GnuTLS. Then, --sysconfdir=/etc will install the Dovecot example configuration file in /etc.

After configure finishes, you should see the following output:

Install prefix ...................... : /usr/local
File offsets ........................ : 64bit
Building with SSL support ........... : yes (OpenSSL)
Building with IPv6 support .......... : yes
Building with pop3 server ........... : yes
Building with user database modules . :  static passwd passwd-file (modules)
Building with password lookup modules :  passwd passwd-file (modules)
Next, compile and install Dovecot using the standard make and make install routine:

lteo:~/dovecot-0.99.10$ make
lteo:~/dovecot-0.99.10$ su
root# make install
Configuration

After compilation is done, it's time to edit the Dovecot configuration file to fit our requirements. A sample configuration file is given in /etc/dovecot-example.conf. Make a copy of it called /etc/dovecot.conf, which is the filename that Dovecot expects:

root:/# cd /etc
root:/etc# cp dovecot-example.conf dovecot.conf
We're now ready to edit dovecot.conf. Since we want to serve just IMAPS, we remove the "imap" keyword and leave "imaps" in the protocols line as follows:

protocols = imaps
Next, we want Dovecot to listen on port 779, and not the default IMAPS port of 993:

imaps_listen = *:779

The asterisk makes Dovecot listen on all IPv4 interfaces, which is what we want in most circumstances.

You may also want to consider increasing the login process count, especially for busy servers. This is the number of login processes that will wait for users to log in. The default number is 3, so we can increase it to 5:

login_processes_count = 5
In terms of the default mail environment, we use the mbox format with the IMAP folders in $HOME/mail/, and the inbox will be $HOME/Mailbox. You can specify these locations as follows:

default_mail_env = mbox:~/mail/:INBOX=/home/%u/Mailbox
If you want to use the maildir format instead, read the doc/configuration.txt file in the Dovecot source distribution. doc/mail-storages.txt also has more information on how both mbox and maildir are stored internally.

Because I'm on OpenBSD, I won't be using PAM (which is the default Dovecot authentication method), so I will change the password database location to use the standard passwd file:

auth_passdb = passwd
Generating SSL Certificates

Since we're running IMAPS, we have to generate SSL certificates first. There are two ways to do this. The first is to use Dovecot's SSL certificate generation script (doc/mkcert.sh), and the second is to generate them using OpenSSL.

Using Dovecot's script is more convenient -- however, there are two caveats. The default filename generated by the script is imapd.pem, while the filename actually used by Dovecot is dovecot.pem. This is just a minor inconvenience; you can always rename the files or change the filenames in /etc/dovecot.conf. The second caveat is that the script does not specify the expiration period for the certificates, so the generated certificates will have an expiration period of 30 days (which I think is the OpenSSL default).

Now, we don't want to re-generate SSL certificates every single month, so I recommend manually generating them with a longer expiration period, say 365 days, using OpenSSL (the second method). To begin, edit the Dovecot-supplied OpenSSL configuration file called doc/dovecot-openssl.cnf. The fields in the file are fairly self-explanatory, so I won't go into details. If you're unfamiliar with X.509 certificates, the most "important" field is the CN field. Make sure that the CN value matches the DNS name of your mail server. For example, if your mail server's DNS name is imapserver.example.com, make sure that the CN field reflects that name. The contents of a sample doc/dovecot-openssl.cnf file are shown here:

    [ req ]
    default_bits = 1024
    encrypt_key = yes
    distinguished_name = req_dn
    x509_extensions = cert_type
    prompt = no
    
    [ req_dn ]
    # country (2 letter code)
    C=US
    
    # State or Province Name (full name)
    ST=North Carolina
    
    # Locality Name (eg. city)
    L=Charlotte
    
    # Organization (eg. company)
    O=Example Corporation
    
    # Organizational Unit Name (eg. section)
    OU=IMAP server
    
    # Common Name (*.example.com is also possible)
    CN=imapserver.example.com
    
    # E-mail contact
    emailAddress=mailadmin@example.com
    
    [ cert_type ]
    nsCertType = server
OpenSSL will generate two certificates: a public certificate and a private certificate. By default, Dovecot looks for the public certificate in /etc/ssl/certs/dovecot.pem and expects the private certificate to be in /etc/ssl/private/dovecot.pem. On a vanilla OpenBSD system, the directory /etc/ssl/certs may not exist yet. If it does not exist, you'll need to create it first.

In the next step, we generate the SSL certificates and install them into their expected locations as follows:

root:/usr/src/dovecot-0.99.10# openssl req -new -x509 -nodes         \
                               -config dovecot-openssl.cnf -days 365 \
                               -out /etc/ssl/certs/dovecot.pem       \
                               -keyout /etc/ssl/private/dovecot.pem
Note to OpenBSD 3.4 administrators: If you installed from ports, the caveats mentioned above do not apply to you. Your public X.509 certificate will be called /etc/ssl/dovecotcert.pem. You can run the mkcert script directly by invoking /usr/local/sbin/dovecot-mkcert.sh. The configuration file is /etc/ssl/dovecot-openssl.cnf.

Adding the Dovecot User Account

Dovecot runs using a few separate processes and exercises the principle of least privilege by running the login processes as a non-root user called "dovecot". In this step, I'll create the user account "dovecot" for this purpose. Most readers are likely familiar with this, so I'll just describe it briefly.

OpenBSD 3.4 administrators can skip this step if Dovecot was installed from ports. If you used ports or a distribution-specific installation, it is likely that the user account would have been created for you.

root:/# adduser
Use option ''-silent'' if you don't want to see all warnings and questions.

Reading /etc/shells
Check /etc/master.passwd
Check /etc/group

Ok, let's go.
Don't worry about mistakes. I will give you the chance later to correct any input.
Enter username [a-z0-9_-]: dovecot
Enter full name []: Dovecot
Enter shell bash csh ksh nologin sh [bash]: nologin
Uid [1002]: <enter>
Login group dovecot [dovecot]: <enter>
Login group is ''dovecot''. Invite dovecot into other groups: guest no
[no]: <enter>
Enter password []:
Enter password again []:

Name:     dovecot
Password: ****
Fullname: Dovecot
Uid:      1002
Gid:      1002 (dovecot)
Groups:   dovecot
HOME:     /home/dovecot
Shell:    /sbin/nologin
OK? (y/n) [y]: y
Added user ''dovecot''
Copy files from /etc/skel to /home/dovecot
Add another user? (y/n) [y]: n
Goodbye!
Migrating Mailboxes

You might have existing mail from another server that you would like to move to your new Dovecot IMAP server. Say your old mail is in mbox format and the messages are stored in a server called oldmail.example.com, organized in the exact directory structure and using the same filenames.

Earlier, we set our inbox to be $HOME/Mailbox and IMAP folders to be in $HOME/mail/, so we can just migrate the inbox and IMAP folders with the secure copy command (scp) as follows:

lteo:~$ scp lteo@oldmail.example.com:~/Mailbox .
lteo:~$ mkdir mail
lteo:~$ cd mail
lteo:~/mail$ scp -pr lteo@oldmail.example.com:~/mail/* .
Dovecot manages IMAP folder subscriptions in a dotfile called .subscriptions in the IMAP folder directory. The .subscriptions file contains the filenames of IMAP folders to which you are subscribed. You can use the following one-liner to easily subscribe to all current folders:

lteo:~/mail$ find . -type f | sed 's/^\.\///' >.subscriptions
To keep things simple, I have just described a method to migrate mail for one user. If you have multiple users, mail migration can be done using a few shell scripts.

If you would like to filter your messages, you can use procmail to filter messages, or just let your users use their mail client to handle it. Filtering messages is another subject altogether, so I won't discuss it in this article.

Starting Dovecot at Boot

If you want to have Dovecot started automatically at boot time, simply add the following lines to /etc/rc.local (on OpenBSD):

if [ -x /usr/local/sbin/dovecot ]; then
        echo -n ' dovecot';       /usr/local/sbin/dovecot
fi
For other systems, just add the equivalent lines to your system's respective startup script(s).

Let's Run It!

Now that everything is set up, you can run Dovecot to test whether it actually works:

root:/# /usr/local/sbin/dovecot
If all goes well, netstat should show you that it's listening on the non-standard port 779 as it was configured to do earlier:

root:/# netstat -an | grep LISTEN
tcp        0     0  *.779                *.*               LISTEN
tcp        0     0  *.22                 *.*               LISTEN
tcp        0     0  127.0.0.1.587        *.*               LISTEN
tcp        0     0  127.0.0.1.25         *.*               LISTEN
tcp        0     0  *.113                *.*               LISTEN
tcp6       0     0  *.22                 *.*               LISTEN
tcp6       0     0  ::1.587              *.*               LISTEN
tcp6       0     0  ::1.25               *.*               LISTEN
tcp6       0     0  *.113                *.*               LISTEN
When you check the processes associated with Dovecot, you'll see that the main Dovecot process and the authentication processes run as root. The five login processes (set earlier in the Configuration section) run using the non-root "dovecot" account:

lteo:~$ ps uaxwww | grep dovecot
root      6830  0.0  0.2   180   612 ??  Ss  1:53AM  0:00.03 /usr/local/sbin/dovecot
root     23920  0.0  0.1   268   536 ??  S   1:53AM  0:00.01 dovecot-auth
dovecot  30444  0.0  0.3   204  1148 ??  S   1:53AM  0:00.05 imap-login
dovecot  20264  0.0  0.3   204  1152 ??  S   1:53AM  0:00.05 imap-login
dovecot  17184  0.0  0.3   204  1152 ??  S   1:53AM  0:00.05 imap-login
dovecot  27273  0.0  0.3   204  1152 ??  S   1:53AM  0:00.05 imap-login
dovecot  11414  0.0  0.3   204  1152 ??  S   1:53AM  0:00.05 imap-login
For more information on what each process does, check out the file doc/design.txt, which documents Dovecot's security design.

At this point, you might want to fire up a mail client and check your mail from your brand-new Dovecot IMAP server to see whether it works. Remember to allow your mail client to accept the self-signed SSL certificate. Also, your mail client should be configured to use IMAPS on the non-standard port 779 (if you selected that port number).

To terminate Dovecot, send a SIGTERM signal to the main Dovecot process (in this case, the Dovecot process running with PID 6830):

root:/# kill -TERM 6830
Optimizing Dovecot's Performance

Dovecot is already pretty fast, so it's probably not necessary to make it even faster in most circumstances. However, if you operate a busy mail server or if you have a need to push performance to the limit (e.g., if you're running on older hardware), you can tune your operating system to help Dovecot a little bit. I'll provide some basic guidelines.

A typical mail server involves a lot of network and file accesses, so choosing to optimize the network and filesystem settings is a good idea. We'll follow the recommendations from the OpenBSD FAQ to tune network and filesystem performance.

If you're operating a busy mail server, you can increase the size of the kernel mbuf cluster map. Assuming you're running an i386-based machine with a 100-Mbps Ethernet interface, a good value would be 8192. Do this by adding the following line to your kernel configuration file (which should be a copy of /usr/src/sys/arch/i386/conf/GENERIC if you're using the generic kernel as a reference):

option NMBCLUSTERS=8192
If your mail server has enough RAM to spare, you can also use a larger percentage of it as your filesystem buffer. By default, only 5% of RAM is used. To increase the filesystem buffer to 30%, add the following line to the kernel configuration file:

option BUFCACHEPERCENT=30

The soft updates feature, which was added in OpenBSD 2.9, significantly speeds up filesystem performance. This, in turn, should increase the speed of your mail server. Soft updates is already enabled by default in the generic OpenBSD kernel; however, if it's not turned on, you can do that by including the following line in the kernel configuration file:

opton FFS_SOFTUPDATES
You'll also need to change /etc/fstab to enable the softdep option so that soft updates will be used. The following shows how soft updates is enabled for the /dev/wd0a partition:

/dev/wd0a / ffs rw,softdep 1 1
You can do the same for the other partitions.

Remember to reboot after recompiling your kernel. The afterboot(8) man page and OpenBSD's online FAQ has detailed information about recompiling an OpenBSD kernel.

Concluding Remarks

I have described a basic installation of Dovecot on OpenBSD. I have tried to keep the steps as generic as possible, so that you can use them on different platforms as well. As mentioned earlier, this is a somewhat minimal installation of Dovecot, so there's still plenty of room left for you to experiment with more advanced IMAP server configurations. The documentation in the doc/ directory of Dovecot's source distribution should give you some ideas, and the Web site has more information as well.

Note that a few features of Dovecot aren't quite there yet, such as support for Maildir++ quota and filesystem quota. If your environment requires these features, you may want to defer setting up Dovecot in a production environment. However, from my experience, Dovecot is ready as it is, and I use it for my own daily work and personal mail. For more critical environments, I recommend checking Dovecot's mailing list (instructions are on Dovecot's Web site) if there are particular issues you're not sure about. It's pretty active so you should be able to obtain help. If you do choose to try out Dovecot, I hope the instructions in this article would be helpful to you.

References

Dovecot Web Site -- http://dovecot.procontrol.fi/

OpenBSD FAQ -- http://www.openbsd.org/faq/

Lawrence Teo is vice president and co-founder of Calyptix Security Corporation (www.calyptix.com), a provider of Internet security solutions based on emerging technologies from scientific research. Prior to this, he held software engineering and research positions in Singapore and Australia. He has been administering Linux and *BSD systems for 7 years. Lawrence holds a Bachelor of Computing degree with First Class Honors from Monash University, Australia, and is currently working on his Ph.D. in security at the University of North Carolina at Charlotte.