Tutorial: Block requests by country

Foremost I translated this topic myself from: Tuto: Bloquer les requêtes selon le pays Just for convenience. So all credits go’s to there! These are only the basics!

Good morning,

Tutorial update on 10/17/21

  1. Create the following hook:
    /etc/yunohost/hooks.d/conf_regen/18-nginx_geoip
#!/bin/bash

# if not present, add package geoip-database with apt install geoip-database

##############################################
#Beware, i'm not sure this command is universal. You must test it before. If not, you can find the result with the command ip route, this one must be like 192.168.0.0/24 or similar. Then replace the variable $network_address with it.
#Attention, je ne suis pas certain que cette commande est universelle. Vous devez la tester au préalable. Si ce n'est pas le cas, vous pouvez trouver la réponse avec la commande ip route, celle-ci doit être de la forme 192.168.0.0/24 ou similaire. Remplacez alors la variable $network_address par celle-ci.
network_address=$(awk '{print $1}' <(grep src <(ip route)))
################################################
action=$1
pending_dir=$4
nginx_dir=$pending_dir/../nginx/etc/nginx
nginx_security_conf=$nginx_dir/conf.d/security.conf.inc
nginx_country_conf=$nginx_dir/conf.d/country.conf

[[ $action == "pre" ]] || exit 0
[[ -d $nginx_dir ]] || exit 0
[[ -e $nginx_security_conf ]] || exit 0

echo "# GeoIP databases
geoip_country /usr/share/GeoIP/GeoIP.dat;

map \$geoip_country_code \$allowed_country {
  default no;
  # France
  FR yes;
  # Italie
  #IT yes;
}

geo \$lan-ip {
  default no;
  $network_address yes;
}" > $nginx_country_conf

echo '

# allow local ip
if ($lan-ip = yes) {
  set $allowed_country yes;
}
# block the country
if ($allowed_country = no) {
  return 444;
}' >> $nginx_security_conf

##############################################################

  1. Create the GeoIp database update script /etc/cron.weekly/Geoipupdate :
#!/bin/bash

maj_geoip () {
    cd /usr/share/GeoIP
    wget https://mailfud.org/geoip-legacy/GeoIP.dat.gz
    gunzip -f GeoIP.dat.gz
    wget https://mailfud.org/geoip-legacy/GeoIPv6.dat.gz
    gunzip -f GeoIPv6.dat.gz
}

