• We value your experience with Plesk during 2024
    Plesk strives to perform even better in 2025. To help us improve further, please answer a few questions about your experience with Plesk Obsidian 2024.
    Please take this short survey:

    https://pt-research.typeform.com/to/AmZvSXkx
  • 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 How to block a country

Martin73

Basic Pleskian
I run a virtual server and register more and more attacks from Asia. Especially from China and via a provider called DigitalOcean.

What is the easiest way to block an entire country in Plesk? With htaccess I can only block access to a single website. And the file has to be read every time a page is accessed. I think it's also not a good idea to block thousands of IP addresses via the Apache & nginx settings. Or is it? How can I block a country for the whole server?

Thank you
Martin

Ubuntu 18.04.3 LTS‬
Plesk Onyx 17.8.11
 
Hello, @Martin73
You can use one of this methods (or all of them) to improve your server protection

Enable fail2ban in Tools & Settings > IP Address Banning
It will automatically ban suspicious IPs by system firewall rules

Try to enable Tools & Settings > Web Application Firewall (ModSecurity)
It will automatically detect hack attempts by web server and block this requests

Install and use Advisor extension to get recommendations about improving server security
Advisor - Plesk Extensions

Use CloudFlare extension which proxy requests to your site and block bad requests from robots
ServerShield by Cloudflare - Plesk Extensions!
 
Fail2Ban and ModSecurity is already enabled. The Advisor is also active. Blocking countries should only be an additional security.
 
Plesk itself does not have this functionality. When needed, we use geolocation based IP blocking on the web server level.

There are modules available for both Apache and Nginx that work with the Maxmind geolocation databases, free or paid.
 
Plesk itself does not have this functionality. When needed, we use geolocation based IP blocking on the web server level.

There are modules available for both Apache and Nginx that work with the Maxmind geolocation databases, free or paid.
Hi Ales,

May I ask, if you can recommend such server tools?

Activation guidance?

And, can they work at the same time the Plesk FW works?
 
Hi,

This could have been done with IPTables, however if used, this prevents Plesk Fire Wall from working...

You may have a look at this solution:
And, how to add a cron:
Also, read this:

************************************************************************************
I chose not to use it, as I needed the Plesk Fire Wall in place. My documentation includes the following:
Download script

Edited file to place countries according to ther codes

Also changed FIREWALLD=0 (16-07-2020) # Use firewalld instead [0/1]
This may allow Fail2Ban or FireWall control
Edited country list according to codes on:
Uploaded file via Plesk
Renames to remove extension *.txt suffix
moved the file to the daily cron directory.
mv /var/www/vhosts/currenge.com/httpdocs/wp-content/uploads/whitelists_upload/ipset-country /etc/cron.daily/ipset-country
Had to save the cron job in a special manner, so it became activated:
cron job activated with saving command:
chmod +x /etc/cron.daily/ipset-country


PROBLEM
Testing for blocked countries shows access. Test via site:
Geo Browse | Free Country Screenshot Tool

ls –la /etc/cron.daily
cp /etc/cron.daily/ipset-country /etc/cron.hourly/ipset-country

chmod +x /etc/cron.daily/ipset-country

chmod +x /etc/cron.hourly/ipset-country

ls –la /etc/cron.daily

/etc/cron.hourly/ipset-country
ipset-country: done

