I recently switched my VPS from Linode to Hetzner. I got more CPU, RAM and storage for a couple of dollars less. Pretty good right?
However it wasn’t after I migrated that I found out Hetzner blocks all outgoing port 25 and 465 traffic.
At least for the first month for new customers.
This means my new server cannot talk SMTP with the rest of the world i.e. my server cannot send mail!
I can see why they would do this, however this is less than ideal if you have a production server with a couple of webshops.
So, now what?
My server cannot send mail itself but it can also not connect to a smarthost (a different server that does the mail sending), because smarthosts are typically also on port 25/465.
I do however have a Raspberry Pi in my home network. What if I run a mail server on a different port there, say 2500?
So, my VPS can relay the mail there. But I don’t want my Pi to be connected to the internet and send mail. So then what? Why not relay from the Pi to an actual smarthost. Which smarthost? Well my ISP offers authenticated SMTP so I can relay mail from my VPS to my Pi and from my Pi to my ISP. And my ISP can send the mail to anywhere.
This could work.
This is what it looks like.
There are two mail server configurations in place. I use
exim4 on Debian and you can easily run
dpkg-reconfigure exim4-config to (re)create a valid Exim config.
This next command will (re)create the file which holds all specific configuration:
It’s a small and easy to understand file. Here follow the complete contents of both files, for reference.
Hetzner VPS exim4 config
dc_eximconfig_configtype='satellite' dc_other_hostnames='topicalcovers.com;brug.info;piks.nl;j11g.com;posthistorie.nl;server.j11g.com' dc_local_interfaces='188.8.131.52' dc_readhost='willempasterkamp.nl' dc_relay_domains='' dc_minimaldns='false' dc_relay_nets='' dc_smarthost='184.108.40.206::2500' CFILEMODE='644' dc_use_split_config='false' dc_hide_mailname='false' dc_mailname_in_oh='true' dc_localdelivery='mail_spool'
Raspberry Pi exim4 config
dc_eximconfig_configtype='smarthost' dc_other_hostnames='' dc_local_interfaces='192.168.178.135' dc_readhost='' dc_relay_domains='posthistorie.nl,topicalcovers.com,piks.nl,j11g.com,server.j11g.com,willempasterkamp.nl' dc_minimaldns='false' dc_relay_nets='220.127.116.11' dc_smarthost='mail.solcon.nl' CFILEMODE='644' dc_use_split_config='false' dc_hide_mailname='false' dc_mailname_in_oh='true' dc_localdelivery='mail_spool'
For this to work you also need to edit your file
/etc/exim4/passwd.client with the a valid mailboxname and password:
The above configs are what you need to do on your servers. Next, you need to change your SPF records.
The SPF records tell the receiving mailserver that the sending mailserver is allowed to relay/send mail for a specific domain.
As you can tell I have multiple domains, so that means editting multiple SPF records. Here is what one SPF records looks like. This is public information, anyone can (and should) look up your domain SPF records.
This is the raw SPF record:
v=spf1 mx ip4:18.104.22.168 ip4:22.214.171.124 ip4:126.96.36.199/24 ip6:2001:9e0:8606:8f00::1 ip6:2a01:7e01::f03c:91ff:fe02:b21b ip6:2001:9e0:4:32::107 ip6:2001:9e0:4:32::108 ip6:2a01:4f8:1c1c:79a1::1 ~all
You can see it’s a mix of IPv4 and IPv6. For readability, the next image is what it actually says.
MX – All mail for this domain should be send TO a specific IPv4 or IPv6 address.
Next: you can see which IPv4 and IPv6 addresses are allowed to send mail for this domain. So where mail is accepted FROM.
So if my VPS wants to send a mail to @gmail.com it will relay the mail to my Pi, which will happily accept the mail, and will relay it to my ISP mail server, and my ISP mail server will try to deliver the mail to Google Mail. Google Mail however will CHECK if the IP address for my ISP mail server MATCHES the SPF records. If Google finds that the IP addresses from my ISP mail servers are not in the SPF records, it will not accept the mail. But if they match, so Google Mail will accept the mail.
Also published on Medium.