Enforce specific referer header using nginx
directives.
This is a follow-up to the earlier blog post on how to stop referral spam using Nginx.
I will require the referer header and ensure that it comes from example.org
domain.
First solution
The easiest solution is to use valid_referers
directive to define referer whitelist.
server { listen 80 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name _; valid_referers server_names *.example.org example.org; if ($invalid_referer) { return 403; } location / { try_files $uri $uri/ =404; } }
example.org
will return 200 OK
.
$ curl -I -H "Referer: https://example.org" http://127.0.0.1
HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Mon, 17 Aug 2020 21:29:16 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Sun, 16 Aug 2020 11:42:58 GMT Connection: keep-alive ETag: "5f391bc2-264" Accept-Ranges: bytes
<a href="http://www.example.org" rel="nofollow">http://www.example.org</a>
will return 200 OK
.
$ curl -I -H "Referer: https://www.example.org" http://127.0.0.1
HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Mon, 17 Aug 2020 21:30:06 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Sun, 16 Aug 2020 11:42:58 GMT Connection: keep-alive ETag: "5f391bc2-264" Accept-Ranges: bytes
<a href="http://www.example.com" rel="nofollow">http://www.example.com</a>
will return 403 Forbidden
.
$ curl -I -H "Referer: https://www.example.com" http://127.0.0.1
HTTP/1.1 403 Forbidden Server: nginx/1.18.0 (Ubuntu) Date: Mon, 17 Aug 2020 21:31:20 GMT Content-Type: text/html Content-Length: 162 Connection: keep-alive
Missing referer header will return 403 Forbidden
.
$ curl -I http://127.0.0.1
HTTP/1.1 403 Forbidden Server: nginx/1.18.0 (Ubuntu) Date: Mon, 17 Aug 2020 21:32:13 GMT Content-Type: text/html Content-Length: 162 Connection: keep-alive
Second solution
Create referer whitelist using /etc/nginx/conf.d/referer_whitelist.conf
configuration file that will contain whitelisted_referer
variable
whose value depends on the supplied http referer
.
map $http_referer $whitelisted_referer { hostnames; "example\.org" 0; # accept example.org "~*.example\.org" 0; # accept *.example.org default 1; # do not accept no referer or any other referer }
Site configuration got simpler, but the first one is a more desirable solution, but it all depends on your requirements.
server { listen 80 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name _; if ($whitelisted_referer) { return 403; } location / { try_files $uri $uri/ =404; } }
example.org
will return 200 OK
.
$ curl -I -H "Referer: https://example.org" http://127.0.0.1
HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Mon, 17 Aug 2020 21:42:47 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Sun, 16 Aug 2020 11:42:58 GMT Connection: keep-alive ETag: "5f391bc2-264" Accept-Ranges: bytes
<a href="http://www.example.org" rel="nofollow">http://www.example.org</a>
will return 200 OK
.
$ curl -I -H "Referer: https://www.example.org" http://127.0.0.1
HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Mon, 17 Aug 2020 21:42:58 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Sun, 16 Aug 2020 11:42:58 GMT Connection: keep-alive ETag: "5f391bc2-264" Accept-Ranges: bytes
<a href="http://www.example.com" rel="nofollow">http://www.example.com</a>
will return 403 Forbidden
.
$ curl -I -H "Referer: https://www.example.com" http://127.0.0.1
HTTP/1.1 403 Forbidden Server: nginx/1.18.0 (Ubuntu) Date: Mon, 17 Aug 2020 21:42:30 GMT Content-Type: text/html Content-Length: 162 Connection: keep-alive
Missing referer header will return 403 Forbidden
.
$ curl -I http://127.0.0.1
HTTP/1.1 403 Forbidden Server: nginx/1.18.0 (Ubuntu) Date: Mon, 17 Aug 2020 21:43:19 GMT Content-Type: text/html Content-Length: 162 Connection: keep-alive
References
Module ngx_http_map_module
Module ngx_http_referer_module