Monday 3 December 2012

DNSCRYPT ON RASPBERRY : PROTECT YOUR PRIVACY

INTRODUCTION :
___________________________________________________________
Nowadays our privacy is more than ever under pressure, when Internet Service Providers or governements are enforcing "security" laws to either watch for criminal activities online, or to censor some websites. Some ISP are also checking to which website you are going to, not to spy on you, but just to lower your connection speed when you go on a bandwidth hungry streaming website (like the famous youtube). Finally, common attacks such as man-in-the-middle can be used againt DNS on open WIFI networks.

If you think that connecting to an HTTPS website is enough to prevent your ISP or anyone else to know where you are going, think again. Indeed, while your connection is fully encrypted from start to end, you still have to ask your DNS server the IP address corresponding to the website name (domain). Consequently, you are telling where you go.

There is a DNS provider out there who has created a tool to remediate this problem : OpenDNS.

Their tool is named DNSCrypt.

Image taken from http://www.opendns.com





DESCRIPTION :
___________________________________________________________
DNSCrypt enables you to encrypt your DNS queries made to OpenDNS's DNS servers. That means that your DNS queries will be protected from spying and tampering, improving both your security and your privacy.

DNSCrypt only works with OpenDNS servers, which means that for using DNSCrypt you will have to agree to use OpenDNS. It won't work with any other DNS provider as queries are made on remote UDP port 443, and OpenDNS IP addresses are used by default.

While I will explain how to setup DNSCrypt on ArchlinuxARM on a Raspberry Pi (Raspberry Pi is a trademark of the Raspberry Pi Foundation), DNSCrypt is in fact available for Windows, Mac, and others Linux distributions.

This article is based on my previous PIWALL article, but it can be adapted to any Linux distribution.


SUMMARY :
___________________________________________________________


1. DNSMASQ
___________________________________________________________
Before installing DNSCrypt, I assume that you have a working dnsmasq (DNS cacher/server) on your system. If this is not the case, you can check the chapter SETTING UP DHCP & DNS in my previous article. Anyway, below is a quick check list for DNS dnsmasq configuration (I skip DHCP parameters) :

$ sudo vi /etc/dnsmasq.conf
## DNS CONFIGURATION ##
# Interfaces for DNS
interface=eth0
listen-address=192.168.1.3
bind-interfaces

# Never forward plain names (without a dot or domain part)
domain-needed

# Never forward addresses in the non-routed address spaces.
bogus-priv

# Max concurrent DNS queries (default = 150)
dns-forward-max=150

# DNS cache size (default = 150)
cache-size=300

The listen address is the one from PiWall. You should modify it accordingly to your system IP address.

$ sudo vi /etc/resolv.conf
nameserver 127.0.0.1
nameserver 208.67.220.220
nameserver 208.67.222.222

Above are the two OpenDNS DNS servers IP addresses.

If your dnsmasq is working correctly, listening on both 192.168.1.3:53 and 127.0.0.1:53, then you can go to the next chapter.





2. DNSCRYPT : INSTALLATION
___________________________________________________________
First check the last version of DNSCrypt source code available on github. At the time I am writing, it is 1.2.0 :
$ wget https://github.com/downloads/opendns/dnscrypt-proxy/dnscrypt-proxy-1.2.0.tar.gz

We will need gcc to build our program from sources :
$ sudo pacman -S gcc

Now let's build DNSCrypt, but be aware that it will take a long time to compile on a Raspberry :
$ tar zxpvf ./dnscrypt-proxy-1.2.0.tar.gz
$ cd dnscrypt-proxy-1.2.0
$ ./configure
$ make
$ sudo make install

If you are setting up DNSCrypt on a PiWall, or are using iptables on another system, you will need to allow beforehand DNScrypt trafic in your rules. Below is an example for the PiWall advanced script :
DNS_SERVER1="208.67.220.220"
DNS_SERVER2="208.67.222.222"

iptables -A GATEWAY_INTERNET -p udp --sport $UNPRIV_PORTS -d $DNS_SERVER1 -m multiport --dports domain,https -j ACCEPT
iptables -A GATEWAY_INTERNET -p udp --sport $UNPRIV_PORTS -d $DNS_SERVER2 -m multiport --dports domain,https -j ACCEPT
iptables -A GATEWAY_INTERNET -p tcp --sport $UNPRIV_PORTS -d $DNS_SERVER1 -m multiport --dports domain,https -j ACCEPT
iptables -A GATEWAY_INTERNET -p tcp --sport $UNPRIV_PORTS -d $DNS_SERVER2 -m multiport --dports domain,https -j ACCEPT

Now let's try to start DNScrypt from the console and check that it launches correctly :
$ sudo /usr/local/sbin/dnscrypt-proxy -a 127.0.0.2:53

