Overriding DHCP- or VPN-assigned DNS servers in Mac OS X Leopard
I'll have to break sad news to you: /etc/resolv.conf has been made redundant in Mac OS X. The dig and nslookup utilities still read it but most applications use a different mechanism for picking DNS servers when resolving host names. They generally go through Darwin's resolver library which instead of reading /etc/resolv.conf looks up DNS servers via the SystemConfiguration framework backed by configd. Survival of the fittest, I guess, or, Darwin's intelligent design.
Ok, ok, I'll stop trying to be funny ... Anyways, this would be all swell if there wasn't the occasional need for manually specifying DNS servers. For me this need typically arises when I connect to a VPN managed by an operator from hell. After hours and hours of hard work (my fingertips still hurt from all the googling) I present to you a solution:
With the VPN connected, launch scutil with root privileges:
hannes-mbp:~ Sysop$ sudo scutil Password:List all network services with DNS configuration:
> list State:/Network/Service/[^/]+/DNS subKey [0] = State:/Network/Service/A3551F2D-62CE-1234-B79A-6EE50CA7AE30/DNS subKey [1] = State:/Network/Service/F194302A-846C-4321-9325-6813DAE148F2/DNSPick one and show its contents.
> show State:/Network/Service/A3551F2D-62CE-1234-B79A-6EE50CA7AE30/DNS <dictionary> { SupplementalMatchDomains : <array> { 0 : } ServerAddresses : <array> { 0 : 192.168.1.74 1 : 217.0.43.81 } SupplementalMatchOrders : <array> { 0 : 100000 } }Ahh, this is the one! So let's get rid of those pesky servers. Obtain a working copy of the DNS configuration entry. It's called ... drum roll ... well, obviously: "d" (rolls eyes).
> d.init > get State:/Network/Service/A3551F2D-62CE-1234-B79A-6EE50CA7AE30/DNS > d.show <dictionary> { SupplementalMatchDomains : <array> { 0 : } ServerAddresses : <array> { 0 : 192.168.1.74 1 : 217.0.43.81 } SupplementalMatchOrders : <array> { 0 : 100000 } }Reset the ServerAddresses entry to an empty array:
> d.add ServerAddresses * > d.show <dictionary> { ServerAddresses : <array> { } SupplementalMatchDomains : <array> { 0 : } SupplementalMatchOrders : <array> { 0 : 100000 } }Write the working copy back:
> set State:/Network/Service/A3551F2D-62CE-1234-B79A-6EE50CA7AE30/DNSNote, that the line
d.add ServerAddresses *clears the ServerAddresses array, thereby removing all DNS-servers tied to that particular connection ("service" in Apple-talk). Without service-specific DNS servers, Mac OS will fall back to DNS servers from other network services. Not sure how exactly that works. If you want to specify particular DNS servers, use
d.add ServerAddresses * 10.0.1.2 112.21.44.66
By the way, the "*" signifies array values, so it's not some kind of wild card.
Check the Networking Preference panel and you will notice those damn grayed out DNS server entries are gone! They will come back next time you connect and they will be first in the list. It would be fairly straight-forward to script the above scutil session but you'd still have to run the script manually after a network connection comes up.