pypolicyd-spf fails if any one DNS server in resolv.conf gives status=REFUSED

Bug #1612061 reported by Brad2014
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
pypolicyd-spf
Invalid
Undecided
Unassigned

Bug Description

OS: CentOS 7
Package: pypolicyd-spf-1.3.2-1.el7.noarch

My /etc/resolv.conf contains 5 IP addresses, the last two of which are (at the moment) unavailable, returning DNS status=REFUSED. The first 3 addresses point to good DNS servers, and return SPF records normally.

All incoming e-mail is marked "Received-SPF: None (no SPF record)", even for domains where SPF records are available.

When the refusing servers are commented out in /etc/resolv.conf, pypolicyd-spf correctly processes incoming e-mail (e.g. marking it Pass or Fail according to the SPF record content).

Expected result: the presence of disabled (or transiently failing) DNS servers in the resolv.conf set should not break lookups, as long as working servers are delivering the desired SPF records.

I did a test receiving mail from <email address hidden>, from a sender which should pass, according to the domains SPF record. A strace of /usr/libexec/postfix/policyd-spf shows that all five DNS servers are being queried, and successful results are being returned by the first three, and the last two are failing (this snippet shows a read from the last good one, [2001:558:feed::2], followed by the read from the next bad one, [75.75.75.75], followed by responding with "Received-SPF: None"):

------ SNIP -------
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 4
fstat(9, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 9), ...}) = 0
read(9, "\325D\354wf\226;", 7) = 7
 | 00000 d5 44 ec 77 66 96 3b .D.wf.; |
bind(4, {sa_family=AF_INET6, sin6_port=htons(54767), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
connect(4, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2001:558:feed::2", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
sendto(4, "G\27\1\0\0\1\0\0\0\0\0\0\22celerityconsulting\3"..., 40, 0, NULL, 0) = 40
select(5, [4], [], [], {20, 0}) = 1 (in [4], left {19, 869393})
recvfrom(4, "G\27\201\200\0\1\0\1\0\0\0\0\22celerityconsulting\3"..., 65535, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2001:558:feed::2", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 105
 | 00000 47 17 81 80 00 01 00 01 00 00 00 00 12 63 65 6c G............cel |
 | 00010 65 72 69 74 79 63 6f 6e 73 75 6c 74 69 6e 67 03 erityconsulting. |
 | 00020 63 6f 6d 00 00 10 00 01 c0 0c 00 10 00 01 00 00 com............. |
 | 00030 07 08 00 35 34 76 3d 73 70 66 31 20 69 6e 63 6c ...54v=spf1 incl |
 | 00040 75 64 65 3a 5f 73 70 66 2e 67 6f 6f 67 6c 65 2e ude:_spf.google. |
 | 00050 63 6f 6d 20 6d 78 3a 75 6e 63 6c 65 62 72 61 64 com mx:unclebrad |
 | 00060 2e 63 6f 6d 20 7e 61 6c 6c .com ~all |
close(4) = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
fstat(9, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 9), ...}) = 0
read(9, "HK\2172jn\231", 7) = 7
 | 00000 48 4b 8f 32 6a 6e 99 HK.2jn. |
bind(4, {sa_family=AF_INET, sin_port=htons(19242), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("75.75.75.75")}, 16) = 0
sendto(4, "G\27\1\0\0\1\0\0\0\0\0\0\22celerityconsulting\3"..., 40, 0, NULL, 0) = 40
select(5, [4], [], [], {20, 0}) = 1 (in [4], left {19, 976096})
recvfrom(4, "G\27\201\205\0\1\0\0\0\0\0\0\22celerityconsulting\3"..., 65535, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("75.75.75.75")}, [16]) = 40
 | 00000 47 17 81 85 00 01 00 00 00 00 00 00 12 63 65 6c G............cel |
 | 00010 65 72 69 74 79 63 6f 6e 73 75 6c 74 69 6e 67 03 erityconsulting. |
 | 00020 63 6f 6d 00 00 10 00 01 com..... |
close(4) = 0
...
write(1, "action=prepend Received-SPF: Non"..., 203) = 203
------ END OF SNIP ------

Hypothesis: the python DNS library is not noticing the status=REFUSED RCODE (response byte 4), and interpreting the response as valid but empty, when it should be invalid and skipped? I'm guessing.

Revision history for this message
Benny Pedersen (z-me-3) wrote :

it would now be nice to know resolv.conf content

and test results from

ping -c 3 ipv4.google.com
ping6 -c 3 ipv6.google.com

i think its not just a pypolicyd-spf problem, more a ipv6 first before ipv4

check that this is working

if so it is edit /etc/gai.conf can change the problem, but not the solution :=)

Revision history for this message
Brad2014 (i-brad) wrote :

A bit more testing: it is definitely a pydns problem. It is reproducible with the following small script:

--- snip.py ---
import DNS
DNS.DiscoverNameServers()
req = DNS.DnsRequest('celerityconsulting.com', qtype='TXT', timeout=20)
resp = req.req()
resp.show()
--- snip ---

The ip6 issue is a red herring. This succeeds when /etc/resolv.conf contains:
--- /etc/resolv.conf ---
nameserver 10.8.0.1
# nameserver 2001:558:feed::1
# nameserver 2001:558:feed::2
# nameserver 75.75.75.75
# nameserver 75.75.76.76
--- END ---

It fails when /etc/resolv.conf contains.
--- /etc/resolv.conf ---
nameserver 10.8.0.1 <-- this returns query status=NOERROR
# nameserver 2001:558:feed::1
# nameserver 2001:558:feed::2
nameserver 75.75.75.75 <-- this returns query status=REFUSED
# nameserver 75.75.76.76
--- END ---

Revision history for this message
Scott Kitterman (kitterman) wrote :

As noted, this is not a bug in the policy server. It is fixed in the current release of py3dns and will be included in the next release of pydns. Here's the fix for anyone that wants to fix it locally in the mean time:

http://bazaar.launchpad.net/~py3dns-hackers/pydns/trunk/revision/109

Also, The Debian (and derivatives such as Ubuntu) already have this patch included. You may want to contact the distribution maintainer of your pydns package as suggest they add the patch as well.

Changed in pypolicyd-spf:
status: New → Invalid
Revision history for this message
Brad2014 (i-brad) wrote : Thanks! Re: [Bug 1612061] Re: pypolicyd-spf fails if any one DNS server in resolv.conf gives status=REFUSED

Thank you for the pointer! I looked for that bug fix, but couldn't find
it. Regards, Brad

On 8/12/16 10:39 AM, Scott Kitterman wrote:
> As noted, this is not a bug in the policy server. It is fixed in the
> current release of py3dns and will be included in the next release of
> pydns. Here's the fix for anyone that wants to fix it locally in the
> mean time:
>
> http://bazaar.launchpad.net/~py3dns-hackers/pydns/trunk/revision/109
>
> Also, The Debian (and derivatives such as Ubuntu) already have this
> patch included. You may want to contact the distribution maintainer of
> your pydns package as suggest they add the patch as well.
>
> ** Changed in: pypolicyd-spf
> Status: New => Invalid
>

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.