You should see DNSCrypt starting, retrieving a certificate, and listening on 127.0.0.2:53. The default 127.0.0.1 is already used by dnsmasq, so we cannot use it. If it does not work here, check your firewall rules, and your system date and time (they must be correct in order for DNSCrypt to check for certificate validity).

Once it's running correctly, interrupt it with CTRL+C and go to the next chapter.





3. DNSCRYPT : CONFIGURATION
___________________________________________________________
Now that both dnsmasq and DNSCrypt are functional, we have to make the former going trough the later. Indeed, dnsmasq will still be the DNS cache/server for the LAN, but it should make it's requests to DNSCrypt.

Before going further, we will make sure DNSCrypt is launched at startup :
$ sudo vi /etc/rc.local
echo "Starting DNSCrypt"
/usr/local/sbin/dnscrypt-proxy -a 127.0.0.2:53 –daemonize

The first thing that comes to mind to make dnsmasq use DNSCrypt, is to modify the /etc/resolv.conf file, as dnsmasq sends it's queries by default to the DNS servers written there :
nameserver 127.0.0.1
nameserver 127.0.0.2

127.0.0.2 being DNSCrypt, it should theoretically work.

In fact, it will on any Linux distribution running on a common hardware with a Real Time Clock (RTC), but it won't on a Raspberry Pi because it does not have one.

Why not having a RTC will prevent DNSCrypt to work with the above configuration on a Raspberry Pi you say ?

Everytime the Raspberry boots up, it starts openntpd to synchronise it's clock from an Internet NTP server. However, the file /etc/ntpd.conf targets a ntp server defined by a domain name :
servers pool.ntp.org

At startup, openntpd will query 127.0.0.1 (dnsmasq) for "pool.ntp.org", dnsmasq will then ask 127.0.0.2 (DNSCrypt) to resolve the name, however DNScrypt cannot initialise because it is waiting openntpd to synchronise system time to be able to retrieve DNS certificates !

That's quite a "chiken-and-egg" story.

While we may be tempted at first to use instead a static NTP IP address, it is not advised. NTP addresses may change, and you would end up with no internet connection.

We can cleanly solve this issue thanks to a dnsmasq parameter, to tell it to use another "resolv.conf" file, as below :
$ sudo vi /etc/dnsmasq.conf
## DNS CONFIGURATION ##
# Interfaces for DNS
interface=eth0
listen-address=192.168.1.3
bind-interfaces

resolv-file=/etc/resolv-dnsmasq.conf

Then we have to create this file :
$ sudo vi /etc/resolv-dnsmasq.conf
nameserver 127.0.0.2

Your regular resolv file can be like this :
nameserver 127.0.0.1
nameserver 208.67.220.220
nameserver 208.67.222.222

Thanks to this modification :
- At startup openntpd can query opendns servers directly (resolv.conf file) to resolv by itself ntp server domain name, synchronising system date and time.
- DNSCrypt can then initialise and pull opendns certificates.
- Any subsequent DNS requests from the LAN to dnsmasq will be forwarded to DNSCrypt (resolv-dnsmasq.conf) if not already in dnsmasq's cache.

Now you can launch DNSCrypt like this :
$ sudo /usr/local/sbin/dnscrypt-proxy -a 127.0.0.2:53 –daemonize

Check that everything works. Once it's ok, reboot your Linux to check that it is still working after the startup.

To check that DNS queries are effectively sent encrypted, you can use tcpdump, and then surf on a computer on your LAN :
$ sudo tcpdump -i eth0 dst host 208.67.222.222 or dst host 208.67.220.220 or src host 208.67.222.222 or src host 208.67.220.220 -n

You should only see remote UDP port 443 being used, not 53 :
23:00:41.806710 IP 192.168.1.3.58619 > 208.67.220.220.443: UDP, length 260
23:00:41.843235 IP 208.67.220.220.443 > 192.168.1.3.58619: UDP, length 496






CONCLUSION
___________________________________________________________
While HTTPS is widespread for securing HTTP, DNS however goes in clear text and there is no common alternative. Thanks to OpenDNS, DNSCrypt brings a solution.

The advantage of implementing DNScrypt on a network gateway is that it then works for every network device you can have on your LAN, even the ones for which there is no client (video games consoles, printers, NAS, iPad, etc...).

Even if DNSCrypt does not fix DNS protocol's vulnerabilities (that should be addressed with the DNSSEC protocol), it still does a good job at improving privacy and security.

As a last note, I'm pleased to see that the Raspberry Pi (256MB model) can handle flawlessly all of these roles :
- Network gateway
- Firewall
- DHCP server
- DNS cache/server with encryption
- NIDS/Snort (Network Intrusion Detection System)
- Alert notifications (firewall or NIDS) by email (requires Python language)

Do not forget to check Raspberry Pi website.





LINKS
___________________________________________________________



Legal notice : banner made from various free pictures available at FreeDigitalPhotos.net