aboutsummaryrefslogtreecommitdiff
path: root/blog/nginx-referrer-ban-list/index.org
blob: a80a6020cae76848c31a2dc0a8cfa79418a7679a (plain) (blame)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#+title: Creating a Referrer Ban List in Nginx
#+date: 2022-11-29
#+description: Learn how to create a ban list for referring sites in Nginx.
#+filetags: :nginx:

* Creating the Ban List
In order to ban list referral domains or websites with Nginx, you need
to create a ban list file. The file below will accept regexes for
different domains or websites you wish to block.

First, create the file in your nginx directory:

#+begin_src sh
doas nano /etc/nginx/banlist.conf
#+end_src

Next, paste the following contents in and fill out the regexes with
whichever domains you're blocking.

#+begin_src conf
# /etc/nginx/banlist.conf

map $http_referer $bad_referer {
    hostnames;

    default                           0;

    # Put regexes for undesired referrers here
    "~news.ycombinator.com"           1;
}
#+end_src

* Configuring Nginx
In order for the ban list to work, Nginx needs to know it exists and how
to handle it. For this, edit the =nginx.conf= file.

#+begin_src sh
doas nano /etc/nginx/nginx.conf
#+end_src

Within this file, find the =http= block and add your ban list file
location to the end of the block.

#+begin_src conf
# /etc/nginx/nginx.conf

http {
  ...

  # Include ban list
  include /etc/nginx/banlist.conf;
}
#+end_src

* Enabling the Ban List
Finally, we need to take action when a bad referral site is found. To do
so, edit the configuration file for your website. For example, I have
all website configuration files in the =http.d= directory. You may have
them in the =sites-available= directory on some distributions.

#+begin_src sh
doas nano /etc/nginx/http.d/example.com.conf
#+end_src

Within each website's configuration file, edit the =server= blocks that
are listening to ports 80 and 443 and create a check for the
=$bad_referrer= variable we created in the ban list file.

If a matching site is found, you can return any
[[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes][HTTP Status
Code]] you want. Code 403 (Forbidden) is logical in this case since you
are preventing a client connection due to a banned domain.

#+begin_src conf
server {
  ...

  # If a referral site is banned, return an error
  if ($bad_referer) {
    return 403;
  }

  ...
}
#+end_src

* Restart Nginx
Lastly, restart Nginx to enable all changes made.

#+begin_src sh
doas rc-service nginx restart
#+end_src

* Testing Results
In order to test the results, let's curl the contents of our site. To
start, I'll curl the site normally:

#+begin_src sh
curl https://cleberg.net
#+end_src

The HTML contents of the page come back successfully:

#+begin_src html
<!doctype html>...</html>
#+end_src

Next, let's include a banned referrer:

#+begin_src sh
curl --referer https://news.ycombinator.com https://cleberg.net
#+end_src

This time, I'm met with a 403 Forbidden response page. That means we are
successful and any clients being referred from a banned domain will be
met with this same response code.

#+begin_src html
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
#+end_src