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):

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:

domain.com
domain.dk
domain.no
... 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.

Denyhosts

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.

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.