Mitigating Log4j / Log4Shell with Fail2Ban

The big cybersecurity news this week is the Apache Log4j zero-day vulnerability nicknamed Log4Shell, which allows an attacker to seize full control of a server by sending a rather innocuous message to a web (or indeed many other types of) server. Surprisingly, it even made the headline news on Radio New Zealand. But what can you do?

I’ve written in the past about fail2ban, an open source program that you can use to help defend your Linux server against malicious applications by instructing your server to drop any traffic from offending sources. I’ve constructed a rule that you can use to help protect your server from malicious traffic sources attempting to break in with Log4Shell.

If you have fail2ban installed, in your filter.d directory, create a file called apache-log4j.conf with the following text:

# catch Log4j vulnerability as per CVE-2021-44228

failregex = ^<HOST> -.*\$\{jndi:(ldap[s]?|rmi|dns):/[^\n]+

… and in your jail.local file, insert the following block:

enabled  = true
filter   = apache-log4j
action = iptables-multiport[name=apache-log4j, port="http,https"]
logpath  = /var/log/apache2/*/access.log
bantime  = 3d
maxretry = 1

You may need to alter the logpath above to match your own log file structure.

And don’t forget to restart the service to pick up the changes after you’ve made these changes with

sudo systemctl restart fail2ban.service

or similar.

Note that this won’t protect you against all attacks, but it will at least slow attackers down. To protect yourself properly, follow the instructions in the CVE database for entry

Note that this won’t protect you against all attacks, but it will at least slow attackers down and minimise your attack surface. To protect yourself properly, follow the instructions in the CVE database for entry CVE-2021-44228 by ideally by upgrading the underlying log4j library or employing one of the mitigations.


  1. Thank you! I was thinking about this exact same method. What about the obfuscated attacks which are using ${${::-j}${::-n}${::-d}${::-i}…..? Should you add that to your check? Would it be easier to just drop all get/put requests containing jndi or the obfuscated variants?

  2. Thanks for these instructions.

    I guess that this is still missing (service restart to read the new configuration):
    systemctl restart fail2ban.service

  3. I’d thought that would have been obvious … but apprarently not. I’ve updated the post to reflect this – thanks for the heads-up!

  4. Thanks for the tip. This should be released as an ‘official’ filter for fail2ban; have you considered submitting a pull request on

    Note that your filter will also work well under nginx; script kiddies don’t even bother to check what kind of webserver is running at the other end, they just blindingly attack everything they see… and this is annoying for more reasons than one.

    Actually, I’ve added your filter with an action to automatically post whatever suspicious IP addresses it catches to — who knows, these might be useful to figure out potentially dangerous attack origins. And, for good measure, I also report any IP addresses directly to Cloudflare’s firewall. Sure, it just goes into my rules and only protects my sites, but the Cloudflare guys are great at figuring things out, and I’m pretty sure that they’ll take a look at IP addresses that have been reported by a lot of users…

    Again, thanks for your filter! It saved me precious time in figuring out the proper regexp 🙂 Then again, I guess I could basically block everything that starts with ${, since I’m quite sure I’m not using any software that requires pushing those characters on web URLs…

  5. Thanks for your feedback, Gwyneth – you’re points are excellent, and thanks for the suggestion to do a PR. Will make that happen in the New Year.

Comments are closed.