如何在 Ubuntu 16.04 上使用 GeoIP 和 Nginx
本教程适用于这些操作系统版本
- Ubuntu 16.04(Xenial Xerus)
- Ubuntu 11.04(Natty Narwhal)
在此页
- 1 条初步说明
- 2 查看 Nginx 是否支持 GeoIP
- 3 下载 GeoIP 数据库
- 4 配置 Nginx
- 5 一个简短的测试
- 6 个链接
本教程介绍了如何在 Ubuntu 16.04 上使用带有 nginx 的 GeoIP 模块来找出访问者的来源。 GeoIP 模块设置了多个变量,如 $geoip_country_name、$geoip_country_code、$geoip_city 等,您可以在 PHP 脚本中或直接在 nginx 配置中使用这些变量,例如根据用户国家/地区以不同语言提供内容。
1 初步说明
我在这里使用网站 www.example.com,文档根 /var/www/www.example.com/web/ 和 Nginx vhost 配置文件 /etc/nginx/sites-enabled/www.example.com.vhost。我将使用本教程进行基本的 Ubuntu-Nginx 设置。
本教程也与 ISPConfig nginx 设置兼容。
给 Ubuntu 用户的注意事项:
因为我们必须以 root 权限运行本教程中的所有步骤,所以我们可以在本教程中的所有命令前加上字符串 sudo,或者我们现在通过键入成为 root
sudo -s
2 查看Nginx是否支持GeoIP
在我们开始之前,我们必须找出 GeoIP 模块是否内置到我们的 nginx 服务器中:
nginx -V
:~# nginx -V
nginx version: nginx/1.10.0 (Ubuntu)
built with OpenSSL 1.0.2g-fips 1 Mar 2016
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --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-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads
3 下载 GeoIP 数据库
在 Debian 和 Ubuntu 上,有包 geoip-database 可以通过 apt 安装,但它有点过时,只包含 GeoIP.dat(国家数据库),而不包含 GeoLiteCity.dat(城市数据库)。因此我们不安装那个包,而是从 GeoIP 网站下载新的副本到 /etc/nginx/geoip 目录:
mkdir /etc/nginx/geoip
cd /etc/nginx/geoip
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
gunzip GeoIP.dat.gz
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz
4 配置 Nginx
现在我们配置nginx。打开 /etc/nginx/nginx.conf...
nano /etc/nginx/nginx.conf
...并将 geoip_country 和 geoip_city 指令添加到 http {} 容器:
[...]
http {
##
# Basic Settings
##
geoip_country /etc/nginx/geoip/GeoIP.dat; # the country IP database
geoip_city /etc/nginx/geoip/GeoLiteCity.dat; # the city IP database
[...]
geoip_country 指令使以下变量可用:
- $geoip_country_code - 两个字母的国家/地区代码,例如 RU、US。
- $geoip_country_code3 - 三字母国家代码,例如 RUS、USA。
- $geoip_country_name - 国家的(详细)名称,例如俄罗斯联邦、美国等。
geoip_city 指令提供以下变量:
- $geoip_city_country_code - 两个字母的国家/地区代码,例如 RU、US。
- $geoip_city_country_code3 - 三字母国家代码,例如 RUS、USA。
- $geoip_city_country_name - 国家名称,例如俄罗斯联邦、美国 - 如果可用。
- $geoip_region - 地区名称(省、地区、州、省、联邦土地等),例如莫斯科市特区 - 如果可用。
- $geoip_city - 城市名称,例如莫斯科、华盛顿、里斯本等 - 如果可用。
- $geoip_postal_code - 邮政编码或邮政编码 - 如果可用。
- $geoip_city_continent_code - 如果可用。
- $geoip_latitude - 纬度 - 如果可用。
- $geoip_longitude - 经度 - 如果可用。
为了使这些变量也可用于您的 PHP 脚本,我们必须设置一些 fastcgi_param 指令。最好在文件 /etc/nginx/fastcgi_params 中执行此操作,其中其他 fastcgi_param 指令是:
nano /etc/nginx/fastcgi_params
[...]
### SET GEOIP Variables ###
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;
(确保您的虚拟主机配置中包含 /etc/nginx/fastcgi_params; 在您的位置 ~ \.php${} 容器中,否则,上述配置对您的虚拟主机毫无用处。)
如果您使用 nginx 作为反向代理并希望将 GeoIP 变量传递到后端,您应该创建/编辑文件 /etc/nginx/proxy.conf...
nano /etc/nginx/proxy.conf
...并向其中添加以下行:
[...]
### SET GEOIP Variables ###
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;
(确保在您的 nginx 代理配置中使用 include /etc/nginx/proxy.conf; 行,否则后端无法使用 GeoIP 变量。)
现在重新加载nginx ...
systemctl reload nginx.service
...以使更改生效。
重启PHP-FPM如下:
systemctl restart php7.0-fpm.service
5 一个简短的测试
要查看 GeoIP 模块是否正常工作,我们可以在我们的 www.example.com 网络空间(例如 /var/www/www.example.com/web)中创建一个小的 PHP 文件:
nano /var/www/www.example.com/web/geoiptest.php
我们可以按如下方式访问 GeoIP 变量:
$geoip_country_code = getenv(GEOIP_COUNTRY_CODE);
或者像这样:
$geoip_country_code = $_SERVER['GEOIP_COUNTRY_CODE'];
<html>
<body>
<?php
$geoip_country_code = getenv(GEOIP_COUNTRY_CODE);
/*
$geoip_country_code = $_SERVER['GEOIP_COUNTRY_CODE']; // works as well
*/
$geoip_country_code3 = getenv(GEOIP_COUNTRY_CODE3);
$geoip_country_name = getenv(GEOIP_COUNTRY_NAME);
$geoip_city_country_code = getenv(GEOIP_CITY_COUNTRY_CODE);
$geoip_city_country_code3 = getenv(GEOIP_CITY_COUNTRY_CODE3);
$geoip_city_country_name = getenv(GEOIP_CITY_COUNTRY_NAME);
$geoip_region = getenv(GEOIP_REGION);
$geoip_city = getenv(GEOIP_CITY);
$geoip_postal_code = getenv(GEOIP_POSTAL_CODE);
$geoip_city_continent_code = getenv(GEOIP_CITY_CONTINENT_CODE);
$geoip_latitude = getenv(GEOIP_LATITUDE);
$geoip_longitude = getenv(GEOIP_LONGITUDE);
echo 'country_code: '.$geoip_country_code.'<br>';
echo 'country_code3: '.$geoip_country_code3.'<br>';
echo 'country_name: '.$geoip_country_name.'<br>';
echo 'city_country_code: '.$geoip_city_country_code.'<br>';
echo 'city_country_code3: '.$geoip_city_country_code3.'<br>';
echo 'city_country_name: '.$geoip_city_country_name.'<br>';
echo 'region: '.$geoip_region.'<br>';
echo 'city: '.$geoip_city.'<br>';
echo 'postal_code: '.$geoip_postal_code.'<br>';
echo 'city_continent_code: '.$geoip_city_continent_code.'<br>';
echo 'latitude: '.$geoip_latitude.'<br>';
echo 'longitude: '.$geoip_longitude.'<br>';
?>
</body>
</html>
在浏览器中调用该文件 (http://www.example.com/geoiptest.php),您应该会看到 GeoIP 正在工作(确保您是从公共 IP 地址而不是本地 IP 地址调用该文件):

也可以直接在 nginx 配置中使用 GeoIP 变量,例如如下:
nano /etc/nginx/sites-enabled/www.example.com.vhost
[...]
location / {
index index.html index.php;
try_files /index_$geoip_country_code.html /index.html;
}
[...]
systemctl reload nginx.service
在此示例中,如果访问者来自德国(国家代码:DE),并且文件 index_DE.html 存在,则提供此文件,否则提供默认的 index.html 文件。
这可用于根据用户来源提供不同语言的内容。
6个链接
- nginx:http://nginx.org/
- nginx 维基:http://wiki.nginx.org/
- Ubuntu:http://www.ubuntu.com/