• Please be aware: Kaspersky Anti-Virus has been deprecated
    With the upgrade to Plesk Obsidian 18.0.64, "Kaspersky Anti-Virus for Servers" will be automatically removed from the servers it is installed on. We recommend that you migrate to Sophos Anti-Virus for Servers.
  • The Horde webmail has been deprecated. Its complete removal is scheduled for April 2025. For details and recommended actions, see the Feature and Deprecation Plan.
  • We’re working on enhancing the Monitoring feature in Plesk, and we could really use your expertise! If you’re open to sharing your experiences with server and website monitoring or providing feedback, we’d love to have a one-hour online meeting with you.

Question Plesk's Fail2ban

mr-wolf

Silver Pleskian
Plesk Guru
I have personally not that much interest in fail2ban. I've written something like that some 8 years ago myself without ever hearing of fail2ban. What I wrote then is similar to what fail2ban is doing now.

I'm writing my iptables rules directly in a file and it's loaded automatically if the interface goes up.
On top of that I have 2 cronjobs that add some additional rules to iptables in memory.

Because @OverWolf wants to implement one of these scripts to block some countries I'm trying to help him.
For this I installed Plesk's fail2ban implementation for the first time to see what it is doing.

I noticed that it's quite bluntly putting itself at the top of the chain and therefore ruining the efficiency that makes iptables so popular. I can't really imagine that I'm the first to notice, so I'm wondering if it's just because I'm using it on my firewall.

Maybe it does insert itself at a more strategic position if it's used with the standard Plesk firewall.
Can someone with the Plesk firewall enabled show me how the INPUT chain looks like when F2B is implemented?

This would help me to be of more assistance to those who want to implement my script that is able to block countries.
Maybe @UFHH01 ?
 
Hi mr-wolf,

thank you for your support/cooperation. If it can help you, you can try to enable firewall at your side and then click on preview bottom. It show you the script (and the INPUT chain) that will be apply to the iptables. I hope that this help you (and me).
 
I have personally not that much interest in fail2ban. I've written something like that some 8 years ago myself without ever hearing of fail2ban. What I wrote then is similar to what fail2ban is doing now.

I'm writing my iptables rules directly in a file and it's loaded automatically if the interface goes up.
On top of that I have 2 cronjobs that add some additional rules to iptables in memory.

Because @OverWolf wants to implement one of these scripts to block some countries I'm trying to help him.
For this I installed Plesk's fail2ban implementation for the first time to see what it is doing.

I noticed that it's quite bluntly putting itself at the top of the chain and therefore ruining the efficiency that makes iptables so popular. I can't really imagine that I'm the first to notice, so I'm wondering if it's just because I'm using it on my firewall.

Maybe it does insert itself at a more strategic position if it's used with the standard Plesk firewall.
Can someone with the Plesk firewall enabled show me how the INPUT chain looks like when F2B is implemented?

This would help me to be of more assistance to those who want to implement my script that is able to block countries.
Maybe @UFHH01 ?

@mr-wolf,

In essence, there are two options

a) use the Plesk Firewall extension to block entire CIDR Blocks associated with specific countries like China and note that this is quite efficient: one can use one entry to block vast ranges of IPs, with Plesk Firewall extension creating an iptables (firewall) ruleset that is persistent (across reboots),

OR

b) use Nginx (with or without geoip module) config files, containing individual IPs or CIDR block ranges in the format

deny ....;
deny .....;
allow;

and place the (custom) config file in /etc/nginx/conf.d and run the command: nginx -t && nginx reload (command may vary across Plesk instances or OSes).


Note that the "Nginx option" is only affecting the traffic that is picked up by Nginx, which is normally Apache related traffic.

The above implies that the Nginx alternative cannot safeguard against

1 - malicious traffic directed at the mail servers,
2 - SSH hack attempts,
3 - attempts to access the MySQL database server,

but the following can be done:

- SSH hack attempts can be prevented by simply using the Plesk Firewall extension to ONLY grant access via SSH to your own IP (and denying all other traffic),
- deny access to the MySQL database server from other IPs than the 127.0.0.1 address: just use Plesk Firewall extension to achieve this.

This would leave Fail2Ban responsible for, in essence, hack attempts directed at the mail servers.


Finally note that Plesk Panel essentially is a custom Nginx server, implying that the Nginx alternative can be used........... but that is not recommend at all.

It is highly recommended to safeguard Plesk administrative interface to IPs that are allowed via the Plesk Firewall extension.

However, this recommendation is not always possible, for instance when having a lot of customers accessing the Plesk Panel: in that case, the Nginx alternative can provide some additional security in the sense that a "allow list" or a "deny list" in a custom config file would be feasible.....but I will not elaborate on that now.

