Blocking Outgoing Traffic with dnsmasq

Gaining power by finding the true name

Summary

Blocking outgoing traffic by dns is easy. You simply add the target sites to te hosts file with an IP 127.0.0.1. This works on your local machine as well as on the router, which is most likely running dnsmasq as a dns proxy. The problem is to find out the names of the target sites. On your PC you can use your browser to find out. On the router you can use the dnsmasq query log. This document shows a comfortable way of doing this.

The Router

To do this you need a router with shell access. Openwrt, dd-wrt, asuswrt-merlin and tomato are the options. I am running aususwrt-merlin, but the built for the n18u is not officially supported. So I currently can't really recommend the otherwise very fine asus rt-n18u I use. You also need to be able to modify the dnsmasq configuration, which asuswrt-merlin provides by making the unused flash available as a writable partition.

The whole Story

When I checked my routers netstat-nat output, the result was somewhat disappointing, albeit interesting.

admin@asus-rt-n18u:/tmp/home/root# netstat-nat 
Proto NATed Address                  Destination Address            State 
tcp   backspace:43777                mail.heute-morgen.de:imaps     ESTABLISHED
tcp   backspace:43778                mail.heute-morgen.de:imaps     ESTABLISHED
tcp   backspace:39825                ea-in-f105.1e100.net:https     ESTABLISHED
tcp   motorola-defy:42120            50.30.0.46:5222                ESTABLISHED
tcp   huawei-p7:48678                ea-in-f108.1e100.net:imaps     ESTABLISHED
tcp   huawei-p7:53513                fra02s27-in-f5.1e100.net:https ESTABLISHED
tcp   huawei-p7:51317                54.239.34.82:https             ESTABLISHED
tcp   huawei-p7:41909                ea-in-f108.1e100.net:imaps     ESTABLISHED
tcp   huawei-p7:43487                fra07s32-in-f8.1e100.net:https ESTABLISHED

As you can see the names obtained by reverse lookup such as 1e100.net do not talk. But since the IPs have been queried using my router I should be able to do something about that. My first idea was to modify dnsmasq accordingly, The friendly people from the dnsmasq mailing list did however point out that the information could easily be parsed from the dnsmasq query log.

So after going through the honorable pain of shell programming I came up with a script that reads stdin and replaces all IP addresses with names before outputting it again. IPs from private networks are reverse looked up via dns. Other IP addresses are searched for in the dnsmasq query log. This gives the names from the A/AAAA records from the original lookups. Just run

netstat -n -4 | ./reverse_replace.sh

to see what it does. Here is an example from my router:

admin@asus-rt-n18u:/tmp/home/root# netstat-nat -n | /mnt/sda1/bin/reverse_replace.sh 
Proto NATed Address Destination Address State
tcp backspace:43777 mail.heute-morgen.de:993 ESTABLISHED
tcp backspace:43778 mail.heute-morgen.de:993 ESTABLISHED
tcp backspace:39825 www.google.com:443 ESTABLISHED
tcp motorola-defy:42120 concentrator-209-ilc.svcmot.com:5222 ESTABLISHED
tcp huawei-p7:48678 gmail-imap.l.google.com:993 ESTABLISHED
tcp huawei-p7:53513 android.l.google.com:443 ESTABLISHED
tcp huawei-p7:51317 api.audible.de:443 ESTABLISHED
tcp huawei-p7:41909 gmail-imap.l.google.com:993 ESTABLISHED
tcp huawei-p7:43487 android.l.google.com:443 ESTABLISHED

This looks better. It needs

log-queries=extra
log-facility=/var/log/dnsmasq.log

in the dnsmasq configuration. The script runs on debian (with ash installed) and on busybox.

There can be only one

Blocking dns queries to block sites only works if the client uses the dns proxy. If the client uses another dns such as 8.8.8.8, it still can access the sites as it likes. An iptables rule stops this.

# Local dnasmasq is the transparent DNS proxy
SUBNET=`nvram get lan_ipaddr_rt | sed 's#[0-9]\+$#0#'`                                                                                               
iptables -t nat -A PREROUTING ! -i `nvram get wan0_ifname` -s $SUBNET/255.255.255.0 -p udp -m udp --dport 53 -j DNAT --to `nvram get lan_ipaddr_rt`  

Note that the nvram get calls are asuswrt specific.