使用 Nginx 和 GeoIP 模块来处理不同国家的访问

如果想屏蔽某个地区的 IP 访问的话,用 iptables 把来自某个国家的 IP 重定向到预定页面不是特别灵活的办法,如果只有一个 IP 可用而有多个网站在同一 VPS 上怎么办?用 iptable 屏蔽某个网站的话也会屏蔽同一 VPS 上的其他网站的访问。所以正统的办法还是用 GeoIP 配合对应的 web 服务器模块,比如:apache + mod_geoip 或者 nginx + http_geoip_module 等。

安装 Nginx

因为要用到 http_geoip_module 模块,系统自带的 nginx 一般不带这个模块,所以要下载 nginx 源代码后自行编译:

# wget http://nginx.org/download/nginx-0.9.6.tar.gz
# tar zxvf nginx-0.9.6.tar.gz
# cd nginx-0.9.6
# ./configure --without-http_empty_gif_module --with-poll_module \
--with-http_stub_status_module --with-http_ssl_module \
--with-http_geoip_module
# make; make install

安装 MaxMind 的 GeoIP 库

MaxMind 提供了免费的 IP 地域数据库(GeoIP.dat),不过这个数据库文件是二进制的,需要用 GeoIP 库来读取,所以除了要下载 GeoIP.dat 文件外(见下一步),还需要安装能读取这个文件的库。

# wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP.tar.gz
# tar -zxvf GeoIP.tar.gz
# cd GeoIP-1.4.6
# ./configure
# make; make install

刚才安装的库自动安装到 /usr/local/lib 下,所以这个目录需要加到动态链接配置里面以便运行相关程序的时候能自动绑定到这个 GeoIP 库:

# echo '/usr/local/lib' > /etc/ld.so.conf.d/geoip.conf
# ldconfig

下载 IP 数据库

MaxMind 提供了免费的 IP 地域数据库,这个数据库是二进制的,不能用文本编辑器打开,需要上面的 GeoIP 库来读取:

# wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
# gunzip GeoIP.dat.gz

配置 Nginx

最后是配置 nginx,在相关地方加上如下的配置就可以了:

# vi /etc/nginx/nginx.conf

http {
...
geoip_country /home/vpsee/GeoIP.dat;
fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
fastcgi_param GEOIP_COUNTRY_CODE3 $geoip_country_code3;
fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;
...
}

server {
...
        location / {
            root   /home/vpsee/www;
            if ($geoip_country_code = CN) {
                root /home/vpsee/cn;
            }
            ...
        }
...
}

这样,当来自中国的 IP 访问网站后就自动访问到预定的 /home/vpsee/cn 页面。关于 Nginx + GeoIP 还有很多有用的用法,比如做个简单的 CDN,来自中国的访问自动解析到国内服务器、来自美国的访问自动转向到美国服务器等。MaxMind 还提供了全球各个城市的 IP 信息,还可以下载城市 IP 数据库来针对不同城市做处理。

评论 (14 Comments)

  1. GeoIP准不。

  2. 应该准吧~,MaxMind 靠这个赚钱呢(他们还有付费版本的 GeoIP)。

  3. 请问将一个物理机(双核,2G内存)虚拟成两个虚拟机(各独占一个processor,各1G内存)。然后在这两个虚拟机上分别同时运行互不相关的task0和task1,消耗时间为t0

    直接在物理机上面同时运行task0和task1,消耗时间为t1

    那么t1通常比t0大百分之几?有没有这方面的测试数据啊?
    谢谢!

  4. 直接在物理机上运行要快一些,因为 CPU 不用在虚拟机之间做切换,虚拟技术的目的是提高服务器的整体利用率和整体性能,针对单个任务虚拟机和同配置的物理机相比性能损失2%-5%左右。

  5. 谢谢你的回复!你起得真早,呵呵。

    将一个物理机(双核,2G内存)虚拟成两个虚拟机(各独占一个processor,各1G内存)。然后在这两个虚拟机上分别同时运行互不相关的task0和task1,消耗时间为t0

    直接在这物理机上面同时运行task0和task1,消耗时间为t1

    将该物理机虚拟化成一台虚拟机,然后同时运行task0和task1,消耗时间为t2

    最后结果是不管什么情况下t2基本比t1多2%-5%左右,但是t0有些情况下(task0,task1对计算资源消耗没有竞争)也只比t1多2%-5%左右,更多的情况下(task0,task1对计算资源消耗有竞争)t0是t1好几倍。所以我觉得,如果将一台物理机虚拟成两台虚拟机后,这两台虚拟机的计算能力之和可能远远比不上他的物理host,性能损耗严重。

    谢谢

  6. GeoIP 网上下得到的一般都不准,我有对比过新浪,跟QQ的ip库。 GeoIP 用于国际还行,国内不行吧

  7. GeoIP 国家判断还是比较准的。

  8. 这样的话,每个国家都要判断,首页登录会不会慢一点啊?

  9. 我怎么用你这个实现不了,博主可以加QQ咨询吗

  10. lz geoip里面有timezone功能,但是返回的是字符串,不是具体的时区号。我应该怎么将字符串转换成具体的时区数字编号呢?

  11. 我第一安装 http_geoip_module模块就出错了。。错误代码:
    ./configure: error: the GeoIP module requires the GeoIP library.
    You can either do not enable the module or install the library.
    博主能看下什么问题吗?

  12. @lnmp
    上面的顺序有点问题,你可能需要先 “安装 MaxMind 的 GeoIP 库”,再 “安装 Nginx” 和 “http_geoip_module 模块”。

  13. @vpsee
    可以了。。安装顺序变换一下就可以了。。
    root /home/vpsee/www;
    if ($geoip_country_code = CN) {
    root /home/vpsee/cn;
    }
    下面那个root /home/vpsee/cn 我改成rewrite 到一个网址应该可以吧。。

  14. 楼主,我还想问下。。就是不同国家来自不懂的网站,这个要怎么设置呢?

发表评论