Hope the above helps a bit.....

Regards........
 
@mr-wolf,

In essence, there are two options

a) use the Plesk Firewall extension to block entire CIDR Blocks associated with specific countries like China and note that this is quite efficient: one can use one entry to block vast ranges of IPs, with Plesk Firewall extension creating an iptables (firewall) ruleset that is persistent (across reboots),

OR

b) use Nginx (with or without geoip module) config files, containing individual IPs or CIDR block ranges in the format

deny ....;
deny .....;
allow;

and place the (custom) config file in /etc/nginx/conf.d and run the command: nginx -t && nginx reload (command may vary across Plesk instances or OSes).


Note that the "Nginx option" is only affecting the traffic that is picked up by Nginx, which is normally Apache related traffic.

The above implies that the Nginx alternative cannot safeguard against

1 - malicious traffic directed at the mail servers,
2 - SSH hack attempts,
3 - attempts to access the MySQL database server,

but the following can be done:

- SSH hack attempts can be prevented by simply using the Plesk Firewall extension to ONLY grant access via SSH to your own IP (and denying all other traffic),
- deny access to the MySQL database server from other IPs than the 127.0.0.1 address: just use Plesk Firewall extension to achieve this.

This would leave Fail2Ban responsible for, in essence, hack attempts directed at the mail servers.


Finally note that Plesk Panel essentially is a custom Nginx server, implying that the Nginx alternative can be used........... but that is not recommend at all.

It is highly recommended to safeguard Plesk administrative interface to IPs that are allowed via the Plesk Firewall extension.

However, this recommendation is not always possible, for instance when having a lot of customers accessing the Plesk Panel: in that case, the Nginx alternative can provide some additional security in the sense that a "allow list" or a "deny list" in a custom config file would be feasible.....but I will not elaborate on that now.

Hope the above helps a bit.....

Regards........
All of the above is not an answer to the question...

But I already tested this.
The answer is...
Yes, F2B always puts itself front row...

I would not use it.
It would create thousands of rules that have to be processed before it starts on the real firewall and this continuously for all traffic.

My "ipset-country" and "ipset-wordfence" only act on new connections and only on specific ports using 1 rule and an efficient engine which stores all the subnets (ipset).
The difference is dramatic.

Some kind of traffic (like SSH) one can block it so much better and quicker with iptables itself.
No need to use security through obscurity by changing the port to another one than 22...
 
@mr-wolf,

You stated

Yes, F2B always puts itself front row...

I would not use it.
It would create thousands of rules that have to be processed before it starts on the real firewall and this continuously for all traffic.

and that is not correct: normal iptables rulesets and/or Plesk Firewall extension related rulesets are on top.

Moreover, one can always change the chronological order of firewall rules by means of (on the one hand) Plesk Firewall extension and (on the other hand) iptables commands.

Furthermore, you state

Some kind of traffic (like SSH) one can block it so much better and quicker with iptables itself.

and that is NOT recommended at all: one has to have thorough knowledge of firewalls and iptables itself AND have a steady hand, since every typo can result in the admin being blocked permanently on the machine (note: that is not the first time that something like that happens, even for the well-seasoned sysadmin).

In general, the Plesk Firewall extension is more easy to implement SSH related iptables firewall rules.

Nevertheless, you can always decide for yourself............you are free to do what you want.

Regards......
 
@mr-wolf,

Totally forgot about the following

No need to use security through obscurity by changing the port to another one than 22...

statement.

Actually, there is a reason to change the default SSH port.

It is common practice for hackers to overload the firewall by attacking on all common ports, hence achieving that the server is not performing well or even becomes ineffective.

The endresult is often that a second type of attack can be easiy executed, with success.

In general, changing the default ports (for SSH and other services) would not mitigate the attack surface, but certainly would decrease the chance that hacks are successful.

Regards............
 
In essence, there are two options

a) use the Plesk Firewall extension to block entire CIDR Blocks associated with specific countries like China and note that this is quite efficient: one can use one entry to block vast ranges of IPs, with Plesk Firewall extension creating an iptables (firewall) ruleset that is persistent (across reboots),

OR

Hi trialotto,
can you explain how to implement the use of firewall to block specific countries ?

Thank you
 
@OverWolf

I will give you a (in my humble opinion "simple") solution, but I first will provide some explanation about two points with respect to the basics of Plesk:

1) firewall rules should be simple and fast: iptables rulesets should be efficient

In every firewall, one can opt for blocking specific IPs and this would often result in huge lists of IPs or CIDR ranges of IPs.

