nginx: How To Block Visitors By Country With The GeoIP Module (Debian/Ubuntu)

Version 1.0
Author: Falko Timme
Follow me on Twitter

This tutorial explains how to use the GeoIP module with nginx to block visitors by country. This is made possible by the GeoIP database which maps users' IP addresses to countries. nginx must be compiled with the HttpGeoipModule to use the GeoIP database.

I do not issue any guarantee that this will work for you!

 

1 Preliminary Note

As mentioned in the introduction, nginx must be compiled with the HttpGeoipModule. To check if your nginx was compiled with that module, run:

nginx -V

If you see --with-http_geoip_module in the output, you are ready to use the GeoIP database with nginx:

[email protected]:~# nginx -V
nginx version: nginx/1.2.1
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-pcre-jit --with-debug --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_realip_module --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_xslt_module --with-ipv6 --with-sha1=/usr/include/openssl --with-md5=/usr/include/openssl --with-mail --with-mail_ssl_module --add-module=/build/buildd-nginx_1.2.1-2.1-amd64-fMGfEu/nginx-1.2.1/debian/modules/nginx-auth-pam --add-module=/build/buildd-nginx_1.2.1-2.1-amd64-fMGfEu/nginx-1.2.1/debian/modules/nginx-echo --add-module=/build/buildd-nginx_1.2.1-2.1-amd64-fMGfEu/nginx-1.2.1/debian/modules/nginx-upstream-fair --add-module=/build/buildd-nginx_1.2.1-2.1-amd64-fMGfEu/nginx-1.2.1/debian/modules/nginx-dav-ext-module
[email protected]:~#

 

2 Installing The GeoIP Database

On Debian/Ubuntu, the GeoIP database can be installed as follows:

apt-get install geoip-database libgeoip1

This places the GeoIP database in /usr/share/GeoIP/GeoIP.dat.

It is possible that it is a bit outdated. Therefore we can optionally download a fresh copy from the GeoIP web site:

mv /usr/share/GeoIP/GeoIP.dat /usr/share/GeoIP/GeoIP.dat_bak
cd /usr/share/GeoIP/
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
gunzip GeoIP.dat.gz

 

3 Configuring nginx

Open /etc/nginx/nginx.conf...

vi /etc/nginx/nginx.conf

... and place this in the http {} block, before any include lines:

[...]
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    map $geoip_country_code $allowed_country {
        default yes;
        FK no;
        FM no;
        EH no;
    }
[...]

This allows all countries, except the three countries set to no (you can find a list of country codes here). To do it the other way round, i.e. block all countries and allow only a few, you'd do it this way:

[...]
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    map $geoip_country_code $allowed_country {
        default no;
        FK yes;
        FM yes;
        EH yes;
    }
[...]

Now, this actually doesn't block any country, it just sets the $allowed_country variable. To actually block countries, you must open your vhost configuration and place the following code in the server {} container (this can go inside and also outside any location {} block):

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

This returns the 444 error code to any visitor from a blocked country. What this does is it closes the connection without sending any headers. You can also use another error code like 403 ("Forbidden") if you like.

Reload nginx afterwards:

/etc/init.d/nginx reload

 

 

About The Author

Falko Timme is the owner of Boost Your Site mit Timme Hosting - ultra-schnelles nginx-WebhostingTimme Hosting (ultra-fast nginx web hosting). He is the lead maintainer of HowtoForge (since 2005) and one of the core developers of ISPConfig (since 2000). He has also contributed to the O'Reilly book "Linux System Administration".

Share this page:

Suggested articles

14 Comment(s)

Add comment

Comments

By: nice

nice... lovely blocking US sites.

By: Trevor Richardson

Exactly what we are looking for to halt request without starting the PHP process.

Thank you!

By: Grzegorz

Its nice solution.But I host multiple small pages on one ubuntu host, and want to allow only one of my pages for specific country. How do I do that?Thank you!

 

By: InsertHost

How I can enable access only to users in a country?

By: Leonardo

Great!!!.

By: great job

Thank so much.  Worked great.

By: AJ

Will This Work for TCP block too?

By: David Rahrer

Is there any way to make this work with different country blocks for different vhosts? I may have one site that does business with a country that others want to block, but the former still wants to block some areas - a custom mix for each vhost. Is this possible? Thanks.

By: eric

yes you can. define multiple variables $allowed_country1-2-3 etc with different mapings, and change the if-else test with the right variable under the right vhost

By: Encino Stan

You should also be able to route to vhost based on what country geoip looks up.

By: Mike

I'm always getting undefined for the country code... can you pls help https://stackoverflow.com/questions/51282599/nginx-geoip-module-undefined-country-code 

By: mike

GeoLite Legacy will not be updated anymore from March 2018:

https://dev.maxmind.com/geoip/legacy/geolite/

Will this guide be updated to use GeoLite2?

https://dev.maxmind.com/geoip/geoip2/geolite2/

 

http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz

is now

http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz

Thank you!

By: John

"http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz

is now

http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz"

this looks identical to me

By: lbarclay

Didn't work for me. Received error : unknown directive "geoip_country"

I added : include /etc/nginx/modules/mod-http-geoip.conf as the first line in nginx.conf; ( link to a file in /usr/share/nginx/modules )

nginix starts, but it doesn't appear to work for GeoIP blocking. Doesn't look like my IP is mapped to any geoip_country_code.

How do you allow for internal private network IP(s) / subnets to be added to an 'allowed country' for testing : 10.149.213.206