Skip to main content.

Adblocking with DNSMasq & Pixelserv


Live demo in BSD Now Episode 058. Originally written by CJ, with edits and additions by TJ, for | Last updated: 2014/10/08

NOTE: the author/maintainer of the tutorial(s) is no longer with the show, so the information below may be outdated or incorrect.

Web advertising can be a nuisance. At best, they clutter up pages and slow browsing down. At worst, they can be scams or malware vectors, or engage in widespread tracking of the end user. Most users are now familiar with ad blocking on their web browsers, but for some devices that isn't practical. What about the ads on games consoles or other devices? What if we want to block advertising on any device connected to the network? To do so, there are two things we need to set up. The first is DNSMasq, a combined DHCP and caching DNS server. The second is pixelserv, a perl script that serves a transparent GIF file, to avoid 404 errors on domains that get blocked by DNSMasq. The ideal place to set this up would be on a gateway, but in reality it could be set up anywhere. For the tutorial, I'm assuming that we're using FreeBSD, and that is our gateway. We'll need the following:

  • DNSMasq (dns/dnsmasq)
  • perl (lang/perl)

Install them via ports or packages and we'll get started.


DNSMasq is configured through /usr/local/etc/dnsmasq.conf. Thankfully, it's quite easy to follow. There are too many usage cases to go through the configuration file line by line, unfortunately. For the most part, in order to get started, you need to make sure that DNSMasq is listening on the required interfaces:

interface= em0

Adjust depending on your NIC driver and IP address. One line we do wish to uncommment is right at the end of the file:


This will allow us to add our ad blocking list to a separate file. This directory will be missing, so it's necessary to create it:

# mkdir /usr/local/etc/dnsmasq.d

Add the address DNSMasq is listening on as the first server in /etc/resolv.conf:


Finally, enable it in rc.conf:

# echo 'dnsmasq_enable="YES"' >> /etc/rc.conf

And start it:

# service dnsmasq start

Next we need some lists.

Downloading the list

To do this, we need to copy and paste a small script that'll download a recent list of domains to redirect using your favorite editor:

# vi /usr/local/bin/

And paste the following into it:



# Don't forget to change the following 
# Including the IP address

fetch -qo - $adlisturl | sed 's/127\.0\.0\.1/192\.168\.1\.1/' > $temp_ad_file
if [ -f "$temp_ad_file" ]
    #sed -i -e '/www\.favoritesite\.com/d' $temp_ad_file
    mv $temp_ad_file $ad_file
    echo "Error building the ad list, please try again."

  Restart the service for it to take effect.

# service dnsmasq restart

If there's a site you'd like omitted from the list, use the commented-out line, for example:

# sed -i -e '/www\.favoritesite\.com/d' $temp_ad_file

Next, make it executable:

# chmod +x /usr/local/bin/

And run it as root:


You'll need working DNS for that script to run. If you look at /usr/local/etc/dnsmasq.d/dns.adlist.conf, you'll see entries like the following:


To test this, try the following:

$ ping

If the reply is coming from the pixelserv IP you set before, the domain is being redirected.


We're nearly finished. Now we need to download the Pixelserv script to serve the GIF placeholder images for our redirected domains. Do so thusly, while also changing the permissions:

# fetch -o /usr/local/bin/pixelserv
# chmod 755 /usr/local/bin/pixelserv

Then edit it:

# vi /usr/local/bin/pixelserv

To make pixelserv serve the entire network, we need to change the LocalHost line. A diff to show the changes:

---    2014-08-30 03:01:15.000000000 -0400
+++    2014-08-30 03:01:17.000000000 -0400
@@ -1,11 +1,11 @@
-#! /usr/bin/perl -Tw
+#!/usr/bin/env perl -Tw

 use IO::Socket::INET;

 $pixel=pack("C*",qw(71 73 70 56 57 97 1 0 1 0 128 0 0 255 255 255 0 0 0 33 249 4 1 0 0 0 0 44 0 0 0 0 1 0 1 0 0 2 2 68 1 0 59));

