DNS is the system which converts a human readable address, like www.google.com, into the IP address that the computer actually uses to route your connection through the internet, e.g. 173.194.34.179.

This works very well, however, it is a clear text protocol. So, even if all other traffic from your computer is encrypted (for example, by routing your outbound traffic through a VPN – more on that later), you may still be “leaking” your browsing activity to others on your network.

Since I intend to do my best to stamp out cleartext wherever it may be, this is a problem for me.

Encrypting DNS

Unfortunately, DNS is still very much a legacy technology as far as modern security practices are concerned, and does not natively support encryption. Fortunately, OpenDNS, a distributed DNS alternative, have provided DNSCrypt, which is open source, and will encrypt dns connections between your computer and their servers.

DNSCrypt will help protect your browsing from being snooped on, however, you should be aware it’s not foolproof; while people on the same WIFI hotspot / your ISP will not be able especially if you see a lot of error (broken trust chain) resolving ... messages in your system log and your connection stops working when forwarding upstream.to see the clear text of the DNS resolution flash by, once it’s resolved into an IP address, they will still see the outbound connection. So, while they won’t see www.google.com in their capture logs, they will still see that you made a connection to 173.194.34.179, which an attacker can resolve back into www.google.com if they have the motivation. To protect against this, you must deploy this technology along side a VPN of some sort, which will encrypt the whole communication, at least until the VPN outputs onto the internet proper.

All that said, I’ve got it turned on on my home network (since there’s no sense in making an attacker’s life easy), and I’ve got it running on my laptop to give me extra protection against snooping while surfing on public wifi, and in the case of my laptop, I also surf over a VPN.

Setting it up

By far and away the easiest thing to do is use DNSCrypt-proxy, which serves as a drop in replacement for your normal DNS server provided by your ISP. Run it on your local machine, configure your network settings to talk to 127.0.0.1, and you’re done.

In my home network, I had an additional complication, in that I run my own DNS server, which provides DNS names for various human readable names for computers and devices around the home (my computers, the NAS, the printers and so on). I wanted to preserve these, and then configure the DNS server to relay anything that wasn’t local (or cached) via the encrypted link. To accomplish this, I needed to run DNSProxy on the network DNS machine along side BIND (the traditional DNS server software), but listening on a different port.

dnscrypt-proxy --local-address=127.0.0.1:5553 --daemonize

Over on github, my fork of the project contains a Debian /etc/init.d startup script which starts the proxy up in this configuration. You may find this useful.

Then, all I’d need to do is configure BIND to use the dns proxy as a forwarder, and I should be done.

In /etc/bind/named.conf.options:

forwarders {
    127.0.0.1 port 5553;
};

You can use pretty much any port that you like, but don’t be tempted to use something obvious like 5353, since this will cause problems with any Avahi/Bonjour services you may have running.

You may also want to put a blank forwarders section in the zone file for your local domain (which is strictly speaking “correct”, but many examples don’t), e.g.:

zone "example.local" {
    type master;
    notify no;
    file "/etc/bind/db.example.local";
    forwarders { };
};

Some gotchas

First, OpenDNS by default provide “helpful” content filtering, typo correction and a search page for bad domains. This last means that any bad domain will resolve to their web servers on 67.215.65.132, which can break your resolv.conf search domain. This can cause problems in certain situations if, for example, you have subdomains or wildcards in your zone file for your local domain, and will make them only accessible by the fully qualified domain name.

A workaround for this is to create a free account on OpenDNS, register your network, and then disable their web content filtering and typo correction, although my feeling is that I may have made a mistake in the configuration.

Second, OpenDNS’ servers do not support DNSSEC despite promises to the contrary. Not sure why, probably because it would break the DNS hijacking which makes the above unrecognised domain redirection possible. Since their business is security, OpenDNS should be doing DNSSEC validation on your behalf, how much of an issue this is an open question.

Still, it’s worth noting, since you will at least see a lot of error (broken trust chain) resolving ... messages in your system log and in all probability your connection will stop working when forwarding upstream.

Happy encrypting!

Update: CloudNS, an Australian based name service, now offer DNSCrypt together with no logging. There are also a number of OpenNIC servers which are starting to support DNS Encryption, so it’s worth keeping an eye on the Tier2 server page.

