Google pushing back on ad blocking, deploying Pihole.

03 November 2022

Note: As I wrote this article, I realized that there wasn't much in the way of actual tutorial documentation for some of this stuff. So, I'll be revisiting it in the near future to rewrite parts in such a way to fit this purpose.

If you keep your ear to the ground about the online world, you might have heard something about Google gearing up to break adblocking, ostensibly as a way to crack down on malicious Chrome addons on a wide scale. As a bit of background, Google isn't really a search company because web search doesn't actually bring in much money, nor a products company (though you can pay money for their services (as long as they keep them alive, anyway)). Free services cost money, after all - electricity, hardware, storage capacity, bandwidth - they aren't free. Google is an advertising company with a lot of leverage over how the Net can be used.

To wit (and I wouldn't be surprised if my blog all but disappears from Google's earch indices for writing this), the Manifest API is the Chrome subsystem that makes it possible to write third-party addons to plug additional functionality into the browser. Additional functionality such as ad blocking, which makes the Net actually usable for most us but also cuts into their revenue. A year or two ago Google announced that version 2 of Manifest was going away, to be replaced with v3. At first scratch this doesn't sound unreasonable because new releases happen. However, not a few skilled and knowledgable technologists have figured out that Manifest v3 breaks adblockers first and foremost by preventing addons from determining what HTTP requests can be made, which is how adblockers work ("Oh, this thing is on my ad blocking list, I won't execute this request.").

If you've ever tried to browse the web without an adblocker, you know all too well how slow and poorly designed many websites are due to all the trackers and advertisements that get loaded.

The obvious solution should be to change browsers, to something like Firefox. Unfortunately the Mozilla Foundation is also going to implement Manifest V3 around the same time. Which will also break adblocking in that browser as well as everything derived from it. While Mozilla makes quite a bit of money from partnered orgs that pay to use them as a platform, as well as partnerships with search engines and distribution deals, Google also funds them. Perhaps I'm thinking conspiratorially, but when a megacorp1 sends a lot of money your way there are usually strings attached, and those strings don't negatively impact said megacorp. It would be incredibly, naively foolish of them to not do so.

At any rate the Manifest v3 changes limit the number of filtering rules to 30,000 and they can't be easily updated periodically.2 So, let's stick a pin in this and talk about something else for a moment.

