In Postfix I'm using:
smtpd_recipient_restrictions = .. reject_unknown_reverse_client_hostname
unknown_client_reject_code = 554
BIND runs on the same machine. /etc/resolv.conf is set as follows:
nameserver 127.0.0.1
I have found that when I stop the "named" daemon, all incoming mail is
rejected with:
554 5.7.1 Client host rejected: cannot find your reverse hostname
Yet the manual states:
"The reply is always 450 in case the address->name lookup failed due to
a temporary problem."
Does an unreachable name server not count as a "temporary problem"?
Thanks,
Jordan Russell
That depends entirely on what your SYSTEM library routines do.
Don't shoot Postfix. It is only the MESSENGER.
Wietse
> (Postfix 2.3.2, Red Hat Enterprise Linux 4)
>
> In Postfix I'm using:
>
> smtpd_recipient_restrictions = .. reject_unknown_reverse_client_hostname
> unknown_client_reject_code = 554
>
> BIND runs on the same machine. /etc/resolv.conf is set as follows:
>
> nameserver 127.0.0.1
>
> I have found that when I stop the "named" daemon, all incoming mail is
> rejected with:
>
> 554 5.7.1 Client host rejected: cannot find your reverse hostname
In addition to what Wietse wrote, enter a fallback nameserver (i.e. your
ISP's nameserver) below localhost in /etc/resolv.conf. We run the same
OS as you and it works for us (we run a split caching nameserver on our
mail server).
You could also try to see to it that your local nameserver does not fall
out for extended periods (yes, I know up2date can ruin custom settings,
been there, seen that, but make a backup of /var/named before you run
up2date).
> Yet the manual states:
>
> "The reply is always 450 in case the address->name lookup failed due to
> a temporary problem."
>
> Does an unreachable name server not count as a "temporary problem"?
>
> Thanks,
> Jordan Russell
--Tonni
--
Tony Earnshaw
reservebergenser :)
[...]
> nded periods (yes, I know up2date can ruin custom settings,
> been there, seen that, but make a backup of /var/named before you run
> up2date).
Oh yes, and make sure that named.conf, rndc.conf and rndc.key are
in /var/named (so that they get covered by the backup) and that the same
files in /etc are symlinks to these (means doing handwork after running
up2date)..
Okay, I looked into this some more...
Postfix is expecting getnameinfo() to return EAI_AGAIN for temporary
failures. I took a look at the current getnameinfo() implementations in
glibc and FreeBSD's libc, and found that neither return EAI_AGAIN for
any reason. Rather, when they fail to retrieve a name, they return
EAI_NONAME regardless of whether the failure is permanent or temporary
in nature. See:
http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/inet/getnameinfo.c?rev=1.34&content-type=text/x-cvsweb-markup&cvsroot=glibc
and
http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/net/getnameinfo.c?rev=1.17.2.1&content-type=text/x-cvsweb-markup
Therefore, on Linux and BSD, failures to contact name servers during
reverse lookups are always treated as permanent failures by Postfix.
gethostbyaddr(), however, does return distinct codes for temporary and
permanent failures. I hacked sockaddr_to_hostname() in util/myaddrinfo.c
to always use the "EMULATE_IPV4_ADDRINFO" version, and
"reject_unknown_reverse_client_hostname" now returns a 450 response when
the name server is down.
Is there any real advantage to using getnameinfo() in place of
gethostbyaddr(), apart from the transparent IPv6 support?
--
Jordan Russell
That would be a bug in the library. The solution is to send a bug
report and request that it be fixed.
Wietse
Supposing I did that, and both the Linux and BSD folks agreed that it
actually was a bug, I'd also have to convince the OS vendors to backport
the fix and put out updated libc packages for their existing releases.
That I don't really see happening.
If you don't believe that this should be addressed at the Postfix level
-- even if only as a temporary workaround until the OS vendors get their
act together -- then perhaps it would be wise to remove the claim in the
reject_unknown_reverse_client_hostname docs that 450 is "always"
returned for temporary problems, since what happens in the real world on
all existing releases of Linux and BSD is just the opposite.
In any event, I will run this by the glibc maintainers and see what they
have to say.
--
Jordan Russell
This happens all the time. If users don't give feedback then bugs
won't be fixed.
> If you don't believe that this should be addressed at the Postfix level
> -- even if only as a temporary workaround until the OS vendors get their
> act together -- then perhaps it would be wise to remove the claim in the
> reject_unknown_reverse_client_hostname docs that 450 is "always"
> returned for temporary problems, since what happens in the real world on
> all existing releases of Linux and BSD is just the opposite.
I could spend the rest of my life adding disclaimers with "oh by
the way don't blame Postfix if the OS produces incorrect answers"
for every feature that Postfix implements.
> In any event, I will run this by the glibc maintainers and see what they
> have to say.
A dead name server must not be a treated as if it is a permanent
error condition, expecially when claiming that a name or address
does not exist. They made the same mistake with a dead name service
for /etc/passwd, which is another cause of mail getting rejected
for the wrong reason.
Wietse
Suppose instead you found all the packages for linux and BSD that used
libc's getnameinfo() and contacted all the maintainers to convince
them to implement a workaround for this bug in libc and then convinced
all the OS vendors to backport all the new packages?
--
Harvey
Changing Postfix to use gethostbyaddr() instead of getnameinfo() seems
infinitely simpler than upgrading all of the world's "broken" libc
packages that have been shipping in every Linux and BSD release since 1999.
Besides, Postfix is probably one of the only programs that actually has
special handling for EAI_AGAIN. Generally, programs don't have two
separate code paths for temporary and permanent name resolution failures.
It appears that adding IPv6 support to the gethostbyaddr() code -- which
again is already there but hiding behind an #ifdef -- would require
fewer than 10 lines of code.
i.e. take this:
if ((hp = gethostbyaddr((char *) &(SOCK_ADDR_IN_ADDR(sa)),
sizeof(SOCK_ADDR_IN_ADDR(sa)),
AF_INET)) == 0)
return (h_errno == TRY_AGAIN ? EAI_AGAIN : EAI_NONAME);
and expand it to:
#ifdef HAS_IPV6
if (sa->sa_family == AF_INET6) {
if ((hp = gethostbyaddr((char *) &(SOCK_ADDR_IN6_ADDR(sa)),
sizeof(SOCK_ADDR_IN6_ADDR(sa)),
AF_INET6)) == 0)
return (h_errno == TRY_AGAIN ? EAI_AGAIN : EAI_NONAME);
} else
#endif
{
if ((hp = gethostbyaddr((char *) &(SOCK_ADDR_IN_ADDR(sa)),
sizeof(SOCK_ADDR_IN_ADDR(sa)),
AF_INET)) == 0)
return (h_errno == TRY_AGAIN ? EAI_AGAIN : EAI_NONAME);
}
Then the getnameinfo() stuff could just be removed.
Problem solved instantly for all past and present Linux and BSD releases.
Later, once all the broken libc's are eradicated from the face of the
earth, it could switch back to using getnameinfo() if need be.
--
Jordan Russell
Please cite the vendor-independent standards document that requires
that gethostbyaddr() supports IPv6, on IPv6 capable platforms.
If such a document does not exist, then the above code is non-portable,
that is, its behavior is undefined. With undefined behavior, different
systems may produce different results, if any result at all.
Wietse