AdBlocking with NGINX: Serving 1 pixel GIF and 204 No Content
There are two parts to a network-based ad block solution – resolving known advertisement host names to another server and have the server present a 1 pixel transparent GIF (for images) or 204 No Content HTTP response. This will effectively hide advertisements. This article addresses the latter part of having a server present 1 pixel transparent GIF and 204 No Content HTTP response for other files types.
Why use NGINX when there are pixelserv and nullserv?
If you recently upgraded to ASUS RT-AC68U with TomatoUSB (Shibby) and had been using the AdBlock script, you will (probably) realise that previous Pixelserv does not execute on ASUS RT-AC68U as it was not compiled for ARM architecture.
Instead of cross-compiling Pixelserv for ASUS RT-AC68U, I decided to leverage NGINX web server in TomatoUSB (Shibby). This way, the ad block solution will not be limited to ASUS RT-AC68U, you can also set up NGINX on Raspberry Pi or any other devices.
Serving 1 pixel transparent GIF and 204 No Content
Below is the config file I have created for ASUS RT-AC68U on TomatoUSB (Shibby). You can replicate the relevant lines to your NGINX config. The important lines that actually does the work are highlighted.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # NGinX generated config file user root; worker_processes 1; worker_cpu_affinity 0101; master_process off; worker_priority 10; error_log /tmp/var/log/nginx/error.log; pid /tmp/var/run/nginx.pid; worker_rlimit_nofile 8192; events { worker_connections 512; } http { log_format main '$remote_addr - $remote_user [$time_local] $status ' '"$request" $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; server { listen 80; server_name AdBlock; access_log /tmp/var/log/nginx/access.log main; expires max; # instructs browser to cache the reply rewrite .+?(png|gif|jpe?g)$ /empty_gif last; # redirect image requests rewrite ^(.*)$ / last; # redirect all other misc requests location / { return 204; # return no content } location /empty_gif { empty_gif; # serving 1 pixel gif } } } |
For those using TomatoUSB (Shibby)’s NGINX Web Server
If you are using TomatoUSB (Shibby)’s NGINX Web Server, simply add the following into the Custom configuration under the Web Server Settings. What it does is defining another HTTP instance that listens on port 80.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # NGINX Custom Parameters. # AdBlock Entries - http://tiny.cc/nginx-adblock http { log_format main '$remote_addr - $remote_user [$time_local] $status ' '"$request" $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; server { listen 80; server_name AdBlock; access_log /tmp/var/log/nginx/access.log main; expires max; # instructs browser to cache the reply rewrite .+?(png|gif|jpe?g)$ /empty_gif last; # redirect image requests rewrite ^(.*)$ / last; # redirect all other misc requests location / { return 204; # return no content } location /empty_gif { empty_gif; # serving 1 pixel gif } } } # End of AdBlock Entries |
It should look like the following.

How does it work?
This section explains the above-mentioned highlighted lines and what they actually do.
Set the expiration time longer
1 | expires max; # instructs browser to cache the reply |
This basically instructs the browser to cache the response so that it does not request it again unless the browser cache is purged.
Redirecting image request and serving 1 pixel transparent GIF
1 2 3 4 | rewrite .+?(png|gif|jpe?g)$ /empty_gif last; # redirect image requests location /empty_gif { empty_gif; # serving 1 pixel gif } |
This regular expression (regex) attempts to match all request that ends with .png, .gif, .jpg and .jpeg and serves a empty_gif (1 pixel transparent GIF) instead.
Redirecting other requests and serves 204 No Content
1 2 3 4 | rewrite ^(.*)$ / last; # redirect all other misc requests location / { return 204; # return no content } |
This regular expression matches all requests that slipped through the previous one (essentially a catch all rule) and returns 204 No Content to the browser. To the browser, this codes means “Okay, I saw your request but I got nothing for you”.
Conclusion
And that is pretty much about it! I will be updating this set of codes when I got new ideas. Do check back for more.