转载自wx公众号小柳实验室, 在原文基础上做了修改,
在之前的帖子我有一篇帖子是ufw + ipset 防火墙:仅允许大陆与 Cloudflare 访问 80/443 一键脚本可以搞定,是针对全部站点,但是如果我需要针对其中一个站点进行限制,那还是使用nginx来得方便
前言
你的服务器是否每天被 /admin、/wp-login.php、/.env 扫描刷屏?
这些攻击 90% 来自境外。如果你的业务只服务中国大陆用户,那完全没必要开放全球访问!
更重要的是:你不需要编译 Nginx,不需要 MaxMind 账号,甚至不用装额外模块
只需利用 亚太网络信息中心(APNIC)公开的官方 IP 数据,配合 Nginx 原生功能,3 步实现精准拦截!
方案对比(供参考)
| 方案 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
| 本文方案(APNIC + allow/deny) | 免费、开源、无需模块、全平台兼容 | 需定期更新 IP 段 | 自主运维、无 CDN、追求可控 |
| CDN 地域封禁 | 5 分钟上线、自动更新、抗 DDoS | 依赖第三方、高级功能收费 | 已接入 CDN 的网站 |
| iptables + ipset | 内核层拦截,性能极高 | 配置复杂,Docker/NAT 环境需调试 | 高并发、安全敏感业务 |
| GeoIP2(MaxMind) | 支持国家/城市级判断 | 需账号、需编译 Nginx | 需要精细地理分析的场景 |
创建自动生成脚本
⚠️提醒:因为使用的是kejilion的反代脚本(docker版nginx),所以站点配置目录是/home/web/conf.d,请根据实际情况修改配置目录
sudo cat > /usr/local/bin/gen-cn-allow.sh << 'EOF'#!/bin/bash# 从 APNIC 官方数据生成 Nginx allow 规则# 适用于任意 Linux 系统OUTPUT_DIR="/home/web/conf.d"mkdir -p "$OUTPUT_DIR"echo "正在下载 APNIC 最新数据..."wget -qO- http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest | \awk -F'|' ' $2 == "CN" && $3 == "ipv4" { prefix = $4; len = 32 - log($5) / log(2); print "allow " prefix "/" len ";"; } $2 == "CN" && $3 == "ipv6" { print "allow " $4 "/" $5 ";"; }' > /tmp/cn_allow.list# 分离 IPv4 和 IPv6grep -E 'allow [0-9]+\.' /tmp/cn_allow.list > "$OUTPUT_DIR/china-ipv4.conf"grep -E 'allow [0-9a-fA-F:]+' /tmp/cn_allow.list > "$OUTPUT_DIR/china-ipv6.conf"# 添加注释头sed -i "1i# Auto-generated from APNIC — $(date)" "$OUTPUT_DIR/china-ipv4.conf"sed -i "1i# Auto-generated from APNIC — $(date)" "$OUTPUT_DIR/china-ipv6.conf"rm -f /tmp/cn_allow.listecho "✅ 中国 IP 白名单已生成:"echo " IPv4: $OUTPUT_DIR/china-ipv4.conf"echo " IPv6: $OUTPUT_DIR/china-ipv6.conf"EOF赋予执行权限
sudo chmod +x /usr/local/bin/gen-cn-allow.sh首次运行生成白名单
sudo /usr/local/bin/gen-cn-allow.sh预期输出:
正在下载 APNIC 最新数据...✅ 中国 IP 白名单已生成: IPv4: /home/web/conf.d/china-ipv4.conf IPv6: /home/web/conf.d/china-ipv6.conf验证生成的文件
# 查看 IPv4 规则数量wc -l /home/web/conf.d/china-ipv4.conf# 查看 IPv6 规则数量wc -l /home/web/conf.d/china-ipv6.conf# 查看文件前 5 行示例head -5 /home/web/conf.d/china-ipv4.conf配置 Nginx
编辑你的站点配置文件(如 /home/web/conf.d/your-site.conf)
server { listen 80; listen [::]:80; listen 443 ssl; listen [::]:443 ssl; listen 443 quic; listen [::]:443 quic; server_name www.2345.com; ssl_certificate /etc/nginx/certs/www.2345.com_cert.pem; ssl_certificate_key /etc/nginx/certs/www.2345.com_key.pem; # 引入中国 IP 白名单(顺序很重要!) include /etc/nginx/conf.d/china-ipv4.conf; include /etc/nginx/conf.d/china-ipv6.conf; # 可选:放行本地回环(避免自己被拦) allow 127.0.0.1; allow ::1; # 拒绝所有未匹配的请求 deny all; # HTTP 重定向到 HTTPS if ($scheme = http) { return 301 https://$host$request_uri; } location / { # 你的其他配置...⚠️ 关键规则:Nginx 按顺序匹配 allow/deny,必须先写 allow,再写 deny all!
实际上就是在ssl配置后面加了以下内容
# 引入中国 IP 白名单(顺序很重要!) include /etc/nginx/conf.d/china-ipv4.conf; include /etc/nginx/conf.d/china-ipv6.conf; # 可选:放行本地回环(避免自己被拦) allow 127.0.0.1; allow ::1; # 拒绝所有未匹配的请求 deny all;验证配置
docker exec nginx nginx -t重载配置(平滑生效,不影响在线用户)
docker exec nginx nginx -s reload验证方法:
国内手机 4G 访问 → 应正常打开;
使用境外代理或 VPS 访问 → 应返回 403 Forbidden;
设置定时任务
(每天凌晨 3 点自动更新)
echo "0 3 * * * root /usr/local/bin/gen-cn-allow.sh && docker exec nginx nginx -t && docker exec nginx nginx -s reload >/dev/null 2>&1" | sudo tee /etc/cron.d/update-cn-ip验证定时任务
查看 cron 任务是否创建成功
cat /etc/cron.d/update-cn-ip检查 cron 服务状态
sudo systemctl status cron⚠️ 重要注意事项
*1. CDN 用户请特别注意!*
如果你使用了 Cloudflare、阿里云 CDN、腾讯云 CDN 等:
用户真实 IP 被隐藏,Nginx 看到的是 CDN 节点 IP(多为境外);直接启用此规则会导致 所有用户被拦截!
✅ 解决方案:
在 CDN后台开启 “回源携带真实IP”(如 Cloudflare 的 CF-Connecting-IP);或改用 CDN 自带的地域封禁功能(更简单可靠)。
2. IPv6 支持按需启用
若服务器未启用IPv6,可删除listen [::]:80;和china-ipv6.conf引用。
3. 性能影响极小
中国大陆IP段约8000+条,Nginx 使用高效前缀匹配,实测无明显延迟。
评论 (0)