-$sock = new IO::Socket::INET (  LocalHost => '',
+$sock = new IO::Socket::INET (  LocalHost => '',
                                 LocalPort => '80',
                                 Proto => 'tcp',
                                 Listen => 30,

There's one last thing to do, and that's to add a rc script to start and stop pixelserv.

# vi /usr/local/etc/rc.d/pixelserv

And paste the following:

# Provides:          pixelserv
# Required-Start:    $network
# Required-Stop:     $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: pixelserv server for ad blocking
# Description:       Server for serving 1x1 pixels
case '$1' in
     echo 'pixelserv: starting'
     /usr/local/bin/pixelserv &
     echo 'pixelserv: stopping'
     killall pixelserv
     echo 'Usage: service $0 {start|stop}'
     exit 1

Save it, change the permissions:

# chmod 555 /usr/local/etc/rc.d/pixelserv

Then go into /etc/rc.conf and add pixelserv to your daemon list:

# echo 'pixelserv_enable="YES"' >> /etc/rc.conf

Start it up:

# service pixelserv start

To test this, go to in your browser. If a 1x1 GIF image shows instead of the site or a 404 error, you've been successful.


  • Much to my disappointment, it doesn't block Google text ads, as appear in the email web client. It's recommended to also install Adblock Plus on all your systems with a web browser.
  • A useful file to set up in addition to dnsmasq-adblock.conf is a custom list that won't be overwritten when the ad list is updated. I use /usr/local/etc/dnsmasq.d/custom-adblock.conf, with a selection of additional addresses in.
  • To keep the ad list updated, it might be worthwhile to set up a cron job to run the ad list download script every now and again.
  • An alternative to pixelserv is to run a real web server and host a 1x1 GIF there instead.
  • It's possible to run most of the commands as a normal user, you just need to change the permissions on the directories we created.

Latest News

New announcement


Hi, Mr. Dexter...

Two Year Anniversary


We're quickly approaching our two-year anniversary, which will be on episode 105. To celebrate, we've created a unique t-shirt design, available for purchase until the end of August. Shirts will be shipped out around September 1st. Most of the proceeds will support the show, and specifically allow us to buy...

New discussion segment


We're thinking about adding a new segment to the show where we discuss a topic that the listeners suggest. It's meant to be informative like a tutorial, but more of a "free discussion" format. If you have any subjects you want us to explore, or even just a good name...

How did you get into BSD?


We've got a fun idea for the holidays this year: just like we ask during the interviews, we want to hear how all the viewers and listeners first got into BSD. Email us your story, either written or a video version, and we'll read and play some of them for...

Episode 210: Your questions, part I


Direct Download:HD VideoMP3 AudioTorrent This episode was brought to you by Headlines A Reimplementation Of Netbsd Using a Microkernel Minix author Andy Tanenbaum writes in Part 1 of a-reimplementation-of-netbsd-using-a-microkernel Based on the MINIX 3 microkernel, we have constructed a system that to the user looks a great deal like NetBSD. It uses pkgsrc,...

Episode 209: Signals: gotta catch ‘em all


Direct Download:HD VideoMP3 AudioTorrent This episode was brought to you by Headlines Trip Report: FreeBSD in China at COPU and LinuxCon This trip report is from Deb Goodkin, the Executive Director of the FreeBSD Foundation. She travelled to China in May 2017 to promote FreeBSD, meet with companies, and participate in discussions around Open...

Episode 208: Faces of Open Source


Direct Download:HD VideoMP3 AudioTorrent This episode was brought to you by Headlines LLVM, Clang and compiler-rt support enhancements In the last month I started with upstream of the code for sanitizers: the common layer and ubsan. I worked also on the elimination of unexpected failures in LLVM and Clang. I've managed to...

Episode 207: Bridge over the river Cam


Direct Download:HD VideoMP3 AudioTorrent This episode was brought to you by Headlines BSDCam recap The 2017 Cambridge DevSummit took place from 2-4 August 2017. The event took place over three days including a formal dinner at St John's College, and was attended by 55 registered developers and guests. Prior to the start of...