You might have heard some folks talking about something called Pi-Hole, which is a service that you can deploy on your home network (or, as I'll talk about later, your VPN server) that does adblocking at the DNS level. Basically it's a replacement DNS server that has its own blocklists, just like adblocking browser addons. When your browser (or anything, really) on your network makes a DNS request for something (say, your browser loads a page and part of it is a bit of Javascript that tracks your activity), the DNS server on your network (which is usually built into your wireless access point) asks your Pi-Hole to resolve it for you. The Pi-Hole checks the request against the blocklists that it has configured, in this example finds it and sends back a response saying the IP address is which, per RFC 5735 means "Forget it, that's not a valid IP."

Your web browser (or whatever else) then says, "Oh, well," and moves on with its life. You don't get tracked and stuff loads faster.

So I built a Pi-Hole for my home network. Scrounging around in my inventory I discovered that I had an older Orange Pi single board computer (from before the Silicon Dry Spell) in a drawer that I then installed Armbian on. I plugged it into the private side of my wireless access point with a length of Ethernet cable and gave it a static IP address:

OpenWRT -> Network -> DHCP and DNS -> Static Leases, select the hostname of the box (Octothorpe) in the MAC-Address column, retype the hostname in the Hostname column, select it in the IPv4-Address column, Save & Apply

This is necessary because your DNSes must always have the same IP address to be useful because you want to find them in the same place all the time. Once that was done I was able to SSH into Octothorpe (the name of my new Pi-Hole), run the configuration utility, and then install the Pi-Hole software using the official instructions. Always a bit paranoid about the stuff I install, I used Method 2 and read through the script before running it. The installation went smoothly and was almost boring. I then went to the LAN interface on the AP (again, running OpenWRT) and configured them to use Octothorpe as its upstream DNS.

Network -> Interfaces -> click the Edit button for each one -> scroll down to "Use custom DNS servers) -> type the IP address of your Pi-Hole (it should be a private address) -> click "Save & Apply"

Even before you configure your Pi-Hole install it's a regular old DNS, so you won't break anything. Then log into your Pi-Hole with a web browser (if you follow the instructions exactly you'll be hitting http://pi-hole/admin/, in my case it's http://octothorpe/admin/) and configure it. There doesn't seem to be any official docs for doing this, so here's a first attempt on my part.

For some reason it's really hard to find a decent list of blocklists to use; I spent quite a while digging and after some experimentation and testing here are the resources I found the blocklists I use:

If you are concerned about family members falling into a certain conspiracy community's rabbit hole you may wish to investigate this blocklist.

At any rate, when you log in you'll see a dashboard that looks like this. To make your Pi-Hole do what it's supposed to do the first thing is to scroll down and click on Adlists on the left-hand side; this is where you specify which lists of things to block. To add each blocklist, do the following:

  • Copy the URL to the blocklist in question in your browser's URL bar.
  • On the Adlist group management page, paste the URL into the Address field.
  • Optionally, type a comment in the other field. It's generally a good idea to leave a note for yourself here that says what the blocklist is for (ads, malware, whatever).
  • Click the Add button.

If you scroll down a little bit you'll see your configured blocklists. You're not done yet, though, now you have to tell your Pi-Hole to download and incorporate the contents of those lists into its database and keep them up to date. If you read the text at the bottom of the "Add a new adlist" box you'll see "Please run pihole -g or update your gravity list online after modifying your adlists." While you can shell back into your Pi-Hole box it's much easier (and faster) to just click the "online" link that will take you to the "Update Gravity (list of blocked domains)" page. Click the big blue "Update" button. It'll take a little while to download the new blocklists (every time you click it, every blocklist you have will be updated), sort them, eliminate the duplicates, and add them to the Gravity database.3 All you really have to do is wait for the green "Success!" box to appear when it's done.

It is helpful to configure a couple of upstream DNSes on your Pi-Hole, also. Here's the thing: Only resolution requests that your Pi-Hole forwards will ever show up, which means that anything caught by the ad blocking filter will never appear, thus helping to preserve your privacy. Click on "Settings" on the left-hand bar, then "DNS" on the top row. I like to use OpenDNS and Quad9 (unfiltered, no DNSSEC) for this. Check all of the boxes for those two services (for both IPv4 and IPv6) and make sure that "Allow only local requests" is checked. If you scroll down a bit I would recommend also checking "Never forward non-FQDN A and AAAA queries" and "Never forward reverse lookups for private IP ranges" for privacy reasons. I find it also speeds things up a little bit by avoiding some pointless DNS lookups. Then scroll all the way to the bottom and click the Save button. If you are concerned about privacy (and if you're setting up network-wide adblocking you probably are) you can also tweak some privacy settings for your Pi-Hole's statistics and dashboards. At least when you're fine-tuning and making sure everything's working, it might be a good idea to set "DNS resolver privacy level" to "Show everything and record everything," because you might need the information to debug. When you're sure everything's stable you can change the privacy settings to "Hide domains and clients" unless something starts acting up. For maximum privacy (or if the system you're running Pi-Hole on doesn't have a lot of available storage) you may wish to set it to "Anonymous mode," which logs nothing. At any rate, make your choice (which you can change later) and click the "Apply" button.

This configuration is highly stable but a little weird. If you look at my dashboard for the last 24 hours (as I write this post) several tens of thousands of DNS queries were made in the last 24 hours, but only two clients were noted, localhost and _gateway. The thing about this is, when you have a really common home network setup (a wireless access point that is both DNS and DHCP server, and every clients runs everything through or to services running on the AP) everything is coming from _gateway (the wireless access point) as far as Pi-Hole is concerned. It's not anything to worry about but it can be confusing at first.

Long-time readers are probably somewhat aware of my network at home and all the stuff on it. You're also probably wondering just what I get out of having a Pi-Hole installed. As I was typing this part of the post I took a quick screenshot of Octothorpe's stats for the last 24 hours. As you can see, everything on my network made a grand total of 41,998 DNS queries in the past day, of which 16,941 of them (roughly 40%) were detected and blocked by Octothorpe.4 If I had more smart devices on my network that I didn't build myself I'm pretty sure those stats would be way higher, as Matt C.A. Smith discovered about two years ago.

I also have a VPN server running Ubuntu Server LTS that I keep forgetting to write up which offers both OpenVPN and Wireguard with an in-house DNS running Unbound for clients to use. Again, I used the standard installation procress from the Pi-Hole documentation but ran into a couple of problems. First of all, Pi-Hole requires and installs lighttpd for its control panel, which is written in PHP. My VPN server had Nginx installed and the two battled it out until I finally uninstalled Nginx.5 Second, on Ubuntu Server the installation script didn't install two important PHP packages, php-pear or php-json. The obvious fix is to install them manually: sudo apt-get install php-json php-pear

The third problem is that one of the packages, php-json isn't enabled so that the PHP service can't find it. The fix is a little tricky to figure but here's how to do it:

sudo su -
cd  /etc/php/7.4/cgi/conf-d
ln -s /usr/share/php7.4-json/json/json.ini 20-json.ini
cd  /etc/php/7.4/cli/conf-d
ln -s /usr/share/php7.4-json/json/json.ini 20-json.ini

# Bouncing lighttpd also restarts php-cgi.
systemctl restart lighttpd

Once you've done this (and you might want to do this before running the Pi-Hole installation script) the control panel will work as expected. If it might help, uninstall Pi-Hole, install those PHP packages, and then re-install it. Then I had to make a couple of minor modifications to my VPN server. I first had to shut Unbound down to get it out of the way for a moment: sudo systemctl stop unbound

Unbound from Ubuntu packages puts all of its configuration information into separate files in /etc/unbound/unbound.conf.d/*.conf to separate them. I have one configuration file for each VPN service, like so:

{23:46:04 @ Sun Oct 23}
[drwho @ jackpoint:(3) unbound.conf.d]$ pwd

{23:46:05 @ Sun Oct 23}
[drwho @ jackpoint:(3) unbound.conf.d]$ ls -alF
total 24
drwxr-xr-x 2 root root 4096 Sep 20 20:36 ./
drwxr-xr-x 3 root root 4096 Aug 17 06:07 ../
-rw-r--r-- 1 root root 2412 Sep 20 20:36 openvpn.conf
-rw-r--r-- 1 root root  302 Aug 27  2018 qname-minimisation.conf
-rw-r--r-- 1 root root  190 Aug 27  2018 root-auto-trust-anchor-file.conf
-rw-r--r-- 1 root root 2426 Sep 20 20:34 wireguard.conf

{23:46:06 @ Sun Oct 23}
[drwho @ jackpoint:(3) unbound.conf.d]$ 

openvpn.conf and wireguard.conf both describe what (VPN) network interface and port to listen on as well as sundry other configuration options. For our purposes they aren't relevant. What is relevant, however, is what port Unbound listens on for each VPN interface. To make room for Pi-Hole I moved each port from 53/tcp and udp to port 5400/tcp and udp (arbitrarily chosen). The salient part of the openvpn.conf file now looks like this:

  port: 5400
  do-ip4: yes
  do-ip6: yes
  do-tcp: yes
  do-udp: yes

The wireguard.conf file looks pretty much the same, only the first interface line reads Restart Unbound: sudo systemctl restart unbound.service

Once that is done, I went back to the Pi-Hole admin panel on my VPN server, Settings -> DNS. Rather than turning on any upstream DNSes I checked the boxes for Custom 1 (IPv4) and Custom 3 (IPv6) and entered the loopback addresses I'd just configured for both and then hit the Save button:

  • Custom 1 (IPv4):
  • Custom 3 (IPv6): ::1#5400

The way the VPN server is now set up, Pi-Hole's DNS resolver (called FTL) is listening on ports 53/tcp and 53/udp on Jackpoint's loopback interface and the two VPN network interfaces. Unbound is listening on ports 5400/tcp and 5400/udp on the same interfaces. There's no real reason they have to be but it doesn't hurt anything, either. The Pi-Hole, whenever a DNS resolution request passes all of its blocklists, asks Unbound for the answer. Unbound then does the usual DNS resolution request song and dance to get the answer, caches it for later, and returns it to Pi-Hole. Pi-Hole then returns it to the VPN client.

One thing I did notice was that the Pi-Hole doesn't seem to prevent Youtube advertisements from butting in. Keeping uBlock Origin enabled in my web browsers does, however. I don't yet know if it's actually possible to use DNS level blocking for this. A stumbled across this blocklist while researching this article but the last time it was updated was about six months ago, and I haven't tested it. There may be others out there, I'm not sure. The reason I thought it important to mention is due to the fact that, even though ad blocking addons will be nerfed by Manifest v3 I think it might be feasible to use browser-side ad blocking to filter commercials out of online streams6 and network-side DNS ad blocking to get rid of the rest. It's something I'll have to test when I have some time.

  1. Google's revenue is, as of June 2022.ev, 69.69 billion US dollars (nice) and the year's not over yet. They also have offices on six out of seven continents with over 170,000 employees globally. If that doesn't fit the definition of a megacorporation (local copy) I don't know what does. 

  2. I don't think anybody's done a study of how many rules are in a blocklist on average. I did some digging and didn't find anything useful. So I took a look at my uBlock Origin configuration on Windbringer (installed in Firefox v105.0.1, 64-bit build, Arch Linux), did some match, and the average number of rules was 13942 (rounded up to the nearest whole number), not counting any custom rules I added myself. The total number of rules in this configuration was 153359 10 blocklists were the ones that uBlock Origin has turned on by default, one was the Online Malicious URL Blocklist that I added myself. Of note, three of those lists are malware and malicious URL blocklists. 

  3. I really don't know what it's called that. 

  4. This is everything on my network that is not otherwise running an adblocker. Windbringer as well as my work laptop both have uBlock Origin installed, and my personal cellphone and tablet both use Blokada for the same purpose. If I didn't I'm fairly sure that those figures would be much higher. 

  5. Amusingly, after I stopped using Nginx on Jackpoint it suddenly became stupidly simpler to proxy YaCy for my website's search engine

  6. I'm really enjoying using Markdown footnotes now that I know how to.