前言

IP2Location主要是用于代替MaxMind GeoIP,原因是GeoIP数据库针对中国的Blacklist黑名单有非常高的误伤率,选择IP2Location可以有效降低误伤,为了业务需求得及时做出改变。在使用IP2Location的过程中发现官网的步骤还是存在一些问题,这里记录和分享下自己逐步解决问题的过程。

更新历史

2020年04月21日 - 初稿

阅读原文 - https://wsgzao.github.io/post/ip2location/


GeoIP和IP2Location简介

GeoIP是一套含IP数据库的软件工具。除此之外还有IP2Location等,国内做得比较深入的是高春辉创建的IPIP.NET

Geo根据来访者的IP, 定位该IP所在经纬度、国家/地区、省市、和街道等位置信息。

GeoIP/IP2Location等通常有两个版本,一个免费版,一个收费版本。

收费版本的准确率高一些,更新频率也更频繁。

Geo IP solution to identify country, region, city, latitude & longitude, ZIP code, time zone, connection speed, ISP, domain name, IDD country code, area code, weather station data, mobile network codes (MNC), mobile country codes (MCC), mobile carrier, elevation and usage type.

GeoIP是大家都非常熟悉的老字号,而这次的主角是IP2Location

IP2Location Nginx Module

This is an IP2Location Nginx Module that enables the user to identify the country code and country name by IP address. In general, it is faster, easier and more accurate than reverse DNS lookups.

https://www.ip2location.com/development-libraries/ip2location/nginx

Installation

IP2Location C library enables the user to find the country, region, city, coordinates, ZIP code, time zone, ISP, domain name, connection type, area code, weather, MCC, MNC, mobile brand name, elevation and usage type that any IP address or hostname originates from. It has been optimized for speed and memory utilization. Developers can use the API to query all IP2Location™ binary databases for IPv4 and IPv6 address.

  • Download IP2location C library from here.

  • Download and decompress this Nginx module package.

  • Change the path to IP2Location library in “ngx_http_ip2location_module.c”.

  • Re-compile Nginx from source to include this module. Add the below directive into the compile of Nginx:

    ./configure --add-module=/absolute/path/to/nginx-ip2location-8.0.0
    make
    make install

  • Edit your Nginx config file to point the correct path of IP2Location database file:

    ip2location_database /absolute/path/to/IP2LOCATION-DB1.BIN;

安装备注

IP2Location官方的执行步骤存在一些问题没有说清楚,这里分享自己实践后的步骤和结论

安装依赖包

1
2
3
4
5
# These are for RedHat, CentOS, and Fedora.
sudo yum install wget git gcc-c++ pcre-devel zlib-devel make libtool autoconf automake

# These are for Debian. Ubuntu will be similar.
sudo apt-get install wget git build-essential zlib1g-dev libpcre3 libpcre3-dev libtool autoconf automake

编译 IP2Location C library

1
2
3
4
5
6
7
8
9
10
11
git clone https://github.com/chrislim2888/IP2Location-C-Library
cd IP2Location-C-Library
autoreconf -i -v --force
./configure
make
make install
# 以下步骤可选
cd data
perl ip-country.pl
cd ../test
./test-IP2Location

编译 Nginx

nginx: download

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Download ip2location-nginx
git clone https://github.com/ip2location/ip2location-nginx

# IP2Location library in "ngx_http_ip2location_module.c"
cd ip2location-nginx
vim ngx_http_ip2location_module.c
#include "IP2Location.h"
#include "/root/ip2location/IP2Location-C-Library-master/libIP2Location/IP2Location.h"

# Download Nginx Stable version
VERSION="1.16.1"
wget http://nginx.org/download/nginx-${VERSION}.tar.gz
tar -xvzf nginx-${VERSION}.tar.gz
cd nginx-${VERSION}

# Compile Nginx
./configure --add-module=../ip2location-nginx
make
sudo make install

# error: Failed dependencies:
# libIP2Location.so.1()(64bit) is needed by nginx-garena-1.16.1-0.noarch
# 一般编译nginx二进制文件不会出现该问题,如果你使用rpmbuild打包就要注意了
rpm -Uvh https://rpms.remirepo.net/enterprise/7/remi/x86_64/libip2location-8.0.7-1.el7.remi.x86_64.rpm

IP2Location Database Download

IP2Location offers 5 free LITE databases and 24 commercial IP geolocation databases. Free database is less accurate comparing to commercial database.

1
2
3
4
5
6
7
8
# Create new directory for IP2Location database.
mkdir -p /usr/share/ip2location
cd /usr/share/ip2location

# Go to https://lite.ip2location.com. Sign up an account for login and password.
# Download and decompress the latest IP2Location LITE database.
wget http://download.ip2location.com/lite/IP2LOCATION-LITE-DB1.BIN.ZIP
unzip IP2LOCATION-LITE-DB1.BIN.ZIP

Configuration

You need to configure Nginx to use IP2LOCATION module.

