• If you are still using CentOS 7.9, it's time to convert to Alma 8 with the free centos2alma tool by Plesk or Plesk Migrator. Please let us know your experiences or concerns in this thread:
    CentOS2Alma discussion

Incoming SPF checking not working

websavers

Regular Pleskian
Hey folks,

I've encountered an issue that appears to be occurring across all of our Plesk 12.5 servers with SPF scanning not occurring on any incoming messages. Here's what I know, using one particular server for testing:

1) Incoming emails get the following headers applied:

When "SPF guess rules" configuration value is set to v=spf1 a/24 mx/24 ptr ~all the headers look like this:

Received-SPF: neutral ({servername} : {server IP} is neither permitted nor denied by domain of {domain}) client-ip={IP}; envelope-from={email}; helo={server};

When "SPF guess rules" configuration value is blank the headers look like this:

Received-SPF: none (no valid SPF record)

I have tested this with multiple domains whose SPF records absolutely exist and end with -all. In the test emails where the above SPF headers came from, I was forging the email by sending it from a non-approved server and manually setting the from and envelope-from values.

The server that's receiving the messages can successfully lookup the DNS records. I tested this by running `dig TXT {domain}` using both root and a non-privileged account.

/var/log/maillog contains ZERO entries about SPF. Not even an indication that the filter is starting up like we used to see with Plesk 11.

I've run mchk and it says the SPF filter has been successfully repaired.

Server Details:

CentOS 6.7 Final
Plesk 12.5.30 Update #25, last updated at Mar 17, 2016 02:38 PM

Related Packages:
psa-spf2-1.2.9-11092910.x86_64
perl-Mail-SPF-2.007-1.el6.art.noarch
postfix-2.11.5-centos6.15081418.x86_64

---

Any suggestions as to how to fix this? I want my SPF scanning to work again.
 
This may be a coincidence, but while troubleshooting this issue, I ran the static SPF testing utility with the exact details of the first message that made it through SPF tests when it shouldn't have. Here's the command and results:

# /usr/bin/spfquery_static -ip 43.252.143.56 -sender joe@{domain} -rcpt-to joe@{domain}

failneutral

Please see http://www.openspf.org/Why?id=joe@{domain}&ip=43.252.143.56&receiver=spfquery : Reason: default

spfquery: 43.252.143.56 is neither permitted nor denied by domain of {domain}

Received-SPF: neutral (spfquery: 43.252.143.56 is neither permitted nor denied by domain of {domain}) client-ip=43.252.143.56; envelope-from=joe@{domain};

I ran it with -debug and all looked great in that it checked the domain's SPF record and reported a fail:

Context: Main query
Response result: fail
Response reason: mechanism
Response err: No errors
StartError
EndError

Then it did the final test against the rcpt-to parameter (I say this because if I leave out rcpt-to it fails perfectly as it should):

spf_compile.c:1210 Debug: Compiling record v=spf1 mx:mad:{domain}
spf_compile.c:1314 Debug: Name starts at mx:mad:{domain}
spf_compile.c:1408 Debug: Adding mechanism type 2
spf_compile.c:847 Debug: SPF_c_mech_add: type=2, value=:mad:{domain}
spf_compile.c:689 Debug: Parsing domainspec starting at @{domain}, cidr is optional
spf_compile.c:523 Debug: Parsing macro starting at @{domain}
spf_dns.c:54 Debug: DNS[cache] lookup: @{domain} MX (15)
spf_dns.c:54 Debug: DNS[resolv] lookup: @{domain} MX (15)
spf_dns_resolv.c:311 Debug: query failed: err = -1 Unknown host (1): @{domain}
spf_dns.c:66 Debug: DNS[resolv] found record
spf_dns.c:69 Debug: DOMAIN: @{domain}a TYPE: MX (15)
spf_dns.c:76 Debug: TTL: 0 RR found: 0 herrno: 1 source: resolv
spf_dns.c:66 Debug: DNS[cache] found record
spf_dns.c:69 Debug: DOMAIN: @{domain} TYPE: MX (15)
spf_dns.c:76 Debug: TTL: 0 RR found: 0 herrno: 1 source: resolv
spf_interpret.c:824 Debug: found 0 MX records for @{domain} (herrno: 1)
--vv--
Context: 2mx query
Response result: neutral
Response reason: default
Response err: No errors
StartError
EndError
--^^--

