Using nginx combined with Pi-hole to block server site tracking
05.02.2025Pi-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.