2018-12-07
Trying to kick spamassassin and perl into the 21st century and prefer IPv6 for DNS traffic
Or in short: Perl considered harmful I want applications to use and prefer IPv6 whenever possible, so I have a /etc/resolv.conf with IPv6 addresses of the nameserver(s) listed first. But I noticed queries from the spamassassin processes still coming in over the legacy IP protocol. Even when listing them in order in /etc/spamassassin/local.cf spamassassin prefers IPv4. And I want it to prefer IPv6 without leaving out IPv4. I like the redundancy but I want to change the preference. Also: I only want to maintain the list of nameservers in /etc/resolv.conf and not in other locations. I wrote a simple test program to understand what the perl Net::DNS::Resolver is doing. With a standard test program like:#!/usr/bin/perl -wT use strict; use Net::DNS; my $resolver = new Net::DNS::Resolver(); print join ' ', $resolver->nameservers(); print "\n";The IPv4 addresses will be listed first, independent of the order in /etc/resolv.conf. Only after changing to:#!/usr/bin/perl -wT use strict; use Net::DNS; my $resolver = new Net::DNS::Resolver(); $resolver->prefer_v6(1); print join ' ', $resolver->nameservers(); print "\n";I will see the IPv6 resolver listed first. But now to convince spamassassin to do the same. Browsing the Net::DNS::Resolver shows the RES_OPTIONS="inet6" option but does not document it. This option confuses spamassassin when starting:export RES_OPTIONS="inet6"root@gosper:/etc/default# service spamassassin restart Restarting SpamAssassin Mail Filter Daemon: Bad arg length for NetAddr::IP::Util::mask4to6, length is 128, should be 32 at /usr/lib/x86_64-linux-gnu/perl5/5.24/NetAddr/IP/Lite.pm line 647. Compilation failed in require at /usr/lib/x86_64-linux-gnu/perl5/5.24/NetAddr/IP.pm line 8. BEGIN failed--compilation aborted at /usr/lib/x86_64-linux-gnu/perl5/5.24/NetAddr/IP.pm line 8. Compilation failed in require at /usr/share/perl5/Mail/SpamAssassin/Util.pm line 70. BEGIN failed--compilation aborted at /usr/share/perl5/Mail/SpamAssassin/Util.pm line 70. Compilation failed in require at /usr/share/perl5/Mail/SpamAssassin/Conf.pm line 85. BEGIN failed--compilation aborted at /usr/share/perl5/Mail/SpamAssassin/Conf.pm line 85. Compilation failed in require at /usr/share/perl5/Mail/SpamAssassin.pm line 71. BEGIN failed--compilation aborted at /usr/share/perl5/Mail/SpamAssassin.pm line 71. Compilation failed in require at /usr/sbin/spamd line 240. BEGIN failed--compilation aborted at /usr/sbin/spamd line 240.So that was a bad idea and is not the answer. Looking at the resolv.conf manpage shows that the option indeed does different things which explains why that was wrong.inet6 Sets RES_USE_INET6 in _res.options. This has the effect of trying an AAAA query before an A query inside the gethostbyname(3) function, and of mapping IPv4 responses in IPv6 "tunneled form" if no AAAA records are found but an A record set exists. Since glibc 2.25, this option is deprecated; applications should use getaddrinfo(3), rather than gethostbyname(3).So if I want perl programs to do what I want, I have to change every one of them to set $resolver->prefer_v6(1);. There is no sane default or a global "get into the 21st century" flag. Changing /usr/share/perl5/Mail/SpamAssassin/DnsResolver.pm to include $res->prefer_v6(1); does help, but will need to be redone when updating spamassassin.