5 thoughts on “Lets Stamp Out Cleartext: Encrypting DNS lookups

  1. Just wanted to say thanks for the init.d script – it helped me setup a cluster of unbound resolvers using dnscrypt-proxy.

  2. [Update: Many thanks for the comments from Maciej Soltysiak of OpenNIC Poland. Please refer to his reply for information. I may update this article in time after more experimentation.]
    Foreword
    My ISP’s DNS server started playing up recently, so I investigated more reliable alternatives. However, I’m wary of the two most well-known public DNS providers, Google and OpenDNS. OpenDNS trumpets its use of DNSSEC but logs your DNS queries, discloses information to advertisers and “analytics companies” and performs censorship to be “family friendly” (http://www.opendns.com/privacy-policy/). Google also collects logs, purportedly for technical purposes (https://developers.google.com/speed/public-dns/privacy) but the meaning of some of the language in their privacy statement is unclear and given Google’s past and current behaviour and attitude to privacy, using Google DNS for privacy feels like having Dracula in charge of a blood bank.
    Hitherto I’ve been avoiding learning about DNS because it’s relatively complex, but this time I had no choice. When I emerged from the rabbit hole, I’d set up a local DNS server on my network that resolves using OpenNIC (an alternative DNS root not under ICANN control) with servers that don’t keep logs and using DNScrypt to authenticate the servers and encrypt the queries and responses.
    Problems with DNS
    Many people are by now aware of threats to the privacy of Internet browsing through things like tracking cookies and web beacons. Meanwhile, many organisations and companies are moving towards supporting https on their web servers so that traffic is encryted as it passes over the Internet. Perhaps less widely recognised, however, are the risks to privacy posed by DNS. A few examples:
    Each time your web browser retrieves information from a server on the Internet, it performs a DNS query to get the IP address of that server. Thus, someone with access to DNS query logs can determine what Internet sites you’ve been visiting and when.
    DNS queries are typically transmitted unencrypted, so can be passively monitored.
    Instead of performing a DNS lookup and returning the result, a malicious DNS server can fake the response to direct your browser elsewhere (DNS hijacking: https://en.wikipedia.org/wiki/DNS_hijacking), block access to certain websites or domains, or if the lookup fails, direct you to a page of advertisements.
    DNS “black holes” can be set up. While these can be useful for blocking spam, on the other hand even legitimate DNS servers can be manipulated by governments to censor parts of the Internet (e.g. Twitter, YouTube) for political or commercial reasons.
    DNS hijacking by consumer ISPs for their own gain rather than customer benefit is unfortunately not uncommon (see the references on the Wiki page above and http://gigaom.com/2014/05/13/atts-gigapower-plans-turn-privacy-into-a-luxury-that-few-would-choose/). Furthermore, there are pressures on ISPs from governments and law enforcement agencies to compromise their customers’ privacy or censor their browsing, in even Western democracies.
    Desirable features for DNS
    So what are some desirable properties of a DNS system? We may desire some or all of the following:
    A decentralised DNS system to prevent censorship.
    Ability to select the location of the DNS server to avoid states with excessive censorship or surveillance.
    Authenticated DNS lookups and responses to prevent tampering with DNS responses by a “man-in-the-middle”.
    Confidentiality: Encrypted DNS lookups and responses to prevent logging by packet sniffing.
    Anonymity: No logging of DNS requests by the DNS server.
    Anonymity: Untracability of the origin of our DNS request.
    Not all of these are easy to achieve, so there are trade-offs involved. The main issues are (i) finding a trustworthy DNS provider and (ii) using technical measures to achieve security of DNS communications.
    Since DNS can be abused by ISPs, the first step is to use an alternative to the ISP’s DNS server. Searching the web for public DNS services will turn up a number of free and paid-for services. Each has different privacy policies (not always obvious) and may offer value-added services such as filtering of web sites that host malware or scams.
    To protect against the response to a DNS query being forged or manipulated, the IETF has developed DNS Security Extensions (DNSSEC) http://www.dnssec.net/ which use digital signatures for authentication and anti-tampering. This was designed to protect against a specific set of threats such as DNS spoofing. However it does not address confidentiality (i.e. it does not support encryption) and one still has to trust that the peer DNS server. To address the problem of confidentiality and other issues, Daniel Bernstein, an American academic, proposed DNSCurve http://dnscurve.org/ which uses high-speed cryptography. However, DNSSEC is not yet widely supported, and the only large-scale DNS provider to offer DNScurve so far is OpenDNS, which has privacy issues.
    So, ideally we want a DNS service provider with those features we require (trustworthy, private, decentralised, value-added services, service availability etc.) which supports DNSSEC or better still, DNSCrypt. Does such a provider exist?
    OpenNIC
    I eventually settled on the Open NIC project http://www.opennicproject.org/, an alternative DNS root and DNS registry free from commercial control. They administer their own top-level domains but can also resolve all ICANN top-level domains. The DNS servers are run by individuals or private organisations and have various management policies. Some of the servers support DNSCrypt. The list of servers is available at http://wiki.opennicproject.org/Tier2 .
    Using DNSCrypt
    DNSCrypt http://dnscrypt.org/ is software based on the DNScurve protocol and that provides confidentiality of DNS queries and responses between the client and the server. The steps are as follows:
    Select the appropriate software depending on how you want to use DNSCrypt.
    Build (or download) and install.
    Configure.
    Test.
    I got a lot of information from Marcus Povey’s blog here: https://www.marcus-povey.co.uk/2013/07/11/lets-stamp-out-cleartext-encrypting-dns-lookups/
    Select software
    There are a few packages depending on how you want to use DNScrypt.
    DNScrypt
    A DNS client that runs on your computer to allow it to use a name resolver that supports DNSCrypt. This is the easiest to set up and configure.
    DNScrypt-proxy
    Acts as a forwarding proxy to allow a local name resolver to access a DNSCrypt-enabled DNS server.
    DNScrypt-wrapper
    A server-side proxy that allows a name resolver (DNS server) to support DNSCrypt https://github.com/Cofyc/dnscrypt-wrapper
    Since I have my a local DNS server for my home network, I needed to use DNScrypt-proxy, comme ça:

    
     Local 
    machines       |                                         T'Internet
     +-----+       |     Local name resolver                                  DNSCrypt-enabled
     |     +-------+        (e.g. bind)                         ####           name resolver 
     +-----+       |         +------+       +-------+         ########           +------+
                   +---------+      +-------+       +=========#########==========+      +
                   |         +------+       +-------+          #######           +------+
                   |                                            #####
                 Local                    DNSCrypt-proxy
                network
    

    Download, (build) and install
    If you use Microsoft Windows or Apple OSX, there may be pre-built packages available: see http://dnscrypt.org/.
    However, you may want to roll up your sleeves and build it yourself. I installed mine on a Raspberry Pi running the Raspberian variant of Debian linux.
    The easiest way is to use the dnscrypt-autoinstall package for debian-like systems put together by a kind chap called Simon Clausen: https://github.com/simonclausen/dnscrypt-autoinstall/blob/master/dnscrypt-autoinstall.sh This automates the entire build and installation procedure, but I didn’t like the init script. I therefore appropriated Marcus Povey’s init script from here: https://github.com/mapkyca/dnscrypt-proxy/blob/master/packages/debian/dnscrypt-proxy
    If you want to build it manually, first build and install libsodium https://github.com/jedisct1/libsodium, which is based on Daniel Bernstein’s libnacl crypto library. (If you forget this step, dnscrypt-proxy will build and run but you may not be able to use DNScurve encryption!)
    Then download and build dnscrypt-proxy:

    $ git clone https://github.com/jrossi/dnscrypt-proxy.git
    $ cd dnscrypt-proxy
    $ ./autogen.sh
    $ ./configure
    $ make
    $ make check
    $ sudo make install
    

    Installation is into /usr/local/sbin by default. This takes some time on the Raspberry Pi! Go and get a cuppa.
    DNSCrypt-proxy configuration
    dncrypt-proxy listens on a specified interface (IP address and port) for DNS queries from a local resolver/caching proxy such as bind, then forwards them to a DNScrypt DNS server (resolver). You need to configure the following items:
    Local address and port on which to listen for queries.
    Remote resolver’s IP address and port.
    The resolver’s certificate provider name and key value.
    The latter two items are provided by the DNS resolver’s administrator. For OpenNIC servers, the information is available from http://wiki.opennicproject.org/Tier2 although the items are not explicitly labelled. DNScrypt queries are often on a different port to the default DNS port 53. Examples of the certificate provider name and key value are 2.dnscrypt-cert.ns3.ca.dns.opennic.glue and 1C19:7933:1BE8:23CC:CF08:9A79:0693:7E5C:3410:2A56:AC7F:6270:E046:25B2:EDDB:04E3.
    These options are specified as arguments on the command line, e.g.

    
    dnscrypt-proxy --local-address=127.0.0.1:5553 --daemonize --resolver-address=176.10.127.43:443 --provider-name=2.dnscrypt-cert.ns3.ca.dns.opennic.glue --provider-key=1C19:7933:1BE8:23CC:CF08:9A79:0693:7E5C:3410:2A56:AC7F:6270:E046:25B2:EDDB:04E3
    

    This instructs dnscrypt-proxy to run as a daemon in the background (--daemonize) listening on the localhost address port 5553 (--local-address=127.0.0.1:5553) connecting to one of the OpenNIC servers. These would be typically set in the init script in /etc/init.d/dnscrypt-proxy. Don’t forget to enable dnscrypt-proxy to start at boot time, too.
    Once the configuration files have been changed, re/start the dnscrypt-proxy daemon (e.g. sudo /etc/init.d/dnscrypt-proxy start) and check the log files in /var/log/syslog or /var/log/daemon.log . A successful DNScrypt startup log looks something like the following:

    
    dnscrypt-proxy[1613]: Starting dnscrypt-proxy 1.4.0
    dnscrypt-proxy[1613]: Initializing libsodium for optimal performance
    dnscrypt-proxy[1613]: Generating a new key pair
    dnscrypt-proxy[1613]: Done
    dnscrypt-proxy[1613]: Server certificate #808464433 received
    dnscrypt-proxy[1613]: This certificate looks valid
    dnscrypt-proxy[1613]: Chosen certificate #808464433 is valid from [2014-02-10] to [2015-02-10]
    dnscrypt-proxy[1613]: Server key fingerprint is A448:B056:C9E0:D320:F0C3:345C:AA58:260C:D67D:1859:BDBD:9E7A:014C:7686:09C3:9E26
    Aug 9 19:46:02 raspberrypi dnscrypt-proxy[1613]: Proxying from 127.0.0.1:5553 to 176.10.127.43:5353
    

    Bind configuration
    In the above example, dnscrypt-proxy listens on port 5553 on the localhost address, so we must configure our forwarding proxy (running on the same machine) to forward DNS queries to that interface.
    For bind, edit the forwarders in the options section of the named.conf.options configuration file (typically stored at/etc/bind/named.conf.options) as follows:

    
    forwarders {
        127.0.0.1 port 5553
    };
    

    You will also need to change the value of the dnssec-validation parameter to yes (it defaults to auto).

    
    dnssec-validation yes;
    

    Once the configuration file has been changed, restart bind (e.g. sudo /etc/init.d/bind restart). To check things are working, first do a DNS lookup (e.g. $ nslookup http://www.amazon.co.uk) to see that DNS is working on your local system. (The server name reported should be the interface of the bind server.) To check that lookups are using dnscurve-proxy, use a network packet analyser (like tcpdump) to examine network traffic between dnscurve-proxy on your local machine and the remote DNS server. For example, say the remote DNS server uses port 443 and the Ethernet port eth0 is connected to the Internet, we can monitor that traffic with the command

    
    $ sudo tcpdump -i eth0 -vvv 'port 443'
    

    Then run a DNS lookup on a different domain to the previous (otherwise you’ll just get a reply from bind’s local cache).

    
    $ dig www.amazon.co.jp
    

    and you should get gobbledegook such as the following

    
    tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
    19:57:25.158916 IP (tos 0x0, ttl 64, id 53899, offset 0, flags [none], proto UDP (17), length 540)
    192.168.10.109.55579 > ns1.ch.dns.d0wn.biz.mdns: [udp sum ok] 14160 updateDA+% [b2&3=0x5971] [31348a] [30566q] [59967n] [767au] Type50645 (Class 17488) (QU)? [|domain]
    19:57:25.166805 IP (tos 0x0, ttl 64, id 53900, offset 0, flags [none], proto UDP (17), length 540)
    192.168.10.109.55579 > ns1.ch.dns.d0wn.biz.mdns: [udp sum ok] 14160 updateDA+% [b2&3=0x5971] [31348a] [30566q] [59967n] [767au] Type50645 (Class 17488) (QU)? [|domain]
    19:57:25.466642 IP (tos 0x0, ttl 49, id 5993, offset 0, flags [none], proto UDP (17), length 332)
    ns1.ch.dns.d0wn.biz.mdns > 192.168.10.109.55579: [udp sum ok] 29238 updateM [b2&3=0x666e] [27192a] [30295q] [64895n] [26494au] Type30578 (Class 3221) (QU)? M-@^@^T^@M-<M-C^@^T^@M-@M-?hM-YMM-u^C]pM-^CkM-CM-R)^E_^G,@M--}M-@,}qrM-tM-^NM-^D^P1cM-oLM-ecM-u^]^S^H^CM-^_M-^XM-iM-qM-^U^DM-^Wd^?^EjPM-^NlwM-(^AM-uHb^D}M-u$M-2M-^AM-TM-+^R;M--M-yM-Mip^IM-6M-Z`T$sOu^J_M-^TlM-*M-IGcM-^QK^@=FM-1M-,^PjM-]M-^GN3UM-<M-8M-[^B8zM-,M-8yoM-wM-L8M-^LB!M-pN^^^NM-KJM-H'M-KeM-^DM-^YM-^VM-^RM-yM-97^?M-lo@^PM-[WTM-^^_M-AS>M-M-QM-q.M-^I.M-=^E$yM-[M-;M-^OM-iheM-^ZM-7M-B%DgM-^M-5Z.T^C_N^KPM-V^_M-*M-= 192.168.10.109.55579: [udp sum ok] 29238 updateM [b2&3=0x666e] [27192a] [30295q] [49961n] [60541au][|domain]
    ...
    

    You can satisfy yourself that the actual lookup does not appear in plaintext.
    Check the logs in /var/log/syslog (labelled [named]) to check nothing untoward is happening. If you get messages such as NS: no valid signature found or NS: got insecure response; parent indicates it should be secure then check that dnssec-validation is set to yes rather than auto.
    You should also not get messages from dnscrypt-proxy such as [dnscrypt-proxy] Unable to retrieve server certificates. If these occur, check the dnscrypt-proxy provider name and key.
    As a final step for assurance, repeat the experiment running the packet sniffer on the default DNS port (53) on the Internet-connected Ethernet interface:

    
    $ sudo tcpdump -i eth0 -vvv 'port 53'
    

    Then run a DNS lookup on a different domain again.

    
    $ dig www.bbc.co.uk
    

    You should find *no* traffic on port 53. (If you do, again check that dnssec-validation is set to yes rather than auto.)
    Finally, you can configure your firewall rules to close UDP/TCP port 53 traffic to/from the Internet.
    Replacing the Root Hints file
    The root hints file (typically /etc/bind/db.root, but set in the configuration) tells bind where to find the nameservers for the root zone (i.e. for each Top Level Domain). The default file points to the default ICANN root servers. However, you will get errors such as the following:

    
    named[11193]: checkhints: unable to find root NS 'ns1.opennic.glue' in hints
    named[11193]: checkhints: unable to find root NS 'ns2.opennic.glue' in hints
    named[11193]: checkhints: unable to find root NS 'ns3.opennic.glue' in hints
    ...
    named[11193]: checkhints: extra NS 'A.ROOT-SERVERS.NET' in hints
    named[11193]: checkhints: extra NS 'B.ROOT-SERVERS.NET' in hints
    named[11193]: checkhints: extra NS 'C.ROOT-SERVERS.NET' in hints
    ...
    

    we can replace this file with one that queries the OpenNIC servers. This can be done with the following:

    
    # dig . NS @75.127.96.89 > /etc/bind/db.root
    

    See the OpenNIC Wiki for more details. http://wiki.opennicproject.org/Tier2ConfigBindHint
    Open Issues
    Availability
    DNSCrypt as currently implemented only uses a single remote resolver. This means you lose DNS if the server becomes unavailable. The man page says that it can also accept a CSV file that contains multiple resolvers, but this feature appears not to have been implemented. As a workaround, I suppose you could have two instances of dnscrypt-proxy listening on different addresses and configure bind to use them both as forwarders.
    Anonymity
    A DNS server may claim not to keep logs of DNS requests and queries but you have to take that on trust. For greater assurance of anonymity, it may be possible to tunnel DNS requests over Tor or I2P using Onioncat https://www.onioncat.org. Some OpenNIC servers claim to support Tor/OnionCat.
    Share this:TwitterFacebookLike this:Like Loading…

    Related

  3. Love the info provided, very helpful and informative. I get an error when trying to install DNSCRYPT though saying my lo address is in use. Should I configure DNSCrypt first you think? I changed the lo address BIND is using to free up 127.0.0.1 for the DNSCrypt install, same error. Should I Disable BIND9, install DNScrypt, enable BIND, then point forwarders to 127.0.0.1? Maybe I’m missing something. Any help would be appreciated.

Leave a Reply