NGINX can be deployed as a reverse proxy in front of applications and can be used to control access to the application based on the GEO Location of the end user. NGINX can be used to restrict access to different parts of applications for specific countries or cities. NGINX uses GeoIP2 database from Maxmind to identify the end user location based on users IP address.
NGINX Plus repository has GeoIP2 module which can be installed as part of NGINX plus installation. NGINX Plus requires paid subscription. In order to use NGINX open source version, the GeoIP2 module needs to be compiled from source and added into the path of NGINX configuration.
The following guide outlines the deployment methodology and installation instructions for deploying NGINX (opensource) as reverse proxy along with GeoIP2 module. The solution comprises of NGINX, GeoIP2 module and Maxmind DB library.
Installation of NGINX Application
Add the NGINX repository for CentOS 7 in the path /etc/yum.repos.d/nginx.repo. Run yum update and install the nginx application. Enable nginx service to start on boot.
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1
$ sudo yum update
$ sudo yum install nginx
Adding GeoIP2 module of NGINX
Verify the nginx version installed via the repository.
$ nginx -v nginx version: nginx/1.20.1
Download the same nginx source code version.
$ wget http://nginx.org/download/nginx-1.20.1.tar.gz
Before compiling the GeoIP2 module, the required libraries and development files need to be installed.
$ sudo yum install make gcc git openssl-devel pcre-devel \ libmaxminddb libmaxminddb-devel libxslt-devel gd-devel \ perl-ExtUtils-Embed gperftools-devel redhat-rpm-config
Clone the git repository for the GeoIP2 module and untar the nginx source code under the same directory path.
$ cd ~ $ git clone https://github.com/leev/ngx_http_geoip2_module.git $ tar zxvf nginx-1.20.1.tar.gz
The NGINX code will be compiled with the same compile time options used for the installed nginx version via the repository. For getting the compile options “nginx -V” command will be used. In addition the GeoIP2 module will be compiled as a dynamic module.
$ nginx -V nginx version: nginx/1.20.1 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) built with OpenSSL 1.1.1g FIPS 21 Apr 2020 TLS SNI support enabled configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-compat --with-debug --with-file-aio --with-google_perftools_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' $ $ $ cd nginx-1.20.1 $ ./configure --add-dynamic-module=../ngx_http_geoip2_module --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-compat --with-debug --with-file-aio --with-google_perftools_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' $ $ make
This will compile dynamic libraries for http and stream geoip2 modules under the objs directory. Copy these modules to nginx installation.
$ ls -l ~/nginx-1.19.9/objs/*.so -rwxrwxr-x. 1 jahanzeb jahanzeb 136936 اپريل 9 10:26 objs/ngx_http_geoip2_module.so -rwxrwxr-x. 1 jahanzeb jahanzeb 112544 اپريل 9 10:26 objs/ngx_stream_geoip2_module.so $ $ sudo cp objs/*.so /usr/share/nginx/modules/ $ sudo chown root:root /usr/share/nginx/modules/*.so
Add the geoip2 modules to the nginx configuration file /etc/nginx/nginx.conf
user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; load_module modules/ngx_http_geoip2_module.so; load_module modules/ngx_stream_geoip2_module.so; ..... ..... .....
Configure the GeoIP variable mappings for City and Countries in the /etc/nginx/nginx.conf file.
..... ..... ..... http { ..... ..... ..... geoip2 /etc/nginx/GeoIP2/GeoLite2-City.mmdb { $geoip2_data_city_name city names en; $geoip2_data_postal_code postal code; $geoip2_data_latitude location latitude; $geoip2_data_longitude location longitude; $geoip2_data_state_name subdivisions 0 names en; $geoip2_data_state_code subdivisions 0 iso_code; } geoip2 /etc/nginx/GeoIP2/GeoLite2-Country.mmdb { $geoip2_data_continent_code continent code; $geoip2_data_country_iso_code country iso_code; } }
In the website configuration file configure the map which will allow or block the countries. The map will be called under the server configuration. In the file /etc/nginx/conf.d/www.website.com.conf
map $geoip2_data_country_iso_code $allowed_country { default yes; CA no; CB no; CC no; } ..... ..... server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name careers.nayatel.com; ..... ..... if ($allowed_country = no) { return 444; } ..... ..... }
Maxmind GeoLite2 Database
Register for a free account and download the GeoLite2 database from Maxmind. Copy the mmdb file to the directory /etc/nginx/GeoIP2.
To check via command line the location of an IP address use the following command.
$ mmdblookup --file /etc/nginx/GeoIP2/GeoLite2-City.mmdb --ip 1.1.1.50 $ mmdblookup --file /etc/nginx/GeoIP2/GeoLite2-City.mmdb --ip 2.2.2.51 country iso_code $ mmdblookup --file /etc/nginx/GeoIP2/GeoLite2-City.mmdb --ip 3.3.3.52 city names en
Download the geoipupdate package from https://github.com/maxmind/geoipupdate/releases and install it.
$ wget https://github.com/maxmind/geoipupdate/releases/download/v4.8.0/geoipupdate_4.8.0_linux_amd64.rpm $ sudo yum localinstall geoipupdate_4.8.0_linux_amd64.rpm
Get the GeoIP configuration file from https://www.maxmind.com/en/accounts/current/license-key/GeoIP.conf.
Verify the configuratio options in the file /etc/GeoIP.conf
AccountID 123456 LicenseKey XXXXXXXXXXXXX # Enter the edition IDs of the databases you would like to update. # Multiple edition IDs are separated by spaces. EditionIDs GeoLite2-Country GeoLite2-City # The directory to store the database files. Defaults to /usr/share/GeoIP DatabaseDirectory /etc/nginx/GeoIP2
Edit the cron file /etc/crontab to schedule weekly updates of the GeoIP database.
53 18 * * 3 root /usr/bin/geoipupdate
References
https://docs.nginx.com/
https://docs.nginx.com/nginx/admin-guide/security-controls/controlling-access-by-geoip/
https://github.com/leev/ngx_http_geoip2_module
https://gist.github.com/kmjones1979/fcabb4731bbf85b9c50189e90d76b1c1
https://dev.maxmind.com/geoip/geoip2/geolite2/
https://github.com/maxmind/geoipupdate/releases