From 314aa3556ea70a8e247632f421c3d8d35bc9eaec Mon Sep 17 00:00:00 2001
From: Jelle van der Waa <jelle@archlinux.org>
Date: Sun, 11 Jul 2021 21:10:38 +0200
Subject: [PATCH] Rate limit archlinux.org and fail2ban abusers

Add a default rate limit for 20 req/s for the uwsgi endpoint and
automatically ban users who reach this limit. The nginx-limit-req rule
does not ban users who reach the rss limit as these are not likely DoS
attempts.
---
 docs/fail2ban.md                                 | 3 +++
 host_vars/archlinux.org/misc                     | 2 +-
 roles/archweb/templates/nginx.d.conf.j2          | 6 ++++++
 roles/fail2ban/templates/nginx-limit-req.jail.j2 | 4 +++-
 4 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/docs/fail2ban.md b/docs/fail2ban.md
index fa6fcb338..cc96bc2d0 100644
--- a/docs/fail2ban.md
+++ b/docs/fail2ban.md
@@ -39,3 +39,6 @@ Add `fail2ban_jails` dict with `dovecot: true` to the host's `host_vars`.
 The nginx_limit_req jail is not enabled on any server. This jail bans IPs based repeated errors on nginx error log. Default blocking is 1 hour(s). Adding to a host:
 
 Add `fail2ban_jails` dict with `nginx_limit_req: true` to the host's `host_vars`.
+
+The `rsslimit` zone is whitelisted from being banned with `ignoreregex`, as we
+choose to not ban RSS abusers.
diff --git a/host_vars/archlinux.org/misc b/host_vars/archlinux.org/misc
index ced9db725..6c832727c 100644
--- a/host_vars/archlinux.org/misc
+++ b/host_vars/archlinux.org/misc
@@ -10,6 +10,6 @@ fail2ban_jails:
   sshd: true
   postfix: false
   dovecot: false
-  nginx_limit_req: false
+  nginx_limit_req: true
 wireguard_address: 10.0.0.1
 wireguard_public_key: 0Vx7jfWinpTPHKPxvmKtZlp3hcLebawz+vQM8EIEm1k=
diff --git a/roles/archweb/templates/nginx.d.conf.j2 b/roles/archweb/templates/nginx.d.conf.j2
index 74201a624..c1ac77b62 100644
--- a/roles/archweb/templates/nginx.d.conf.j2
+++ b/roles/archweb/templates/nginx.d.conf.j2
@@ -1,5 +1,9 @@
 # limit rss requests to 1 r/m
 limit_req_zone $binary_remote_addr zone=rsslimit:8m rate=1r/m;
+
+# limit general requests to 20 r/s to block DoS attempts.
+limit_req_zone $binary_remote_addr zone=archweblimit:10m rate=20r/s;
+
 limit_req_status 429;
 
 uwsgi_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=archwebcache:10m inactive=60m;
@@ -193,5 +197,7 @@ server {
         uwsgi_cache_revalidate on;
         uwsgi_cache_key $cache_key;
         add_header X-Cache-Status $upstream_cache_status;
+
+        limit_req zone=archweblimit burst=10 nodelay;
     }
 }
diff --git a/roles/fail2ban/templates/nginx-limit-req.jail.j2 b/roles/fail2ban/templates/nginx-limit-req.jail.j2
index 63a6ad37d..0189fc2a3 100644
--- a/roles/fail2ban/templates/nginx-limit-req.jail.j2
+++ b/roles/fail2ban/templates/nginx-limit-req.jail.j2
@@ -10,4 +10,6 @@ action = iptables-multiport[name=ReqLimit, port="http,https", protocol=tcp]
 logpath = /var/log/nginx/*/error.log
 findtime = 5min
 bantime = 1hours
-maxretry = 10
\ No newline at end of file
+maxretry = 10
+# Do not fail2ban archweb's rss limit.
+ignoreregex = rsslimit
-- 
GitLab