I got the cheapest VPS for this site. Currently the blog itself is hosted by GitLab Pages but analytics and comments are on a VPS that I maintain1.

It got me thinking, as compute resources are very limited, what would be the best way to protect the server from malicous users, DOS attacks, DDOS attacks, etc?

At work everything is usually behind a firewall, load-balancers of different kinds, and public IP address of the server is never exposed. On top of that, everything’s always already setup when I come around.

I’m sure that the most effective way would be to use Cloudflare’s DNS proxy, as I’m already using Cloudflare as authoritative nameserver. All I need to do to enable it is to toggle a few switches in the UI. But this also means that I have no chance to mess everything up and leak my data. My precious data. On top of that this site would be inaccessible from Russia, as Cloudflare’s IPs are blocked there. Some would actually consider it an added benefit but not me in this case.

So I’m on my own here. I did close all the ports besides 80/443 on my server of course, but that doesn’t really help the ports that are actually exposed.

I decided to look around and see how other people do it, and from my research, rate limiting and fail2ban seem to be the way to go for simple setups.

Basic idea is very simple: don’t respond to users that make too many requests, and if they keep at it, add a firewall rule to drop them at the earliest stage of processing their request.

The setup was really easy. All I needed to do was:

root@12005:~# cat /etc/nginx/conf.d/http_default_override.conf
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
root@12005:~# grep limit_req /etc/nginx/sites-enabled/comments.dtsykunov.com.conf -B 1
[...]
--
    location / {
        limit_req zone=one burst=10 nodelay;
--
    location / {
        limit_req zone=one burst=10 nodelay;

It made my nginx return 503 if someone tries to make too many requests.

  • install fail2ban
apt install fail2ban
  • and enable a few predefined jails2 3
root@12005:~# cat /etc/fail2ban/jail.d/nginx.conf
[nginx-http-auth]
enabled  = true
backend  = auto

[nginx-botsearch]
enabled  = true
backend  = auto

[nginx-bad-request]
enabled  = true
backend  = auto

[nginx-limit-req]
enabled  = true
backend  = auto

From this point forward, anyone who tries to play too much with my server will get thrown into literal jail.

Just so you know, it still leaves plenty of room to break my server for especially motivated users. For example4, you could flood me with so many requests that firewall rules would take too long to parse.


  1. I’m thinking about moving the blog there as well, but I don’t see any motivation for it right now. ↩︎

  2. If you want to leave as much at default as possible, make sure these jails don’t use systemd backend. Otherwise you’ll need to configure nginx to write it’s logs to journald, which isn’t the default on debian. ↩︎

  3. If you plan to use nginx-bad-request make sure that your page doesn’t make many bad requests by default. If I didn’t notice it, fail2ban would ban every user who visited my page because it used to make requests to non-existent favicons. ↩︎

  4. I do realize that I’m giving you ideas, but hey, if you are really inclined, do whatever. It’ll give me a chance to write another blog post. ↩︎