SPF

Uit De Vliegende Brigade
Naar navigatie springen Naar zoeken springen

Een SPF-record lijkt op reverse DNS: Het is een DNS-entry (een tekstveld om precies te zijn) dat aangeeft welke computers geauthoriseerd zijn om namens een bepaald domein e-mail te versturen. Zonder SPF-records zal e-mail snel als spam worden aangemerkt. Daarnaast is een domein met correcte SPF-records minder interessant voor spoofing, omdat dat gemakkelijk onthuld kan worden.

Header-meldingen

Voorbeeld van header-meldingen voor een domein waar SPF nog niet is ingesteld: De e-mail is verstuurd naar een Gmail-account:

Received-SPF: 
   none (google.com: info@example.de does not designate permitted sender hosts)
   client-ip=83.173.149.10; 
   Authentication-Results: mx.google.com;

spf=none 
   (google.com: info@example.de does not designate permitted sender hosts) 
   smtp.mail=info@example.de

En nu voor een verbeterde variant (niet precies vergelijkbaar met de situatie hiervoor):

Received-SPF: 
   pass (plesk2.dudsfsd.net: domain of example.de designates 37.79.127.236 as permitted sender)
   client-ip=37.79.127.236;
   envelope-from=info@example.de;

Theorie

Een SPF-entry, ook bekend als SPF resource record (RR), komt in twee smaken: SPF RR en SPF TXT RR. Het gaat alleen om deze laatste.

Syntaxis

Enkele identieke manieren om de syntaxis te beschrijven:

v=spf1 [ [sender mechanism] [sender mechanism] ... [modifier1] [modifier2] ]
v=spf1 [ [mechanism]        [mechanism]        ... [modifier1] [modifier2] ]
v=spf1 [ [[pre] type]       [[pre] type]       ... [modifier1] [modifier2] ]
v=spf1 [ [[qualifier] type] [[qualifier] type] ... [modifier1] [modifier2] ]

Een SPF TXT RR kan uit meerdere type's bestaan die door een spatie worden gescheiden, en wordt van links naar rechts geëvalueerd. Evaluatie stopt als een passende regels is gevonden, of als het eind van het record is bereikt. Type's moeten dus van specific naar algemeen worden opgegeven. Dit is de reden waarom -all de laatste type in een record is.

spf1

Een record begint verplicht met

v=spf1

Op dit moment is versie 1 de enige bestaande versie.

Qualifiers

Een mechanism kan voorafgegaan worden door een qualifier die aangeeft hoe het betreffende mechanisme geëvalueerd dient te worden:

+ Pass - Dit is de standaardwaarde. Je kunt '+' daarom weglaten
- Fail
~ Softfail
? Neutral

Types

Mechanismes om designated outbound mailers te specifieren:

ip4     - Dit IPv4-adres/range mag verzenden
ip6     - Dit IPv6-adres/range mag verzenden
a       - Gebruik DNS A-records voor verificatie
mx      - Gebruik DNS MX-records voor verificatie
ptr     - Gebruik DNS PTR-records voor verificatie
exists  - Test voor het bestaan van een domein
include - Incorporeer de positieve types van het gerefereerde SPF-record

Er is een behoorlijke flexibiliteit in de syntaxis van records. Daarnaast is macro-expansion gedefineerd. Zie [1] voor details.

En als laatste: Je kunt maar één SPF-record per domeinnaam hebben. Sommige mensen hadden bedacht om bv. een apart SPF-record voor IPv4 en een apart record voor IPv6 te hebben, maar dat werkt niet.

IPv4, IPv6 & URL's

Ik begreep dat je van een bepaalde server zowel het IPv4-adres als het IPv6-adres moet specificeren, als deze beide gebruikt kunnen worden door de SMTP-server. Daarnaast geloof ik dat je de bijbehorende URL kunt gebruiken om deze beide af te vangen.

ip4-mechanisme

ip4:<ip4-address>
ip4:<ip4-network-address>/<prefix-length> <=> <ip4-network-address>/<CIDR>

Waarbij prefix=length hetzelfde is als CIDR, oftewel Classless Inter-Domain Routing. Het getal na de schuine streep, geeft het aantal vastgestelde bits aan in het netmask. Een paar ipv4-voorbeelden:

