- Базы с данными
В интернете есть два достойных упоминания сайта с базами для геолокации. Первый - это, конечно, www.maxmind.com где есть два варианта баз - платные и бесплатные. Второй - www.ipgeobase.ru. Я предпочитаю использовать данные с обеих сайтов, данные для России и Украины брать с ipgeobase (по идее, у них по этим странам данные должны быть точнее), а для остальных стран - с maxmind. Пишем скрипт для скачивания архивов с данными:#!/bin/sh wget http://ipgeobase.ru/files/db/Main/geo_files.zip wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City-CSV.zip
Теперь необходимо переконвертировать данные в формат, который можно скормить nginx. Создаем директорию convert и распаковываем туда файлы из архивов. Для конвертации я написал на perl пару скриптов.
1_ipgeobase.pl - создаем файл для nginx из файлов с ipgeobase. Тащим данные только для России и Украины.#!/usr/bin/perl -w # 1_ipgeobase.pl #------------------------------------------------------------------------------- # convert ipgeobase.ru txt files for use with nginx geo #------------------------------------------------------------------------------- # (c) Skull 2015 #------------------------------------------------------------------------------- use strict; use warnings; use utf8; use open qw/:std :utf8/; use Net::CIDR; $|=1; my %ids; my(@tr) = ('А,а,a','Б,б,b','В,в,v','Г,г,g','Д,д,d','Е,е,ye','Ё,ё,jo','Ж,ж,zg','З,з,zh','И,и,i','Й,й,i','К,к,k','Л,л,l','М,м,m','Н,н,n','О,о,o','П,п,p','Р,р,r','С,с,s','Т,т,t','У,у,u','Ф,ф,f','Х,х,h','Ц,ц,ts','Ч,ч,ch','Ш,ш,sh','Щ,щ,shh','Ь,ь,','Ы,ы,y','Ъ,ъ,','Э,э,je','Ю,ю,ju','Я,я,ja'); open (local *IN,'<:encoding(cp1251)','cities.txt') or die "Can't open cities.txt"; while (my $s =
Net::CIDR - этот пакет тащим с сайта search.cpan.org, создаем в convert директорию Net и туда помещаем CIDR.pm.) { my ($id,$city,$region,$district) = split(/\t/,$s); $ids{$id} = $city if $city; } close IN; open (local *OUT0,'>','geo_country_ipgeobase.conf'); open (local *OUT1,'>','geo_city_ipgeobase.conf'); open (local *IN,'<:encoding(cp1251)','cidr_optim.txt') or die "Can't open cidr_optim.txt"; while (my $s = ) { chomp $s; my ($start,$stop,$inetnum,$country,$id) = split(/\t/,$s); $inetnum =~ s/ //g; foreach my $cidr(Net::CIDR::range2cidr($inetnum)) { if(defined $country and ($country eq 'RU' or $country eq 'UA')){ print $cidr,"\n"; print OUT0 "$cidr $country;\n"; if(exists $ids{$id}){ my $city = ucfirst(translate($ids{$id})); if($city eq 'Moskva'){ $city = 'Moscow'; } $city =~ s/(-)(\w)(.+?)/$1\u$2$3/g; $city =~ s/( )(\w)(.+?)/$1\u$2$3/g; $city =~ s/\"//g; $city =~ s/\'//g; if($city =~ / /){ $city = '"'.$city.'"'; } print OUT1 "$cidr $city;\n"; } } } } close IN; close OUT0; close OUT1; print "Done for ipgeobase.ru\n"; exit; sub translate{ my($i) = @_; foreach my $x(@tr){ my($x0,$x1,$x2) = split ',',$x; $i =~ s/$x0/$x2/g; $i =~ s/$x1/$x2/g; } return $i; }
После отработки скрипта получим два файла: geo_city_ipgeobase.conf и geo_country_ipgeobase.conf.
2_maxmind.pl - создаем файл для nginx из файлов с maxmind. Тащим данные для всех стран кроме России и Украины.#!/usr/bin/perl -w # 2_maxmind.pl #------------------------------------------------------------------------------- # convert MaxMind GeoLite2-City CSV for use with nginx geo #------------------------------------------------------------------------------- # (c) Skull 2015 #------------------------------------------------------------------------------- use strict; use warnings; use utf8; use open qw/:std :utf8/; $|=1; my(%city,%country,%net); print "Read geo_country_ipgeobase.conf..."; open(local *IN,'<','geo_country_ipgeobase.conf') or die "Can't open geo_country_ipgeobase.conf"; my $y =
После отработки скрипта получим два файла: geo_city_maxmind.conf и geo_country_maxmind.conf.; while (my $in = ){ my($i0,$i1) = split ' ',$in,2; $net{$i0} = 1; } close IN; print " done\n"; # parse MaxMind files print "Read GeoLite2-City-Blocks-IPv4.csv..."; my($count_mm,$count,$count_s) = (0,0,0); open(local *IN,'<','GeoLite2-City-Blocks-IPv4.csv') or die "Can't open GeoLite2-City-Blocks-IPv4.csv"; $y = ; while (my $in = ){ $count_mm++; } close IN; print " done\n"; open(local *IN,'<','GeoLite2-City-Locations-en.csv') or die "Can't open GeoLite2-City-Locations-en.csv"; my $x = ; while (my $in = ){ chomp $in; my(@x) = split ',',$in; if($x[10]){ $city{$x[0]} = $x[10]; } if($x[4]){ $country{$x[0]} = $x[4]; } } close IN; open IN,'<','GeoLite2-City-Blocks-IPv4.csv' or die "Can't open GeoLite2-City-Blocks-IPv4.csv"; open OUT2,'>','geo_country_maxmind.conf' or die "Can't open geo_country_maxmind.conf"; open OUT3,'>','geo_city_maxmind.conf' or die "geo_city_maxmind.conf"; $x = ; while (my $in = ){ chomp $in; my(@x) = split ',',$in; if(!$net{$x[0]}){ if(exists $country{$x[1]} and $country{$x[1]} ne 'RU' and $country{$x[1]} ne 'UA'){ if($country{$x[1]} =~ / /){ $country{$x[1]} = '"'.$country{$x[1]}.'"'; } print OUT2 $x[0],"\t",$country{$x[1]},";\n"; if(exists $city{$x[1]}){ $city{$x[1]} =~ s/\"//g; $city{$x[1]} =~ s/\'//g; if($city{$x[1]} =~ / /){ $city{$x[1]} = '"'.$city{$x[1]}.'"'; } print OUT3 $x[0],"\t",$city{$x[1]},";\n"; } $count++; $count_s++; if($count_s >= 100000){ print "$count / $count_mm\n"; $count_s=0; } } } } close IN; close OUT2; close OUT3; print "$count / $count_mm\n"; print "Done for maxmind.com\n"; exit;
Создаем директорию# mkdir /usr/local/etc/nginx/geoip
Переносим туда четыре файла: geo_city_ipgeobase.conf, geo_city_maxmind.conf, geo_country_ipgeobase.conf, geo_country_maxmind.conf
На этом создание файлов с geo-данными для nginx закончено. Эту операцию необходимо проделывать каждый раз когда обновляются файлы с данными на сайтах ipgeobase и maxmind.
Создаем файл /usr/local/etc/nginx/geoip/bad_countries.conf. В этом файле хранятся данные по странам, которым запрещен доступ к сайтам web-сервера. Формат файла:US 0; CH 1; IN 1;
1 - посетителю из этой страны запрещен доступ.
- Конфигурация nginx
/usr/local/etc/nginx/nginx.confhttp { geo $ip2city { default UNKNOWN; 192.168.1.0/24 My City; 127.0.0.1/32 My City; include geoip/geo_city_ipgeobase.conf; include geoip/geo_city_maxmind.conf; } geo $ip2country { default ZZ; 192.168.1.0/24 RU; 127.0.0.1/32 RU; 127.0.0.0/24 US; include geoip/geo_country_ipgeobase.conf; include geoip/geo_country_maxmind.conf; } map $ip2country $bad_country { default 0; include geoip/bad_countries.conf; } }
- /usr/local/etc/nginx/sites/mysite.conf - сайт, который обслуживает nginx.
Вариант 1, если геоданные нужны в пределах server. Nginx должен быть собран с поддержкой 3rd party headers_more module (опция HEADERS_MORE в конфиге FreeBSD порта) иначе more_set_input_headers работать не будет.server { more_set_input_headers 'X-Geoip-City-Name: $ip2city'; more_set_input_headers 'X-Geoip-Country-Code: $ip2country'; if ($bad_country){ return 444; } }
Вариант 2, если геоданные нужны только скриптам. Передаем через fastcgi без всяких дополнительных модулей. Параметры задаются в location /cgi-bin/.server { location ~ /cgi-bin/ { fastcgi_param HTTP_X_GEOIP_CITY_NAME $ip2city; fastcgi_param HTTP_X_GEOIP_COUNTRY_CODE $ip2country; } if ($bad_country){ return 444; } }
if ($bad_country){...} - здесь задается реакция сайта на список "плохих" стран. Для посетителей из запрещенных стран возвращается ответ HTTP 444.
- /usr/local/etc/nginx/sites/proxysite.conf - прокси для сайта на другом веб-сервере. В файле /usr/local/etc/nginx/proxy_vars.conf должны быть строчки:
proxy_set_header X-Geoip-City-Name $ip2city; proxy_set_header X-Geoip-Country-Code $ip2country;
- /usr/local/etc/nginx/sites/mysite.conf - сайт, который обслуживает nginx.
- Применить изменения.
Если не добавлялось новых сайтов, то можно просто перечитать конфиг# /usr/local/etc/rc.d/nginx reload
Иначе необходима полная перезагрузка# /usr/local/etc/rc.d/nginx restart
Статья опубликована: 2015-04-18 20:48:51
Последние правки: 2015-07-16 15:56:01
Добавляем в nginx геолокацию (geoip).
Одна из самых привлекательных по моему мнению функций в nginx - это возможность определения страны, города по ip-адресу посетителя. Эта функция называется геолокация (geoip).