DEV
BLOG
  • Design
  • Data
  • Discernment

We believe in AI and every day we innovate to make it better than yesterday. We believe in helping others to benefit from the wonders of AI and also in extending a hand to guide them to step their journey to adapt with future.

Know more

Our solutions in action for customers

DOWNLOAD

Featured Post

How we spoke to data in 2 days

What would you do in two days? Let me be more precise, what would you do on a weekend? Depending on the kind of person you are, the answers may differ. Some may wanna stay in, have a good sleep, take it slow. If you are like me, you would be on the road riding […]

Know More

MENU

  • HOME
  • SERVICES
  • PRODUCTS
  • CASE STUDIES
  • INDUSTRIES
  • CAREERS
  • CONTACT US

Artificial Intelligence

Blockchain

Enterprise Solutions

Blog
White Papers
Resources
Videos
News

Enabling Geography-based Access Restriction in Nginx Servers

  • mm
    by Arun Jayakumar on Wed May 27

If you’re a web developer, you probably already know what Nginx is. For those who don’t know what it is, Nginx is an open-source web server. Since 2004, developers have been using Nginx for hosting high performance and scalable web applications. Today, millions of websites use Nginx, including websites of companies like Netflix, Dropbox, Airbnb, Box, Tumble, etc.

Nginx is my personal favorite web server, I’ve deployed 100s of web applications in it. Recently, in one of the web applications I built, the client wanted to restrict access to the application based on geography. That is, only grant access to a user if they are from a specific list of countries. And there I stumbled upon a problem with Nginx’s geography-based access restriction feature.

What happened to Nginx’s Access restriction based on geography?

Nginx supported a pretty decent functionality for restricting user access based on geographic locations. It used the GeoIP module, which offers identification of the location of internet users. However, with the recent update of GeoIP module, databases are discontinued and the current version of Nginx doesn’t support it. Even though the current version of Nginx comes with a default GeoIP module, the server cannot access the geolocation data from the module since the updated GeoIP version (GeoIP2) is not prebuilt in it. The module is not available in official Ubuntu repos or their official PPA. So my only option was to build Nginx from source by adding the GeoIP2 module source. It was kinda a long process so I thought to prepare a simple tutorial for it so that the other fellow developers out there who want to do the same can get it done faster.

Backup old Nginx configs

sudo cp /etc/nginx/ /home/ubuntu

Remove old Nginx installation

sudo apt-get remove --purge nginx nginx-common

Download Nginx

wget http://nginx.org/download/nginx-1.16.1.tar.gz

Unzip Nginx Source

tar xvfz nginx-1.16.1.tar.gz

Download GeoIP2 Nginx Module

git clone https://github.com/leev/ngx_http_geoip2_module.git

Install new Geoip mmdb extension support

sudo add-apt-repository ppa:maxmind/ppa
sudo apt update
sudo apt install libmaxminddb0 libmaxminddb-dev mmdb-bin

Install Dependencies for Building Nginx

sudo apt-get install libpcre3
sudo apt-get install libpcre3-dev
sudo apt-get install zlib1g zlib1g-dev libssl-dev
sudo apt-get install build-essential

Download Other modules for building Nginx

PCRE version 4.4 – 8.40

wget https://ftp.pcre.org/pub/pcre/pcre-8.40.tar.gz && tar xzvf pcre-8.40.tar.gz

zlib version 1.1.3 – 1.2.11

wget http://www.zlib.net/zlib-1.2.11.tar.gz && tar xzvf zlib-1.2.11.tar.gz

OpenSSL version 1.0.2 – 1.1.0

wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz && tar xzvf openssl-1.1.0f.tar.gz

Install Nginx

