Wordpress - Fail2Ban - PHP

  1. Go to Networking ⇾ Fail2Ban Intrusion Detector: Log Filters page;
  2. Click Add a new log filter button;
  3. Fill the following fields:
    3.1. Filter name: wordpress;
    3.2. Regular expressions to match:
    <HOST>.*POST.*(wp-login\.php|xmlrpc\.php|account\/signin).* 200
    
    3.3. Click Create button;
  4. Go to Networking ⇾ Fail2Ban Intrusion Detector: Filter Action Jails page;
  5. Click Add a new jail button;
  6. Fill the following fields:
    6.1. Jail name : wordpress-domain-com;
    6.2. Filter to search log for: wordpress;
    6.3. Currently enabled? set to Yes;
    6.4. Log file paths:
    /var/log/virtualmin/domain.com_access_log
    
    6.5. Click Create button;
  7. Enjoy, and please let’s close this thread already!

Note: A backend may need to be manually defined as described in this comment.

Thank you very much Ilia for providing us with that need solution.

Has anybody else implemented it?

After 48 h my wordpress-domain-com jail remains empty even though I have in the logs many xmlrpc.php and wp-login.php lines. I am not sure if the filter-action-jail is reading my logs. I added all my xyz.com_access_log files of all my domains running on this server there, one per line. How can I proof if they are read at all?

Well, all my jails are empty in the UI. When I print the database I can see some dovecot sinners. So I might have another problem.

But I am sure this is the solution. If anybody else can give confirmation of its functionality we can close the thread.

You could try:

fail2ban-client status

and then:

[root@hostname ~]# fail2ban-client status wordpress-domain-com
Status for the jail: wordpress-domain-com
|- Filter
|  |- Currently failed:	0
|  |- Total failed:	13341
|  `- File list:	/var/log/virtualmin/domain.com_access_log
`- Actions
   |- Currently banned:	0
   |- Total banned:	221
   `- Banned IP list:	

SYSTEM INFORMATION
OS type and version Ubuntu Linux 22.04.4
Webmin version 2.111
Usermin version 2.010
Virtualmin version 7.10.0
Theme version 21.10
Package updates All installed packages are up to date

@Ilia
I have added this filter but it doesn’t work correctly with [recidive]
Once the Ip has been banned and found by by [recidive] it errors the wordpress filter for that IP.

2024-05-03 07:52:06,324 fail2ban.actions        [790]: NOTICE  [recidive] Unban 103.10.44.7
2024-05-03 07:52:06,150 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 198.12.236.217 - 2024-05-03 07:52:06
2024-05-03 07:52:05,373 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 92.205.168.116 - 2024-05-03 07:52:05
2024-05-03 07:52:01,192 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 107.190.135.10 - 2024-05-03 07:52:01
2024-05-03 07:51:57,757 fail2ban.actions        [790]: NOTICE  [wordpress-ilikebicycles-com] 35.214.190.212 already banned
2024-05-03 07:51:57,731 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 35.214.190.212 - 2024-05-03 07:51:57
2024-05-03 07:51:52,921 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 35.214.190.212 - 2024-05-03 07:51:52
2024-05-03 07:51:50,197 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 194.163.128.165 - 2024-05-03 07:51:50
2024-05-03 07:51:49,032 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 46.229.230.81 - 2024-05-03 07:51:48
2024-05-03 07:51:43,528 fail2ban.actions        [790]: ERROR   Failed to execute ban jail 'wordpress-ilikebicycles-com' action 'firewallcmd-ipset' info 'ActionInfo({'ip': '35.214.190.212', 'family': 'inet4', 'fid': <function Actions.ActionInfo.<lambda> at 0x7fc9dc20d630>, 'raw-ticket': <function Actions.ActionInfo.<lambda> at 0x7fc9dc20dcf0>})': Error starting action Jail('wordpress-ilikebicycles-com')/firewallcmd-ipset: 'Script error'
2024-05-03 07:51:43,527 fail2ban.utils          [790]: ERROR   7fc9dccfb8a0 -- returned 13
2024-05-03 07:51:43,527 fail2ban.utils          [790]: ERROR   7fc9dccfb8a0 -- stderr: ''
2024-05-03 07:51:43,527 fail2ban.utils          [790]: ERROR   7fc9dccfb8a0 -- stderr: "Try `iptables-restore -h' or 'iptables-restore --help' for more information."
2024-05-03 07:51:43,527 fail2ban.utils          [790]: ERROR   7fc9dccfb8a0 -- stderr: 'Error occurred at line: 2'
2024-05-03 07:51:43,527 fail2ban.utils          [790]: ERROR   7fc9dccfb8a0 -- stderr: "Error: COMMAND_FAILED: '/usr/sbin/iptables-restore -w -n' failed: iptables-restore v1.8.7 (nf_tables): invalid port/service `0-65535' specified"
2024-05-03 07:51:43,526 fail2ban.utils          [790]: ERROR   7fc9dccfb8a0 -- stderr: 'ipset v7.15: Set cannot be created: set with the same name already exists'
firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 0 -p tcp -m multiport --dports "$(echo '0:65535' | sed s/:/-/g)" -m set --match-set f2b-wordpress-ilikebicycles-com src -j REJECT --reject-with icmp-port-unreachable
2024-05-03 07:51:43,524 fail2ban.utils          [790]: ERROR   7fc9dccfb8a0 -- exec: ipset create f2b-wordpress-ilikebicycles-com hash:ip timeout 0 
2024-05-03 07:51:43,118 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 2a01:4f8:1c1e:4404::1 - 2024-05-03 07:51:43
2024-05-03 07:51:42,992 fail2ban.filter         [790]: INFO    [recidive] Found 35.214.190.212 - 2024-05-03 07:51:42
2024-05-03 07:51:42,982 fail2ban.actions        [790]: NOTICE  [wordpress-ilikebicycles-com] Ban 35.214.190.212
2024-05-03 07:51:42,781 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 35.214.190.212 - 2024-05-03 07:51:42
2024-05-03 07:51:42,643 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 35.214.190.212 - 2024-05-03 07:51:42
2024-05-03 07:51:33,114 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 185.141.171.198 - 2024-05-03 07:51:33
2024-05-03 07:51:32,817 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 161.132.40.116 - 2024-05-03 07:51:32
2024-05-03 07:51:29,548 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 103.145.50.69 - 2024-05-03 07:51:29
2024-05-03 07:51:26,045 fail2ban.filter         [790]: INFO    [wordpress-ilikebicycles-com] Found 194.5.237.145 - 2024-05-03 07:51:25
2024-05-03 07:51:25,029 fail2ban.actions        [790]: NOTICE  [recidive] Ban 192.3.176.170
2024-05-03 07:51:24,875 fail2ban.filter         [790]: INFO    [recidive] Found 192.3.176.170 - 2024-05-03 07:51:24

What about the other jails, like SSH, do they work correctly on your system?

Yes all other jails work with [recidive]

2024-05-03 11:29:24,255 fail2ban.actions        [793]: NOTICE  [recidive] Ban 45.117.177.144
2024-05-03 11:29:24,176 fail2ban.filter         [793]: INFO    [recidive] Found 45.117.177.144 - 2024-05-03 11:29:24
2024-05-03 11:29:24,167 fail2ban.actions        [793]: NOTICE  [sshd] Ban 45.117.177.144
2024-05-03 11:29:23,594 fail2ban.filter         [793]: INFO    [sshd] Found 45.117.177.144 - 2024-05-03 11:29:23
2024-05-03 11:25:30,235 fail2ban.filter         [793]: INFO    [sshd] Found 45.117.177.144 - 2024-05-03 11:25:30
2024-05-03 11:19:53,152 fail2ban.actions        [793]: NOTICE  [sshd] Unban 45.117.177.144
2024-05-03 11:09:54,224 fail2ban.filter         [793]: INFO    [recidive] Found 45.117.177.144 - 2024-05-03 11:09:54
2024-05-03 11:09:54,214 fail2ban.actions        [793]: NOTICE  [sshd] Ban 45.117.177.144
2024-05-03 11:09:53,928 fail2ban.filter         [793]: INFO    [sshd] Found 45.117.177.144 - 2024-05-03 11:09:53
2024-05-03 11:03:44,589 fail2ban.filter         [793]: INFO    [sshd] Found 45.117.177.144 - 2024-05-03 11:03:44

