Fail2ban Behind Reverse Proxy
Assumptions, Prerequisites, Prior Set Up
This guide is for when the reverse proxy & FoundryVTT server are both on separate machines
This guide builds upon the prior one and details how to setup fail2ban to block bad bots, automated login attempts, and repeated connection attempts that are likely malicious, when your server is behind a reverse proxy.
If you haven't taken a look already my prior post detailed how to go about setting up fail2ban rules.
https://blog.iterlyze.com/2024/11/fail2ban-foundryvtt.html
This guide assumes you are using a Debian 12 server (or Ubuntu) and have a basic idea of how to use a Linux shell. Some other assumptions that won't affect setting up fail2ban include that you are using Nginx as the reverse proxy, nftables as your system's firewall frontend, and that you are forwarding traffic to a FoundryVTT server.
Make sure the reverse proxy and the server it sends traffic to is working before trying to set up fail2ban. If you are setting up FoundryVTT & a reverse proxy for the first time the official FoundryVTT site has some great step by step guides you can follow. You can use Apache (widely used), Nginx (fast & efficient), or Caddy (easy to use).
Recommended Linux Installation Guide | Foundry VTT Community Wiki
Caddy Proxy Server | Foundry Virtual Tabletop
Nginx Proxy Server | Foundry Virtual Tabletop
Apache Proxy Server | Foundry Virtual Tabletop
If you have trouble with the Linux commands the following blog post may help https://blog.iterlyze.com/2020/10/i-recently-made-quick-draft-of-useful.html
(If you need help with the basics i'm happy to answer questions)
Introduction
These steps should work for any reverse proxy & log file you want fail2ban to take a look at. The issue when using a reverse proxy between your servers and the internet is that fail2ban and your firewall primarily block at the network/transport layer while the ip address of the connecting device is encapsulated by your reverse proxy in the application layer. While there are some features you can use for looking at strings in the application layer, if you are using https you won't be able (unless you use a different setup). The solution is to have fail2ban operate on your reverse proxy instead of the server. I'll include the commands for setting up fail2ban at the end (Starting on step 8) with less explanation than the previous post. If you run into problems, start with the simple setup then slowly add to it.
Login to the root account, with su or use sudo before running the commands below.
Step 1) Install needed software
apt-get update;
apt-get install -y lsyncd;
On the reverse proxy install fail2ban and a firewall (If you want to use nftables as your firewall).
apt-get update;
apt-get install fail2ban nftables;
Step 2) Create directory on Reverse Proxy
On the reverse proxy create a directory to store your log filesmkdir -p ~/foundryLogs;
Step 3) Create Directory & Configs On Server with Logs (FoundryVTT)
mkdir /var/log/lsyncd;
touch /var/log/lsyncd/lsyncd.{log,status};
mkdir /etc/lsyncd;
In order for lsyncd to work correctly we need to create a location for it to store it's own log files. (idk why when you install the package it doesn't just make this for you). The first command creates a directory in the /var/log folder. The second command creates two files lsyncd.log and lsyncd.status in the /var/log/lsyncd/ folder. The third command creates a directory in the /etc/ folder where you will place the lsyncd configuration called named lsyncd.conf.lua. This file is written using valid Lua syntax, so if you know that programming language it might make things a little bit easier for you to write without error. (Knowing Lua is not needed, I don't know Lua)
Continue with creating the configuration file. You will need to make sure the directories match the ones you have created, that you use absolute paths when defining them, and that the usernames match for the source (FoundryVTT) and destination (rsync section) You might like to note that you can easily find the IP address of each machine by logging in and running hostname -I
nano /etc/lsyncd/lsyncd.conf.lua
settings { logfile = "/var/log/lsyncd/lsyncd.log", statusFile = "/var/log/lsyncd/lsyncd.status", inotifyMode = "Modify" } sync { default.rsyncssh, delay = 1, source = "/home/username/foundryuserdata/Logs/", host = "192.168.1.xxx", targetdir = "/home/username/foundryLogs/", exclude= { 'error.*','dianogstics.*','news.*','*.json', 'debug.log.*' }, rsync = { rsh = "/usr/bin/ssh -l username -i /home/username/.ssh/id_ed25519 -o UserKnownHostsFile=/home/username/.ssh/known_hosts" } }
(When we send changes)
(Where we send changes from)
(Where we send changes to)
(What we don't send)
(Specific Whom & How we send changes)
-o tells rsync where the list of known hosts is.
Step 4) Create SSH keys on both your server (FoundryVTT) and your reverse proxy.
Step 5) Test that lsyncd is working
systemctl status lsyncd
If they haven't, check your firewall configuration, or check again after the next step.
Step 6) Configure your firewall
#!/usr/sbin/nft -f flush ruleset table inet filter { chain input { type filter hook input priority 2; policy accept; ct state established, related accept ct state invalid drop iif lo counter accept ct state new tcp dport 22 accept ct state new tcp dport 80 accept ct state new tcp dport 443 accept ct state new tcp dport 30000 accept drop } chain forward { type filter hook forward priority filter; policy drop; } chain output { type filter hook output priority filter; policy accept; } }
Flush Ruleset
table inet filter {
chain input {
type filter hook input priority 2; policy accept;
ct state established, related accept
ct state invalid drop
iif lo accept
ct state new tcp dport 22 accept
ct state new tcp dport 80 accept
ct state new tcp dport 443 accept
ct state new tcp dport 30000 accept
drop
Step 7) Restart your firewall
Assuming that it works, below is a quick config for setting up fail2ban. (If you haven't already read the other post)
Step 8) Create Local Configs
Step 9) Set your settings
[DEFAULT] findtime = 2h maxretry = 5 bantime.increment = true bantime.rndtime = 1024 banaction_allports = nftables-allports banaction = nftables-allports [nginx-botsearch] maxretry = 2 [foundryvtt] findtime = 3m maxretry = 3 bantime = 60 port = 80 logpath = /home/username/foundryuserdata/Logs/debug.log backend = polling ignoreip = 192.168.1.0/24
[sshd] enabled = true [nginx-bad-request] enabled = true [nginx-botsearch] enabled = true [nginx-http-auth] enabled = true [foundryvtt] enabled = true
Step 10) Create a regular expression to detect log entries
[Definition]
failregex = ^\{\"ip\":\"<HOST>\",\"level\":\"warn\",\"message\":\"((Administrator authentication failed for session [a-zA-Z0-9]{24}; invalid password)|(User authentication failed for user [a-zA-Z0-9]{1,50}; invalid password\",\"session\":\"[a-zA-Z0-9]{24}))\",\"status\":40[13],\"timestamp\":\"\"}$
Step 11) Test
systemctl restart nftables; systemctl restart fail2ban
Try to get yourself banned, and then issue the command to unban all ip's fail2ban-client unban -all
If you notice, there are some discrepancies in the settings i've listed, it means you can try your own values and customize it to what appears to work best for your system.
Comments
Post a Comment