aboutsummaryrefslogtreecommitdiff
path: root/blog/2022-11-29-nginx-referrer-ban-list.org
blob: 2f71666e7b985439e571936d49eb95951216d41e (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
127
128
129
130
131
132
133
+++
date = 2022-11-29
title = "Creating a Referrer Ban List on Nginx"
description = "A quick explanation detailing my own way of banning referral domains on 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:

```sh
doas nano /etc/nginx/banlist.conf
```

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

```conf
# /etc/nginx/banlist.conf

map $http_referer $bad_referer {
    hostnames;

    default                           0;

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

## 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.

```sh
doas nano /etc/nginx/nginx.conf
```

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

```conf
# /etc/nginx/nginx.conf

http {
  ...

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

## 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.

```sh
doas nano /etc/nginx/http.d/example.com.conf
```

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 [HTTP Status 
Code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) you want. Code 
403 (Forbidden) is logical in this case since you are preventing a client 
connection due to a banned domain.

```conf
server {
  ...

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

## Restart Nginx

Lastly, restart Nginx to enable all changes made.

```sh
doas rc-service nginx restart
```

## Testing Results

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

```sh
curl https://cleberg.net
```

The HTML contents of the page come back successfully:

```html
<!doctype html>...</html>
```

Next, let's include a banned referrer:

```sh
curl --referer https://news.ycombinator.com https://cleberg.net
```

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.

```html
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
```