Using certain applications (telnet, fetchmail, for example) but not
others (ping, simple gethostbyname() wrapper I wrote) it seems that if
dns is enabled in nsswtich.conf, even if it is *after* files (hosts:
files dns), the bad applications (telnet, fetchmail) go out to DNS and
use the address found there even though there is a matching entry in
/etc/hosts and both host.conf and nsswitch.conf specify using
/etc/hosts first and dns last. However, this only occurs when the host
in question is reference by FQDN, not by short name.
If I take dns out of hosts: line in nsswitch.conf, everything works
ok, thus demonstrating the entry in /etc/hosts is valid. First I'll
ping the FQDN and the short name, then telnet to port 25 on both the
FQDN and the shortname. All works fine.
PING mail.scires.com (10.0.0.4) from 10.0.101.74 : 56(84) bytes of
data.
64 bytes from mail.scires.com (10.0.0.4): icmp_seq=1 ttl=128
time=0.191 ms
--- mail.scires.com ping statistics ---
1 packets transmitted, 1 received, 0% loss, time 0ms
rtt min/avg/max/mdev = 0.191/0.191/0.191/0.000 ms
PING mail.scires.com (10.0.0.4) from 10.0.101.74 : 56(84) bytes of
data.
64 bytes from mail.scires.com (10.0.0.4): icmp_seq=1 ttl=128
time=0.326 ms
--- mail.scires.com ping statistics ---
1 packets transmitted, 1 received, 0% loss, time 0ms
rtt min/avg/max/mdev = 0.326/0.326/0.326/0.000 ms
Trying 10.0.0.4...
telnet: connect to address 10.0.0.4: Connection refused
Trying 10.0.0.4...
Connected to mail.scires.com.
Escape character is '^]'.
220 mail.scires.com GroupWise Internet Agent 6.0.2 Beta (C)1993, 2002
Novell, Inc. Ready
QUIT
Connection closed by foreign host.
Trying 10.0.0.4...
Connected to mail.
Escape character is '^]'.
220 mail.scires.com GroupWise Internet Agent 6.0.2 Beta (C)1993, 2002
Novell, Inc. Ready
quit
221 mail.scires.com Closing transmission channel
Connection closed by foreign host.
Now, if I edit nsswitch.conf and add dns to the end of the hosts: line
so that it reads
hosts: files dns
And do the above 4 commands (ping FQDN, ping short name, telnet FQDN,
telnet short name), in one case I will get a bad result -- a DNS
lookup succeeds, producing the *outside* address of the box, which of
course causes no end of trouble. The other operations all succeed
because the entry in /etc/hosts is used.
PING mail.scires.com (10.0.0.4) from 10.0.101.74 : 56(84) bytes of
data.
64 bytes from mail.scires.com (10.0.0.4): icmp_seq=1 ttl=128
time=0.234 ms
--- mail.scires.com ping statistics ---
1 packets transmitted, 1 received, 0% loss, time 0ms
rtt min/avg/max/mdev = 0.234/0.234/0.234/0.000 ms
PING mail.scires.com (10.0.0.4) from 10.0.101.74 : 56(84) bytes of
data.
64 bytes from mail.scires.com (10.0.0.4): icmp_seq=1 ttl=128
time=0.190 ms
64 bytes from mail.scires.com (10.0.0.4): icmp_seq=2 ttl=128
time=0.191 ms
--- mail.scires.com ping statistics ---
2 packets transmitted, 2 received, 0% loss, time 1002ms
rtt min/avg/max/mdev = 0.190/0.190/0.191/0.013 ms
Trying 66.152.29.4...
telnet: connect to address 66.152.29.4: Connection refused
Trying 10.0.0.4...
Connected to mail.
Escape character is '^]'.
220 mail.scires.com GroupWise Internet Agent 6.0.2 Beta (C)1993, 2002
Novell, Inc. Ready
quit
221 mail.scires.com Closing transmission channel
Connection closed by foreign host.
This seems horribly wrong! FWIW, I'm using a stock RH8.0, kept
up-to-date with ximian red-carpet service.
I also performed strace on the telnet FQDN step, and side-by-side
diffs clearly show /etc/hosts being read by both, then when dns is
enabled (but still last!), a dns lookup is performed anyway, and this
result is used.
Is this behaviour a) observed by anyone else b) correct c) insane d)
insane but can be worked around? Currently I'm favoring d, by running
scripts that rewrite fetchmailrc and other files when I move inside
and outside the firewall to hardcode the IP. I want to be able to
hardcode the IP inside the firewall in one place (/etc/hosts), but use
DNS outside the firewall for the same names.
P.S. the little gethostbyname wrapper looks like this:
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
struct hostent* serverhostp;
int i;
if ((serverhostp = gethostbyname(argv[1])) == 0)
{
printf("gethostbyname %s failed", argv[1]);
exit(EXIT_FAILURE);
}
for (i = 0; i < serverhostp->h_length; ++i)
{
printf("%2.2x ", *serverhostp->h_addr++);
}
printf("\n");
return 0;
And when run produces output thusly:Quote:}
0a 00 00 04
0a 00 00 04