spf-discuss
[Top] [All Lists]

HOWTO: track SPF requests to see who says to be you

2004-11-25 06:15:49
[The following text is distributed under the GFDL licence and
therefore can be added to any Web page about SPF. Fixing the english
mistakes is of course allowed.]

You want to publish SPF records but you fear that some of your email
will be rejected by SPF-checking sites?

You have heard that SPF records not ending in -all are for sissies
only but you're not sure?

You have read some people's messages on spf-discuss saying there is no
problem with forwarding and no problem with roaming users, but you do
not trust them?

You abide by the rule that changes in architecture should be
field-tested before being rolled out? 

You are right. Here is a way to test what the SPF checkers will
see. You just need a DNS server able to log requests (we will use BIND
9).

<troll>This is a patent-pending technique, invented by me. I intend to
grant a RAND licence to anyone I like. The obvious prior art does not
bother me, since the DNS records are not archived, it will be
impossible to prove that other people used that technique before
me.</troll>

First, you need a *dedicated* name server. Unfortunately, there is no
way in BIND 9 to log requests on a per-zone or per-view basis. You do
not need a dedicated machine but you need a dedicated name daemon (you
can use several IP addresses on one machine, if there is already a
name server running, this is not covered in this HOWTO.)

Then, you need to configure it to log requests. In named.conf:

logging {
              channel "query_log" {
                   file "/var/tmp/query.log" versions 3 size 2m;
                   print-time yes;
                   print-category yes;
               };
              category "queries" { "query_log"; };
};

Read the BIND's ARM (Administrator Resource Manual) to get the
details. Basically, It tells BIND to log every query to
/var/tmp/query.log.

You must *restart* the name server. Reloading is not sufficient. Then,
you should have a /var/tmp/query.log file and requests sent to the
name server will be logged in it.

Then, configure your name server to serve the SPF tracking zone:

options {
   ... (Other options)
      recursion no;
};

zone "spf-tracker.example.net" {
    type master;
    file "spf-tracker.example.net";
};

And in the spf-tracker.example.net file, you put something like:

$TTL    86400
@       IN      SOA   ns.spf-tracker.example.net. hostmaster.example.net. (
                  2004112501         ; Serial
                      604800         ; Refresh
                       86400         ; Retry
                     2419200         ; Expire
                       86400 )       ; Negative Cache TTL
@       IN      NS      ns
@       IN      MX     0   0.0.0.0
@       IN      TXT   "v=spf1 -all"
ns       IN      A      X.Y.Z.T

And reload your name server. The last step is to actually delegate
spf-tracker.example.net to ns.spf-tracker.example.net (not covered in
this HOWTO).

Then, it is time to modify your SPF record. Keep an eye on your
favorite draft-of-the-day, I use draft-schlitt-spf-00
(http://www.midwestcs.com/spf/spf_classic_libspf2/draft-schlitt-spf-00.html)
and read about macros. I have choosen the following string to make the
actual DNS request:

%{i}._.%{h}._.%{s}._.%{r}.spf-tracker.example.net 

although experience seems to indicate that %{r} is not widely
implemented.

To make the SPF checkers query that string, I add it in my SPF record,
just *before* the final "?all" (since we are testing, we use a ? for
the last mechanism):

example.net. IN TXT "v=spf1 mx 
+exists:%{i}._.%{h}._.%{s}._.%{r}.spf-tracker.example.net ?all"

That's all. Soon, you will see SPF checkers starting to query you. You
can test right now by sending mail from various places and different
setups to echo(_at_)generic-nic(_dot_)net or 
spfenabled(_at_)pobox(_dot_)com(_dot_)

Here is a typical request, as logged by BIND:

25-Nov-2004 13:46:33.580 queries: client 208.58.1.193#17010: query: 
80(_dot_)67(_dot_)170(_dot_)20(_dot_)_(_dot_)foo(_dot_)bar(_dot_)_(_dot_)bortzmeyer\(_at_)example(_dot_)net(_dot_)_(_dot_)r(_dot_)spf-tracker(_dot_)example(_dot_)net
 IN A -

You can see that the SPF checker is 208.58.1.193 (a Pobox machine),
its SMTP client was 80.67.170.20, which announced itself in HELO as
foo.bar, the sender claimed to be bortzmeyer(_at_)example(_dot_)net(_dot_) 

Writing the Python or Ruby script to parse the log and make statistics
is left as an exercice. In practice, it is more interesting to
manually examine the log: each line is a problem, a sender which did
not pass through your known SMTP senders. Either it was a worm or a
configuration bug that you should investigate before switching from
"?all" to "-all".