# Sample resolv.conf showing the issue
; generated by /sbin/dhclient-script
search mcdc
nameserver 10.0.4.48 # Primary (failing) DNS
nameserver 8.8.8.8 # Secondary (working) DNS
When applications like wget or curl fail to use fallback nameservers specified in /etc/resolv.conf, it typically indicates one of these scenarios:
- The glibc resolver isn't properly cycling through nameservers
- DNS timeout thresholds are too aggressive
- The application implements its own DNS resolution logic
First verify resolver behavior using different tools:
# Using getent (uses glibc resolver)
getent hosts google.com
# Using dig (bypasses local resolver)
dig @8.8.8.8 google.com +short
# Timeout simulation
time curl --connect-timeout 5 http://google.com
Create /etc/resolv.conf with proper timeout and attempts:
options timeout:1 attempts:5 rotate
nameserver 10.0.4.48
nameserver 8.8.8.8
Key parameters:
timeout: Wait time per query (seconds)attempts: Retries per nameserverrotate: Round-robin nameserver selection
For applications using glibc resolver, set environment variables:
export RES_OPTIONS="rotate timeout:1 attempts:2"
curl http://example.com
For curl specifically:
curl --dns-servers 8.8.8.8,10.0.4.48 http://example.com
- Check resolver config:
ldd $(which curl) | grep libresolv strace -e connect curl http://example.com 2>&1 | grep 'connect(' - Test with different DNS libraries:
# Using c-ares (alternative DNS library) curl --dns-interface eth0 http://example.com
For production systems, consider:
- Setting up local DNS caching (dnsmasq/unbound)
- Implementing DNS failover at network level
- Using /etc/nsswitch.conf to control resolution order
# Example nsswitch.conf modification
hosts: files dns [NOTFOUND=return] mdns4_minimal
html
When troubleshooting DNS resolution in Linux, I recently encountered a puzzling behavior where network utilities like wget and curl would only use the first nameserver entry in /etc/resolv.conf, ignoring subsequent entries even when the primary server fails. Here's a deep dive into the problem and solutions.
Here's what my /etc/resolv.conf looks like:
; generated by /sbin/dhclient-script search mcdc nameserver 10.0.4.48 nameserver 8.8.8.8
Testing with nslookup works as expected - it properly falls back to Google's DNS (8.8.8.8) when the primary server fails:
nslookup www.google.com ;; Got SERVFAIL reply from 10.0.4.48, trying next server Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: www.google.com canonical name = www.l.google.com.
However, when using curl or wget:
curl www.google.com curl: (6) Could not resolve host: www.google.com
Using strace revealed these tools only attempt the first nameserver:
strace -e trace=network curl www.google.com
[...]
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("10.0.4.48")}, 16) = 0
This behavior stems from how the glibc resolver works:
- The resolver has a single-threaded retry mechanism
- Default timeout between retries is too long (5 seconds per RFC)
- Many applications don't implement proper fallback logic
1. Using getaddrinfo() with Proper Timeouts
For programmers developing network applications, always implement proper timeout handling:
#include <netdb.h>
#include <stdio.h>
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM
};
struct addrinfo *result;
int status = getaddrinfo("www.google.com", "80", &hints, &result);
if (status != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
2. System-wide Configuration Changes
Modify /etc/resolv.conf options:
options timeout:1 attempts:2 rotate nameserver 10.0.4.48 nameserver 8.8.8.8
Key parameters:
timeout:1- Reduce timeout to 1 secondattempts:2- Make 2 attempts per nameserverrotate- Round-robin between nameservers
3. Using Alternative DNS Utilities
For scripting, consider using tools with better DNS handling:
# Using dig with explicit nameserver dig @8.8.8.8 www.google.com +short # Using DNS cache daemon like nscd sudo apt install nscd sudo service nscd restart
For critical applications, you might want to implement custom DNS resolution:
import socket
import dns.resolver
def resolve_host(hostname):
resolvers = ['10.0.4.48', '8.8.8.8']
for resolver in resolvers:
try:
dns_resolver = dns.resolver.Resolver()
dns_resolver.nameservers = [resolver]
answer = dns_resolver.resolve(hostname)
return str(answer[0])
except:
continue
raise Exception("All DNS servers failed")
print(resolve_host("www.google.com"))
Based on my testing, the most reliable approach is to combine:
- System-wide
/etc/resolv.confconfiguration with proper timeout settings - Application-level retry logic
- Consider using local DNS caching daemon
Remember that DNS resolution behavior can vary between different Linux distributions and glibc versions, so always test your specific environment.