Keeping bad actors out
Self hosting is a lot of fun. From running your own services to checking that backups work. There are, however, people that make it a sport to try and login on the systems you build for yourself. There is a great tool that you can use to detect and block these actors; fail2ban.
For fail2ban to work with custom services (it already has a lot built-in) you need to create some filters. You place them in /etc/fail2ban/filter.d in a file with a descriptive name, such as forgejo.conf or freshrss.conf.
Filters for Forgejo
Of all my services, forgejo is the most attacked one. It makes sense, it is well known and has excellent documentation. To block anybody that tries to log into my instance I created a couple of filter rules.
[Definition]
failregex = ^.*Failed authentication attempt for .* from <HOST>
^.*Invalid user .+ from <HOST> port .*
^.*User .+ from <HOST> not allowed because not listed in AllowUsers
Then I created a /etc/fail2ban/jail.d file called forgejo.conf. It contains the instructions what to do with the above filter.
[forgejo]
enabled = true
filter = forgejo
logpath = /var/lib/docker/containers/**/*-json.log
maxretry = 4
bantime = 14400
findtime = 14400
chain = DOCKER-USER
ignoreip = 127.0.0.1/8 10.0.0.0/8 172.27.0.0/16 192.168.1.0/24
As i am running everything as docker containers I am looking at the output of the containers, the *-json.log files. I tell it which filter to use, my aptly named forgejo filter, and finally I tell it to which iptables chain the ban should be added. When running things using docker, you will run into the fact that it will try to control everything, including networking. The DOCKER-USER list is there to add custom rules.
Be sure to add your own IP address to the ignoreip list so that you do not get blocked yourself.
FreshRSS
The same setup goes for FreshRSS. The filter is a little simpler:
[Definition]
failregex = ^{"log":"<HOST> .+\" 403 \d+ .*$
And the jail itself looks the same:
[freshrss]
enabled = true
filter = freshrss
logpath = /var/lib/docker/containers/**/*-json.log
maxretry = 4
bantime = 14400
findtime = 14400
chain = DOCKER-USER
ignoreip = 127.0.0.1/8 10.0.0.0/8 172.27.0.0/16 192.168.1.0/24
Default jails
On my ubuntu instance I also enable the SSH jail, which is done through the defaults jail.
[sshd]
enabled = true
Checking that everything works
You can use the logfile /var/log/fail2ban.log to check that everything works as expected. Also check out iptables -L to see all the IPs being added to the REJECT list.
Sometimes you want to check that your filter works, especially after upgrading versions or when you found a new way you wanted to block someone. The tool fail2ban-regex is very useful here:
fail2ban-regex /var/lib/docker/containers/4131da65deefeb601933cf58e2a8498872a0416192354e3411e447c6857bc384/4131da65deefeb601933cf58e2a8498872a0416192354e3411e447c6857bc384-json.log /etc/fail2ban/filter.d/forgejo.conf
Of course you will need to change the path to the docker container log file.