cd nginx-1.16.1
./configure --prefix=/usr/share/nginx \ --sbin-path=/usr/sbin/nginx \ --modules-path=/usr/lib/nginx/modules \ --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --pid-path=/run/nginx.pid \ --lock-path=/var/lock/nginx.lock \ --user=www-data \ --group=www-data \ --build=Ubuntu \ --http-client-body-temp-path=/var/lib/nginx/body \ --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ --http-proxy-temp-path=/var/lib/nginx/proxy \ --http-scgi-temp-path=/var/lib/nginx/scgi \ --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \ --with-openssl=../openssl-1.1.0f \ --with-openssl-opt=enable-ec_nistp_64_gcc_128 \ --with-openssl-opt=no-nextprotoneg \ --with-openssl-opt=no-weak-ssl-ciphers \ --with-openssl-opt=no-ssl3 \ --with-pcre=../pcre-8.40 \ --with-pcre-opt='-g -Ofast -fPIC -m64 -march=native -fstack-protector-strong -D_FORTIFY_SOURCE=2' \ --with-zlib-opt='-g -Ofast -fPIC -m64 -march=native -fstack-protector-strong -D_FORTIFY_SOURCE=2' \ --with-ld-opt='-lpcre -Wl' \ --with-pcre-jit \ --with-zlib=../zlib-1.2.11 \ --with-compat \ --with-file-aio \ --with-threads \ --with-http_addition_module \ --with-http_auth_request_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_mp4_module \ --with-http_random_index_module \ --with-http_realip_module \ --with-http_slice_module \ --with-http_ssl_module \ --with-http_sub_module \ --with-http_stub_status_module \ --with-http_v2_module \ --with-http_secure_link_module \ --with-mail \ --with-mail_ssl_module \ --with-stream \ --with-stream_realip_module \ --with-stream_ssl_module \ --with-stream_ssl_preread_module \ --with-debug \ --add-dynamic-module=/home/arun/ngx_http_geoip2_module \ --with-cc-opt='-g -O2 -fPIC -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' \ --with-ld-opt='-Wl,-Bsymbolic-functions -fPIC -pie -Wl,-z,relro -Wl,-z,now'

Note : replace the paths in the configure command, check all lines eg : –add-dynamic-module=/home/arun/ngx_http_geoip2_module \

make
make install

Copy the GeoIP2 ” .so ” files from the source directory to

/usr/share/nginx/modules, here the source dir is home/arun/ngx_http_geoip2_module

Check Installation

sudo nginx -v && sudo nginx -V

check /var/lib/nginx directory is present if not create one by sudo mkdir /var/lib/nginx

Check syntax and potential errors

sudo nginx -t

Create service file for Nginx

sudo nano /etc/systemd/system/nginx.service

copy – paste the content

[Unit]
Description=A high performance web server and a reverse proxy server
 After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSc=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

Start the service

sudo systemctl start nginx.service && sudo systemctl enable nginx.service

If sites-available and site enabled directory are missing in /etc/nginx create these directories.

Edit nginx.conf in /etc/nginx and remove the server block code and add include /etc/nginx/sites-enabled/*; at the very beginning of http block

create a file in sites-available and make a link of the file to sites-enabled and check its working

GeoIp2 Config

Edit nginx.conf sudo nano /etc/nginx/nginx.conf

add the content to the very beginning of nginx.conf file

load_module modules/ngx_http_geoip2_module.so;
load_module modules/ngx_stream_geoip2_module.so;

add the content and end of the http block

geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    auto_reload 60m;
    $geoip2_metadata_country_build metadata build_epoch;
    $geoip2_data_country_code country iso_code;
    $geoip2_data_country_name country names en;
}

  map $geoip2_data_country_code $allowed_country {
             default yes;
             US no;
         ID no;
    	 CU no;
         IQ no;
         SY no;
         SO no;
         KP no;
            VE no;
        }

geoip2 /usr/share/GeoIP/GeoLite2-City.mmdb {
    auto_reload 60m;
    $geoip2_metadata_city_build metadata build_epoch;
   $geoip2_data_city_name city names en; 
}   

In the Vhost file add the country headers in response headers, this will be helpful in debugging.

to add headers edit vhost file and add the content in the server block.

add_header X-GeoCountry $geoip2_data_country_name;
add_header X-GeoCode $geoip2_data_country_code;
add_header X-GeoCity $geoip2_data_city_name;

To block the access, add the content in the server block of the Vhost file.

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

To send a new page instead of error code, add

error_page /blocked.html

Restart Nginx

sudo service nginx restart

For updating Geo IP database add a cron to run geoipupdate command

Install geoipupdate

sudo apt-get install -y geoipupdate

or

get DEB file from https://github.com/maxmind/geoipupdate/releases and install it


Author

  • mm
    Arun Jayakumar

Arun is the VP of Engineering at Accubits Technologies. He oversees Accubits’s development teams. He brings more than 6 years of experience in the tech industry as a developer, technologist, engineering, and business leader. He is a goal-oriented Product and Technology leader with a track record of defining vision & strategy, product architecture, roadmap, execution strategy, growing teams to deliver highly scalable products in hyper-growth organization with a relentless focus on customer backward thinking.

Categories

View articles by categories

  • Uncategorized

Subscribe now to get our latest posts

All Rights Reserved. Accubits INC 2020