Ad-blocking is becoming more of a necessity these days, and while there are many browser plugins that will strip ads, they can be slow and memory-hungry. Blocking ads via DNS is an interesting alternative, that can work along-side browser-based solutions, and because it's done on the gateway, any computer that connects to the internet via the gateway will benefit from it.
Normally, when a browser wants to load an ad from, say, annoyingads.com, it will do a DNS lookup on that domain name to get its IP address, and then send a request to that IP address to get an ad:

However, since we are running our own DNS server, we can circumvent this process by returning something different for the IP address. If we set up a dummy web server and return the IP address of that[1]We could just return an invalid IP address, but the browser will try to connect to it, and it will take some time before it gives up, which will slow down page loads noticeably., when the browser tries to load an ad, it will connect to that instead of the real server. If we configure the dummy web server to return blank images, then all we will see in the web page is empty space, rather than ads.

Installing the web server
Download the daemon version of pixelserv from here and save it somewhere e.g. /root/bin/pixelserv.pl.
Make sure it's executable, then run it:
sudo chmod 755 pixelserv.pl sudo ./pixelserv.pl
Open a browser and go to http://10.0.0.1 - you should receive a 1x1 image.
Setting up the DNS blacklist
Save the script below somewhere (e.g. /root/bin/get-dns-blacklist.sh), which downloads a list of domains known to serve ads:
curl "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=bindconfig&showintro=0&mimetype=plaintext" \ | sed -e "s/null.zone.file/\/etc\/bind\/db.pixelserv/" \ >/etc/bind/zones.blacklist service bind9 reload
Make sure it's executable, then run it:
sudo chmod 755 get-dns-blacklist.sh sudo ./get-dns-blacklist.sh
Check that the zones blacklist file (/etc/bind/zones.blacklist) was created and populated.
Create a zone file e.g. /etc/bind/db.pixelserv:
$TTL 86400 ; one day @ IN SOA ads.example.com. hostmaster.example.com. ( 2001010100 ; serial number YYYYMMDDNN 28800 ; refresh 8 hours 7200 ; retry 2 hours 864000 ; expire 10 days 86400 ) ; min ttl 1 day NS my.dns.server.org A 10.0.0.1 @ IN A 10.0.0.1 * IN A 10.0.0.1
Then, add an entry to /etc/bind/named.conf.local:
include "/etc/bind/zones.blacklist" ;
Test the ad-blocker
The DNS server should still be running with the old settings, so if we do a DNS lookup on a blacklisted domain, it should still resolve to the real IP address:
Now, if we restart the DNS server:
sudo service bind9 restart
and run the same query again, we can see that the returned IP address is different, and the domain name is now pointing to us.
This means that any attempt to connect to 101com.com will actually connect to our pixelserv web server, and any attempt to retrieve an ad will receive a 1x1 image instead.
Configuring the ad-blocker to run at system startup
We want pixelserv to run at startup, so we can add it to /etc/rc.local:
# start pixelserv /root/bin/pixelserv.pl &
Note the trailing ampersand, which tells the script to run in the background, so that the startup script doesn't block, waiting for it to finish.
We also want to regularly download the latest blacklist, so we schedule a cron job to run the download script:
sudo crontab -e
In the screenshot, I've set the job to run at 3am every day, and to log the output, in case there are problems.
« Setting up a WiFi access point | Tutorial index | Setting up OpenVPN » |
1. | ↵ | We could just return an invalid IP address, but the browser will try to connect to it, and it will take some time before it gives up, which will slow down page loads noticeably. |