Pi-Hole is, in my opinion, a great tool for blocking ads, tracking and malware. But sometimes it seems to be blocking a bit too much. One case I identified were sites that would come up as small ads in my Google searches. I still wanted those links to work. My analysis showed that the needed target URL was nicely encoded in the advertisement URL. So I thought of nginx for a solution.

The easy part with nginx is the redirection of one URL to another URL. Just use rewrite or return filters. This works very well, until the URL uses encoded characters. I also wanted to cover this case and did some research on options. The one I found was using perl to do the encoding/decoding.

After installing nginx, I created the file /etc/nginx/sites-available/googleadservices-redirect, linked it to the sites-enabled and used it in a SSL configured nginx instance:

perl_set $localuri '
  sub {
    my $r = shift;
    my $arg_adurl = $r->variable("arg_adurl");
    my $arg_adurl_decoded = $r->unescape($arg_adurl);
    return $arg_adurl_decoded;
  }
';

server {
  listen 443 ssl default_server;
  listen [::]:443 ssl default_server;

  ssl_certificate /etc/nginx/ssl/nginx-self-signed.crt;
  ssl_certificate_key /etc/nginx/ssl/nginx-self-signed.key;

  gzip off;

  server_name www.googleadservices.com;

  return 301 $localuri;
}

As all redirects are only in local networks, self signed certificates created via openssl were good enough:

openssl req -x509 -newkey rsa:4096 -days 365 -nodes -keyout /etc/nginx/ssl/nginx-self-signed.key -out /etc/nginx/ssl/nginx-self-signed.crt -subj "/CN=www.googleadservices.com"
  -addext "subjectAltName=DNS:www.googleadservices.com,DNS:googleadservices.com,IP:192.168.0.250"

On the other side, I only needed to support most modern software, so I restricted encryption options in /etc/nginx/nginx.conf and enabled the perl module:

http {
  perl_modules perl/lib;
  ...;
  ssl_protocols TLSv1.3;
  ssl_ecdh_curve X25519:prime256v1:secp384r1;
  ssl_prefer_server_ciphers on;
  ...;
}

I redirected the DNS www.googleadservices.com via Pi-hole to the nginx installation and then I had the necessary redirects working locally. Problem solved.