SEE UPDATE BELOW!
I also enjoy using Dnsmasq on my local machine, and I had this problem
too. Here is the solution:
From man 5 resolver
:
The configuration for a particular client may be read from a file
having the format described in this man page. These are at present
located by the system in the /etc/resolv.conf file and in the files
found in the /etc/resolver directory.
/etc/resolver/
is not present by default; you must create it yourself.
Also from the man page:
domain
Domain name associated with this resolver configuration. This
option is normally not required by the Mac OS X DNS search system
when the resolver configuration is read from a file in the
/etc/resolver directory. In that case the file name is used as the
domain name.
So if you wanted all dns queries for the top level domain of dev
to be
routed to the local nameserver, you would:
# mkdir /etc/resolver
# echo 'nameserver 127.0.0.1' > /etc/resolver/dev
configd
does not alter files in /etc/resolver/
, so this setting will
persist through network changes and reboots.
UPDATE 17 July 2012
Unfortunately, as of OS X Lion, the top resolver (as shown by scutil
--dns
) disappears when no interfaces are active:
# scutil --dns # Online
DNS configuration
resolver #1
nameserver[0] : 127.0.0.1
...
resolver #8
domain : dev
nameserver[0] : 127.0.0.1
# scutil --dns # Offline
DNS configuration
resolver #1
...
resolver #8
domain : dev
nameserver[0] : 127.0.0.1
Notice that resolver #1 is empty, but that the /etc/resolver derived
nameserver entry remains.
It turns out that since you can specify the resolver domain directly in
the /etc/resolver/ file, specifying the special Internet root domain .
causes the creation of a global resolver entry that looks like:
resolver #8
nameserver[0] : 127.0.0.1
Now all DNS queries are routed to localhost, even when offline.
Of course, you will still have to resolve your chosen domains as
127.0.0.1 using something like dnsmasq's --address option:
# dnsmasq --address=/dev/127.0.0.1
In summary:
- Set all your network interface dns servers to 127.0.0.1:
networksetup -setdnsservers Ethernet 127.0.0.1
networksetup -setdnsservers Wi-Fi 127.0.0.1
...
- Create a file /etc/resolver/whatever:
nameserver 127.0.0.1
domain .
- Set up a local DNS server and be happy.
cf. http://opensource.apple.com/source/configd/configd-395.11/dnsinfo/dnsinfo_flatfile.c
By 'DNS failover' I take it you mean DNS Round Robin combined with some monitoring, i.e. publishing multiple IP addresses for a DNS hostname, and removing a dead address when monitoring detects that a server is down. This can be workable for small, less trafficked websites.
By design, when you answer a DNS request you also provide a Time To Live (TTL) for the response you hand out. In other words, you're telling other DNS servers and caches "you may store this answer and use it for x minutes before checking back with me". The drawbacks come from this:
- With DNS failover, a unknown percentage of your users will have your DNS data cached with varying amounts of TTL left. Until the TTL expires these may connect to the dead server. There are faster ways of completing failover than this.
- Because of the above, you're inclined to set the TTL quite low, say 5-10 minutes. But setting it higher gives a (very small) performance benefit, and may help your DNS propagation work reliably even if there is a short glitch in network traffic. So using DNS based failover goes against high TTLs, but high TTLs are a part of DNS and can be useful.
The more common methods of getting good uptime involve:
- Placing servers together on the same LAN.
- Place the LAN in a datacenter with highly available power and network planes.
- Use a HTTP load balancer to spread load and fail over on individual server failures.
- Get the level of redundancy / expected uptime you require for your firewalls, load balancers and switches.
- Have a communication strategy in place for full-datacenter failures, and the occasional failure of a switch / database server / other resource that cannot easily be mirrored.
A very small minority of web sites use multi-datacenter setups, with 'geo-balancing' between datacenters.
Best Answer
First of all, this is the relevant section from
resolv.conf(5)
:Ie,
search
is not simply off by default; ifsearch
is not specified it uses eitherdomain
, or if that is also not specified it uses any domain part present in whatgethostname(2)
returns (ie, anything after the first dot in the local system hostname).The actual implementation is a little strange, however. What happens in practice (as observed in glibc 2.26) is this:
If there is no
search
, nodomain
and the hostname according togethostname(2)
has no domain part, search is disabled.If, on the other hand, you specify
search .
(ordomain .
and nosearch
) it still searches, but the returned result will be the same as if it didn't, it just makes redundant identical queries. (Bug?)This is kind of weird behavior, the case where "the root domain is assumed" leads to search getting disabled while explicitly specifying the root domain instead generates redundant queries.
As for how to set the system hostname, there are different schools of thought.
Using the FQDN across the board is probably the most obvious approach nowadays, it removes any possible question marks regarding which domain will be used to construct the FQDN.
If you have the system hostname set to just the actual hostname (no domain), you get different values from
gethostname(2)
andgethostname(3)
(the latter dynamically generates the FQDN as necessary by using the resolver, in practice typically matching an entry in/etc/hosts
for the local system). Depending on what an application asks for it will get either just the hostname or the FQDN, as can be seen with eghostname
vshostname --fqdn
.Less expected is how the above choice actually also affects the ability to disable
search
.But, strange as it may be, the bottom line seems to be that if you want to globally disable search, whether names you look up are explicitly absolute (have a trailing dot) or not, current glibc versions seem to only properly disable search if
gethostname(2)
returns a hostname lacking a domain.