Showing posts with label Sender Policy Framework. Show all posts
Showing posts with label Sender Policy Framework. Show all posts

Sunday, November 4, 2018

Goodness, Enumerated by Robots. Or, Handling Those Who Do Not Play Well With Greylisting

SMTP email is not going away any time soon. If you run a mail service, when and to whom you present the code signifying a temporary local problem code is well worth your attention.

SMTP email is everywhere and is used by everyone.

If you are a returning reader, there is a higher probability that you run a mail service yourself than in the general population.

This in turn means that you will be aware that one of the rather annoying oversights of the original and still-current specifications of the SMTP based mail system is that while it's straightforward to announce which systems are supposed to receive mail for a domain, specifying which hosts would be valid email senders was not part or the original specification at all.

Note: This piece is also available without trackers but classic formatting only here.

Any functioning domain MUST have at least one MX (mail exchanger) record published via the domain name system, and registrars will generally not even let you register a domain unless you have set up somewhere to receive mail for the domain.

But email worked most of the time anyway, and while you would occasionally hear about valid mail not getting delivered, it was a rarer occurrence than you might think.

Then a few years along, the Internet grew out of the pure research arena and became commercial, and spam started happening. Even in the early days of spam it seems that a significant subset of the messages, possibly even the majority, was sent with faked sender addresses in domains not connected to the actual senders.

Over time people have tried a number of approaches to the problems involved in getting rid of unwanted commercial and/or malware carrying email. If you are interested in a deeper dive into the subject, you could jump over to my earlier piece Effective Spam and Malware Countermeasures - Network Noise Reduction Using Free Tools (also here).

Two very different methods of reducing spam traffic were originally formulated at roughly the same time, and each method's adherents are still duking it out over which approach is the better one.

One method consists simply of implementing a strict interpretation of a requirement that was already formulated in the SMTP RFC at the time.

The other is a complicated extension of the SMTP-relevant data that is published via DNS, and full implementation would require reconfiguration of every SMTP email system in the world.

As you might have guessed, the first is what is commonly referred to as greylisting, where we point to the RFC's requirement that on encountering a temporary error, the sender MUST (RFC language does not get stronger than this) retry delivery at a later time and keep trying for a reasonable amount of time.

Spammers generally did not retry as per the RFC specifications, and even early greylisting adopters saw huge drop in the volume of spam that actually made it to mailboxes.

On the other hand, end users would sometimes wonder why their messages were delayed, and some mail administrators did not take well to seeing the volume of data sitting in the mail spool directories grow measurably, if not usually uncontrollably, while successive retries after waiting were in progress.

In what could almost almost appear as a separate, unconnected universe, other network engineers set out to fix the now glaringly obvious omission in the existing RFCs.

A way to announce valid senders was needed, and the specification that was to be known as the Sender Policy Framework (SPF for short) was offered to the world. SPF offered a way to specify which IP addresses valid mail from a domain were supposed to come from, and even included ways to specify how strictly the limitations it presented should be enforced at the receiving end.

The downsides were that all mail handling would need to be upgraded with code that supported the specification, and as it turned out, traditional forwarding such as performed by common mailing list software would not easily be made compatible with SPF.

The flame wars over both methods. You either remember them or should be able to imagine how they played out.

And while the flames grew less frequent and generally less fierce over time, mail volumes grew to the level where operators would have a large number of servers for outgoing mail, and while the site would honor the requirement to retry delivery, the retries would not be guaranteed to come from the same IP address as the original attempt.

It was becoming clear to greylisting practitioners that interpreting published SPF data as known good senders was the most workable way forward. Several of us already had started maintaining nospamd tables (see eg this slide and this), and using the output of

$ host -ttxt domain.tld

(sometimes many times over because some domains use include statements), we generally made do. I even made a habit of publishing my nospamd file.

As hinted in this slide, smtpctl (part of the OpenSMTPd system and in your OpenBSD base system) now since OpenBSD 6.3 is able to retrieve the entire contents of the published SPF information for any domain you feed it.

Looking over my old nospamd file during the last week or so I found enough sedimentary artifacts there, including IP addresses for which there was no explanation and that lacked a reverse lookup, that I turned instead to deciphering which domains had been problematic and wrote a tiny script to generate a fresh nospamd on demand, based on fresh SPF lookups on those domains. The list of domains fed to the script is available here, but please do edit to suit your local needs.

For those wary of clicking links to scripts, it reads like this:

#!/bin/sh
domains=`cat thedomains.txt`
outfile=nospamd
generatedate=`date`
operator="Peter Hansteen <peter@bsdly.net>"
locals=local-additions

echo "##############################################################################################">$outfile;
echo "# This is the `hostname` nospamd generated from domains at $generatedate. ">>$outfile;
echo "# See https://bsdly.blogspot.com/2018/11/goodness-enumerated-by-robots-or.html for some">>$outfile;
echo "# background and on why you should generate your own and not use this one.">>$outfile;
echo "# Any questions should be directed to $operator. ">>$outfile;
echo "##############################################################################################">>$outfile;
echo >>$outfile;

