• Skip to content
  • Skip to primary sidebar
  • Skip to footer

Foliovision

Making the web work for you

Main navigation

  • Weblog
    • FV Player
    • WordPress
    • Video of the Week
    • Case Studies
    • Business
  • About
    • Testimonials
    • Meet the Team
    • We Support
    • Careers
    • Contact
    • Pricing
  • Products
  • Support
    • FV Player Docs
    • Pro Support
  • Login
  • Basket is empty
Affordable VAST/VPAID for Wordpress has arrived. Serve ads with your videos starting today!

How to setup fail2ban for WordPress with CDN

22 June 2022 / Martin / Leave a Comment

How to block bruteforce login cracking with fail2ban

For years we have been using fail2ban to block bad login attempts on WordPress. fail2ban saved us from millions of password guessing attempts. What’s especially wonderful about fail2ban is that it’s in front of your WordPress install and requests from known bad IP’s don’t even reach WordPress. Pure WordPress solutions like Limit Login Attempts Reloaded, LoginLockdown, SiteGround Security allow bad actors to load php and WordPress which means they can still hack away at your server or DDOS your server by overloading it.

We like fail2ban enough that we include an automated integration of fail2ban for WordPress/nginx or WordPress/Apache in our BusinessPress plugin. The security is based on feeding the IP addresses of bad requests into iptables via fail2ban. Hack attempt, banned. Twelve failed login attempts, banned. Easy as pie.

Some blocked IP’s continue to send hundreds of requests

However recently we noticed that some of the blocked IP addresses are still able to send in more requests.

For a moment we thought that the issue might be with ServerPilot. ServerPilot is a service to manage your server and the web stack. It uses UFW (Uncomplicated Firewall) to establish some basic security rules. Since it’s just a wrapper around iptables and fail2ban (by default) also uses iptables, we thought it might be running into some kind of conflict. So we tried to switch fail2ban to use UFW instead. Of course this did not fix anything. UFW is just a front end for iptables!

Watching our logs, the situation was getting more and more serious. We found an IP that got banned at Jun 2, 2022 at 05:24:03, yet it was allowed to do 4,000 more login attempts between 05:24 and 07:58 on that same day and nothing seem to stop it.

Here’s how that looked like in /var/log/fail2ban.log:

2022-06-02 05:24:03,648 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:03,648 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:04,250 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:04,250 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:04,451 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:04,452 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:05,053 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:05,054 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:05,655 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:05,656 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:06,257 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:06,258 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:06,459 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:06,459 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:06,854 fail2ban.actions        [16639]: NOTICE  [wordpress] Ban 113.108.8.77
2022-06-02 05:24:07,061 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:07,062 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:07,594 fail2ban.filter         [16639]: INFO    [repeated] Found 113.108.8.77
2022-06-02 05:24:07,663 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:07,664 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:08,265 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:08,266 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:08,867 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:08,867 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:09,469 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:09,469 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:09,703 fail2ban.actions        [16639]: NOTICE  [wordpress] 113.108.8.77 already banned
2022-06-02 05:24:10,071 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:10,072 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:10,673 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:10,674 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:11,277 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:11,278 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:11,479 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:11,479 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:12,682 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:12,682 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:12,883 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:12,884 fail2ban.filter         [16639]: INFO    [wordpress] Found 113.108.8.77
2022-06-02 05:24:12,907 fail2ban.actions        [16639]: NOTICE  [wordpress] 113.108.8.77 already banned

We logged the iptables rules every minute to ensure the IP addresses are not getting lost and that it’s not just some fail2ban bug.

Danger of Established Connections

Finally we posted a question to Server Fault where we include our iptables rules as well. It did not take long before A.B. suggested that we are not doing anything about the connections which are already established. Basically if a malicious user it able to do a WordPress login attempt and it fails, he can just use that same connection again and again.

So it seemed that it’s really a design flaw of fail2ban as its default install is set to reject requests when it should be set to drop requests.1

We tried different ways of trying to break the established connections (tcpkill, ss) but nothing worked or it wouldn’t not work with fail2ban.

Solution: Don’t REJECT but DROP bad requests

In the end the trick was to configure fail2ban to use DROP with iptables instead of just REJECT. With REJECT the sender gets back some information about the server refusing the request, but it allows the sender to establish the connection and keep using it. That’s why iptables would fail to block these IP addresses. When using DROP the actual connection does not succeed and it times out. Then it’s not possible to send in more login attempts.

Here’s how to make this change in fail2ban configuration:

  1. Open the /etc/fail2ban/action.d/iptables.conf file in your favourite editor
  2. Find the blocktype definition and comment it out by appending # in front of it
  3. Append blocktype = DROP below

Then restart fail2ban using service fail2ban restart and finally when you run iptables -vnL you should notice all the banned IP addresses are using the DROP rule:

Chain f2b-repeated (1 references)
 pkts bytes target     prot opt in     out     source               destination         
  448 26880 DROP       all  --  *      *       84.115.217.111       0.0.0.0/0           
  575 29900 DROP       all  --  *      *       180.191.22.74        0.0.0.0/0           
  522 27144 DROP       all  --  *      *       103.129.213.100      0.0.0.0/0           
  967 50284 DROP       all  --  *      *       86.97.64.156         0.0.0.0/0           
    0     0 DROP       all  --  *      *       175.176.23.18        0.0.0.0/0 

Do not forget about your CDN

You must not forget that these malicious users can also use your CDN to send in the bad requests. It’s important to block any POST requests on your CDN. It’s easy to do with Bunny CDN although I wish it would be on by default:

If you would like to also block IP addresses which do some malicious requests like in our New Feature for BusinessPress: Fail2Ban for WordPress Hack Attempts article, you must be even more careful. BusinessPress will detect the real user IP address reliably thanks to the X-Pull header and will not ban the CDN IP address. This is a good thing – banning the CDN IP address would be a disaster, locking visitors out of media files, but in default configuration it still leaves a path for bad actors to assault your server.

The fix is relatively simple, and again, it involves tightening your CDN configuration. What you need to do is build a whitelist of file types which are accepted.

Block everything except these known file types. With Bunny CDN it is easy to establish a rule to only allow the known file types to pass and block everything else:

Conclusion

It was quite a ride making fail2ban work reliably again, but now that we’ve figured out how the bad actors were able to continue to hack at our servers, the solutions are easy to implement and free.

Lessons to take away:

  • check your logs
  • don’t trust default configurations
  • test carefully: what seems intuitive (banning instead of dropping) is not always what it seems

If anyone has some additional tips on how to tune fail2ban/iptables, we’d love to hear them.


  1. Perhaps this is because SSH, which is the default protocol which fail2ban monitors, automatically closes a connection after three failed in log attempts. Hence there’s no way for a bad actor to keep a connection open. ↩

Martin Vicenik

Martin Viceník

Martin graduated as an engineer in Computer Science from Slovak Technical University in Bratislava. He grew up in Liptovský Mikuláš in northern Slovakia next to the beautiful Tatra mountains. He is the developer behind our FV Player.

Categories: IT, WordPress Tags: fail2ban, hosting, iptables, security, WordPress

Related Posts

  1. New Feature for BusinessPress: Fail2Ban for WordPress Hack Attempts

  2. How to block malicious web requests with BusinessPress

    How to block malicious web requests with BusinessPress

  3. How to block repeated offenders with BusinessPress

    How to block repeated offenders with BusinessPress

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You can click here to Subscribe without commenting

Primary Sidebar

My Account

  • My Licenses
  • My Profile
  • Invoices
  • Affiliate Area
  • Log Out

Categories

  • Business
  • Camera Reviews
  • Case Studies
  • Design
  • Flowplayer
  • Internet Marketing
  • IT
  • Life
  • SEO
  • Slovak
  • Video of the Week
  • WordPress

Footer

Our Plugins

  • FV WordPress Flowplayer
  • FV Thoughtful Comments
  • FV Simpler SEO
  • FV Antispam
  • FV Gravatar Cache
  • FV Testimonials

Free Tools

  • Pandoc Online
  • Article spinner
  • WordPress Password Finder
  • Delete LinkedIn Account
  • Responsive Design Calculator
Foliovision logo
All materials © 2023 Foliovision s.r.o. | Panská 12 - 81101 Bratislava - Slovakia | info@foliovision.com
  • This Site Uses Cookies
  • Privacy Policy
  • Terms of Service
  • Site Map
  • Contact
  • Tel. ‭+421 2/5292 0086‬

We are using cookies to give you the best experience on our website.

You can find out more about which cookies we are using or switch them off in settings.

Powered by  GDPR Cookie Compliance
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.

Necessary Cookies

Strictly Necessary Cookie allow you to log in and download your software or post to forums.

We use the WordPress login cookie and the session cookie.

If you disable this cookie, we will not be able to save your preferences. This means that every time you visit this website you will need to enable or disable cookies again.

Support Cookies

Foliovision.com uses self-hosted Rocket.chat and self-hosted Freescout support desk to provide support for FV Player users. These cookies allow our visitors to chat with us and/or submit support tickets.

We are delighted to recommend self-hosted Rocket.chat and especially Freescout to other privacy-conscious independent publishers who would prefer to self-host support.

Please enable Strictly Necessary Cookies first so that we can save your preferences!

3rd Party Cookies

This website uses Google Analytics and Statcounter to collect anonymous information such as the number of visitors to the site, and the most popular pages.

Keeping this cookie enabled helps us to improve our website.

We reluctantly use Google Analytics as it helps us to test FV Player against popular Google Analytics features. Feel free to turn off these cookies if they make you feel uncomfortable.

Statcounter is an independent Irish stats service which we have been using since the beginning of recorded time, sixteen years ago.

Please enable Strictly Necessary Cookies first so that we can save your preferences!