10.0.0.1/32 → 10.0.0.1 is het basisadres, 32 bits zijn vastgelegd. Masker = 255.255.255.255 → 2^0 = 1 IP-adres beschikbaar
10.0.0.1/30 → 10.0.0.1 is het basisadres, 30 bits zijn vastgelegd. Masker = 255.255.255.252 → 3 IP-adressen beschikbaar
10.0.0.1/24 → 10.0.0.1 is het basisadres, 24 bits zijn vastgelegd. Masker = 255.255.255.0   → 2^8 = 256 IP-adressen beschikbaar
10.0.0.1/20 → 10.0.0.1 is het basisadres, 20 bits zijn vastgelegd. Masker = 255.255.258.0   → ?
10.0.0.1/16 → 10.0.0.1 is het basisadres, 16 bits zijn vastgelegd. Masker = 255.255.0.0     → 2^16 = 1.048.576 IP-adressen beschikbaar
10.0.0.1/8  → 10.0.0.1 is het basisadres,  8 bits zijn vastgelegd. Masker = 255.0.0.0       → 2^24 IP-adressen beschikbaar

ip6-mechanisme

ip6:<ip6-address>
ip6:<ip6-network-address</<prefix-length> <=> <ip6-network-address</<CIDR>

Include-mechanisme

Tekst van openspf.org/SPF_Record_Syntax:

include:<domain>

The specified domain is searched for a match. If the lookup does not return a match or an error, processing proceeds to the next directive. Warning: If the domain does not have a valid SPF record, the result is a permanent error. Some mail receivers will reject based on a PermError.

Examples:

In the following example, the client IP is 1.2.3.4 and the current-domain is example.com.

v=spf1 include:example.com -all
  • If example.com has no SPF record, the result is PermError.
  • Suppose example.com's SPF record were "v=spf1 a -all". Look up the A record for example.com. If it matches 1.2.3.4, return Pass.
  • If there is no match, other than the included domain's "-all", the include as a whole fails to match; the eventual result is still Fail from the outer directive set in this example.

Trust relationships — The "include:" mechanism is meant to cross administrative boundaries. Great care is needed to ensure that "include:" mechanisms do not place domains at risk for giving SPF Pass results to messages that result from cross user forgery. Unless technical mechanisms are in place at the specified otherdomain to prevent cross user forgery, "include:" mechanisms should give a Neutral rather than Pass result. This is done by adding "?" in front of "include:". The example above would be:

v=spf1 ?include:example.com -all

In hindsight, the name "include" was poorly chosen. Only the evaluated result of the referenced SPF record is used, rather than acting as if the referenced SPF record was literally included in the first. For example, evaluating a "-all" directive in the referenced record does not terminate the overall processing and does not necessarily result in an overall Fail. (Better names for this mechanism would have been "if-pass", "on-pass", etc.)

Modifiers

Als laatste kan een SPF-regel modifiers bevatten. Er zijn er twee, en ze mogen beiden slechts eenmaal gebruikt worden:

redirect
exp

Deze worden hier niet verder behandeld.

Voorbeelden

De MX-entry die bij het domein hoort is ok. De rest niet:

v=spf1 mx -all

Geen enkele server is geauthoriseerd. Dit domein verstuurd waarschijnlijk geen email:

v=spf1 -all

Alle servers zijn geauthoriseerd. Dat is gek:

v=spf1 +all

Het a-record van domein mail.example.com geeft de geauthoriseerde server weer:

v=spf1 a:mail.example.com -all

Allow any IPv6 address between 1080::8:800:0000:0000 and 1080::8:800:FFFF:FFFF:

v=spf1 ip6:1080::8:800:200C:417A/96 -all

Drie IPv4-adressen mogen emailen:

v=spf1 ip4:204.200.197.197 ip4:199.236.109.182 ip4:72.54.24.99 -all

Alle ip-adressen 2a01:7c7:7c7:: - 2a01:7c7:7c7::ff (128-120=8 bits submask) mogen emailen. Dit is een effectieve regel om alle potentiële mailservers van TransIP te dekken:

v=spf1 ip6:2a01:7c7:7c7::/120 -all

Casus Sep. 2015: TransIP Web-Only

Een domein draait op een VPS bij TransIP. Email wordt exterm verzorgd door TransIP. Wat zijn de goede instellingen voor SPF?

Test: Verzenden van een email middels de SMTP Authentication Support-module voor Drupal naar een Gmail-account.

Eerste iteratie (do. 17 sep.) - Fail

Header:

Received-SPF: fail (google.com: domain of info at example5 punt nl does not designate 2a01:7c7:7c7::69 as permitted sender) client-ip=2a01:7c7:7c7::69;
spf=fail (google.com: domain of info at example5 punt nl does not designate 2a01:7c7:7c7::69 as permitted sender) smtp.mailfrom=info at example5 punt nl

