Quispiam
power computing
So yesterday I get an email saying “Hey, this person from this company is trying to send me and email and they keep getting bounces…” and a quick grep of the maillog revealed:
May 19 11:02:24 barweb1 postfix/smtpd[30761]: NOQUEUE: reject: RCPT from mx0a-000e6001.pphosted.com[67.231.144.81]: 450 Server configuration problem; from=; to= proto=ESMTP helo=
No worries, apart from the reject this looks OK, but I wonder why they were rejected ? I take a peek at the lines before this one
May 19 11:02:24 mailserver postfix/spawn[30752]: warning: command /usr/bin/perl exit status 255 May 19 11:02:24 mailserver postfix/smtpd[30761]: warning: premature end-of-input on private/spf while reading input attribute name May 19 11:02:24 barweb1 postfix/smtpd[30761]: warning: problem talking to server private/spf: Success
Ahh crap, this means there is an error in the spf perl process, I didnt write this and have a limited understanding of the code, hope its easy to find the problem I think to myself.
Running the command by hand and feeding it the required data yielded the following:
Bad arg length for Socket::unpack_sockaddr_in, length is 4096, should be 16 at
/usr/lib/perl5/i386-linux/Socket.pm line 383.
What the hell does that mean ? I started tracking it down through the perl process postfix-policyd-spf-perl.pl
( that can be found at https://launchpad.net/postfix-policyd-spf-perl/ ) and eventually worked out that it was somewhere in the Mail::SPF module. So then I whip out my trusty CPAN and install Mail::SPF assuming the elderly unit is in need of a module update. This does nothing and the problem still exists. Ok, fine, now its time to get dirty and write a script, may be that will help narrow down the issue
use Mail::SPF; use Data::Dumper; my $spf_server = Mail::SPF::Server->new(); $request = eval { Mail::SPF::Request->new( scope => 'mfrom', identity => 'some.user@pearson.com', ip_address => '67.231.144.81', helo_identity => 'mx0b-000e6001.pphosted.com' ); }; $result = $spf_server->process($request); print "$result";
Same error, as expected, but now I can trace it through Mail::SPF::Server->process
routine. This leads me to the Net::DNS::Resolver module and once again I turn to CPAN to update Net::DNS. But same problem, it looks like its not these modules.
Back for another dirty test script to help narrow the problem even further.
use Net::DNS::Resolver; use Data::Dumper; $res = Net::DNS::Resolver->new( debug => 1 ); $packet = $res->send('spf.pearson.com', 'A'); print Dumper($packet);
Error still exists, but now I am sure the send
routine of the Net::DNS::Resolver module can help point the way. I eventually tracked the problem down to Net::DNS::Resolver::Base.pm
and the line which updates the answerfrom
property
$buf = read_tcp($sock, $len, $self->{'debug'}); $self->answerfrom($sock->peerhost);
Looking at the answerfrom
routine tells me nothing and didn’t look like it would be buggy, so I look at the peerhost routine in IO::Socket.pm
sub peername { @_ == 1 or croak 'usage: $sock->peername()'; my($sock) = @_; ${*$sock}{'io_socket_peername'} ||= getpeername($sock); }
This is all well beyond my skills at this stage as it seems that getpeername
is inbuilt to Perl, so I thinks to myself “update Perl”. But as alluded to before this machine is elderly and has some pretty legacy perl code running on it, I dont want to jump up to the latest and greatest Perl. I did update Perl to 5.8.9 from v5.8.8, but alas that did nothing. I am beginning to suspect we probably have the problem on this machine because it is a little long on the tooth and running some old kernel and the c header files are out of date. We have a couple of XEN virtuals around here that I can verify this on. I log into one and test Perl is the same, yep 5.8.8 and the test code runs fine ! Bugger it.
It is advisable to update this old unit, but right now that is impossible, so I hack around the error by placing the following code, highlighted, in Net::DNS::Resolver::Base.pm
$buf = read_tcp($sock, $len, $self->{'debug'}); eval { $self->answerfrom($sock->peerhost); }; if($@ && $self->{'debug'}) { print "An error with the socket probably: Bad arg length for Socket::unpack_sockaddr_in, length is 4096, should be 16 skipping n"; } print ';; received ', length($buf), " bytesn" if $self->{'debug'};
Now when I run my test-spf
on the geriatric unit I get the right response
user@host:~# perl test-spf.pl pass (Mechanism 'include:spf.pearson.com' matched)
So, we all agree this is far from ideal this it does get us out of hot water for the time being.
Matt.