一、基于Nginx (非编译模块)方式限制
使用编译模块更简单,具体参考:https://nginx.org/en/docs/http/ngx_http_geoip_module.html
1. 安装 GeoIP2 模块
我使用的系统是红帽系,首先DNF或YUM安装
#RedHat 旧分支系列
yum install epel-release -y
yum install nginx-module-geoip2 -y
#RedHat部分新版发行版自带了(检查命令)
ldconfig -p | grep maxmind
#输出 libmaxminddb.so.0 (libc6,x86-64) => /lib64/libmaxminddb.so.0
#Ubuntu
apt install libnginx-mod-http-geoip2
#Nginx 自己编译加参数
--add-dynamic-module=ngx_http_geoip2_module
2. 下载 GeoIP 数据库
可以去官网注册后下载:https://www.maxmind.com/
其他镜像:
我们使用国别就可以了,因为需求是判断允许访问的国家。如果有特殊需求同样的写法。
3. Nginx 配置
配置如下,例子是只允许日本访问:
load_module modules/ngx_http_geoip2_module.so;
http {
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
$geoip_country_code country iso_code;
}
map $geoip_country_code $allowed_country {
default 0;
JP 1;
}
#网站配置
server {
listen 80;
if ($allowed_country = 0) {
return 403;
}
....
}
}
二、基于Nginx Lua方式限制
此方法依赖libmaxminddb.so,如果没有请自行安装:
#检查,如果是 so.0 是只有运行库,没有开发链接文件 需要额外安装开发包
[root@***** geoip]# ldconfig -p | grep maxmind
libmaxminddb.so.0 (libc6,x86-64) => /lib64/libmaxminddb.so.0
#安装开发包
dnf install libmaxminddb-devel -y

1、检查当前Nginx是否包含Lua模块
# 检查命令(V大写)
nginx -V

如果发现模块包含“--add-module=/www/server/nginx/src/lua_nginx_module” 即可。
2. 克隆lua-resty-maxminddb (读取数据库lua包)
测试环境为了方便使用宝塔安装的nginx 1.31版本,工作路径其实是存在的。
#克隆项目包
cd /www/server/nginx
git clone https://github.com/anjia0532/lua-resty-maxminddb.git
#复制到工作路径
mkdir -p /www/server/nginx/lib/lua/resty/
cp lua-resty-maxminddb/lib/resty/maxminddb.lua /www/server/nginx/lib/lua/resty/
#检查
ls /www/server/nginx/lib/lua/resty/

3. nginx 配置&测试
#打开Nginx配置路径(宝塔环境可以跳过,因为已经有这个配置了,而且是同一个路径)
vi /www/server/nginx/conf/nginx.conf
#在http下增加,如果已经有了添加“;”后继续补上这个地址,nginx只允许设置一个
lua_package_path "/www/server/nginx/lua/?.lua;;";
#lua_package_path 多路径用“;”分割。
测试require
mkdir -p /www/server/nginx/lua
vi /www/server/nginx/lua/test.lua
#内容
local mmdb = require "resty.maxminddb"
ngx.say("ok")
#找一个server中添加
location /lua-test {
default_type text/html;
charset utf-8;
content_by_lua_file /www/server/nginx/lua/test.lua;
}
#nginx 测试
nginx -t
#nginx reload 后访问
nginx -s reload
4. GeoIP数据导入
数据和第一章下载数据库一致,将数据库文件上传到服务器即可。
# 创建文件夹
mkdir -p /www/geoip
#下载到此目录,也可以自己上传
wget https://git.io/GeoLite2-Country.mmdb
#写一个新的lua脚本
vi /www/server/nginx/lua/geo.lua
geo.lua
ngx.header.content_type = "text/html; charset=utf-8"
local maxminddb = require "resty.maxminddb"
maxminddb.init("/www/geoip/GeoLite2-Country.mmdb")
local data = maxminddb.lookup(ngx.var.remote_addr)
if data then
ngx.say("IP: ", ngx.var.remote_addr)
ngx.say("<br>")
ngx.say("Country: ", data.country.iso_code)
else
ngx.say("unknown")
end
记得一定要重载nginx
nginx -s reload
访问测试:

5. 写一个只允许中国访问的脚本
local maxminddb = require "resty.maxminddb"
-- 初始化数据库
maxminddb.init("/www/geoip/GeoLite2-Country.mmdb")
-- 获取客户端IP
local ip = ngx.var.remote_addr
-- 查询国家
local res = maxminddb.lookup(ip)
if not res or not res.country then
ngx.exit(403)
end
local country = res.country.iso_code
-- 只允许中国
if country ~= "CN" then
ngx.status = 403
ngx.say("您所在的国家禁止访问哦!")
ngx.exit(403)
end
#允许中日美
local allow = {
CN = true,
JP = true,
US = true
}
if not allow[country] then
ngx.exit(403)
end
6. 生产优化
nginx支带了内存字典,可以把数据库放入内存里面,分配10M就够,国家数据库只有8M左右。和上面每个请求请求一次都要单独创建更高效。
# nginx配置
http {
lua_shared_dict geoip 10m;
init_by_lua_block {
local maxminddb = require "resty.maxminddb"
maxminddb.init(
"/www/geoip/GeoLite2-Country.mmdb"
)
}
}
#lua脚本
local maxminddb = require "resty.maxminddb"
local res = maxminddb.lookup(
ngx.var.remote_addr
)
如果要全局生效,就把脚本放到nginx全局配置文件,http下
http{
.......
access_by_lua_file /www/server/nginx/lua/country_allow.lua;
.......
}
COMMENTS
评论 0
安全验证