for dom in $domains; do 
 echo "processing $dom";
 echo "# $dom starts #########">>$outfile;
 echo >>$outfile;
 echo $dom | doas smtpctl spf walk >>$outfile;
 echo "# $dom ends ###########">>$outfile;
 echo >>$outfile;
done

echo "##############################################################################################">>$outfile;
echo "# processing done at `date`.">>$outfile; 
echo "##############################################################################################">>$outfile;

echo "adding local additions from $locals";
echo "# local additions below here ----" >>$outfile;
cat $locals >> $outfile;

If you have been in the habit of fetching my nospamd, you have been fetching the output of this script for the last day or so.

What it does is simply read a prepared list of domains, run them through smtpctl spf walk and slap the results in a file which you would then load into the pf configuration on your spamd machine. You can even tack on a few local additions that for whatever reason do not come naturally from the domains list.

But I would actually recommend you do not fetch my generated data, and rather use this script or a close relative of it (it's a truly trivial script and you probably can create a better version) and your own list of domains to generate a nospamd tailored to your local environment.

The specific list of domains is derived from more than a decade of maintaining my setup and the specific requests for whitelisting I have received from my users or quick fixes to observed problems in that period. It is conceivable that some domains that were problematic in the past no longer are, and unless we actually live in the same area, some of the domains in my list are probably not relevant to your users. There is even the possibility that some of the larger operators publish different SPF information in specific parts of the world, so the answers I get may not even match yours in all cases.

So go ahead, script and generate! This is your chance to help the robots generate some goodness, for the benefit of your users.

In related news, a request from my new colleagues gave me an opportunity to update the sometimes-repeated OpenBSD and you presentation so it now has at least some information on OpenBSD 6.4. You could call the presentation a bunch of links in a thin wrapper of advocacy and you would not be very wrong.

If you have comments or questions on any of the issues raised in this article, please let me know, preferably via the (moderated) comments field, but I have also been known to respond to email and via various social media message services.

Update 2018-11-11: A few days after I had posted this article, an incident happened that showed the importance of keeping track of both goodness and badness for your services. This tweet is my reaction to a few quick glances at the bsdly.net mail server log:

A little later I'm clearly pondering what to do, including doing another detailed writeup.
Fortunately I had had some interaction with this operator earlier, so I knew roughly how to approach them. I wrote a couple of quick messages to their abuse contacts and made sure to include links to both my spamtrap resources and a fresh log excerpt that indicated clearly that someone or someones in their network was indeed progressing from top to bottom of the spamtraps list.
As the last tweet says, delivery attempts stopped after progressing to somewhere into the Cs. The moral might be that a list of spamtraps like the one I publish might be useful for other sites to filtering their outgoing mail. Any activity involving the known-bad addresses would be a strong indication that somebody made a very unwise purchasing decision involving address lists.

Update 2019-08-07: Gmail seems to be stuck on considering bsdly.net mail spam these days. If you are using a Google-attached mail service and have not received mail you were expecting from me, please check your spam folder and if you find anything, please use the "Report as not spam" feature.

Update 2019-08-07: Updated script and generated file comment with encouragement to generate your own nospamd based on local needs, included link to the list used for the last generate-nospamd run.
Goodness, Enumerated by Robots. Or, Handling Those Who Do Not Play Well With Greylisting is © 2018 Peter N. M. Hansteen (published 2018-11-04)
You might also be interested in reading selected pieces via That Grumpy BSD Guy: A Short Reading List (also here).

Thursday, October 20, 2016

Is SPF Simply Too Hard For Application Developers?

The Sender Policy Framework (SPF) is unloved by some, because it conflicts with some long-established SMTP email use cases. But is it also just too hard to understand and to use correctly for application developers?

Here is a story involving a web-based contact form that indicates that this may be the case.


A wise man once noted that only two things in life are inevitable: death and taxes.

Just how taxes and interactions with the tax authorities are handled vary widely from jurisdiction to jurisdiction, but in Norway, where I live, the default mode of contact with the tax authorities for most of us is via web forms protected by sometimes cumbersome authentication procedures and the occasional alert via SMS text message to your phone.

Note: This piece is also available without trackers but classic formatting only here.

And we're used to that the things just work with only occasional and very minor technical embarrassments for the people who operate the thing.

Then in August 2016, I tried to report a bug via the contact form at Altinn.no, the main tax authorities web site.

The report in itself was fairly trivial: The SMS alert I had just received about an invoice for taxes due contained one date, which turned out to be my birth date rather than the invoice due date. Not a major issue, but potentially confusing to the recipient until you actually log in and download the invoice as PDF and read the actual due date and other specifics.

The next time I checked my mail at bsdly.net, I found this bounce.

The meat of the message is

support@altinn.no
    SMTP error from remote mail server after RCPT TO::
    host mx.isp.as2116.net [193.75.104.7]: 550 5.7.23 SPF validation failed   


which means that somebody, somewhere tried to send a message to support@altinn.no, but the message could not be delivered because the sending machine did not match the published SPF data for the sender domain.

SPF expands to "Sender Policy Framework", which is one of the early and still valid ways for a domain to publish which hosts are supposed to be sending mail on the domain's behalf.

There is no requirement to refuse delivery of mail from a host that is not in a domain's SPF record, and emphatically so when no such record exists. On the other hand, when a domain does publish SPF data, rejecting mail from hosts that are not in the set published is a valid and accepted action.

What happened is actually quite clear even from the part quoted above: the host mx.isp.as2116.net [193.75.104.7] tried to deliver mail on my behalf (I received the bounce, remember), and since I have no agreement for mail delivery with the owners and operators of that host, it is not in bsdly.net's SPF record either, and the delivery fails.

The bounce message contained one Received: header which tells part of the story, and after decoding the MIME-encoded part it becomes clear that it contains my bug report with some slightly odd markup.

So it's clear that what produced the bounce was that the contact form had tried to deliver mail using the address I had given the contact form.

I can hear your groans all the way from there to here.

My original bug report had not been delivered, but I thought perhaps I could help them with the other problem, so I sent off a new message to the addresses that were given as contacts in the altinn.no domain's whois info, taking care to send it from a machine that was properly authorized to send mail for my domain.

The full text of the message is available here, in Norwegian. The message includes the bounce with a short introduction that said essentially "this is the result of trying to submit a bug report via your web contact form. This is clearly an SPF problem, please look into that".

Then that message bounced, too.

The exact reason is likely buried in the configuration files for altinn.no's MX, but it could be that it has some reservations against accepting mail from what it sees as a subdomain that doesn't have an MX record of its own.

Anyway, by then I had spent far too much time on this rather trivial matter while I was supposed to be doing other things, so I quickly wrote up a summary and sent it off to the same contact addresses, this time from my gmail.com account, with the various accumulated data as attachments.

Then, as often happens when dealing with the authorities, nothing happened. For quite a while.

It was only on October 18, 2016 that my gmail.com account received a reply from the support address, which quoted my last message in full, and added their resolution text saying:

"Løsning:
Det kan se ut som du har Sender Policy Framework (SPF) aktivert på din mailserver, Det er en kjent svakhet ved vårt kontaktskjema at mailservere med SPF ikke støttes.
"

Translation:

"Solution:
It looks like you have Sender Policy Framework (SPF) enabled on your mailserver, It is a known weakness of our contact form that mailervers with SPF are not supported.
"

Once again, I can hear and fully sympathize with your groans.

This is as perfectly wrong as can be, in fact the exact opposite of right.

The obvious answer should be, as you will agree if you're still reading: The form's developer should place the user's email address in the Reply-To: field, and send the message as its own, valid local user. That would solve the problem.

So I put it to you: Is SPF, the Sender Policy Framework, simply too hard for application developers to understand?

Yes, I'm well aware that SPF also breaks traditional forwarding of the type generally used by mailing lists and a few other use cases. Just how afraid should we be when those same developers come to do battle with the followup specifications such as DKIM and (shudder) the full DMARC specification?

I anticipate your feedback in comments, or if you have things you really want me to only paraphrase in public, email.



Update 2016-12-02: While looking for something else entirely, I stumbled across the DMARC FAQ, where the next to final entry describes the exact problem described in this column. Developers should perhaps learn to read FAQs.

To wit,


Why are messages I send on behalf of visitors to my website being blocked?

This depends on how you are sending these messages. If you are simply taking the website visitor’s email address and inserting it into the “From:” header of the message, and sending that message from your own servers, then you are impersonating the domain in their email address – in a way that is indistinguishable from spammers. These practices may have worked previously – in many cases for decades – because before spam became a literally overwhelming problem, nobody checked. The most successful initial mechanisms to combat such spam were IP address-based blocklists, and so your site may have been allowed to continue because it did not appear on such a list.
For the past decade, however email authentication has been introduced as a filtering mechanism, and is increasingly being used to detect and block such messages.As a best practice, you should instead be using a domain you control in the address of the From: header, and use mechanisms like SPF, DKIM, and DMARC to show that this message is authorized to use your domain. In the example below, the site visitor’s name is shown in the descriptive part of the From: header, and the Reply-To: header is set to the website visitor’s address, but the actual address used in the From: header clearly indicates that your website is the origin of the message.
From: "John Doe via the Example Website" <service@website.example.com>
Reply-To: "John Doe" <john@firstmailboxprovider.com>
To: "Bob Smith" <bob@secondmailboxprovider.com>
Subject: "An article I thought you would find interesting"

Taken from the DMARC.ORG FAQ: 4.23 Why are messages I send on behalf of visitors to my website being blocked? as of December 2. 2016.