Going to use iptables and not only relay on ufw (unubtu firewall which may not be activated, once Plesk FW is in-place.

/etc/cron.hourly/ipset-country:
UFW is not supported, disable it first (or set UFW=1)
run-parts: /etc/cron.hourly/ipset-country exited with return code 1


**********************************************************************************************


Alternative to block only one country, lets say I r an

Create a list of CIDR IP of that country, from:

For I ran it is:

I attached the lists I created at the time, for that country in a PDF file

Those rules are run as CLI on server SSH
Opening TWO SSH ports at the same time
After adding the rules on one port
you run activation on that port
and within 60 seconds run confirm on the second port
those commands are at the bottom of the PDF file.

**********************************************************************************************


I also recommend:
Use two fixed IPs (mobile+PC) that only them would be allowed access to login page and some ports as SSH 22 and Plesk 8443/7
moving all traffic for host according to IP (and not host name) to be moved to main example.com LOG on Plesk, so you can monitor it
And activate lots of .htaccess rules which protect the host server

Lots of rules are on:

Remember to white list your fixed IP and server IP and Plesk IPs on the rules
For example:
RewriteCond %{REMOTE_ADDR} !^555\.555\.555\.555$
Allow from 555.555.555.555


**********************************************************************************************

And Ninja Fire Wall is a great tool too. You should white list your fixed IP according to guidance
 

Attachments

  • block i ran.pdf
    94.1 KB · Views: 3
I found a possibly another way, which seems VERY interesting.
It involved PHP short code, which tests IP as part of the top of PHP regular files, against list generated for IPs covering all IPs in country (CIDR).

See this:

In the file check_banned.php

<?php
$ip = strip_tags(trim($_SERVER["REMOTE_ADDR"]));

// Read file with list of banned ips
$file = ban_list.txt;
$myfile = fopen($file, "r") or die("Unable to open file!");
$ban_list = fread($myfile, filesize($file));
fclose($myfile);

// Check if ip is in ban list
$pos = strpos($ban_list, $ip);

if($pos === false) $ip_found = false;
else $ip_found = true;

if($ip_found){
header('HTTP/1.0 403 Forbidden');

// here is the important change
die("script terminated because IP is in ban list");
}
else {
// if IP not banned, do nothing.



}

?>


**************************************************************************************
Then, at the top of every PHP script you wish to protect, you could simply do this at the very top:

<?php
include_once("check_banned.php");
?>


And list could be generated here:
 
I found a possibly another way, which seems VERY interesting.
It involved PHP short code, which tests IP as part of the top of PHP regular files, against list generated for IPs covering all IPs in country (CIDR).

See this:

In the file check_banned.php

<?php
$ip = strip_tags(trim($_SERVER["REMOTE_ADDR"]));

// Read file with list of banned ips
$file = ban_list.txt;
$myfile = fopen($file, "r") or die("Unable to open file!");
$ban_list = fread($myfile, filesize($file));
fclose($myfile);

// Check if ip is in ban list
$pos = strpos($ban_list, $ip);

if($pos === false) $ip_found = false;
else $ip_found = true;

if($ip_found){
header('HTTP/1.0 403 Forbidden');

// here is the important change
die("script terminated because IP is in ban list");
}
else {
// if IP not banned, do nothing.



}

?>


**************************************************************************************
Then, at the top of every PHP script you wish to protect, you could simply do this at the very top:

<?php
include_once("check_banned.php");
?>


And list could be generated here:
Not really the most ideal. You're adding a significant overhead by using PHP instead of Apache to process these rules. It may not be pretty, but I'd guess dropping a bunch of denys into ,htaccess will be signficantly faster.
 
.htaccess crashes from adding about 50,000 lines, each one bei g a CIDR IP range, i.e. 5.5.5.5/16...

A country may easily have a 50,000 CIDR IP ranges..
 
Just a quick note that if you don't want to roll your own solution that our Juggernaut Firewall product supports blocking countries at the server and domain level. Country blocks at the server level use ipset so they are very efficient while domain level blocking uses the mod_maxminddb apache module:


If you want to do this using PHP then you should still use the mod_maxmind module as the geolocation data will be available to PHP in the the $_SERVER vars.
 
Just a quick note that if you don't want to roll your own solution that our Juggernaut Firewall product supports blocking countries at the server and domain level. Country blocks at the server level use ipset so they are very efficient while domain level blocking uses the mod_maxminddb apache module:


If you want to do this using PHP then you should still use the mod_maxmind module as the geolocation data will be available to PHP in the the $_SERVER vars.

Seemingly Danami (juggernaut) canceled a license I purchased around the day I purchased it, to my understanding, not wanting to support of such kind of "complicated" Fire-Wall activity requested by me.
 

Attachments

  • Juggernaut anwer.png
    Juggernaut anwer.png
    192.2 KB · Views: 15
Seemingly Danami (juggernaut) canceled a license I purchased around the day I purchased it, to my understanding, not wanting to support of such kind of "complicated" Fire-Wall activity requested by me.
We only refund money in the extreme case where it looks like it would be impossible to make the end customer happy. In that case your money was refunded completlely (we ate the payment processing fees).
 
Such feature may be achieved using ModSecurity GeoIP module on Plesk.

Below is a full guidance:



ModSecurity Blocking Countries Guidance



1) Download the Geo2ip lite database:

# curl -Lo /usr/share/GeoIP/GeoLiteCountry.dat.gz https://dl.miyuru.lk/geoip/dbip/country/dbip4.dat.gz

Or download some other DB files from:


Or, a paid one from Maxmind.


Note: 1) The IP Data Base file should be updated once in a month (/a while) as IPs are transferred between ISPs in various countries. The Maxmind file updates about once a month.
Note: 2) The Maxmind file FORMAT is expected to be change on May 2022. If not updating to a newer ModSecurity suitable module, the near future (from May 2022) Maxmind file should be converted to the legacy used file format. On December 2021, it downloads as file.dat.gz, so note the two file formats in the file name, before its uncompressed.


2) uncompress the file (Converted the zip *.gz file to a *.dat file):

# gunzip /usr/share/GeoIP/GeoLiteCountry.dat.gz

3) Uploaded the COUNTRY file to:

# /usr/share/GeoIP/GeoLiteCountry.dat

4) Enable GeoIP in a file according to which ModSecurity Rule set is used:

For OWASP:
# vi /etc/apache2/modsecurity.d/rules/owasp_modsecurity_crs_3-plesk/10-crs-setup.conf

un-commented the following line:
SecGeoLookupDB /usr/share/GeoIP/GeoLiteCountry.dat

5) Manually Create a ModSecurity rule

Using OWASP:
# touch /etc/apache2/modsecurity.d/rules/owasp_modsecurity_crs_3-plesk/country_block.conf
Using COMODO:
# touch /etc/apache2/modsecurity.d/rules/comodo_free/country_block.conf


Place the rule in the just created file:

SecRule REMOTE_ADDR "@geoLookup" "phase:1,chain,id:99999932392,drop,log,msg:'Blocking %{geo.country_code}'"

SecRule GEO:COUNTRY_CODE "@pm XX XX XX"


Note: "XX" are to be replaced with the actual country codes.
Also rule id (in the above example - "99999932392") should be unique, otherwise, the apache2 service wouldn't



Country two charts ISO code list is available here:

ISO 3166-1 alpha-2 - Wikipedia


You may copy country code already set in one line, from the below example, blocking all countries, but not USA, Canada, Russia, most Western European countries, and Israel.



SecRule REMOTE_ADDR "@geoLookup" "phase:1,chain,id:99999932392,drop,log,msg:'Blocking %{geo.country_code}'"

SecRule GEO:COUNTRY_CODE " @pm AF AG AI AL AM AO AQ AR AS AW AX AZ BA BB BD BF BG BH BI BJ BL BM BN BO BQ BR BS BT BV BW BY BZ CC CD CF CG CI CK CL CM CN CO CR CU CV CW CX CZ DJ DM DO DZ EC EE EG EH ER ET FJ FK FM FO GA GD GE GF GG GH GI GL GM GN GP GQ GS GT GU GW GY HK HM HN HR HT HU ID IE IM IN IO IQ IR JE JM JO KE KG KH KI KM KN KP KR KW KY KZ LA LB LC LK LR LS LY MA MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NP NR NU OM PA PE PF PG PH PK PL PM PN PR PS PT PW PY QA RE RO RS RW SA SB SC SD SG SH SI SJ SK SL SN SO SR SS ST SV SX SY SZ TC TD TF TG TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM UY UZ VA VC VE VG VI VN VU WF WS XK YE YT ZA ZM ZW"


6) Test server configuration and fix before restart if needed:

# apachectl configtest

7) Restart the server, to make sure the new configuration takes place:

# systemctl restart apache2

8) Test the blocking happens.

You may use mobile phone Opera browser that has a built-in VPN, allowing to choose Asia/Europe/America as a location.

