Blocking ad servers with dnsmasq

Posted by lindenle on Tue 19 Jun 2007 at 08:59

I was chatting with a colleague over IRC on Tuesday and he was complaining about the new update for Bind9 that broke his automatic blocking of ad servers. Naturally I was curious and asked him what he was talking about..

He pointed me to the site pgl.yoyo.org/adservers that provides a list of the currently known banner ad distribution domains. The avid web surfer in me immediately decided I could no longer live with banner adds while web browsing at home and I set out to solve this problem. The easiest solution would have been to ask "Bob" for his scripts and install Bind9 on my server. I however already run dnsmasq on said server and figured there must be a way to bend it to my will. Reading the dnsmasq manpage I found the following:

A, --address=/<domain>/ [domain/] <ipaddr>
              Specify an IP address to  return  for  any  host  in  the  given
              domains.   Queries in the domains are never forwarded and always
              replied to with the specified IP address which may  be  IPv4  or
              IPv6.  To  give  both  IPv4 and IPv6 addresses for a domain, use
              repeated -A flags.  Note that /etc/hosts and DHCP  leases  over-
              ride this for individual names. A common use of this is to redi-
              rect the entire doubleclick.net domain to  some  friendly  local
              web  server  to avoid banner ads. The domain specification works
              in the same was as for --server, with  the  additional  facility
              that  /#/  matches  any  domain.  Thus --address=/#/1.2.3.4 will
              always return 1.2.3.4 for any query not answered from /etc/hosts
              or  DHCP  and  not sent to an upstream nameserver by a more spe-
              cific --server directive."

This seemed to be exactly what I wanted. It redirects any server in a given domain to a specified ip address. Now all I had to do was write a script to download the list, rewrite my dnsmasq.conf file and restart dnsmasq at regular intervals.

The following bash script is the result of about an hour of hacking yesterday. It downloads a plain text list of ad servers from yoyo, rewrites "/etc/dnsmasq.conf" and restarts the server:

#!/bin/sh

### short script that downloads a list of ad servers for use with
### dnsmasq to block ads.
###

# the ipaddress where we want to send the requests to, instead of the
# bannerservers

addcatcherip='192.168.1.4'
configfile=/etc/dnsmasq.conf

# the args to add to the request to the yoyo server, to tell it that we want
# a hosts file and that we want to redirect to the addcatcher
listurlargs="hostformat=nohtml&showintro=0&mimetype=plaintext"

# URL of the ad server list to download
listurl="http://pgl.yoyo.org/adservers/serverlist.php?${listurlargs}"

# location of a file where hostnames not listed can be added
extrasfile='/etc/banner_add_hosts.manual'

## command to reload dnsmasq - change according to your system
## not sure if we need this for dnsmasq
reloadcmd='/etc/init.d/dnsmasq restart'  

# temp files to use
tmpfile="/tmp/.adlist.$$"
tmpconffile="/tmp/.dnsmasq.conf.$$"

# command to fetch the list (alternatives commented out)
fetchcmd="/usr/bin/wget -q -O $tmpfile $listurl"

$fetchcmd 

# add the extras
 [ -f "$extrasfile" ]  && cat $extrasfile >> $tmpfile

# check the temp file exists OK before overwriting the existing list
if  [ ! -s $tmpfile ] 
then
echo "temp file '$tmpfile' either doesn't exist or is empty; quitting"
exit
fi

# get a fresh list of ad server addresses for dnsmasq to refuse
cat $configfile | grep -v "address=" > $tmpconffile

while read line; do
    ADDRESS="/${line}/${addcatcherip}"
    echo "address=\"${ADDRESS}\"" >> $tmpconffile
done < $tmpfile 

mv $tmpconffile $configfile
$reloadcmd
rm $tmpfile
exit

The script has the nice feature that hosts can be added by hand in the file /etc/banner_add_hosts.manual. I installed it in /usr/local/bin and changed the permissions to 700 and ran the script:


$ sudo cp update_bannerhosts /usr/local/bin
$ sudo chown root.root /usr/local/bin/update_bannerhosts
$ sudo chmod 700 /usr/local/bin/update_bannerhosts
$ sudo  /usr/local/bin/update_bannerhosts
Restarting DNS forwarder and DHCP server: dnsmasq.

Looking at my /etc/dnsmasq.conf revealed the addition of many lines of new address entries:

address="/ac.rnm.ca/192.168.1.4"
address="/accelerator-media.com/192.168.1.4"
address="/action.ientry.net/192.168.1.4"
address="/actionsplash.com/192.168.1.4"
address="/actualdeals.com/192.168.1.4"

Next I ran a few quick tests to see that all ad domains were being redirected to my addcatcherip.

$ nslookup doubleclick.net
Server:         192.168.1.4
Address:        192.168.1.4#53

Name:   doubleclick.net
Address: 192.168.1.4
$ nslookup ads.doubleclick.net
Server:         192.168.1.4
Address:        192.168.1.4#53

Name:   ads.doubleclick.net
Address: 192.168.1.4

Sure enough any server in the domain doubleclick.net is now resolving to my local ip address. The next big test was to open a web page and see if the banner ads were gone, I chose heise.de and sure enough the big banner add at the top was now gone. Success!

The last step in this project was to add crontab entry to run the new script every 4 hours to update the list of ad servers:


$ cat /etc/cron.d/update_bannerhosts

#Update the banner hosts...
0 0,4,8,12,16,18,20 * * * root /usr/local/bin/update_bannerhosts

I hope this helps some people get rid of banner ads without having to install and learn Bind9.


This article can be found online at the Debian Administration website at the following bookmarkable URL (along with associated comments):

This article is copyright 2007 lindenle - please ask for permission to republish or translate.