Blocking Outgoing Traffic with dnsmasq
Gaining power by finding the true name
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.
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 126.96.36.199: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 188.8.131.52: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
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 184.108.40.206, 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.