HowtoForge

Setting Up A Spam-Proof Home Email Server (The Somewhat Alternate Way) (Debian Squeeze)

Setting Up A Spam-Proof Home Email Server (The Somewhat Alternate Way) (Debian Squeeze)

Introduction

Email spam is a huge problem. I have found for myself quite a simple solution, however it'll take some time to "migrate" completely over to it.

The solution is to create a unique email address everytime I have to give an email address to someone else or to some website to sign up. If I want an account at twitter, I'd use "www.twitter.com@MYDOMAIN.COM". For webbased services, I use the full domain name incl. subdomain (www) on the left of the @ (some poorly designed websites do not recognizes the www. as valid email address, for those I just leave it away).

For people I use a format like that: "email.john.doe@MYDOMAIN.COM". You could also use like "from.john.doe@MYDOMAIN.COM". The good thing is, the left side of the @ for email addresses is almost "unlimited".

Because I generate unique email addresses for every contact, I can easily find out where my email address got leaked and then I can easily remove it.

This howto will set up a full functioning email server with according scripts to make easy email management. It includes also the DNS setup part - even if you are on a dynamic address - e.g. if you want to run your own little mailserver from home.

 

Summary

In this howto I use Debian Squeeze as server. For other Linux distros you'll have to make according changes yourself.

A short summary of what is being done in this howto is like this:

 

Credits

In this howto I also relay on a few other howtos here - especially regarding the setup of the bind and email server. For those, I copied more or less from Falko's Perfect Debian Server howtos. Also the email relay section was borrowed from a howto here by sjau. Without those, I probably would not have been able to set this up.

 

Obtaining a Domain Name

Before you can start running your own mailserver you need a domain name for which you can also set MX records. I don't want to make any suggestion as there are tons and tons of domain registrars out there. One of the cheapest I know of is GoDaddy.

I don't use GoDaddy myself but as far as I've heard they provide a solid service.

 

Handle Dynamic IPs

Another challenge to be facing is how to handle things on a dynamic ip address. If you don't have a dedicated box rented somewhere but use your home internet connection, then very likely you have not a static ip.

In the web it's essential to have a static ip so that others always know where to reach you. However there are services that help you with that.

One of the services I use is EveryDNS. They let me host the DNS for the domain name.

As of now they still offer the service for free. Although they got bought up in 2010, the promise was, that then-customers who have donated money, can also in future use the system for free. On their webpage, they don't mention anything yet that new customers need to pay - but I don't know for sure.

The reason for EveryDNS is, that they offer also a little perl script that can be used to update the DNS. This is essential as your IP changes over time if you don't have a static IP address. You can get the perl script from here.

When you have a domain name then first go to What Is My IP. It will show you your current public ip address. Then create an account at EveryDNS and make at least the following entries where MYDOMAIN.COM would be your domain name:

(1) Make an "A" record type, set as fully qualified domain name "MYDOMAIN.COM" and set as value your public ip address

(2) Make a "CNAME" record type, set as fully qualified domain name "*.MYDOMAIN.COM" and set as "MYDOMAIN.COM"

(3) Make a "MX" record type, set as fully qualified domain name "MYDOMAIN.COM", set as value "MYDOMAIN.COM" and set as "MX Value" "10"

What we just did is setup the DNS for the domain. The main domain is found at your IP address (a-record), all other domains are also found there (the * in the cname record pointing to the main domain) and we also operate a mail server there (mx record).

 

root user

The following things are being done as root user - unless told otherwise.

 

Dyn. IP Update

As said before, if you don't have a static IP address you will need to regurarly update the DNS info.

 

(1) Get the perlscript and make it executable

cd /root
wget http://www.everydns.net/eDNS.pl
chmod 0755 eDNS.pl

 