Even the usage of CIDR ranges of the kind 42.224.0.0/12 (one for China) would simplify firewall rulesets, but one still has to add an awful lot of CIDR ranges.

In order to keep the firewall performant AND in order to keep the firewall itself protected (!), a simple set of iptables rulesets should be set.

In essence, that would imply the policy: one should opt for "deny all, except for good IPs"

The issue with this policy is that one does not always know what "good IPs are" .......... making this policy only useful for:

- SSH and associated ports: deny all, with the exception of the IPs of sysadmins
- MySQL and associated ports: deny all, with the exception of the local IP (127.0.0.1) and trusted remote machines

and so on.

2) an Apache + Nginx setup is valuable

Most of the malicious traffic is aimed at your web server (Apache) and the applications hosted by the web server.

One can try to block specific IPs with a firewall ruleset and that should be done for specific bad crawlbots: just add the IPs or IP ranges via the Plesk Firewall extension.

On the other hand, a lot of IPs from "visitors" cannot be deemed "bad" or "good" upfront: one really does not know.

For instance, many Chinese IP addresses are not associated with malicious traffic, it is often some specific set of CIDR ranges.

Now we have to make decisions on what is good or bad: we can leave that up to Fail2Ban (not recommended) OR we will decide for ourselves (a better idea!).

Suppose we want to block a huge amount of IPs and CIDR ranges.

Blocking them with the firewall makes the firewall contain huge lists of IPs and CIDR ranges...........and that is not always a good idea: performance penalties are present AND even some types of hack attempts are aiming to overload the firewall, in order to get in via a backdoor.

However, most services (SSH, MySQL) are not attacked, if the policy from point 1 is implemented: hack attempts do not get through the firewall.

Now let's focus on the malicious traffic aimed at Apache (the web server).

It is not recommended to let Apache do all the work when defending against malicious traffic, since Apache is very bad at it and very resource hungry.

Just adding a layer in front of Apache is an excellent idea: that "layer" can do all the work that Apache should not!

Nginx
is the ideal candidate: it is efficient, fast, reliable and a default component of Plesk, without much need of customization.

In short, using Nginx in front of Apache allows us to add a layer of protection.


What about that solution?

Well, let's define the problem and challenge: we want to block certain CIDR ranges belonging to a specific country.


Hmm, Nginx normally has something like a geoip module, but at the current moment, that module is not shipped with the default Nginx binary of Plesk.

That is too bad, since using the geoip module would involve a database with IPs (and the database has to be updated regularly), which is quite convenient and efficient.

But the convenience of a ready-steady database is not outweighing the discomfort of creating a custom Nginx binary, amongst others due to the facts that (on the one hand) Nginx compilation is not that easy as it might seem and (on the other hand) the custom binary is very likely to be or will be erased when Plesk's default binary gets updated.


So, we should work around that issue by using a fool-proof solution, using the default Nginx directives "deny" and "allow".......

...........and we should know which IPs to block.


We can know the IPs to block by having a look at Index of /ipcountry (note: this is an example of a site that maintains CIDR lists, one of many).

When clicking on CN.cidr, one gets redirected to a page with subnets associated with China.

The list is a bit "rough" and, normally, one has to do some clean-up.......... however, Nginx does handle potential double entries perfectly fine, so no worries about that!


What we have to do now is the following (steps in chronlogical order)

1 - login to SSH

2 - create a directory with the command: mkdir /CIDR (or any other name for the directory)

3 - cd into /CIDR and run the command: curl -O http://www.iwik.org/ipcountry/CN.cidr

4 - run the command: grep -r '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' CN.cidr | sort -n | uniq -c | awk -F' ' '{print "deny "$2";"}' > /etc/nginx/conf.d/CN.conf

NOTE: the CN.conf contains all the CIDR ranges belonging to China and those ranges are blocked with the deny directive.

5 - run the command: nginx -t && nginx reload

NOTE: "nginx -t" is a test to perform a check that the nginx config is proper, whereas "nginx reload" is the command to reload all config, including the new CN.conf file.


And that is all there is to it!

In general, the above steps can be repeated for every country that you want to block entirely.

However, note the following:

- one can alter the [countrycode].conf files to allow for some specific ip ranges: just delete the entry in question and run the command from step 5,
- one can use other CIDR ranges then those from the site iwik.org,
- one can create and use a bash script to automate steps 1 to 5 for each country and/or to update the [countrycode].conf files regularly.


The endresult: you will have a block of bad IPs where you need it the most, at the application level.

Do not forget to use the firewall (read: iptables) or Plesk Firewall extension on all other crucial services and ports, such as SSH and MySQL!!


