If you use Symbiosis to host multiple email domains, you’ll want to help your users configure their mail clients to connect. It’s simple to do this for Exim, with a one-time change to your server configuration.
To follow this guide, you will need to be comfortable with the Linux/Unix command line and with editing simple text files. If you’re not, then please contact our support team for help.
What is SNI?
Server Name Indication (SNI) is a TLS mechanism that lets your client tell the server which domain it wants to connect to, so that the server can provide the correct security certificate to the client. It’s widely used for web sites, but less widely implemented in mail servers. It also helps prevent “server name mismatch” errors.
A note on paths
Symbiosis understands that /srv/
contains directories named for local domains, and Exim in Symbiosis understands that too. If you’re using Exim on another operating system, you might be able to use the same configuration snippet by altering the paths in it.
Configuring Exim
In Exim, the variable $tls_sni
contains the SNI string, if there is one. It’s not sanitised, so we’ll put in a test to ensure the string contains a domain, and then look for an SSL certificate in the expected place. We’ll also add logging of the string, to make debugging a bit easier.
So, you’ll need to edit /etc/exim4/symbiosis.d/00-main/50-tls-options
, then rebuild the Exim configuration. Note that you’ll need to remove or comment out the existing definitions of tls_certificate
and tls_privatekey
.
# log the TLS_SNI string when an email is accepted. log_selector = +tls_sni #tls_certificate = /etc/ssl/ssl.combined #tls_privatekey = /etc/ssl/ssl.combined # here we test that $tls_in_sni really is a domain, but constructing an arbitrary email address foo@... # and then extracting the domain with a function that should fails if the email address is not valid # then we looks to see that the cert exists, and use it # otherwise we use the default cert in /etc/ssl tls_certificate = \ ${if and {\ { eq {${domain:foo@$tls_in_sni}} {$tls_in_sni}}\ { exists{/srv/$tls_in_sni/config/ssl/current/ssl.combined} }\ }\ {/srv/$tls_in_sni/config/ssl/current/ssl.combined}\ {/etc/ssl/ssl.combined}\ } # "tls_privatekey" defaults to the value of tls_certificate, which is fine. #
Testing the configuration
When you’ve made the change to 50-tls-options
, you’ll need to test that your configuration is safe, then deploy and finally test that the new configuration is actually working.
# change directory cd /etc/exim4 # this is safe make test # make sure only the expected changes are present diff exim4.conf exim4.conf.tmp
If you’re happy with those changes, then use Exim to check the syntax as follows:
# check the syntax exim -bV -C exim4.conf.tmp
The output should look something like this:
Exim version 4.89 #1 built 10-Feb-2018 08:26:05 Copyright (c) University of Cambridge, 1995 - 2017 (c) The Exim Maintainers and contributors in ACKNOWLEDGMENTS file, 2007 - 2017 Berkeley DB: Berkeley DB 5.3.28: (September 9, 2013) Support for: crypteq iconv() IPv6 PAM Perl Expand_dlfunc GnuTLS move_frozen_messages Content_Scanning DKIM DNSSEC Event OCSP PRDR PROXY SOCKS TCP_Fast_Open Lookups (built-in): lsearch wildlsearch nwildlsearch iplsearch cdb dbm dbmjz dbmnz dnsdb dsearch ldap ldapdn ldapm mysql nis nis0 passwd pgsql sqlite Authenticators: cram_md5 cyrus_sasl dovecot plaintext spa tls Routers: accept dnslookup ipliteral iplookup manualroute queryprogram redirect Transports: appendfile/maildir/mailstore/mbx autoreply lmtp pipe smtp Fixed never_users: 0 Configure owner: 0:0 Size of off_t: 8 Configuration file is /etc/exim4/exim4.conf.tmp
Deploying your configuration
If no errors are shown, then deploy. This will build the configuration, and reload Exim
cd /etc/exim4 make
Verifying it works
Finally, test that Exim is doing the right thing. This will work best if you’ve kept /srv/
tidy. Ideally, it only contains directories, each of which is named for a domain. Hidden files (with names starting with a dot) are ok, but anything else will produce unnecessary output with this test.
for m in `ls /srv` do servername=$m; echo -n "$m: "; (sleep 0.3;echo quit)|openssl s_client -connect localhost:smtp -starttls smtp -servername $servername 2>&1 | openssl x509 -noout -subject; done
Ideally, for every domain that has a certificate, you’ll see a line like this, with the two domains matching. For other domains, the CN will be your default domain.
example.com: subject=CN = example.com
Subdomain implementation strategy
The instructions above will allow Exim to serve the SSL certificate for all your domains. But, Symbiosis publishes subdomains like “mx.example.com” and “mail.example.com“. Symbiosis’ Let’s Encrypt certificates will automatically cover “www.example.com“, but not the “mx” and “mail” subdomains, so you might want to add coverage for those by creating the aliases /srv/mx.example.com/
and /srv/mail.example.com/
pointing to /srv/example.com/
.
So, for each domain that you install, you might want to run the following (replacing example.com
with the correct domain name):
# set your domain name here domain=example.com # create the links cd /srv/ ln -s $domain mx.$domain/ ln -s $domain mail.$domain/ # symbiosis will do these bits on a schedule, but you might want to speed it up # generate DNS symbiosis-dns-generate --verbose # get certificates symbiosis-ssl --verbose