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 reboot yum --disableexcludes=main update reboot
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:
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.
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:
PURGE_DENY = 4w BLOCK_SERVICE = ALL DENY_THRESHOLD_VALID = 5 ADMIN_EMAIL = root SMTP_FROM = DenyHosts <email@example.com> SYSLOG_REPORT = yes SYNC_SERVER = http://xmlrpc.denyhosts.net:9911 SYNC_INTERVAL = 1h SYNC_UPLOAD = yes
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.
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.