Hope the above helps a bit....

Kind regards........
 
@OverWolf

4 - run the command: grep -r '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' CN.cidr | sort -n | uniq -c | awk -F' ' '{print "deny "$2";"}' > /etc/nginx/conf.d/CN.conf
.

I checked and that provider does not aggregate the subnets
I would replace that line by this one:

Code:
wget -q -O - http://www.iwik.org/ipcountry/CN.cidr | egrep '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' | aggregate 2>/dev/null | sed 's/.*/deny &;/' > /etc/nginx/conf.d/CN.conf

The essence being the use of "aggregate"
The other differences (sed instead of awk) is merely personal preference.

I noticed the reduction to 4870 lines instead of 8016
 
Last edited:
trialotto and mr-wolf.. Thank you both.

I have two question about your explanation :
a) what about performance if I configure a huge amount of IP (from various country, not only cn) ? Isn't a trouble for nginx to read every times this db? Or if I configure all "good" cidr for firewall isn't also a kill performance ?

b) I would like to check other services; for example I would block some country from using ftp or postfix. So, in this case if I use your solution, I should configure another "good" CIDR and so other performance are gone (ssh, mysql, ftp, postfix, etc). If I configure for every services an IP block/good list my firewall will use every resource.

I have had some trouble with f2b and a brute force attack. I have describe it in this post : Question - Brute force attack has put down dovecot service. That's why I would limit some country effecively without losing performance. A country block is a good thinks but if f2b performance are these, well... :(

So, if I can integrate --seconds 1 --hitcount 10 in iptables and firewall, I think that it's a good thing. Is it ?
 
@OverWolf

With respect to your first question

a) what about performance if I configure a huge amount of IP (from various country, not only cn) ? Isn't a trouble for nginx to read every times this db? Or if I configure all "good" cidr for firewall isn't also a kill performance ?

I must emphasize that in a firewall

- huge lists of individual IPs can often (but not always) be compacted to CIDR ranges,
- huge lists of CIDR ranges is just as bad as huge lists of individual IPs, irrespective of the question whether good or bad IPs are added to the firewall rulesets,

whereas Nginx does not have a real performance penalty on adding huge lists OR changes of those lists: Nginx is flexible and fast, when it concerns config.

WIth respect to your second question

b) I would like to check other services; for example I would block some country from using ftp or postfix. So, in this case if I use your solution, I should configure another "good" CIDR and so other performance are gone (ssh, mysql, ftp, postfix, etc). If I configure for every services an IP block/good list my firewall will use every resource.

I can state the following

- FTP: using passive FTP ports is the most easy option to prevent a lot of attempts to hack ftp services (most hack attempts are not aiming at the passive FTP ports)
- SMTP/Postfix: use blacklists within postfix (read: this is a whole different story, so I will not elaborate on this, but the idea/method is the same as with Nginx)

and that only leaves SSH and MySQL to be configured with Plesk Firewall extension (note that I recommend the extension, as a practical GUI for iptables).

With respect to this stament

I have had some trouble with f2b and a brute force attack. I have describe it in this post : Question - Brute force attack has put down dovecot service. That's why I would limit some country effecively without losing performance. A country block is a good thinks but if f2b performance are these, well...

I can say the following:

- it is not very likely and/or very uncommon that Dovecot is attacked: the attacks are mostly bypassing Dovecot and are directly aiming at Postfix (SMTP)
- it is not very likely that your Dovecot service went down to an attack: just reboot the Dovecot service and you are often fine

but, in general, you can take some security measures in order to decrease attacks on and/or risks associated with Postfix (or SMTP in general):

a) one should be more strict in the jail settings for Fail2Ban: for instance, use postfix related jails with

- a max retry value of 2 (maxretry = 2 )
- a ban period of 3600 (this allows F2B's recidive jail pick up the bad IP that keeps on trying)

AND use an (active and) strict recidive jail with

- maxretry = 2
- a ban period of 86400 (i.e. 24 hours, this in order to prevent that your iptables rulesets are becoming too large in number)

and just monitor the jails and (!) logs in order to fine-tune the jails,

b) use Postfix blacklist, in order to block bad IPs permanently: for instance, permanently block all IPs that are recurring in the recidive jail.

Note that the "action", as mentioned in point b, can be automated with Fail2Ban, just by adding a "second recidive jail" (read: duplicate entries marked as recidive in /var/log/fail2ban.log should be filtered out and blocked permanently) with a custom action (read: adding an action that adds the bad recidive IP to a Postfix blacklist).

In essence, it is not worthwhile to add each individual bad IP to a Postfix blacklist: just automate (with the tools available, such as Fail2Ban).

