Skip to content

[feature] Geolocation Blocking #730

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Revan335 opened this issue Mar 31, 2024 · 21 comments
Open

[feature] Geolocation Blocking #730

Revan335 opened this issue Mar 31, 2024 · 21 comments
Assignees

Comments

@Revan335
Copy link

Hello,

how can I use Geolocation Blocking?
For example only from Germany, USA, Austria ... can I access to the Docker Container ... and Access/Connections from others are blocked.

This can increase the Security and lower Risk of Hacking ...

NPM don't have this Feature.
Have SWAG this? I don't know.

Can you add this?

Many Thanks!

Greetings

Revan335

@Zoey2936
Copy link
Member

Hello, I will add this with the PHP rewrite (see #731). But until then: You can mount geo databases into the NPMplus container and configure geoblocking in the advanced tab. (The nginx geoip module and the maxmind module are compiles into NPMplus)

@Zoey2936 Zoey2936 self-assigned this Mar 31, 2024
@viriatusX
Copy link

Hello, I will add this with the PHP rewrite (see #731). But until then: You can mount geo databases into the NPMplus container and configure geoblocking in the advanced tab. (The nginx geoip module and the maxmind module are compiles into NPMplus)

How i can configure in Advanced tab?
I have already mapped the Geo2Ip DBs in /data/geo2ip.

What line do I have to put? Thanks

@Zoey2936
Copy link
Member

Zoey2936 commented May 1, 2024

@Matthias-vdE
Copy link

Matthias-vdE commented Aug 8, 2024

@Revan335 Did you manage to get this up and running? I've been reading through the document but can't seem to figure out the exact config I need to put in the Advance tab to explicitly allow/block certain countries.

From my understanding, it should be as simple as adding

geoip2 /data/etc/goaccess/geoip/GeoLite2-Country.mmdb {
    auto_reload 60m;
    $geoip2_data_country_code default=ZZ country iso_code;
}

if ($geoip2_data_country_code != "BE") {
    return 403;
}

Or alternatively:

geoip2 /data/etc/goaccess/geoip/GeoLite2-Country.mmdb {
    auto_reload 60m;
    $geoip2_data_country_code default=ZZ country iso_code;
}

map $geoip2_data_country_code $allowed_country {
    default no;
    BE yes;
}

if ($allowed_country = no) {
    return 444;
}

To the advanced tab, but that makes the host go Offline.

@Zoey2936
Copy link
Member

Zoey2936 commented Aug 8, 2024

what is written in your log?

@Matthias-vdE
Copy link

Matthias-vdE commented Aug 8, 2024

The docker logs say this when I apply the Advanced Configuration

[Nginx    ] › ⬤  debug     Deleting file: /data/nginx/proxy_host/10.conf
[Nginx    ] › ⬤  debug     Deleting file: /data/nginx/proxy_host/10.conf
[Nginx    ] › ⬤  debug     Could not delete file: {
  "errno": -2,
  "code": "ENOENT",
  "syscall": "unlink",
  "path": "/data/nginx/proxy_host/10.conf"
}
[Nginx    ] › ⬤  debug     Deleting file: /data/nginx/proxy_host/10.conf.err
[Nginx    ] › ⬤  debug     Could not delete file: {
  "errno": -2,
  "code": "ENOENT",
  "syscall": "unlink",
  "path": "/data/nginx/proxy_host/10.conf.err"
}
[Nginx    ] › ℹ  info      Reloading Nginx
2024/08/08 21:21:30 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:21:30 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:21:30 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:21:30 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:21:30 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:21:30 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:21:30 [warn] 1023#1023: deleting socket /run/nginx-10.sock

Then the host is marked "Offline" in the UI.

When I remove the configuration again:

[Nginx    ] › ⬤  debug     Deleting file: /data/nginx/proxy_host/10.conf
[Nginx    ] › ⬤  debug     Could not delete file: {
  "errno": -2,
  "code": "ENOENT",
  "syscall": "unlink",
  "path": "/data/nginx/proxy_host/10.conf"
}
[Nginx    ] › ℹ  info      Reloading Nginx
2024/08/08 21:23:41 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:23:41 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:23:41 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:23:41 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:23:41 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"
2024/08/08 21:23:41 [warn] 1023#1023: "ssl_stapling" ignored, issuer certificate not found for certificate "/data/tls/dummycert.pem"

And the status goes back to Online. This is the same for every host.

The container is running as root and does have rights to create/delete files:

-------------------------------------
 _ _  ___  __ __       _
| \ || . \|  \  \ ___ | | _ _  ___
|   ||  _/|     || . \| || | |[_-[
|_\_||_|  |_|_|_||  _/|_| \__|/__/
                 |_|
-------------------------------------
Version:  2.11.3+dbb0883
Date:     Thu Aug  8 17:57:28 CEST 2024
User:     root
PUID:     0
User ID:  0
PGID:     0
Group ID: 0
-------------------------------------

@Zoey2936
Copy link
Member

Zoey2936 commented Aug 8, 2024

I think you need to put geoip2 and map into the cusatom/http_root file

@Matthias-vdE
Copy link

Matthias-vdE commented Aug 8, 2024

I think you need to put geoip2 and map into the cusatom/http_root file

I think that was it! Placing the following in the custom/http_top.conf file:


geoip2 /data/etc/goaccess/geoip/GeoLite2-Country.mmdb {
    auto_reload 60m;
    $geoip2_data_country_code default=ZZ country iso_code;
}

map $geoip2_data_country_code $allowed_country {
    default no;
    BE yes;
}

And then placing the if statement in the Advanced Configuration. Or even better, in the server_proxy.conf file so it applies automatically to all hosts:

if ($allowed_country = no) {
    return 444;
}

Seems to have done the trick... I am now seeing HTTP 444 in the access log after starting a VPN to Germany or France:

[08/Aug/2024:21:33:16 +0200] HOSTNAME PROXYIP 0.000 "GET / HTTP/2.0" 444 0 0

Many thanks!

@Bricou13
Copy link

@Zoey2936

First of all, a huge thank you for the work done around Nginx Proxy Manager Plus which I have just discovered, and of which I was using the original NPM which does not evolve too much.

@Matthias-vdE

Did you manage to get it to work? I've looked through the docs and discussions, but I can't seem to get it to explicitly allow/block certain countries.
I placed the following in the custom/http_top.conf file like you said :

charset utf-8;
geoip2 /opt/npmplus/goaccess/geoip/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_data_country_code default=ZZ country iso_code;
}

geo $allowed_ip {
default no; # It is prohibited by default
172.31.4.0/19 yes; # We allow the local network
}

map $geoip2_data_country_code $allowed_country {
default $allowed_ip;
FR yes; # We allow the French IP
}

And then placing the if statement in the Advanced Configuration like you said, Or even better, in the server_proxy.conf file so it applies automatically to all hosts:

if ($allowed_country = no) {
return 444;
}

But when I do this, and I restart the docker all the sites are no longer accessible even in France, which is not the aim of the game.

Could you please provide the configuration you are using or someone else can answer me so that I can implement this module which is an interesting component of NPMPlus

Thanking you all in advance.

@Matthias-vdE
Copy link

Matthias-vdE commented Mar 20, 2025

@Bricou13

Yup, still works for me. For reference, this is my full /opt/npm/custom_nginx/http_top.conf file:

geoip2 /data/goaccess/geoip/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_data_country_code default=ZZ country iso_code;
}

map $geoip2_data_country_code $allowed_country {
default no;
BE yes;
}

geo $lan-ip {
default no;
192.168.0.0/16 yes;
172.16.0.0/12 yes;
10.0.0.0/8 yes;
}

map $http_upgrade $connection_upgrade_keepalive {
default upgrade;
'' '';
}

And in my Advanced Config for any host:

if ($lan-ip = yes) {
    set $allowed_country yes;
}

if ($allowed_country = no) {
    return 403;
}

So I set the "allowed country" variable to yes if we're coming in via a LAN IP address since geo-IP obviously won't work then.

@Bricou13
Copy link

@Matthias-vdE

My sincere gratitude for your prompt response. I just implemented it, and now everything is working perfectly, adding yet another layer of security to this magnificent NPMPlus project. I still need to finish integrating Open-Appsec.
Indeed, given your configuration, I was missing certain lines that allowed this module to function properly.
Thank you again to you and to the entire community for their valuable help and information.
Sincerely,

@metaathron
Copy link

Hi. It seems, that 2025-03-20 update broke this function.
Since then I get this error:
nginx: [emerg] unknown directive "geoip2" in /data/custom_nginx/http_top.conf

http_top.conf contains
geoip2 /opt/npmplus/goaccess/geoip/GeoLite2-Country.mmdb { $geoip2_data_country_code country iso_code; $geoip2_data_country_name country names en; }

I have checked, that the GeoLite2-Country.mmdb exists.

@Zoey2936
Copy link
Member

You need load the module via env, as written in the changelogs

@metaathron
Copy link

Thank you, Zoey. I have completely missed that information. First thing I did, was reading the changelog, but I was probably blind.

@ElegosAkla
Copy link

ElegosAkla commented Mar 28, 2025

I might be mistaken, but in the advanced configuration of the host, shouldn't we also include the following to allow Let's Encrypt to renew certificates?

##### Geo blocking
    if ($lan-ip = yes) {
        set $allowed_country yes;
    }
##### Exception for Let's Encrypt (ACME challenge)
    if ($uri ~* ^/.well-known/acme-challenge/) {
       set $allowed_country yes;
    }
    if ($allowed_country = no ) {
        return 403;
    }

@Zoey2936
Copy link
Member

you can test it with the built-in reachability test

@Mr-Neutron
Copy link

Mr-Neutron commented Apr 1, 2025

I'm following this discussion with great interest, as I'm desperately trying to get geoblocking in npmplus to work. I have a question: I've loaded all the necessary envs for geoIP in compose.yaml, but I still get the following error when loading GeoLite2-Country.mmdb in http_top.conf:

"log":"nginx: [emerg] MMDB_open("/opt/npmplus/goaccess/geoip/GeoLite2-Country.mmdb") failed - Error opening the specified MaxMind DB file in /data/custom_nginx/http_top.conf:1\n"

Maybe someone can give me a hint where the problem is?

I did it with:
geoip2 /opt/npmplus/goaccess/geoip/GeoLite2-Country.mmdb {
}

@Zoey2936
Copy link
Member

Zoey2936 commented Apr 1, 2025

Can you try to remove the line break after geoip2

@Mr-Neutron
Copy link

Mr-Neutron commented Apr 1, 2025

Can you try to remove the line break after geoip2

you mean like:
geoip2 /opt/npmplus/goaccess/geoip/GeoLite2-Country.mmdb { $geoip2_data_country_code country iso_code; $geoip2_data_country_name country names en; }

if yes, still the error:
{"log":"nginx: [emerg] MMDB_open("/opt/npmplus/goaccess/geoip/GeoLite2-Country.mmdb") failed - Error opening the specified MaxMind DB file in /data/custom_nginx/http_top.conf:1\n","stream":"stderr","time":"2025-04-01T19:27:04.365067848Z"}

@Zoey2936
Copy link
Member

Zoey2936 commented Apr 1, 2025

since it is inside the container /opt/npmplus should be /data

@Matthias-vdE
Copy link

Alternatively, OpenAppSec supports geoblocking straight out of the box from their management UI. So if you don't want to mess around with config files too much, you can do it this way as well. (Not sure if that's per se easier, but it wasn't too hard to get openappsec up and running.)

@Zoey2936 Zoey2936 changed the title Geolocation Blocking [feature] Geolocation Blocking May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

8 participants