last=/usr/local/etc/last
update=$(sed -n 's,.*<b>\(.*\)</b>,\1,p' <(curl -s https://mailfud.org/geoip-legacy/ | grep 'Latest update'))
[[ "$(<$last)" != "$update" ]] && (echo "$update" > "$last";maj_geoip)
exit 0

Give the right in execution to the script:

sudo chmod 500 /etc/cron.weekly/Geoipupdate

Regenerate the configuration of Nginx in Yunohost:

yunohost tools regen-conf nginx --force

That’s it, it’s over.

To authorize a country, simply add it to the hook. To remove one, either pass the value yes to no, or comment on the line with a sharp. Do not forget to regenerate Yunohost’s conf nginx with regen-conf so that it is taken into account.


Important: What is below is partially obsolete, I left it for info and not to “break” the discussion thread. We must now follow what is above.

Depending on your use of Yunohost, it is not necessarily necessary to leave access from anywhere. For example, for personal use of Nextcloud, access is sufficient only from France for example and sometimes from abroad when traveling. In this case, it is possible to prohibit access from abroad with the Ip geolocation lists available here 8 and in case of travel abroad, activate access from the country concerned quickly with its iso code available on this page 4

For more info about this jump to the original topic.

2 Likes

ALSO, @admins, maybe a settings pane for this? Due to things in the world right now!

1 Like

@someonsusername
If I add multiple countries like this:

# France
FR yes;
CH yes;
DE yes;

NGINX crashes upon reboot. The displayed error when restarting nginx is as following:

nginx[2303]: nginx: [emerg] invalid number of the geo parameters in /etc/nginx/conf.d/country.conf:14

Line 14 is the line with the closing bracket “}”

For anyone who comes in the future looking to do this; there are some typos in the original script at /etc/yunohost/hooks.d/conf_regen/18-nginx_geoip

Here’s one that works:

#!/bin/bash
################################################
# if not present, add package geoip-database with apt install geoip-database
################################################

network_addresses=$(ip route | grep src | awk '{print $1}')
action=$1
pending_dir=$4
nginx_dir=$pending_dir/../nginx/etc/nginx
nginx_security_conf=$nginx_dir/conf.d/security.conf.inc
nginx_country_conf=$nginx_dir/conf.d/country.conf

[[ $action == "pre" ]] || exit 0
[[ -d $nginx_dir ]] || exit 0
[[ -e $nginx_security_conf ]] || exit 0

# Start of the configuration file
echo "# GeoIP databases
geoip_country /usr/share/GeoIP/GeoIP.dat;

map \$geoip_country_code \$allowed_country {
  default no;
  JP yes; # Japan
  US yes; # United States
  CA yes; # Canada
  MX yes; # Mexico ETC
}" > $nginx_country_conf

# Corrected geo block:
echo -n "
geo \$lan-ip {
    default no;" >> $nginx_country_conf

# Add each network address on its own line
while IFS= read -r address; do
    echo "    $address yes;" >> $nginx_country_conf
done <<< "$network_addresses"

# Add localhost
echo "    127.0.0.1 yes;
}" >> $nginx_country_conf

# Rest of the security configuration
echo '

# allow local ip
if ($lan-ip = yes) {
    set $allowed_country yes;
}
# block the country
if ($allowed_country = no) {
    return 444;
}' >> $nginx_security_conf

##############################################################
  1. Then chmod +x /etc/yunohost/hooks.d/conf_regen/18-nginx_geoip

Then follow the rest of the original instructions:
3. Create the GeoIp database update script in /etc/cron.weekly/Geoipupdate
4. chmod that too

sudo chmod 500 /etc/cron.weekly/Geoipupdate
  1. Regenerate the configuration of Nginx in Yunohost:
yunohost tools regen-conf nginx --force

Did you install it?

Hello,

Are you talking about the original script on the first post of this topic or the original script from the french topic? Because the latest version is dated 07/14/22 and here it is an old version dated 10/17/21.

Something to the clean thing would have been welcome, because there, it’s a bit of a clutter now.

So, if I understand correctly … is this script that works without problem?
Have you tried it and therefore, no problem?

I’m talking about the DeepL script posted here by @someonesusername, which does not work because nginx does not accept multiline link this:

# France
FR yes;
# Italie

@JfmbLinux : It works! I tested it by creating the ngnix script by allowing north america and EU countries but excluding japan, then regenerating the config. I then got on proton VPN as a japanese IP and could not access. I then switched to Germany via the VPN and I could access just fine. THen I went back, added Japan ,regenerated, and activated VPN to Japan again and I could access just fine :slight_smile:

1 Like

Can’t you access the Yunohost Admin interface, Yunohost portal … Apps installed and visible by anonymous visitors?
I think I’m going to get started too, fed up with attempts (postfix …).

I am curious to see a screenshot of the refusal, to see what it gives :wink:

I don’t understand, i use my script with multiline and it works without problems. Why Nginx wouldn’t accept multilines?

I recommend using the script from french topic because it has changed and support now server with ipv4 only or ipv4+ipv6 or ipv6 only. It creates now the cron job without do it separately.

Beware, the hook only block nginx requests. If you want to block on other services like postfix, that’s not what you should use. I invite you to read french topic, alternatives are mentioned. And you can read why i’m not in favour of geo-blocking for postfix.

1 Like

This may be helpful GitHub - friendly-bits/geoip-shell: User-friendly and powerful geoblocker for Linux
I still didn’t test it but looks nice

I would like to find a way to block these attempts (postfix),
It comes from Russia, China, Bulgaria, even Seychelles, Brazil …

There are some who tried to have fun tonight and this morning … :thinking:

List of IPS

[Fail2Ban] dovecot: banned 2001:470:1:c84::30
[Fail2Ban] postfix: banned 193.32.162.83
[Fail2Ban] postfix: banned 193.32.162.66
[Fail2Ban] postfix: banned 193.32.162.97
[Fail2Ban] postfix: banned 193.32.162.81
[Fail2Ban] postfix: banned 193.32.162.73
[Fail2Ban] postfix: banned 92.118.39.63
[Fail2Ban] postfix: banned 92.118.39.65
[Fail2Ban] postfix: banned 92.118.39.66
[Fail2Ban] postfix: banned 92.118.39.61
[Fail2Ban] postfix: banned 92.118.39.64
[Fail2Ban] dovecot: banned 199.45.154.157

And that is only a small list …

as soon as your server is exposed on the (evil) internet, you can’t prevent spammers from taking an interest in it.
It is not because your server has F2B Postfix bans that it is not secure.
You can add F2B rules, use geo-blocking via iptables, portentry,etc… I use a few additional filters (postfix-auth, postfix-sasl,etc…) but don’t forget to whitelist yunohost diagnostic IP if you add F2B rules. And don’t forget that you can receive mails from foreign countries if you use geoblocking.

I know, there will always be these attempts, I did the necessary for the secure and I even pushed security a little further.

The script tells you what it shows, it returns a 444 page (ie nothing). When I’m at an IP that is blocked I can’t access anything, no apps and no admin.

1 Like

My modern French is not good enough to follow the conversation there so I don’t know which script you refer to.

When I used your script with the multiline and then regenerated I kept getting an nginx error. I poked around and multiple random threads on the Internet pointed at multiline issues that I tried it without that, as well as some other tweaks and that’s what I get and it works. Im not a programmer or a security person so I’d tak any advice.