Hope the above helps a bit.........

Regards......
 
Hi trialotto,

I already use f2b with maxretry and recidive, my question was about that even if I've adopted these two action my Dovecot gone offline for a brute force attack that send over 20 request per second! and f2b failed to manage this situation. That's why I would consider to integrate an hitcount over one or two seconds and I hope that this can mitigate an attack like that.
 
@OverWolf

You can do the following for this one (or more) truly malicious IPs (steps in chronological order):

1) go to "Plesk Panel > Tools & Settings > Firewall (click) > Modify Plesk Firewall Rules (click) > Add custom rule (click)"

2) name the custom rule something like "notorious" or "bad" (or whatever you think is appropriate)

3) select the following

- Match direction: incoming
- Action: deny
- Ports: TCP (leave the remainder blank)
- Sources: add the bad IPs

and press "OK"

4) make sure the rule is on top: use the arrows in order to make your custom rule the first rule in the Plesk Firewall

5) select "Apply Changes" and follow the remainder of the procedure

and that is all.


This way, the really bad IPs are blocked on all ports, including the mail related ports.

It is just one line and it makes it more easy to control your firewall, as opposed to altering both the IMAP and POP3 rules in the firewall.


Moreover, this one custom rule prevents that you have to implement all kinds of settings for Dovecot, which can also impact connections from good IPs.

For instance, when setting a limit on the number of requests or connections per interval of time, one will create the risk that specific mail clients are also hindered.

Take the mail client Mozilla Thunderbird, which can be a nasty bugger that can make a huge number of connections in a short time interval.

Any throttling or limiting of connections would be risky in the sense that one can block genuine connections, which would not be desirable.


The goal was essentially to block a very bad IP, so introducting a custom rule to the Firewall would be a better idea than changing config on Dovecot, since that change in configuration would affect ALL types of connections, originating from both good as bad IPs.

In short, what you want to achieve is best described by the before mentioned goal and a corresponding alteration of the Firewall.


Hope the above helps a bit.

Regards.............
 
I checked and that provider does not aggregate the subnets
I would replace that line by this one:

Code:
wget -q -O - http://www.iwik.org/ipcountry/CN.cidr | egrep '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' | aggregate 2>/dev/null | sed 's/.*/deny &;/' > /etc/nginx/conf.d/CN.conf

The essence being the use of "aggregate"
The other differences (sed instead of awk) is merely personal preference.

I noticed the reduction to 4870 lines instead of 8016
-----------------------------
The above does not work. Produces a 0 byte file.
 
-----------------------------
The above does not work. Produces a 0 byte file.
I thought there was an error in it, but that wasn't true...

Code:
wget -q -O - http://www.iwik.org/ipcountry/CN.cidr | egrep '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' | aggregate 2>/dev/null | sed 's/.*/deny &;/' > /etc/nginx/conf.d/CN.conf

head /etc/nginx/conf.d/CN.conf
deny 1.0.1.0/24;
deny 1.0.2.0/23;
deny 1.0.8.0/21;
deny 1.0.32.0/19;
deny 1.1.0.0/24;
deny 1.1.2.0/23;
deny 1.1.4.0/22;
deny 1.1.8.0/21;
deny 1.1.16.0/20;
deny 1.1.32.0/19;

Do you have aggregate installed?

Code:
sudo apt-get install aggregate || sudo yum install aggregate
 
Last edited:
I thought there was an error in it, but that wasn't true...

Code:
wget -q -O - http://www.iwik.org/ipcountry/CN.cidr | egrep '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' | aggregate 2>/dev/null | sed 's/.*/deny &;/' > /etc/nginx/conf.d/CN.conf

head /etc/nginx/conf.d/CN.conf
deny 1.0.1.0/24;
deny 1.0.2.0/23;
deny 1.0.8.0/21;
deny 1.0.32.0/19;
deny 1.1.0.0/24;
deny 1.1.2.0/23;
deny 1.1.4.0/22;
deny 1.1.8.0/21;
deny 1.1.16.0/20;
deny 1.1.32.0/19;

Do you have aggregate installed?

Code:
sudo apt-get install aggregate || sudo yum install aggregate

Nope. That would answer it, but I don't see a package for aggregate with yum (centos 7)

OK, (editing), cuz I didn't have epel-release loaded. I'll try it after installing aggregate. Thanks.
 
Last edited:
Nope. That would answer it, but I don't see a package for aggregate with yum (centos 7)

OK, (editing), cuz I didn't have epel-release loaded. I'll try it after installing aggregate. Thanks.
I prefer Debian or Ubuntu...
The package can also be easily installed from source...
 
Back
Top