Block ads with OpenWRT dnsmasq

Block ads with OpenWRT dnsmasq and automate downloading of the latest list once a week. This solution can also be applied to blocking crytocoin miner domains.

Updates

  • 2017-09-26: Extended this article to include details on blocking cryptocoin miners.
  • 2018-04-22: Added information on how to use OpenWRT adblock package to simplify things.

Motivation

I do not mind seeing ads but they must not be intrusive. Try browsing my blog without ad blocker (if you are using it now) and you will see that I do not place ads in places where it disrupts natural flow of reading.

On PC, it is possible to install ad blockers into browsers. Some browsers even come with such a feature builtin too. However, you cannot do that on some devices, such as Smart TV. Therefore, I had to find an effective way to block ads with my OpenWRT router.

In September 2017, I came across news reports that some websites including seemingly legitimate ones are using their visitors web browsers to perform cryptocoin mining without their knowledge. Subsequently, I found that Adblock Plus subscriptions page now has a filter called NoCoin. I raised an issue on GitHub requesting the author to introduce a host file variant of NoCoin and the author created it within hours. I then updated this blog post to include additional information on that.

Using OpenWRT adblock package

When I was writing this post, I had no idea a package called adblock already exists on OpenWRT repository. It is available for OpenWRT/LEDE 17.x. To install:

opkg update
opkg install luci-app-adblock

You are more likely to prefer using packages over manual setup. However, if you do like manual approach, read on.

Manual setup

Pre-requisites

Firstly, I am assuming you are using OpenWRT. It comes with dnsmasq which is a DNS forwarder.

Bash script for retrieving latest block list host file

Copy the script below into your OpenWRT. Place it somewhere that can persist over reboots, /opt/dnsmasq-blocklist/update-blocklist.sh.

#!/bin/sh
set -e

mkdir -p /tmp/dnsmasq-blocklist
curl -s --max-filesize 524288 -o /tmp/dnsmasq-blocklist/danpollock.hosts "http://someonewhocares.org/hosts/zero/hosts"
curl -s --max-filesize 65536 -o /tmp/dnsmasq-blocklist/nocoin.hosts "https://raw.githubusercontent.com/hoshsadiq/adblock-nocoin-list/master/hosts.txt"
/etc/init.d/dnsmasq restart

Notes:

  1. As an example, the script above downloads Dan Pollock’s host file. The line after it downloads cryptocoin miner host file. You can use whichever you prefer as long as it is not too big or else your OpenWRT device will run out of free RAM.
  2. The block list is downloaded into an in-memory temporary storage for speed and to reduce writes to flash.
  3. In this case, curl is preferred over wget because it can limit file size of download, in case the block list someday gets too big, the router may not have enough RAM to operate properly. Therefore, this acts as a safeguard.
  4. If you want to download from an SSL source, you need to install SSL libraries.

Grant execute permission to the script

Run the following command:

chmod +x /opt/dnsmasq-blocklist/update-blocklist.sh

Run the script on startup

Place the following lines into /etc/rc.local above the exit 0 line.

# Update dnsmasq block list
/opt/dnsmasq-blocklist/update-blocklist.sh

Update block list once a week

Edit crontab, crontab -e. Place the following line:

0 2 * * 1 /opt/dnsmasq-blocklist/update-blocklist.sh

If you are unfamiliar with cron syntax, the above means the script is executed once every Monday at 2am.

You can also add the line above via LuCI GUI, System > Scheduled Tasks.

Configure dnsmasq to load the block list

Edit /etc/config/dhcp, add the line below into config dnsmasq:

config dnsmasq
    ...
    list addnhosts '/tmp/dnsmasq-blocklist/danpollock.hosts'
    list addnhosts '/tmp/dnsmasq-blocklist/nocoin.hosts'
    ...

Restart dnsmasq to take effect:

/etc/init.d/dnsmasq restart