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.

2 Likes

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!

1 Like

@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.