Tweede iteratie (vr. 18 sep.) - Fail

SPF-record - Vantevoren:

v=spf1 a mx a:transip.nl mx:transip.nl a:mail.example2.nl mx:mail.example2.nl 
a:submission2.mail.example2.nl a:outbound0.mail.example2.nl -all

Header:

Received-SPF: fail (google.com: domain of info at example5 punt nl does not designate 2a01:7c7:7c7::72 as permitted sender) client-ip=2a01:7c7:7c7::72;
spf=fail (google.com: domain of info at example5 punt nl does not designate 2a01:7c7:7c7::72 as permitted sender) smtp.mailfrom=info at example5 punt nl

Nieuw SPF-record:

De verzendende servers hebben ipv6-adressen 2a01:7c7:7c7::69 en 2a01:7c7:7c7::72. Wat zal ik daar 's van maken:

  • Van 69 naar 72 is 3 cijfers en dus met 2 bits af te dekken → 2a01:7c7:7c7::69/126 → 2a01:7c7:7c7::69 is het basisadres, en er zijn 2 bits beschikbaar om af te wisselen
  • Om het wat ruimer in te stellen: 2a01:7c7:7c7:: → Nu is het laatste octet ongedefineerd. Dat is 16 bits. Dus 128-16 = 112 bits zijn gedefineerd: 2a01:7c7:7c7::/112 - Is dit een geldige notatie?
  • Ultratools heeft een aardig tooltje. Met 2a01:7c7:7c7:: en 2a01:7c7:7c7::ff als input, krijg je 2a01:7c7:7c7:0:0:0:0:0/120 (256 hosts) als output. Daar kan ik goed mee leven:
v=spf1 ip6:2a01:7c7:7c7:0:0:0:0:0/120 a mx a:transip.nl mx:transip.nl a:mail.example2.nl 
mx:mail.example2.nl a:submission2.mail.example2.nl a:outbound0.mail.example2.nl -all

Derde iteratie (vr. 18 sep.) - Pass

Header:

Received-SPF: pass (google.com: domain of info@example.com designates 2a01:7c7:7c7::69 as permitted sender) client-ip=2a01:7c7:7c7::69;
spf=pass (google.com: domain of info@example.com designates 2a01:7c7:7c7::69 as permitted sender) smtp.mailfrom=info@example.com

Nieuw SPF-record:

Waarschijnlijk kan de spf-regel een stuk korter, en dit is het moment om dat uit te proberen:

v=spf1 ip6:2a01:7c7:7c7::/120 -all

Vierde iteratie (vr. 18 sep.) - Pass

Het ziet er goed uit. Er is een kansje dat dit voorbarig is, en DNS-entries nog niet zijn gepropageerd. Huidige SPF-record:

v=spf1 ip6:2a01:7c7:7c7::/120 -all

Header test-email:

Received-SPF: pass (google.com: domain of info@example.com designates 2a01:7c7:7c7::72 as permitted sender) client-ip=2a01:7c7:7c7::72;
spf=pass (google.com: domain of info@example.com designates 2a01:7c7:7c7::72 as permitted sender) smtp.mailfrom=info@example.com

Vijfde iteratie (za. 19 sep.) - Pass

Nu weet ik het zeker. Header:

Received-SPF: pass (google.com: domain of info@example.com designates 2a01:7c7:7c7::72 as permitted sender) client-ip=2a01:7c7:7c7::72;
spf=pass (google.com: domain of info@example.com designates 2a01:7c7:7c7::72 as permitted sender) smtp.mailfrom=info@example.com

Naderhand

Alleen een IPv6-adres vermelden, geeft storingen indien ook gebruik wordt gemaakt van IPv4. Je moet beide toevoegen.

Casus sep. 2015: Softfail & VPS

Dit betreft een site met een eigen mailserver, plus dat het iets ingewikkelder ligt.

Eerste iteratie - Softfail

Received-SPF: softfail (google.com: domain of transitioning info@example.com
does not designate 2a01:7c8:aaae:5c7:795b:8b65:d534:335e as permitted sender) 
client-ip=2a01:7c8:aaae:5c7:795b:8b65:d534:335e;

spf=softfail (google.com: domain of transitioning info@example.com does not 
designate 2a01:7c8:aaae:5c7:795b:8b65:d534:335e as permitted sender) 
smtp.mailfrom=info@example.com
Received: by example6-01.colo.example3.net (Postfix, from userid 33)

Nieuwe SPF-regel:

