The fail2ban daemon is running with root privileges. According to its documentation, this application supports running as a non-root user, which is preferable. fail2ban handles data from external sources (log text), which makes
it part of the external attack surface.
We recommend that all services be running as separate non-root users, with capabilities constrained to the minimum required for operation.
Disclaimer, I’ve been a fierce critic of fail2ban, for SSH I’m a huge advocate of just firewalling sshd behind spiped:
This drastically increase protection against zero-days on SSH since an attacker would need a zero-day on spipedandsshd
spiped is much more lightweight than wireguard (or worse openvpn), it can be run as a non-priviledged-user, and fully-systemd-hardened
It reduces to almost zero the attack surface on mis-configured sshd. (because the attacker needs to go through spiped before hitting sshd, and spiped is basically a “256bit-combination port knocker”)
It’s written by Colin Percival, “the tarsnap guy”, cryptographer, former FreeBSD Security officer. So I trust the security of it. (and also how sound the crypto is)
I’m happy to see a security audit recommending against fail2ban. Because fail2banmust to run as root, as it updates the firewall rules. (which is a reason why I do not like fail2ban, because it makes the firewall rules non-auditable) Also fail2ban had some vulnerability in the past where injecting the right strings in the logs could lead to being able to run unintended code. (Not RCE, but almost)
I’m a huge fail2ban critic, but I understand why some people want to run it for web servers protection, and stuff like this. (I would still not run it personally, as it is a huge pile of spaghetti python code) But if you do run it, I agree with the security auditor: run it as a user. You can use haproxy runtime-maps to maintain a list of banned IPs for a service behind haproxy for example, and updating the map can be done as a non-root-user with access to the unix socket.
I agree with everything, however… “Because fail2ban must to run as root, as it updates the firewall rules.” is not really correct. You can have proper privilege separation in that kind of app by immediately splitting into a) a log reader, b) a parser with no privileges other than running, c) two privileged scripts which exit on arguments that are not IP addresses and add/remove them from ipset. That’s a setup that’s easy to verify and almost equivalent to no-root.
You can have proper privilege separation in that kind of app by immediately splitting into a) a log reader, b) a parser with no privileges other than running, c) two privileged scripts which exit on arguments that are not IP addresses and add/remove them from ipset. That’s a setup that’s easy to verify and almost equivalent to no-root.
You are right. You can use ipset or even better switch to nftables and uses regular nftables sets. However, last time I checked, this is not the default configuration of fail2ban, and very little official documentation on this topic. IMHO, this shows how much the fail2ban team prioritise security-theater over real security.
The last paragraph kind of contradicts the one before it. The last one explains clearly why fail2ban doesn’t need to run as root, because it doesn’t necessarily need to update firewall rules. I e.g. use it to update a text file with IP addresses that Apache uses as an allowlist.
The last paragraph kind of contradicts the one before it.
Not really, but you’re right, it’s confusing. In the second-last paragraph, I made the assumption that mullvad uses fail2ban to block IPs either on SSH or on OpenVPN/Wireguard. In this context, your only option (AFAIK) is firewall blocking.
In the last paragraph, I am talking about web filtering. Yes you’re right. You can use apache/haproxy allow list files, but I don’t think it is Mullvad’s (and 99% of people’s) use-case.
I have not deeply looked into sshguard. But looking at it briefly, it looks better (as it uses ipset which can be used for privileges separation). However, I am bothered by the whole concept of blacklisting IPs. It doesn’t protect against zero-days, because if there is a zero-day announced bots will exploit it before getting blacklisted after X-retries. If you’re trying to prevent password brute-forcing, public key authentication will prevent this, without the risk of getting blacklisted from your own server.
I think the article link by @j3s in their comment summarise my opinion very well. And a lot of it is applicable to sshguard.
Anyway, to answer your original question :P, yes sshguard is an improvement, but I still think the solution designed is wrong. I would still recommend spiped instead.
Thanks for mentioning this, I’d never heard of it. I don’t like fail2ban so I’ve always been hiding behind wireguard/tailscale etc on top of disallowing passwords. I can really see a use for spiped in quite a few areas of my job
Disclaimer, I’ve been a fierce critic of
fail2ban
, for SSH I’m a huge advocate of just firewallingsshd
behindspiped
:spiped
andsshd
spiped
is much more lightweight thanwireguard
(or worseopenvpn
), it can be run as a non-priviledged-user, and fully-systemd-hardenedsshd
. (because the attacker needs to go throughspiped
before hittingsshd
, andspiped
is basically a “256bit-combination port knocker”)I’m happy to see a security audit recommending against
fail2ban
. Becausefail2ban
must to run as root, as it updates the firewall rules. (which is a reason why I do not likefail2ban
, because it makes the firewall rules non-auditable) Also fail2ban had some vulnerability in the past where injecting the right strings in the logs could lead to being able to run unintended code. (Not RCE, but almost)I’m a huge
fail2ban
critic, but I understand why some people want to run it for web servers protection, and stuff like this. (I would still not run it personally, as it is a huge pile of spaghetti python code) But if you do run it, I agree with the security auditor: run it as a user. You can usehaproxy
runtime-maps to maintain a list of banned IPs for a service behindhaproxy
for example, and updating the map can be done as a non-root-user with access to the unix socket.I agree with everything, however… “Because fail2ban must to run as root, as it updates the firewall rules.” is not really correct. You can have proper privilege separation in that kind of app by immediately splitting into a) a log reader, b) a parser with no privileges other than running, c) two privileged scripts which exit on arguments that are not IP addresses and add/remove them from ipset. That’s a setup that’s easy to verify and almost equivalent to no-root.
I wrote something about various way of improving on SSH security https://blog.viraptor.info/post/who-cares-about-security-by-obscurity
You are right. You can use
ipset
or even better switch tonftables
and uses regularnftables
sets. However, last time I checked, this is not the default configuration offail2ban
, and very little official documentation on this topic. IMHO, this shows how much thefail2ban
team prioritise security-theater over real security.The last paragraph kind of contradicts the one before it. The last one explains clearly why fail2ban doesn’t need to run as root, because it doesn’t necessarily need to update firewall rules. I e.g. use it to update a text file with IP addresses that Apache uses as an allowlist.
Not really, but you’re right, it’s confusing. In the second-last paragraph, I made the assumption that mullvad uses
fail2ban
to block IPs either on SSH or on OpenVPN/Wireguard. In this context, your only option (AFAIK) is firewall blocking.In the last paragraph, I am talking about web filtering. Yes you’re right. You can use apache/haproxy allow list files, but I don’t think it is Mullvad’s (and 99% of people’s) use-case.
piggybacking to say the same! here’s my little (mildly inflammatory) writing on the subject: https://j3s.sh/thought/fail2ban-sux.html
I’ve been using sshguard for years, but not thought too hard about it - how does it compare to fail2ban?
I have not deeply looked into
sshguard
. But looking at it briefly, it looks better (as it usesipset
which can be used for privileges separation). However, I am bothered by the whole concept of blacklisting IPs. It doesn’t protect against zero-days, because if there is a zero-day announced bots will exploit it before getting blacklisted after X-retries. If you’re trying to prevent password brute-forcing, public key authentication will prevent this, without the risk of getting blacklisted from your own server.I think the article link by @j3s in their comment summarise my opinion very well. And a lot of it is applicable to
sshguard
.Anyway, to answer your original question :P, yes
sshguard
is an improvement, but I still think the solution designed is wrong. I would still recommendspiped
instead.Thanks for mentioning this, I’d never heard of it. I don’t like fail2ban so I’ve always been hiding behind wireguard/tailscale etc on top of disallowing passwords. I can really see a use for spiped in quite a few areas of my job