Choose Asia, which in my case used Singapore IP. Set Opera to also include VPN for search results.
Then, check on the mobile Opera is set for Asia, on Google:

“What is my IP?”

And copy the IP to check it’s indeed in Asia, on a service as (replace the 8.8.8.8 IP with the one you got):



Now, access your website. You may get on the browser client a ‘502’ error on the browser. Log file will look something like:



2021-mm-dd 12:51:40Error77.111.245.12403GET / HTTP/1.0 5.00 KApache SSL/TLS access
2021-mm-dd 12:51:40Error77.111.245.12 [client 77.111.245.12] ModSecurity: Access denied with connection close (phase 1). Matched phrase "SG" at GEO:COUNTRY_CODE. [file "/etc/apache2/modsecurity.d/rules/comodo_free/country_block.conf"] [line "1"] [id "99999932392"] [msg "Blocking SG"] [hostname "currenge.com"] [uri "/"] [unique_id "Ya88vB9V-Qu@vxwlDnpcQwAAAAA"] Apache error
2021-mm-dd 12:51:40Error77.111.245.12 62778#0: *180 upstream prematurely closed connection while reading response header from upstream nginx error


** See more recommendations in the attached PDF file **
 

Attachments

  • ModSecurity Blocking Countries Guidance.pdf
    149.2 KB · Views: 6
Step $4 for Comodo rule set:

4) Enable GeoIP in a file according to which ModSecurity Rule set is used:

For OWASP:
# vi /etc/apache2/modsecurity.d/rules/owasp_modsecurity_crs_3-plesk/10-crs-setup.conf

un-commented the following line:
SecGeoLookupDB /usr/share/GeoIP/GeoLiteCountry.dat


For COMODO:
# vi /etc/apache2/modsecurity.d/rules/comodo_free/00_Init_Initialization.conf

Add the below line at the end of the file:
SecGeoLookupDB /usr/share/GeoIP/GeoLiteCountry.dat
 
To the best of my knowledge, nowadays, Human still do NOT use IPv6. IPv6 is BLOCKED on my server on the AWS level.



Updating CRS (i.e., COMODO) which is done a daily basis, moves the *.conf files to a backup and creates a NEW one, thus the Plesk GUI Custom directives should be used.

This is seen afterwards on the file:

/etc/apache2/plesk.conf.d/modsecurity.conf


SecDefaultAction \
"phase:1,deny,status:403,log,auditlog"
SecDefaultAction \
"phase:2,deny,status:403,log,auditlog"

SecGeoLookupDB /usr/share/GeoIP/GeoLiteCity.dat

SecRule REMOTE_ADDR "@geoLookup" "phase:1,chain,id:99999932392,drop,log,msg:'Blocking %{geo.country_name} (%{geo.country_code})',logdata:'{country_code=%{geo.country_code}, country_code3=%{geo.country_code3}, country_name=%{geo.country_name}, country_continent=%{geo.country_continent}, city=%{geo.city}}'"
SecRule GEO:COUNTRY_CODE "@pm AF AG AI AL AM AO AQ AR AS AW AX AZ BA BB BD BF BG BH BI BJ BL BM BN BO BQ BR BS BT BV BW BY BZ CC CD CF CG CI CK CL CM CN CO CR CU CV CW CX CZ DJ DM DO DZ EC EE EG EH ER ET FJ FK FM FO GA GD GE GF GG GH GI GL GM GN GP GQ GS GT GU GW GY HK HM HN HR HT HU ID IM IN IO IQ IR JE JM JO KE KG KH KI KM KN KP KR KW KY KZ LA LB LC LK LR LS LY MA MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NP NR NU OM PA PE PF PG PH PK PL PM PN PR PS PT PW PY QA RE RO RS RU RW SA SB SC SD SG SH SI SJ SK SL SN SO SR SS ST SV SX SY SZ TC TD TF TG TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM UY UZ VA VC VE VG VI VN VU WF WS XK YE YT ZA ZM ZW"



If you do NOT update CRS, you may use the guidance placed above. I recommend you read it all, as there are some important action recommendations in it.
 
Back
Top