Many Apache administrators encounter this frustrating scenario: your web server keeps performing reverse DNS (rDNS) lookups for every client IP address, even when you've explicitly configured HostnameLookups Off
. The worst part? When PTR records are missing, Apache waits up to 28 seconds before timing out - a massive performance killer.
While HostnameLookups Off
should theoretically prevent this, several other factors can trigger reverse DNS queries:
# Common culprits in httpd.conf:
LogFormat "%h %l %u %t \"%r\" %>s %b" common # %h does hostname resolution
Require host example.com # Host-based authentication
mod_remoteip configurations with proxy checks
Here's the complete debugging approach I've refined through troubleshooting dozens of servers:
- Verify ALL LogFormat directives:
# Safe format without host resolution: LogFormat "%a %l %u %t \"%r\" %>s %b" myformat
- Audit authentication modules:
# Replace host-based auth with IP-based: Require ip 192.168.1.0/24
- Check mod_remoteip settings:
RemoteIPInternalProxy 10.0.0.0/8 RemoteIPHeader X-Forwarded-For # Critical: Add this to prevent lookups: RemoteIPTrustedProxyList /path/to/trusted_proxies.txt
When all else fails, this nuclear option prevents all DNS queries:
# In httpd.conf:
HostnameLookups Off
# Add to startup script (e.g., apache2.service):
ExecStartPre=/bin/bash -c 'echo "127.0.0.1 $(hostname)" >> /etc/hosts'
Use this awk command to analyze request times:
awk '$11 > 5 {print $1,$11}' access_log | sort | uniq -c | sort -nr
This shows IPs with response times >5 seconds - typically indicating DNS lookup issues.
Reverse DNS lookups are one of the most common yet overlooked performance bottlenecks in Apache configurations. When your server waits 20-30 seconds for a failed PTR record lookup, this directly impacts:
- Page load times
- Server throughput
- Connection queue handling
Add this to your httpd.conf to log resolution times:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" dns_debug CustomLog logs/access_log dns_debug
Look for these patterns in logs:
# Successful (fast) lookup: 192.168.1.100 - - [timestamp] "GET / HTTP/1.1" 200 1234 5432 # Failed (slow) lookup: client.example.com - - [timestamp] "GET / HTTP/1.1" 200 1234 21000
- HostnameLookups Directive:
# In main server config or virtual host HostnameLookups Off
- Disable mod_rewrite Host Checks:
# Replace this: RewriteCond %{REMOTE_HOST} ^trusted\.domain\.com$ # With IP-based version: RewriteCond %{REMOTE_ADDR} ^192\.168\.1\.100$
- Review All Access Controls:
# Problematic: <Require host example.com> # Preferred: <Require ip 192.168.1.0/24>
When you absolutely need hostnames (e.g., for analytics):
# In your application code (PHP example): $hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']); # Cache results in Redis/Memcached with 24h TTL
Benchmark before/after changes using ab:
ab -n 1000 -c 50 http://yourserver/testpage.html # Compare: Requests per second: Before 12.34 vs After 87.65