Jan 242014

My company is an Exchange shop – amongst other things, we develop software that integrate with Exchange server for calendar synchronization purposes.

As we “eat our own dog food” – or “drink our own champagne” if you will – we run Exchange server. We are a small shop, so we only have one server, with no redundancy etc.

In case of server downtime, we need a backup MX hosted somewhere other than our datacenter, so incoming mail isn’t lost while the Exchange server is down.

We used to have a VM with a traditional hosting provider, but that setup became too complicated (the “best” way for us to pay them was with Paypal, and there were problems with them not being able to verify our VAT number after we were merged with our parent company).

So I chose to setup a new VM on Windows Azure for that purpose. I wanted it to be Linux based, to save money on licenses and hardware, and the previous MX was also running CentOS. I have most experience with RedHat and the derived CentOS distribution, and that is what I chose on Azure as well.

Installing the VM

The people at OpenLogic have created an image that can be used directly from the Azure VM Gallery.

When provisioning the CentOS VM you have to add a username and password which will allow you to log on to the VM over SSH. You also add firewall rules, so only specified ports can be accessed on the server. In my case I just wanted ports 22 and 25 for SSH and SMTP.

After provisioning that VM, it is possible to connect to it with SSH. The CentOS version is 6.3. I wanted to be sure to run the latest kernel and other software packages with all security fixes, so I chose to update CentOS.

The VM is pre-configured to ignore kernel updates – there was a bug with the ata_piix drivers so the OpenLogic folks patched the kernel, and to avoid problems the chose to ignore kernel updates, so people did not accidentally update to an unpatched kernel and rendered their Azure VM unbootable.

To upgrade CentOS, I ran these commands (with rebooting, acknowledging prompts, and logging in etc. in between):

yum --disableexcludes=main install kernel-headers
yum upgrade
yum --disableexcludes=main update

Afterwards, the CentOS versions i 6.5, and it is running the latest kernel from the CentOS 6.5 repository.

Configuring Postfix as backup MX

CentOS comes with the Postfix mail transfer agent (SMTP server). Postfix is easy to configure, and has a reputation as being secure.

The only changes to the Postfix configuration to make it a backup MX are these:

in /etc/postfix/main.cf change or add these configuration statements:

inet_interfaces = all 
relay_domains = $mydestination, /etc/postfix/relaydomains
maximal_queue_lifetime = 10d
message_size_limit = 35840000

The above tells Postfix to listen on all network interfaces, allow mail relaying for $mydestination (the server itself) and the domains in the file /etc/postfix/relaydomains. Messages should be queued for 10 days, and the message size limit should be appr. 35 MB.

The /etc/postfix/relaydomains file contains a list of all domains to relay e-mail for. One domain name on each line in the file:

... many more

That is all there is to it for Postfix configuration.

The VM should also be configured to start Postfix:

chkconfig add postfix
chkconfig --list postfix

The first line adds postfix to be started on boot, and the second line shows the runlevels where postfix is started. Runlevel 3 is the normal text mode boot runlevel.


Obviously I used a long and complex password for the user account on the server. But still, to prevent brute force password attacks, I normally use Denyhosts to automatically block IP addresses that have login failures too often. It works by checking the ssh server log to see whether any IP address is unsuccessfully attempting to log on too many times. If one is found, it is added to /etc/hosts.deny which is kind of a black list of IP addresses that this host will never talk to. Read more on http://denyhosts.sourceforge.net/ if you want to try it.

Installing it is fairly simple: Download the package, unpack it, and  run ‘python setup.py install’. Then copy the default configuration file (denyhosts.cfg-dist) to denyhosts.cfg, and make your changes to the defaults. Finally add the init script to the boot scripts, and off you go.

My configuration changes are:

SMTP_FROM = DenyHosts <denyhosts@myownhostname.cloudapp.net>
SYNC_SERVER = http://xmlrpc.denyhosts.net:9911

Basically, I tell it to block access to everything if an IP is banned, allow 5 failed attempts before banning an IP, e-mail root whenever an IP is banned, and also log it to syslog. And use the global denyhosts sync-server to cooperate with other denyhosts users.

Finally, to make denyhosts start automatically, copy the init-script and install it.

cp /usr/share/denyhosts/daemon-control-dist /etc/init.d/denyhosts
chkconfig --add denyhosts
chkconfig --list denyhosts

Opening the firewall

CentOS and RedHat have a nice text-based UI to open ports in the firewall. You can use that (on CentOS it is called system-config-firewall-tui) to open port 25 on the local firewall.

In conclusion

Finally, I just needed to change the DNS records for our domains so that the new MX is listed as secondary mail exchanger with lower priority than our primary MX, and I was all set.

  4 Responses to “Setting up a backup MX using CentOS on Azure”

  1. Hi Rasmus!

    Thank you for your contribitions on making this happen in Azure.
    I know you are creating a backup MX, but wouldn’t it be preferable to builtin eg. SpamAssasin and ClamAV for further protection?

    To the best of my knowledge the server wouldn’t need to backup mails containing spam or viruses in its queue.

    • I haven’t had the need for spam or AV scanning on the backup MX. Its purpose is just to hold mail in case the primary MX is down or unreachable.
      I have filters etc. on the primary MX.

  2. In which file the denyhost stores the denied hosts?

    • It’s been a while since I worked with this, and am no longer working with Linux admin stuff, so I can’t look it up. If I remember correctly, it uses /etc/hosts.deny which it updates on the fly.

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>