1
2
3
4
5
6
7
8
9
10
11
12
# Edit
vi /etc/nginx/nginx.conf

# Add following lines under `http` context:

http {
ip2location on;
ip2location_database /usr/share/ip2location/IP2LOCATION-LITE-DB1.BIN;
#ip2location_database /usr/share/ip2location/IP-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-ISP-DOMAIN.BIN
ip2location_access_type shared_memory;
}

可选参数 ip2location_access_type file_io|shared_memory|cache_memory
默认为 shared_memory
建议不要选择 file_io, 否则可能会严重拖慢响应速度

Syntax

Syntax: ip2location on|off
Default: off
Context: http, server, location
Description: Enable or disable IP2LOCATION Nginx module.

Syntax: ip2location_database path
Default: none
Context: http
Description: The absolute path to IP2LOCATION BIN database.

Syntax: ip2location_access_type file_io|shared_memory|cache_memory
Default: shared_memory
Context: http
Description: Set the method used for lookup.

Syntax: ip2location_proxy cidr|address
Default: none
Context: http
Description: Set a list of proxies to translate x-forwarded-for headers for.

Syntax: ip2location_proxy_recursive on|off
Default: off
Context: http
Description: Enable recursive search in the x-forwarded-for headers.

Variables

The following variables will be made available in Nginx: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ip2location_country_short
ip2location_country_long
ip2location_region
ip2location_city
ip2location_isp
ip2location_latitude
ip2location_longitude
ip2location_domain
ip2location_zipcode
ip2location_timezone
ip2location_netspeed
ip2location_iddcode
ip2location_areacode
ip2location_weatherstationcode
ip2location_weatherstationname
ip2location_mcc
ip2location_mnc
ip2location_elevation
ip2location_usagetype

You may block the traffic from United States in Nginx as below:

1
2
3
4
5
6
7
if ( $ip2location_country_short = 'US' ) {
return 444;
}

if ( $ip2location_country_short = 'SG' ) {
return 444;
}

还可以参照GeoIP的配置方法

1
2
3
4
5
6
7
8
9
10
11
12
map $ip2location_country_short $blacklist_country {
default no;
CN yes;
}

server {
listen 80;
server_name wangao.com;
if ($blacklist_country = yes) {
return 444;
}
}

浏览器访问检查nginx log结果

1
2
3
4
5
tailf /var/log/nginx/access.log

xxx - - [21/Apr/2020:17:18:11 +0800] "GET / HTTP/1.1" 200 396 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"

xxx - - [21/Apr/2020:17:18:42 +0800] "GET / HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"

IP2Location Python Library

This module is a Python Library to support all IP2Location™ database products. It has been optimized for speed and memory utilization. Developers can use this API to query all IP2Location™ binary databases for IPv4 and IPv6 address.

https://www.ip2location.com/development-libraries/ip2location/python

1
2
3
4
5
6
7
8
9
10
11
12
import IP2Location

IP2LocObj = IP2Location.IP2Location()
'''
Cache the database into memory to accelerate lookup speed.
WARNING: Please make sure your system have sufficient RAM to use this feature.
'''
# database = IP2Location.IP2Location(os.path.join("data", "IPV6-COUNTRY.BIN"), "SHARED_MEMORY")
IP2LocObj.open("data/IP-COUNTRY-REGION-CITY-LATITUDE-LONGITUDE-ZIPCODE-TIMEZONE-ISP-DOMAIN-NETSPEED-AREACODE-WEATHER-MOBILE-ELEVATION-USAGETYPE-SAMPLE.BIN")
rec = IP2LocObj.get_all("19.5.10.1")

print rec.country_short
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import IP2Location
import sys
import argparse

def ip2location_search(ip, db):
IP2LocObj = IP2Location.IP2Location()
'''
Cache the database into memory to accelerate lookup speed.
WARNING: Please make sure your system have sufficient RAM to use this feature.
'''
# database = IP2Location.IP2Location(os.path.join("data", "IPV6-COUNTRY.BIN"), "SHARED_MEMORY")
IP2LocObj.open(db)
rec = IP2LocObj.get_all(ip)
print rec.country_short

def _parse_args():
parser = argparse.ArgumentParser(description="Search IP in IP2Location Database")
parser.add_argument("-i", "--ip", help="Input ip", required=True)
parser.add_argument("-d", "--db", help="Path to ip2location db", required=True)
return parser.parse_args()

if __name__ == "__main__":
args = _parse_args()
ip = args.ip
db = args.db
ip2location_search(ip, db)

Country blocking using Nginx with IP2Location Module

After few days of trying, trying and trying, finally find out the way to compile the IP2Location module into the Nginx in Ubuntu server. I try to compare multiple way of doing the country block with Nginx, where in my previous post, the country blocking is done with GeoIP module (which I found out more easy compare to the IP2Location module), and also the country block without any 3rd party plugin for Nginx, with this method, that’s no any compilation of Nginx needed in order to make it, it’s most suitable for the current running Nginx which install directly from the APT repo.

