System administrators will probably agree violently with the proposition that network services should be able to log all accesses. Whenever a server accepts a new connection, there may be code like this:
void
handleConnection(int theSocket)
{
struct sockaddr_in sin;
socklen_t slen;
int fd;
struct hostent *hp;
pid_t pid;
/* Accept new connection */
slen = sizeof(sin);
fd = accept(theSocket, (struct sockaddr *) &sin, &slen);
if (fd < 0)
return;
hp = gethostbyaddr(&sin.sin_addr, 4, AF_INET);
if (hp != NULL) {
syslog(LOG_NOTICE, "Accepted connection from %s (%s)",
hp->h_name, inet_ntoa(sin.sin_addr));
} else {
syslog(LOG_NOTICE, "Accepted connection from %s",
inet_ntoa(sin.sin_addr));
}
processRequest(fd);
close(fd);
return;
}
This code tries to look up the fully qualified domain name of the client host, and if available, include it in the log file, for the convenience of the administrator.
However, there is one small problem with this code that usually will not show up during ordinary testing. If the server accepts a connection from a remote client, the name lookup will usually have to go through the DNS. And we all know that DNS can be slow, and if a DNS server is down, queries may take quite a while to complete. But as the name lookup happens inside the main process of the network service, no new connections will be serviced during this time. Even worse, if the service is single-threaded, all processing will stop during this time. Needless to say, it is a simple exercise for many attackers to disable their DNS server.
Therefore, it is usually the best solution to show only the IP address in log files; if the administrator needs to know, he can translate the addresses manually or by running a script on the log file.
For multi-threaded services that create separate processes for each connection, another solution is to perform the address to name lookup in the sub-processes. Now if the client's DNS hangs, the only one getting hurt is the client. Processing for everyone else proceeds just as usual.