We are going to look at how to implement advert blocking on an Edgerouter at a network level using DNS. This can also be applied to other software routing devices. There are many ways to block adverts these days – various browser plugins, browsers with built in blocking, proxy servers (normal or transparent) and also with DNS. Whatever your thoughts are regarding websites using adverts for revenue generation, the fact is many sites have obscene amounts of ads.
Quite often adverts are designed to dupe you by purposely making them look like the link you are actually after. A typical example of this is where you have a ‘download’ button which is actually an advert to download something else entirely. This is not only deceitful but is down right unacceptable. Until all adverts become unobtrusive, targeted and honest I will keep blocking them; even if this means I can’t access websites which block you for blocking ads.
Although ‘adblock‘ is a great browser plugin for Chrome and Safari etc it doesn’t cover all devices, such as tablets and phones. Sure there are browsers with build in ad blocking and you can configure adblock as a local proxy etc but there is another way – with DNS.
The Edgerouter uses dnsmasq for its DNS forwarding service. Although it maybe wouldn’t be my first choice it works well. Most clients on a home network will likely configure themselves with DHCP so providing your Edgerouter is configured to be the DNS server handed out by DHCP this will work.
The general idea of this method is to coerce dnsmasq to return a specific IP address when looking up certain hostnames (namely those of known advertising networks) and to have a pixel server running on that IP to serve a single pixel image. By doing this you are effectively turning all adverts into a single transparent pixel. You can do this without a pixel server but it’s much cleaner and browsers will be happier.
First up lets create the shell script by SSH’ing to your edgerouter.
admin@edgerouter:~$ sudo vi /config/user-data/update-adblock-dnsmasq.sh
Then paste in this shell script.
#!/bin/bash if grep -q adblock /var/spool/cron/crontabs/root then echo "Cron OK" else echo "0 3 * * * /config/user-data/update-adblock-dnsmasq.sh" >> /var/spool/cron/crontabs/root fi ad_list_url="http://pgl.yoyo.org/adservers/serverlist.php?hostformat=dnsmasq&showintro=0&mimetype=plaintext" #The IP address below should point to the IP of your router or to 0.0.0.0 pixelserv_ip="192.168.0.2" ad_file="/etc/dnsmasq.d/dnsmasq.adlist.conf" temp_ad_file="/etc/dnsmasq.d/dnsmasq.adlist.conf.tmp" curl -s $ad_list_url | sed "s/127\.0\.0\.1/$pixelserv_ip/" > $temp_ad_file domains="ads.adplxmd.com seethisinaction.com" for domain in $domains do echo "address=/$domain/$pixelserv_ip" >> $temp_ad_file done if [ -f "$temp_ad_file" ] then mv $temp_ad_file $ad_file else echo "Error building the ad list, please try again." exit fi /etc/init.d/dnsmasq force-reload
‘pixelserv_ip’ should be set to the machine running your pixel server. You can also just set this to ‘0.0.0.0’ but that is a bit nasty.
The ‘domains=’ section can be used to add custom domains which are not contained in the list downloaded from the predefined advert list.
Next make this script executable and run it.
admin@edgerouter:~$ sudo chmod +x /config/user-data/update-adblock-dnsmasq.sh admin@edgerouter:~$ sudo /config/user-data/update-adblock-dnsmasq.sh
There should now be a new file created in the dnsmasq config directory.
admin@edgerouter:~$ head -3 /etc/dnsmasq.d/dnsmasq.adlist.conf address=/101com.com/192.168.0.2 address=/101order.com/192.168.0.2 address=/123found.com/192.168.0.2
You will also now have a crontab entry created.
admin@edgerouter:~$ sudo crontab -l | tail -1 0 3 * * * /config/user-data/update-adblock-dnsmasq.sh
The cron will run every morning at 3am and update the list. If you reboot the edgerouter you will need to execute the script – this will recreate the cron entry for you.
Now we test with a known host name to make sure it is working. Do this from a client machine on your network which is configured to use the edgerouter for DNS, or specify the edgerouter for the lookup.
MacBook-Pro:~$ dig 101com.com @192.168.0.1 +short 192.168.0.2
The result should be whatever you set ‘pixelserv_ip’ to be.
The last step is to configure a pixel server. There are dedicated pixel servers out there such as pixelserv but I just use Apache on my Pi.
In the Apache default site config, configure the 404 to be a single pixel image.
root@pi~$ vi /etc/apache2/sites-enabled/000-default <Directory /var/www/html/> ErrorDocument 404 /pixel.gif </Directory>
You will probably want this configured for both HTTP and HTTPS as adverts will be served over the same protocol as the rest of the web page to avoid browser ‘insecure content’ errors.
Next, create the pixel file and reload Apache.
curl https://madpsy.uk/wp-content/uploads/2015/11/pixel.gif > /var/www/html/pixel.gif service apache2 reload
That’s it! You can now test by browsing to our test host name again, with a random path. You should pretty much see nothing but more importantly there should be no error.
You will notice it shows ‘test 1×1’ as the title, indicating our single pixel image is being displayed.
I’ve been running this for months now and not had any problems with it. If you do find problems you can debug if the ad blocking is fault by changing your local machine’s DNS servers to google’s (188.8.131.52, 184.108.40.206) or by deleting /etc/dnsmasq.d/dnsmasq.adlist.conf and reloading dnsmasq on the Edgerouter.