Restricting the users' access based on their location

Issue

This article shows how to configure Nginx to accept geoIP based restrictions at an Engine Yard installation.

Solution

Please follow the steps below. 

1. Make sure you have the needed v5 cookbooks downloaded from the Engine Yard repository: https://github.com/engineyard/ey-cookbooks-stable-v5/tree/next-release/cookbooks 

ey-custom
nginx
unicorn

2. Create

  • a folder called nginx_geoip​ under cookbooks
  • a new folder called recipes ​under nginx_geoip


3. Create a file called default.rb​in cookbooks/nginx_geoip/recipes

bash 'install_nginx_geo' do
user 'root'
cwd '/data/nginx'
code <<-EOH
rm GeoLiteCity.dat
rm GeoIP.dat
wait_interval 5
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
gunzip GeoIP.dat.gz
EOH
end

4. Edit cookbooks/ey-custom/recipes/after-main.rb​ and add the following into it include_recipe "nginx_geoip"

5. Edit the following file cookbooks/nginx/templates/default/common.fcgi.conf.erb​ and insert the following to the end of the file

#GEOIP.
fastcgi_param GEOIP_ADDR          $remote_addr;
fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
fastcgi_param GEOIP_COUNTRY_CODE3 $geoip_country_code3;
fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;

fastcgi_param GEOIP_CITY_COUNTRY_CODE $geoip_city_country_code;
fastcgi_param GEOIP_CITY_COUNTRY_CODE3 $geoip_city_country_code3;
fastcgi_param GEOIP_CITY_COUNTRY_NAME $geoip_city_country_name;
fastcgi_param GEOIP_REGION $geoip_region;
fastcgi_param GEOIP_CITY $geoip_city;
fastcgi_param GEOIP_POSTAL_CODE $geoip_postal_code;
fastcgi_param GEOIP_CITY_CONTINENT_CODE $geoip_city_continent_code;
fastcgi_param GEOIP_LATITUDE $geoip_latitude;
fastcgi_param GEOIP_LONGITUDE $geoip_longitude;

6. Edit the following files cookbooks/nginx/templates/default/common.proxy.conf.erb and ​insert the following snippet under proxy_set_header  X-Queue-Start    't=$start_time'; <% end %>

########
#GEOIP Proxy headers
########
proxy_set_header GEOIP_COUNTRY_CODE $geoip_country_code;
proxy_set_header GEOIP_COUNTRY_CODE3 $geoip_country_code3;
proxy_set_header GEOIP_COUNTRY_NAME $geoip_country_name;

proxy_set_header GEOIP_CITY_COUNTRY_CODE $geoip_city_country_code;
proxy_set_header GEOIP_CITY_COUNTRY_CODE3 $geoip_city_country_code3;
proxy_set_header GEOIP_CITY_COUNTRY_NAME $geoip_city_country_name;
proxy_set_header GEOIP_REGION $geoip_region;
proxy_set_header GEOIP_CITY $geoip_city;
proxy_set_header GEOIP_POSTAL_CODE $geoip_postal_code;
proxy_set_header GEOIP_CITY_CONTINENT_CODE $geoip_city_continent_code;
proxy_set_header GEOIP_LATITUDE $geoip_latitude;
proxy_set_header GEOIP_LONGITUDE $geoip_longitude;


7. Edit the file cookbooks/nginx/templates/default/nginx-plusplus.conf.erb​, look for the following: http { include /etc/nginx/mime.types;

  #################
  #EDIT FOR GEOIP #
  #################
  geoip_country /etc/nginx/GeoIP.dat;
  geoip_city /etc/nginx/GeoLiteCity.dat;
  #Loads in the GEOIP files

  map $geoip_country_code $allowed_country{
  default yes; #allows all countries by default
  GB no; #blocks the country GB (United Kingdom)
}

Look for the following in the same file: <% if @behind_proxy %>replace the old snippet with the following

set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.31.0.0/16;
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

8. Edit the file cookbooks/nginx/templates/default/server.conf.erb​look for ​location / {​ & if (-f $document_root/system/maintenance.html) { return 503; }

place the following snippet between 503 and location / {

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

9. Edit the file cookbooks/nginx/templates/default/ssl.conf.erb​look for ​location / {​ & if (-f $document_root/system/maintenance.html) { return 503; }

place the following snippet between 503 and location / {

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

10. Save, upload and apply.


Notes

  • To add more countries edit cookbooks/nginx/templates/default/nginx-plusplus.conf,
    using 2 letter country code for that end.
  • Engine Yard v5 Stack is the only requirement as it already comes pre-bundled with the correct add-ons for nginx webserver.

 

Credit: Callum Pease