v=spf1 ip6:2a01:7c8:aaae:5c7:795b:8b65:d534:335e MX -all

Tweede iteratie - Fail

Vreemd dat er nu een IPv4-afzender-adres staat. Sois:

Received-SPF: fail (google.com: domain of info@example.com does not designate 37.79.127.236 as permitted sender) 
client-ip=37.79.127.236;
spf=fail (google.com: domain of info@example.com does not designate 37.79.127.236 as permitted sender) 
smtp.mailfrom=info@example.com
Received: by example6-01.colo.example3.net (Postfix, from userid 33)

Nieuwe SPF-regel:

v=spf1 ip4:37.79.127.236 ip6:2a01:7c8:aaae:5c7:795b:8b65:d534:335e MX -all

Casus Sep. 2015: Fail of niet?

Beginsituatie

In een vlijtige bui heb ik het SPF-record van een domein 'verbeterd' en nu geeft het soms foutmeldingen. Dit is de foutregel die bij een terugkerende email gegeven werd:

5.7.1 failed SPF. The SPF-record you have published in your DNS is invalid

Dit is de header van een email dat ik vanuit het betreffende account naar een eigen Gmail-account heb gestuurd:

Received: by 10.37.93.8 with SMTP id r8csp2225592ybb;
Received: from outbound2.mail.example2.nl (outbound2.mail.example2.nl. [2a01:7c7:7c7::73])
Received-SPF: pass (google.com: domain of info@example.nl designates 2a01:7c7:7c7::73 as permitted sender) client-ip=2a01:7c7:7c7::73;
Authentication-Results: mx.google.com;
spf=pass (google.com: domain of info@example.nl designates 2a01:7c7:7c7::73 as permitted sender) smtp.mailfrom=info@example.com

Eerste iteratie - Di. 29 sep.

Nieuwe SPF-regel. Deze is een verruiming van de oorspronkelijke regel. De toevoeging include:_spf.example3.email is de standaard-SPF-regel die TransIP lijkt toe te passen bij aanvraag van een Email-Only-account:

v=spf1 include:_spf.example3.email ip4:37.79.127.236 ip6:2a01:7c7:7c7::/120 -all

Tweede iteratie - Wo. 30 sep.

Opnieuw met succes een testmail verstuurd:

Received: from outbound0.mail.example2.nl (outbound0.mail.example2.nl. [2a01:7c7:7c7::69])
Received-SPF: pass (google.com: domain of info@example.com designates 2a01:7c7:7c7::69 as permitted sender) client-ip=2a01:7c7:7c7::69;
Authentication-Results: mx.google.com;
spf=pass (google.com: domain of info@example.com designates 2a01:7c7:7c7::69 as permitted sender) smtp.mailfrom=info@example.com

Geen wijzigingen aangebracht aan de SPF-regel.

Casus okt. 2015: SMTP via Ziggo

Iemand gebruikte SMTP van Ziggo voor versturen van email via een werkstation. Zoals de meeste providers, gebruikt Ziggo meer dan één IP-adres/URI voor uitgaande email. Dit is het rijtje dat ik heb kunnen achterhalen:

smtpq1.tb.mail.iss.as9143.net (212.54.42.164)
smtpq5.tb.mail.iss.as9143.net (212.54.42.168)
smtpq6.tb.mail.iss.as9143.net (212.54.42.169)

Dit is gemakkelijk te vangen in een subnet, bv.:

212.54.42.1/24

maar dat dekt alleen IPv4 en niet IPv6. Daarom wellicht handig om te werken met URL's:

smtpq1.tb.mail.iss.as9143.net/24

Daarnaast kwam ik in een posting ook nog dit rijtje tegen:

smtpq1.gn.mail.iss.as9143.net (212.54.42.164)
smtpq4.gn.mail.iss.as9143.net (212.54.42.168)

en dat is te vangen in bv.:

smtpq1.gn.mail.iss.as9143.net/24

Casus nov. 2015: SMTP via VPS

Deze casus lijkt op deze casus hierboven

Casus juni 2016: SMTP via KPN Exchange

Email wordt verstuurd door een mail server van KPN: cpsmtpb-ews05.kpnxchange.com (213.75.39.8). De betreffende openspf-pagina suggereert als toevoeging aan het SPF-record:

   v=spf1 [...] a:cpsmtpb-ews05.kpnxchange.com -all

Oplossing 10 juni 2016

  • Toegevoegd aan spf-record: a:kpnxchange.com
  • Is dit voldoende, of moet het geëxpandeerd worden naar een compleet CIDR-subnet?

Zie ook

Bronnen