
不论在自己公司还是客户那儿的搭建的 WEB服务器,一旦将其端口或IP映射到公网,基本每秒都在遭受全球范围内的自动化扫描与入侵尝试。其中,又以美国IP的异常请求尤为猖獗,成为国内服务器安全防护需要重点关注的对象。为此,本文将以 Ubuntu 24.04 为操作环境,详细介绍如何在Nginx 1.24 中使用 GeoIP2 模块,过滤屏蔽特定国家/地区(以美国为例)的IP访问,希望可以帮助你上线的服务器,一定程度上减少被攻陷的机率。sudo apt updatesudo apt install -y software-properties-common unzip vim
sudo apt install -y nginx libnginx-mod-http-geoip2
root@P15:/
mkdir /usr/share/GeoIP
| 数据库说明 | 说明 | 文件大小 |
| GeoLite2-City | 城市级别地理位置数据 | ~70MB |
| GeoLite2-Country | 国家级别地理位置数据 | ~7MB |
| GeoLite2-ASN | ASN 网络运营商数据 | ~9MB |
Maxminds 网站的数据最权威、更新最及时,但需要注册账户并获取许可证密钥才能实现数据库的自动更新
https://www.maxmind.com/en/geolite2/signup
DB-IP 提供了 MMDB 格式和 CSV 格式的完全免费、无需注册的数据库,访问地址如下:
https://db-ip.com/db/lite.php
可以通过下面的命令进行数据库更新,将文件放到 /usr/share/GeoIP 目录
cd /usr/share/GeoIP && wget https://download.db-ip.com/free/dbip-country-lite-$(date +%Y-%m).mmdb.gzgunzip -f dbip-country-lite-$(date +%Y-%m).mmdb.gzrm -rf /usr/share/GeoIP/*.mmdb.gzmv -f dbip-country-lite-$(date +%Y-%m).mmdb GeoLite2-Country.mmdb
用户 lwpk110 在 Github 上提供了 MaxMind GeoLite2、DB-IP 等数据库的自动化下载和发布服务。因下载的文件名包含年月日等信息,且不是每日更新,故无法使用常规命令行方式,实现数据库文件的自动更新。但是,它提供开箱即用的 GeoIP 查询 API 服务和 Web 界面,支持Docker轻量部署,一键启动。感兴趣的朋友可以访问下面的访问深入学习
https://github.com/lwpk110/free-geoip-databases
mmdblookup 是一个命令行工具,主要用途是查询和读取特定 IP 地址在数据库文件(后缀为 .mmdb)中的的地理位置信息
apt install mmdb-bin
mmdblookup --file /usr/share/GeoIP/GeoLite2-Country.mmdb --ip 8.8.8.8
mmdblookup --file /usr/share/GeoIP/GeoLite2-Country.mmdb --ip 8.8.8.8 country iso_code
执行上面的命令后,会返回下面的结果:
{"continent": { "code": "NA" <utf8_string> "geoname_id": 6255149 <uint32> "names": { "de": "Nordamerika" <utf8_string> "en": "North America" <utf8_string> "es": "Norteamérica" <utf8_string> "fa": " امریکای شمالی" <utf8_string> "fr": "Amérique Du Nord" <utf8_string> "ja": "北アメリカ大陸" <utf8_string> "ko": "북아메리카" <utf8_string> "pt-BR": "América Do Norte" <utf8_string> "ru": "Северная Америка" <utf8_string> "zh-CN": "北美洲" <utf8_string> } }"country": { "geoname_id": 6252001 <uint32> "is_in_european_union": false <boolean> "iso_code": "US" <utf8_string> "names": { "de": "Vereinigte Staaten von Amerika" <utf8_string> "en": "United States" <utf8_string> "es": "Estados Unidos de América (los)" <utf8_string> "fa": "ایالات متحدهٔ امریکا" <utf8_string> "fr": "États-Unis" <utf8_string> "ja": "アメリカ合衆国" <utf8_string> "ko": "미국" <utf8_string> "pt-BR": "Estados Unidos" <utf8_string> "ru": "США" <utf8_string> "zh-CN": "美国" <utf8_string> } }}
使用 vim 打开目标文件 /etc/nginx/nginx.conf,在http块中进行如下配置。以美国为例,禁止通过公网访问此服务器。
user www-data;worker_processes auto;pid /run/nginx.pid;error_log /var/log/nginx/error.log;include /etc/nginx/modules-enabled/*.conf;
events { worker_connections 768; }
http { geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb { $geoip2_country_code country iso_code; } map $geoip2_country_code $deny_country { default no; US yes; }
sendfile on; tcp_nopush on; types_hash_max_size 2048;
include /etc/nginx/mime.types; default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
gzip on;
include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*;}
使用 vim 打开目标文件 /etc/nginx/sites-enabled/default,在server块中进行如下配置,应用禁止美国访问的规则。
server { listen 80 default_server; listen [::]:80 default_server;
if ($deny_country = yes) { return 403 "Access denied from your region.\n"; }
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / { try_files $uri $uri/ =404; }}
检查配置是否正确
sudo nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful
重新加载 nginx 使配置生效
sudo mmdblookup --file /usr/share/GeoIP/GeoLite2-Country.mmdb --ip <美国IP地址> country iso_code
执行下面的命令,生成 update_geoip.sh 的脚本用来实现数据库文件的更新
cat >> /usr/share/GeoIP/update_geoip.sh << 'EOF'#!/bin/bashcd /usr/share/GeoIP || exit 1
CURRENT_DATE=$(date +%Y-%m)DBIP_FILE="dbip-country-lite-${CURRENT_DATE}"GZ_FILE="${DBIP_FILE}.mmdb.gz"DOWNLOAD_URL="https://download.db-ip.com/free/${GZ_FILE}"
wget -q -O "$GZ_FILE" "$DOWNLOAD_URL"
gunzip -f "$GZ_FILE"
rm -f ./*.mmdb.gz
mv -f "${DBIP_FILE}.mmdb" "GeoLite2-Country.mmdb"EOF
为脚本添加可执行权限
chmod +x /usr/share/GeoIP/update_geoip.sh
将脚本添加到 crontab 的月度计划
(crontab -l 2>/dev/null; echo "0 3 20 * * /usr/share/GeoIP/update_geoip.sh") | crontab -
验证 crontab 配置
crontab -lsudo crontab -l
nginx版本要求:为保证 geoip2 模块的正常使用,建议安装的 nginx 版本至少要需要满足 1.9.11 或 以上
使用 map的优势:map 指令在 Nginx 启动时即完成映射表的构建,在请求处理阶段只需进行高效的哈希查找,性能远优于在多个 location 中使用 if 条件判断。
处理代理和 CDN:如果你的 Nginx 前方有 CDN(如 Cloudflare)或负载均衡器(LSB),真实客户端 IP 地址可能存在于 X-Forwarded-For 等请求头中。这时你需要使用 geoip2_proxy 指令来指定可信的代理 IP 段,并告诉模块从正确的头部读取 IP。
http { geoip2_proxy 10.0.0.0/8; # 您的内网或代理IP段 geoip2_proxy_recursive on; # 递归地从 X-Forwarded-For 中取最左侧的非代理IP geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb { $geoip2_country_code country iso_code; }}
map $geoip2_country_code $allow_country { default no; CN yes; HK yes; }server { if ($allow_country = no) { return 403; } }
通过以上步骤,我们就可以构建一个基于国家地理位置的WEB访问控制策略,能够有效拦截源自特定国家(如美国)的流量,提升了上线服务器的带宽利用率和安全性。
该文章在 2026/5/11 10:25:29 编辑过