Notice that it *keeps* the @ from the email address when it does that final lookup, which apparently causes a DNS lookup failure, as it should considering it's not a valid hostname when it's still got the @ in it.

Then SPF does what it's (probably?) supposed to do and merges the results of the first test (fail) with the second test (neutral) turning the result into a "failneutral" which oddly favours the "neutral" result.

It seems like this entire issue may be created by the SPF binary failing to parse the email address properly for the passed rcpt-to value. If the binary itself can't be patched, then perhaps rcpt-to values shouldn't be passed to it until it can be?

Would be great to get some comments on this from a Plesk dev.
 
I've resolved this issue. However I believe it's caused by a bug in Plesk's SPF implementation.

I've discovered that SPF DNS checks do not run at all when "SPF guess rules" are configured in Plesk. I had SPF guess rules configured to the default:

v=spf1 a/24 mx/24 ptr ~all

When this was set, all incoming email was *only* checked against those guess rules and no DNS lookups were actually performed on the domain of the email sender. This results in ONLY neutral results. Since our SPF checking mode is configured to reject when SPF resolves to Fail, it would never reject messages, making it seem like incoming SPF scanning wasn't working.

According to OpenSPF's website, guess rules should *only* be applied when a domain does not have an SPF record. This means that Plesk's current behaviour for SPF filtering when a Guess rule is configured is incorrect.

The workaround is to not set an SPF guess rule in Plesk's mail config. It's technically a workaround and not a solution because while it results in the issue being fixed, it also means we can't specify guess rules that behave as they're supposed to, even though the Plesk interface provides such an option.

Here are my conclusions after completing hours of troubleshooting:

1) There is a bug in Plesk's incoming SPF checking algorithm such that when a guess rule is configured, it fails to actually check the sender domain for an SPF record, and use the domain's actual record, prior to applying the configured guess rules. Instead it only ever uses the guess rules.

The expected behaviour is for Plesk to use a domain's configured SPF record when one exists. Only when the domain does not have an SPF record should the guess rules be used.

It's important to note at this point that there were *not* DNS looup failures on any of the servers I tested this on. By removing the guess rule, all SPF checking works perfectly as it should, meaning it must be successfully looking up the senders' SPF records.

2) There really should be either more logging by default, or the option to enable more verbose logging, when it comes to milter and SPF. At the moment there are only log entries when there's a milter failure and since the issue above meant that the SPF check was always resulting in neutral, I had no logging to help me figure out what was happening. After fixing the above issue, here's what the failure log entries look like:

Mar 19 15:02:50 {servername} postfix/cleanup[6661]: 8B086342855F: milter-reject: END-OF-MESSAGE from unknown[{IP1}]: 5.7.1 Command rejected; from=<{email}> to=<{email}> proto=SMTP helo=<{IP2}>

As you can see from that log entry, it would also be very handy to have an indication of why the message was rejected. Was it SPF? Was it DomainKeys? Was it Greylisting?

I had even temporarily enabled -v -v verbose debug logging in Postfix's config file, but it didn't result any additional milter logging.

3) The spfquery_static binary appears to have a bug such that its results are incorrect when a rcpt-to address is specified. This is due to the code not successfully parsing the @ out of the rcpt-to email address prior to proceeding with DNS lookups. See the post above for more details on this. This bug *seems* to be completely unrelated to the reason I created this thread and was only discovered as I was using the utility for testing purposes.

I hope to see a Plesk dev respond to these two possible bugs soon.

-Jordan
 
Back
Top