Setting up DNS for developers (OS X)

Every time I set up a new Mac, I end up fiddling with my DNS settings to:

  • set up custom domains for web services that will run on my Mac
  • configure third-party DNS servers
    • but still be able to access internal domains
    • that work behind corporate firewalls

If you’ve ended up on this post, I guess you’re also trying to do one (or many) of the above. Let’s talk through the options.

Custom domains

There are a couple of ways we can set up custom domains. We can set up the domains individually with your hosts file, or we can set up an entire top level domain (TLD).

The hosts file is the simplest solution, and it requires no additional software. If you’re only going to run one or two services on your Mac, this is good enough.

If you’ll be running more web services, setting up an entire top level domain would be easier. Any time you set up a new site you just need to worry about your web server configuration, and the domain you choose will just work.

Set up individual domains (the hosts file)

The hosts file is a simple mapping of IP addresses to the domains they serve. On Mac OS X, your host files lives at /private/etc/hosts.

It looks like this:

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost

To set up a new domain, append 127.0.0.1 the.new.domain to the end of the file. You can do this for as many domains as you need to.

And that’s it! Just save the file, and you’re done.

Set up a custom top level domain (dnsmasq)

dnsmasq is your own little DNS server. With a little bit of configuration, you can set up an entire top level domain to resolve to your Mac, and leave all other domains going through your normal DNS provider.

Let’s get dnsmasq installed and configure .test domains to point to your Mac (it’s a good idea to stick to .test 😉):

sudo brew install dnsmasq

echo "address=/.test/127.0.0.1" \
    | sudo tee /usr/local/etc/dnsmasq.conf

sudo brew services restart dnsmasq

(We’re using the Brew package manager. It’s a lifesaver for development on OS X. If you haven’t got it already, go ahead and check it out; I’ve no idea how to install dnsmasq without it 🤷)

Then we just need to make sure your Mac sends all .test lookups to dnsmasq:

sudo mkdir -p /etc/resolver
echo "nameserver 127.0.0.1" | sudo tee /etc/resolver/test

And we’re all done!

Third-party DNS

I always set up third-party DNS for a few reasons:

  • Resilience: I want to keep doing my job when my company’s network is having DNS troubles (I haven’t worked a job where this hasn’t happened)
  • Privacy: I’m not okay with my company tracking my web traffic
  • And to actually do my job: Corporate firewalls tend to be overly restrictive and block websites I need to do my job (my own personal sites, for example 🙄)

If your company runs internal web services, a third-party provider might block you from accessing them. That’s the first problem we’ll solve.

The other problem you might encounter is DNS traffic being blocked (this is rarely intentional). This is a royal pain in the arse. Some DNS providers support the DNS-over-HTTPS (DoH) protocol, so we can work around the block with a little extra software.

Using a third-party DNS provider breaks internal domains

This is pretty easy to fix as long as your internal domains are predictable. For example, if they all end in corporate.local.

First, let’s figure out your network’s default DNS servers:

ipconfig getoption en0 domain_name_server

This gives me 192.168.0.1.

Let’s set up your Mac to forward all corporate.local lookups to that default DNS server:

sudo mkdir -p /etc/resolver
echo "nameserver 192.168.0.1" \
    | sudo tee /etc/resolver/corporate.local

DNS traffic is blocked

To be continued… This section will talk about dnscrypt-proxy