(2) Create a bash script that calls the perl script (there's other ways but I found that the simplest):

touch eDNS.sh
echo "#!/bin/bash" > eDNS.sh
echo "perl /root/eDNS.pl -u USERNAME -p PASSWORD -d MYDOMAIN.COM" >> eDNS.sh

Replace USERNAME and PASSWORD with your everydns login credentials.

 

(3) Setup a cron to run it regurarly

I love to work with a cron.txt file that contains all crons. I think it's a lot simpler to maintain it like that.

First you have to check out if there is already a cron entry:

crontab -l

If there is no cron entry yet, then just run the following commands

touch cron.txt
chmod 0700 cron.txt
echo "*/5 * * * * /root/eDNS.sh >/dev/null 2>&1" > cron.txt

If there are already cron entries, copy them, create a cron.txt file and insert them and add the following command also:

*/5 * * * * /root/eDNS.sh >/dev/null 2>&1 

Now we load the cron.txt as cron:

crontab cron.txt

And we check if it was added properly:

crontab -l

 

LAN/Routing/Bind

The next problem we're facing then is how to resolve the domain in your lan. If your mail server is behind a router then I will probably have a local ip like 192.168.0.x or 10.0.0.x.

If you are behind a router, you will need to forward the following ports to your server: 25, 80, 143, 443, 991. There could be more ports required like 587.

Also we face the problem on how to resolve the domain name from inside the lan. From outside the lan you have the DNS entry that should point to your current IP address. However when you are inside the lan and make a dns query it will only return your public ip and usuall it will fail then.

There are several solutions for that problem - if the problem even exists at all.

One way would be the use of dnsmasq in routers (e.g. dd-wrt or tomato-wrt). However as I can't guarantee for it to work, the only other option I see is to setup a full fledged DNS server on your mailserver.

In this tutorial I'll use a chrooted Bind9 as I am the most familiar with it. For other DNS servers you'll find plenty of documentation online.

 

(1) Install the software and stop it

apt-get install bind9
/etc/init.d/bind9 stop

 

(2) Change the /etc/default/bind9 config so that the options line is like this:

OPTIONS="-u bind  -t /var/lib/named" 

 

(3) Create the necessary directories under /var/lib:

mkdir -p /var/lib/named/etc
mkdir /var/lib/named/dev
mkdir -p /var/lib/named/var/cache/bind
mkdir -p /var/lib/named/var/run/bind/run

 

(4) Then move the config directory from /etc to /var/lib/named/etc:

mv /etc/bind /var/lib/named/etc

 

ln -s /var/lib/named/etc/bind /etc/bind

 

(6) Make null and random devices, and fix permissions of the directories:

mknod /var/lib/named/dev/null c 1 3
mknod /var/lib/named/dev/random c 1 8
chmod 666 /var/lib/named/dev/null /var/lib/named/dev/random
chown -R bind:bind /var/lib/named/var/*
chown -R bind:bind /var/lib/named/etc/bind

 

(7) Edit the /etc/rsyslog.d/bind-chroot.conf file and add

$AddUnixListenSocket /var/lib/named/dev/log 

 

(8) Restart services

/etc/init.d/rsyslog restart
/etc/init.d/bind9 start

and check /var/log/syslog for errors.

Now we have setup Bind9 in a chrooted environment. The next thing to do is to acutally add a zonefile for your domain.

 

(9) Edit /etc/bind/named.conf.local and add

zone "MYDOMAIN.COM" IN {
        type master;
        file "/etc/bind/zones/MYDOMAIN.COM.db";
        allow-update { none; };
};

 

(10) Create the zone folder and zonefile

mkdir /etc/bind/zones
touch /etc/bind/zones/MYDOMAIN.COM.db
chown -R bind:bind /etc/bind/zones/MYDOMAIN.COM.db

 

(11) Add your zonefile info to MYDOMAIN.COM.db

$TTL    86400
@               IN SOA  @ MYDOMAIN.COM. (
                                        1              ; serial
                                        2600              ; refresh
                                        15M             ; retry
                                        3600              ; expiry
                                        360 )            ; minimum
@               IN NS           ns.MYDOMAIN.COM.
ns              IN A            LOCALIP
www             IN A            LOCALIP
MYDOMAIN.COM.             IN A            LOCALIP
MYDOMAIN.COM.     IN MX   10      LOCALIP

Of course replace MYDOMAIN.COM with your actual domain name and LOCALIP with your static LAN IP address. Bascially we tell here that the nameserver for that domain is hosted on "ns.MYDOMAIN.COM" and "ns.MYDOMAIN.COM" is to be found at the static local ip address.

 

(12) Restart Bind9

/etc/init.d/bind9 restart

 

(13) Change router NS resolution

While Bind9 is setup now, there's one last thing to do. On your router you have to change the nameserver resolution order. The first nameserer must now be your "mail server" with the according static local ip. Otherwise the whole bind9 setup was for nothing. As the second nameserver enter the value of what was aleady in there as first one. Depending on your router it can be a bit trickier.

Setting Up A Spam-Proof Home Email Server (The Somewhat Alternate Way) (Debian Squeeze)