Domain Name Service (DNS) is one of the building blocks of the Internet, yet people pay very little attention to it. Using it optimally, can help you run much much more faster but also more secure.
In this tutorial, I will show you how to reduce your DNS queries and secure them using encryption. This is all about how you can secure your Mac, by switching on default DNS security options and running software such as DNSmasq.
Setting up /etc/hosts correctly
Very few people make the most out of the
/etc/hosts is the file that is read before a DNS query is made. In it, there are domain name entries mapped to their IP addresses.
In our case,
/etc/hosts can be well used to block DNS queries, such as the ones performed by malware, advertisement tracking and other unwanted domains.
To block a domain, simply add an entry
0.0.0.0 unwanted-domain.com to the file. The 0.0.0.0 points to an impossible path, resulting in a dropped query.
In order to get setup, let's quickly add an extensive ad and malware blocking list to our file.
curl "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" | sudo tee -a /etc/hosts
$ wc -l /etc/hosts 41090 /etc/hosts
As we can see, we have now successfully blacklisted ~40.000 domain names. The beauty about it? Even an anti-ad blocker script can't notice it.
Improving Speed by Caching DNS Queries
The next step is to use DNSmasq, which is basically a local DNS server, that caches your queries, prevents upstreaming queries for unqualified names, and blocks entire TLDs. This is also the first building block for encrypting your queries, using DNSCrypt, later on.
Install DNSMasq on Mac
The best way to install DNSmasq is through
brew. In case you haven't downloaded brew, go ahead and install it.
$ brew install dnsmasq $ cp /usr/local/opt/dnsmasq/dnsmasq.conf.example /usr/local/etc/dnsmasq.conf
Edit the configuration:
$ vim /usr/local/etc/dnsmasq.conf
Read through the configuration. Here is what I recommend:
# Forward queries to DNSCrypt on localhost port 5355 server=127.0.0.1#5355 # Never forward plain names domain-needed # Examples of blocking TLDs or subdomains address=/.onion/0.0.0.0 address=/.local/0.0.0.0 # Never forward addresses in the non-routed address spaces bogus-priv # Reject private addresses from upstream nameservers stop-dns-rebind # Query servers in order strict-order # Set the size of the cache # The default is to keep 150 hostnames cache-size=8192 # Optional logging directives log-async log-dhcp log-facility=/var/log/dnsmasq.log # Uncomment to log all queries #log-queries
Then start the program using sudo – it needs sudo to bind itself to a priviledged port (53):
$ sudo brew services start dnsmasq
Now you need to tell the operating system to use DNSmasq instead of relying on an external DNS server. For this you need to open System Preferences > Network, selecting the active interface and click on Advanced. Select the tab DNS, click on + and enter
If you want to go all console, enter this:
$ sudo networksetup -setdnsservers "Wi-Fi" 127.0.0.1
Make sure DNSmasq is correctly configured:
$ scutil --dns DNS configuration resolver #1 nameserver : 127.0.0.1 flags : Request A records, Request AAAA records Reachable, Local Address, Directly Reachable Address $ networksetup -getdnsservers "Wi-Fi" 127.0.0.1
Note If you are using DNSmasq with a VPN, your VPN software might just override your DNS settings on connecting. This happens to me. I still haven't found the optimal solution myself, but more on the topic can be found here.
Setting up DNSCrypt
DNScrypt will encrypt all of traffic to DNS servers.
To install it use brew:
$ brew install dnscrypt-proxy
Now you need to find the
homebrew.mxcl.dnscrypt-proxy.plist file, which I found either under
If you still can't find it, search using find:
$ find / -name homebrew.mxcl.dnscrypt-proxy.plist
Open it to make sure it includes the
<!DOCTYPE plist PUBLIC "-/Apple/DTD PLIST 1.0/EN" "http:/www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>homebrew.mxcl.dnscrypt-proxy</string> <key>KeepAlive</key> <true/> <key>RunAtLoad</key> <true/> <key>ProgramArguments</key> <array> <string>/usr/local/opt/dnscrypt-proxy/sbin/dnscrypt-proxy</string> <string>/usr/local/etc/dnscrypt-proxy.conf</string> </array> <key>UserName</key> <string>root</string> <key>StandardErrorPath</key> <string>/dev/null</string> <key>StandardOutPath</key> <string>/dev/null</string> </dict> </plist>
Find the line containing the
.conf string, in my example
<string>/usr/local/etc/dnscrypt-proxy.conf</string>. Edit the file, make sure it includes the following:
## Full path to the list of available DNSCrypt resolvers ResolversList /usr/local/opt/dnscrypt-proxy/share/dnscrypt-proxy/dnscrypt-resolvers.csv ## This is actually the Resolver that should be used; should be one of those contained in the list. ResolverName random ## Local address and port to listen to. LocalAddress 127.0.0.1:5355 ## Run the proxy as a background process. Daemonize yes ## Cache DNS responses to avoid outgoing traffic when the same queries are repeated multiple times in a row. LocalCache on ## Run the server as a less-privileged system user. User nobody
Now you are all setup. Save the file and start the proxy server.
$ sudo brew services start dnscrypt-proxy
Check that it's actually bound to port 5355 and that the process is truly running:
$ sudo lsof -Pni UDP:5355 dnscrypt- 39324 nobody 6u IPv4 0x469e69288063ae1f 0t0 UDP 127.0.0.1:5355 $ ps A | grep dnscrypt 39324 ?? Ss 0:00.01 /usr/local/opt/dnscrypt-proxy/sbin/dnscrypt-proxy /usr/local/etc/dnscrypt-proxy.conf
Confirm then that the outgoing DNS traffic is encrypted:
$ sudo tcpdump -qtni en0 IP 184.108.40.206.59444 > 220.127.116.11.443: UDP, length 512 IP 18.104.22.168.443 > 22.214.171.124.59444: UDP, length 368 dig +short -x 126.96.36.199 resolver2.dnscrypt.eu.
By using DNSmasq in combination with DNScrypt we reduce the following risks:
- Man in the Middle Attacks (such as DNS spoofing)
Not only do we reduce risks, we also improve speed by caching results locally. Thus, resulting in better privacy online.
- Mac Security & Privacy Guide - this is the guide I relied heavily upon for my setup.