Create your own SPF Macro DNS Host - Auto SPF Flattening aka Compression
I have been reviewing different options for SPF records recently and came across a few interesting articles. One in particular that caught my attention was:
An SPF DNS Server
https://blog.jverkamp.com/2020/07/16/an-spf-dns-server/
Essentially, JP builds an SPF hosting macro server using python and twisted
This solution appears to work well; however is definitely 'roll your own'.
As an email specialist I'm familiar with RBL (Realtime Block List) and how they leverage DNS to get a quick response to whether an IP should be blocked and whether an MTA should accept a message sent from it. It was during my investigation of SPF Macro's that the similarities of how the two worked became apparent.
While there are not many (if any) open source/off the shelf SPF macro hosting solutions. I began looking at things from the point of view 'building your own RBL' and working backwards for the SPF record use case. The concept of SPF is like RBL in reverse, i.e. a permit list.
Thankfully hosting your own RBL was a much more widely discussed topic and I came across rbldnsd https://rbldnsd.io/ which can be used to host your own RBL.
According to their website "rbldnsd is a small and fast DNS daemon which is especially made to serve DNSBL zones. rbldnsd is extremely fast - it outperforms both bind and djbdns greatly. It has very small memory footprint."
I decided to test and investigate further, using the RBL host to deliver DIY SPF Macro hosting. So I stood up a docker container of rbldnsd using a 7 year old image (which is fine, as the project seems to have stopped ~2015):
https://github.com/kurthuwig/docker-rbldnsd
All I needed to do was :
1. Port forward UDP 53 through my firewall to the docker host - this could be hosted on AWS or Azure of course.
2. Create a config file - started with the test one here : http://www.corpit.ru/mjt/rbldnsd.html
3. Run the docker container with the 'command' relative to your config file.
4. Update your DNS host (e.g. Cloudflare) to point 'NS' record for the subdomain hosting SPF _spf.<mydomain>.com to the hostname of my home connection (ns1.<mydomain.com).
5. This then allowed me to perform NS lookups on 5.129.10.10.<mydomain>.com._spf.<mydomain>.com to get a response - any response for SPF is considered a 'pass'. e.g. if the server responds with 127.0.0.2
6. I then went a step further and configured my 'TXT' record on the sending domain for SPF to:"v=spf1 exists:%{ir}.%{d}._spf.<mydomain>.com -all"
"v=spf1 include:%{ir}.%{d}._spf.<mydomain>.com -all"
EDIT: by using SPF macro with include and rbldnsd it allows you to only leverage the TXT record and not the A record; this allows you to responds with 'v=spf1 -all' or 'v=spf1 exists:%{ir}.%{d}.salesforce.com -all' to reference another macro lookup. The advantage of this is that using exists: looks for whether an 'A' record is present or not and doesnt matter what it is.
NOTE: the 'i' in the %{ir} refers to IP address e.g. 10.10.129.5, however rbldnsd responds to the reverse (5.129.10.10) so the 'r' in %{ir} reverses the IP to cater for this. The %{d} is optional and could be useful where you hosting multiple domains - 'd' is the sending envelope domain used for the SPF check. so if my domain was microsoft.com and the sending IP was 10.10.129.5 the lookup that would be checked would be:
5.129.10.10.microsoft.com._spf.example.com e.g.
nslookup 5.129.10.10.microsoft.com._spf.example.com. which if listed in SPF should recieve an 'A' record response of 127.0.0.2 as an example.
Following this I was able to test my SPF record using https://www.kitterman.com/spf/validate.html which confirmed it passed:
Watch this space; I plan to put together technical step by step on this.
Comments
Post a Comment