IP2Location is one of the most famous IP location provider in the market and they are from Penang. I being use their service since many years ago and that’s the reason why I wanna try out to doing the Nginx country block with IP2Location module.

I can’t really find a full and complete step on the installing and compiling of the module, that’s why it take me many days to figure out how to make the whole thing work nicely.

The following script basically just download all necessary module source code (OpenSSL, PCRE, IP2Location C module, IP2Lacation Nginx module, Nginx 1.15 .0 source code) and compile all. After that, create the system service and put the Nginx into auto start mode and include the IP2Location database into Nginx.conf. Beside that, I also include the script to auto download the database directly from IP2Location server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
sudo apt update && sudo apt upgrade -y && \
sudo apt install build-essential dh-autoreconf unzip -y && \
sudo mkdir nginx-dev && cd nginx-dev && \

sudo wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.42.tar.gz && \
sudo tar -zxf pcre-8.42.tar.gz && \
cd pcre-8.42 && \
sudo ./configure && \
sudo make && \
sudo make install && \
cd .. && \

sudo wget http://zlib.net/zlib-1.2.11.tar.gz && \
sudo tar -zxf zlib-1.2.11.tar.gz && \
cd zlib-1.2.11 && \
sudo ./configure && \
sudo make && \
sudo make install && \
cd .. && \

sudo wget https://www.openssl.org/source/openssl-1.0.2o.tar.gz && sudo tar xzvf openssl-1.0.2o.tar.gz && \
cd openssl-1.0.2o && \
sudo ./config --prefix=/usr && \
sudo make && \
sudo make install && \
cd .. && \

sudo rm *.gz && \

sudo wget https://github.com/chrislim2888/IP2Location-C-Library/archive/master.zip && \
sudo unzip master.zip && \
cd IP2Location-C-Library-master && \
sudo autoreconf -i -v --force && \
sudo ./configure && \
sudo make && \
sudo make install && \
cd ~/nginx-dev && \
sudo rm master.zip && \

sudo wget https://github.com/ip2location/ip2location-nginx/archive/master.zip && \
sudo unzip master.zip && \
sudo rm master.zip && \
sudo sed -i 's/#include "IP2Location.h"/#include "\/home\/ubuntu\/nginx-dev\/IP2Location-C-Library-master\/libIP2Location\/IP2Location.h"/g' ~/nginx-dev/ip2location-nginx-master/ngx_http_ip2location_module.c && \
sudo mkdir /etc/ip2location && cd /etc/ip2location && \

sudo curl -o DB1-IP-COUNTRY.BIN.ZIP "https://www.ip2location.com/download?token=B7DAFhxJcAyim6NQsXWV1pGzy3deiiGUqjv5B2OOCn6YuUPWSLRTbytJCGXVZEPp&file=DB1BIN" && \
sudo unzip -o DB1-IP-COUNTRY.BIN.ZIP && \
sudo rm !(*.BIN) && \

cd ~/nginx-dev && \
sudo wget https://nginx.org/download/nginx-1.15.0.tar.gz && \
sudo tar zxf nginx-1.15.0.tar.gz && \
cd nginx-1.15.0 && \

sudo ./configure --prefix=/usr/share/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--add-module=../ip2location-nginx-master \
--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.0.2o \
--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.42 \
--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 && \

sudo make && \
sudo make install && \
sudo ldconfig && \
sudo nginx -v && sudo nginx -V && \
sudo mkdir -p /var/lib/nginx && sudo nginx -t && \

sudo echo "
[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
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target " > ~/nginx.service && \

sudo mv ~/nginx.service /etc/systemd/system/nginx.service && \

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

sudo sed -i 's/default_type application\/octet-stream;/default_type application\/octet-stream;\nip2location on;\nip2location_database \/etc\/ip2location\/IP-COUNTRY.BIN;\nip2location_access_type shared_memory;/g' /etc/nginx/nginx.conf

After finish run above command, just add the following script into your Nginx.conf or your website virtual host directive in or to make rewrite all incoming traffic to your desire destination

1
2
3
4
5
6
7
8
server{
listen 80;
server_name _;

if ($ip2location_country_short ~ ^MY$) {
rewrite ^(.*)$ http://www.google.com last;
}
}

Finally you may testing your configure by browsing the server IP using any of your browse, if you are from Malaysia, than you should be redirected to Google home page

参考文章

How to use IP2Location GeoLocation with Nginx

How to Install IP2Location Nginx Module on Debian

Upgrade to GeoIP2 with NGINX on CentOS/RHEL

文章目录
  1. 1. 前言
  2. 2. 更新历史
  3. 3. GeoIP和IP2Location简介
  4. 4. IP2Location Nginx Module
    1. 4.1. Installation
    2. 4.2. 安装备注
  5. 5. IP2Location Database Download
  6. 6. Configuration
  7. 7. Syntax
  8. 8. Variables
  9. 9. IP2Location Python Library
  10. 10. Country blocking using Nginx with IP2Location Module
  11. 11. 参考文章