- Making a Mailserver (Part 1) - What's in a Name
- Making a Mailserver (Part 2) - My Personal Daemons: Exim and Dovecot
- Making a Mailserver (Part 3) - Let's Encrypt Webmail
- Making a Mailserver (Part 4) - Credibility is Critical
- Making a Mailserver (Part 5) - Wonderful Spam
- Making a Mailserver (Part 6) - Server Migration & Backup
You May Not Want Webmail, But...
Consider webmail as an optional section, Let's Encrypt as mandatory. Webmail is not something that I recommend you set up on your mailserver, but webmail is handy as a when all else fails backup. When you're travelling, you can't be sure that you can SSH to your mailserver. Protocols outside of HTTP, HTTPS and DNS are often blocked, which makes mutt not an option. When visiting friends and family, I've found mail clients can be forbidden SMTP or IMAP protocol access to locations outside of the ISP.On the downside, setting up a web server uses valuable server resources, increases complexity and widens your security exposure.
On the security point, I use squirrelmail and honestly I don't know that it's a very good option. I think squirrelmail is easy to set up and lightweight to run, but development appears to have stopped, which means that security updates won't be arriving. On the other hand, from the remote attacker standpoint if an attacker doesn't already have the username and password of a mail user, then they only have the squirrelmail login page to hack away at. Well hackers are inventive, there should be other avenues into it than just that page. An attacker could craft a malicious message, targeted to exploit squirrelmail, that a user might open via squirrelmail. It's an acceptable risk to me, for now.
If you're not interested in setting up a webmail front-end, what this section will additionally do is provide an easier path to set up Apache for the generation of Let's Encrypt certificates to use with your IMAP and SMTP server daemons.
Apache
Apache will host the squirrelmail install or, at the very least, host the method by which you can easily generate a certificate for your mailserver via letsencrypt. If only required for the latter option, Apache need only be enabled for the duration of the certificate generation and subsequent renewals, saving server resources and reducing your security exposure.On a default install of Apache there is probably not a lot required to be configured. Apache comes with a default site for both SSL and HTTP. In the /etc/apache2/sites-available/ one should see a "default" and "default-ssl" file.
Check that mod_ssl is enabled:
$ sudo a2enmod mod_sslCheck whether the "default-ssl" and "default" sites are enabled:
$ ls -la /etc/apache2/sites-enabled/You don't need the default site, because you shouldn't be serving up other pages for sport, only webmail over SSL (HTTPS).
-rw-r--r-- 1 root root 692 Dec 3 2015 default -> ../sites-available/default
-rw-r--r-- 1 root root 7251 Dec 3 2015 default-ssl -> ../sites-available/default-ssl
$ sudo a2ensite default-sslIdeally you would copy those sites and customise your own sites based on those files, for example:
$ sudo a2dissite default
$ ls -la /etc/apache2/sites-enabled/Notice that when you use the a2ensite / a2dissite a symbolic link is created from sites-enabled to sites-available.
lrwxrwxrwx 1 root root 47 Jun 1 16:45 ssl-mail.moff.tech.conf -> ../sites-available/ssl-mail.moff.tech.conf
We'll discuss now the customisation of the ssl site file, including the stanza for squirrelmail. Please bear in mind the following:
- This is an abridged version to highlight the things that need to be changed.
- I'm not promising you the most secure or optimised configuration.
- It's really up to you to understand and research the settings here via Apache's useful, although sometimes dense, documentation. For security, you might want to start here.
<VirtualHost *:443>I'm using example.com because I don't want spam robots harvesting my email address from this blog post.
ServerName mail.moff.tech:443
DocumentRoot "/usr/share/squirrelmail"
ServerAdmin me@example.com
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
</VirtualHost>
We've altered the document root to be the squirrelmail install directory. If squirrelmail isn't installed yet, then this is going to cause Apache to complain when reading the config. At the very least, install squirrelmail (we'll customise it later) and set the document root accordingly. Note that this should not be set to the /etc/squirrelmail directory.
If you don't want to use squirrelmail, just leave DocumentRoot as default.
We'll revisit the SSL certs after sorting out letsencrypt. For now, leave them at the defaults (self signed certs), whatever they be called.
Don't move on to the letsencrypt stage until you can get Apache to start your ssl site successfully and have checked that your mail web address resolves and serves some web page - albeit with a self signed cert warning from your browser.
Let's Encrypt and Apache Integration
I don't need to go into a lot of detail here for setting up a Let's Encrypt certificate. Let's Encrypt have issued a million certificates and there's about as many user howtos and blogs to step you through. It works remarkably well as long as you do everything to the letter and have a simple Apache ssl site setup, like ours.
In truth you can use the letsencrypt standalone option and skip Apache altogether.
I've used the letsencrypt.sh client and it works well enough. I see that Let's Encrypt are now pushing something called certbot. I guess that's an experiment for me to do another time (and blog post).
Update: As of January, I notice that the letsencrypt-auto now presses certbot-auto. When running an update you receive "You are running with an old copy of letsencrypt-auto that does not receive updates, and is less reliable than more recent versions. We recommend upgrading to the latest certbot-auto script, or using native OS packages." However the cert is still succesfully issued.
Update: As of January, I notice that the letsencrypt-auto now presses certbot-auto. When running an update you receive "You are running with an old copy of letsencrypt-auto that does not receive updates, and is less reliable than more recent versions. We recommend upgrading to the latest certbot-auto script, or using native OS packages." However the cert is still succesfully issued.
Once you've stepped through the setup, check the location of the cert files. This is probably going to vary depending on the client you used to get the cert issued.
root@mail:/etc/apache2/ssl# ls -la /etc/letsencrypt/live/mail.moff.tech/That confirmed, you can head back to the Apache ssl site and verify the certificates. Where you had this:
total 8
drwxr-xr-x 2 root root 4096 Jun 11 10:14 .
drwx------ 3 root root 4096 Jun 11 10:14 ..
lrwxrwxrwx 1 root root 43 Jun 11 10:14 cert.pem -> ../../archive/mail.moff.tech/cert1.pem
lrwxrwxrwx 1 root root 44 Jun 11 10:14 chain.pem -> ../../archive/mail.moff.tech/chain1.pem
lrwxrwxrwx 1 root root 48 Jun 11 10:14 fullchain.pem -> ../../archive/mail.moff.tech/fullchain1.pem
lrwxrwxrwx 1 root root 46 Jun 11 10:14 privkey.pem -> ../../archive/mail.moff.tech/privkey1.pem
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pemYou should now have (or add) this:
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
SSLCertificateFile /etc/letsencrypt/live/mail.moff.tech/cert.pemReload (you don't need to restart) Apache and check for errors at startup. Now you can disable Apache if you don't want to set up webmail.
SSLCertificateKeyFile /etc/letsencrypt/live/mail.moff.tech/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/mail.moff.tech/chain.pem
The certificate you've been issued only lives for a few months. Consider a crontatb entry to renew the certificate. For example, this renews every three months (months 3, 6, 9, 12) on the 8th day:
1 0 29 JAN,APR,JUL,OCT * /root/letsencrypt/letsencrypt-auto renewI have a script (tested and verified with crontab) to handle the renewal process because, as we will see shortly, when the certificates are required for multiple jobs the file permissions don't suit every daemon. Check out letsencrypt-handle-certs.sh on my gitlab repository.
Finally, when Apache is enabled, verify your SSL/TLS strength via SSL Labs.
Squirrelmail
The default install of sqm offers an apache.conf but I recommend that you ignore it. It doesn't show you the HTTPS context and you don't want to expose configtest.php anywhere.
There is a lovely script to configure Squirrelmail just as you want it:
$ sudo squirrelmail-configureSome of the config points are these:
$imapServerAddress = 'mail.moff.tech';
$imapPort = 993;
$useSendmail = false;
$smtpServerAddress = 'mail.moff.tech';
$smtpPort = 25;
Troubleshooting squirrelmail
When sending an email via Squirrelmail, it may fail with a 550 message about relay not being permitted. This is because Squirrelmail didn't pass AUTH so the server doesn't trust the client and won't relay for it. The quick resolution is to add the server IP into the list of "Machines to relay mail for" in the Exim config as I mentioned in part 2.I found that Squirrelmail will try an AUTH before Exim offers it. In other words, if you set this in /etc/squirrelmail/config.php:
$smtp_auth_mech = 'login';Then the result may be a new problem:
Bad sequence of commandsExim wants to do AUTH after TLS but Squirrelmail tries to do AUTH before that. The workaround for this is to set $smtp_auth_mech = 'none'; and make sure that the IP of the server is set as a host to be a smarthost for. This setup of Squirrelmail doesn't use TLS to connect to Exim, I can't make that work with AUTH. I ended up with a message about being unable to open the TCP stream and this in the syslog:
503 AUTH command used when not advertised
SMTP protocol synchronization error (input sent without waiting for greeting): rejected connection from H=mail.moff.tech [64.x.x.x] input="\026\003\001"
Since packets from Squirrelmail never leave the box, from a security standpoint there's little to gain with a TLS connection - unless you distrust your server processes or users. Some web searching might reveal a solution to setting up Squirrelmail with TLS and AUTH. If you find one, let me know!
Squirrelmail will use the system user credentials by default. If you try to login as root, then squirrelmail will fail to get in. You'll see something like this in the syslog:
Jun 22 22:57:07 mail dovecot: imap-login: Login: user=<root>, method=PLAIN, rip=x.x.x.x, lip=y.y.y.y, mpid=25745, TLS, session=<N5s1LuQ1HQBAFlV3>Setting the servername to match the one on the certificate will avoid errors such as this:
Jun 22 22:57:07 mail dovecot: imap: Error: user root: Invalid settings in userdb: userdb returned 0 as uid
Jun 22 22:57:07 mail dovecot: imap: Error: Invalid user settings. Refer to server log for more information.
Jun 11 12:06:05 mail dovecot: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=::1, lip=::1, TLS, session=<Tvayzf00ZQAAAAAAAAAAAAAAAAAAAAAB>Above, the certificate servername validation was probably failing. You can't use the loopback address or you'll get that kind of error.
Additionally, an error log message like this one:
Jun 11 11:55:55 mail dovecot: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=x.x.x.x, lip=y.y.y.y, TLS: SSL_read() failed: error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca: SSL alert number 48, session=<qutPqf00mABSh18U>Will likely happen if the CA is unknown. You might see this if you've copied a self signed cert from another server without copying the "Self CA" as well. Rather than faff about sorting out a self signed cert, use Let's Encrypt.
Dovecot Certificate Integration
To splice the new certs into the Dovecot configuration, you might get away with simply calling the Let's Encrypt cert files where they stand.Edit /etc/dovecot/dovecot.conf:
ssl_cert = </etc/letsencrypt/live/mail.moff.tech/fullchain.pemThen reload and watch the logs for errors.
ssl_key = </etc/letsencrypt/live/mail.moff.tech/privkey.pem
After my first attempt at adding the Let's Encrypt cert, Thunderbird reported that my cert was still essentially self signed. I hadn't used the "full chain" file so apparently that meant Thunderbird wasn't too sure who the root CA was. This is possibly because Thunderbird didn't have the intermediate CA certs stored. Mozilla applications will apparently tuck a received Intermediary CA cert away for later reference. Using the full chain file allows Thunderbird to iterate the chain of authority.
That's also why you set the chain file in the Apache config.
Exim4 Certificate Integration
The exim4 config file states categorically:# Full paths to Certificate and Private Key. The Private Key fileAs it's a bad idea to tinker with the cert file permissions and owner/group. Copy them into the /etc/exim4/ directory and set the permissions accordingly:
# must be kept 'secret' and should be owned by root.Debian-exim mode
# 640 (-rw-r-----). exim-gencert takes care of these prerequisites.
# ls -l /etc/exim4/ | grep 'pem'If you're copying over the old files, then you don't need to change the exim4 default configuration. If you're editing the exim config, here's how:
-rw-r----- 1 root Debian-exim 3456 Jun 12 22:01 fullchain.pem
-rw-r----- 1 root Debian-exim 1704 Jun 12 22:01 privkey.pem
/etc/exim4/conf.d/main/03_exim4-config_tlsoptions:
.ifndef MAIN_TLS_CERTIFICATENotice that we're using fullchain again.
#MAIN_TLS_CERTIFICATE = CONFDIR/exim.crt
MAIN_TLS_CERTIFICATE = CONFDIR/fullchain.pem
.ifndef MAIN_TLS_PRIVATEKEY
#MAIN_TLS_PRIVATEKEY = CONFDIR/exim.key
MAIN_TLS_PRIVATEKEY = CONFDIR/privkey.pem
I'm handling these steps in a cert renewal script, but at the time of writing I'm not ready to publish that script due to it having had very little testing.
After updating the cert file location, reload exim.
# service exim4 reloadWatch /var/log/syslog, /var/log/exim4/mainlog and /var/log/exim4/rejectlog for unusual messages.
No comments:
Post a Comment