in jail.local

[recidive]
enabled = true
maxretry = 2
ignoreip = 127.0.0.1 x.x.0.0/13 104.x.218.x 172.x.53.x
findtime = 1d

[DEFAULT]
maxretry = 5
[wordpress-ilikebicycles-com]
enabled = true
filter = wordpress
logpath = /var/log/virtualmin/ilikebicycles.com_access_log
maxretry = 2
ignoreip = 127.0.0.1 x.x.0.0/13 104.x.218.x 172.x.53.x
findtime = 10m
bantime = 10m

in jail.conf nothing for [wordpress-ilikebicycles-com] went in jail.conf

[recidive]

logpath  = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime  = 1w
findtime = 1d

That’s odd, as recidive should check for entries in /var/log/fail2ban.log file, and I can see WordPress bans in fail2ban.log file in our system. I’m not sure what’s wrong on your side; try to increase the log level to get more perspective.

the file /etc/fail2ban/filter.d/wordpress.conf
only has this in it:
[Definition]

where does it pull

<HOST>.*POST.*(wp-login\.php|xmlrpc\.php|account\/signin).* 200

from?

As indicated in my initial post:

/var/log/virtualmin/domain.com_access_log

I should have asked where is it defined?

so the file /etc/fail2ban/filter.d/wordpress.conf
having only

[Definition]

and blank after that is correct?

should

failregex = <HOST>.*POST.*(wp-login\.php|xmlrpc\.php|account\/signin).* 200

be in that file? it is not.

It was added to log filters and /etc/fail2ban/filter.d/wordpress.conf was created with only [Definition] and blank after that

There also has to be a /etc/fail2ban/jail.d/10-wordpress.conf file with the following content:

[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/virtualmin/domain.com_access_log
maxretry = 6
bantime = 3600

there is not

Should I add it?

Did you follow my initial instructions?

yes I did.

I am deleting both filter and jail will restart then add them to see if the system creates the correct files

I have re-run tests and sadly, a backend needs to be additionally defined on some OS. For example, if you add to the jail.local file, under [wordpress-domain-com]:

backend = auto

…restart Fail2Ban, then it starts to work as expected!

I will automate it in the Wordpress Kit, though!

@Jamie, I’m thinking of adding a backend dropdown (i.e. Check for log file updates using) to the Filter Action Jails page, similarly to what I previously added for the Default Jail Options page.

It has to be manually set to a non-default value in some cases for a jail to work correctly, for example, with custom Apache log files.

Furthermore, we need the port option to also be available from the Filter Action Jails page, to apply a block for specific port(s) only!

Sure, send me a PR for this!

Done!

Every virtual wordpress site writes its logs in its own subdirectory but the Fail2Ban architecture is made for a consolidated operation

You can add multiple log files on a single jail. Log files after the first one has to be indented.
example:

[sample-jail]
enabled  = true
logpath  = /var/log/virtualmin/site1.com_access_log
	/var/log/virtualmin/site2.com_access_log
    /var/log/virtualmin/site3.com_access_log
    /var/log/virtualmin/site4.com_access_log
    /var/log/virtualmin/site5.com_access_log

In my case I had to generate the 10-wordpress.conf file in /etc/fail2ban/jail.d myself. It didn’t help to go through the process Ilia mentioned.

As long as I didn’t had the .conf file, all my jails were suspended.

Thanks again for all support and help. Everything is working fine now!

The ticket can be closed now.