Nginx IP过滤应分层配置、按需选型:小规则用allow/deny直写,大名单用include分离,动态策略用geo模块避免if陷阱,并叠加限速与iptables应对高频攻击。

高效不是堆规则,而是分层、可维护、不拖慢请求处理。Nginx 的 IP 过滤核心在于“用对位置、选对方式、避免冲突”。直接写 allow/deny 最快,但规模一大就难管;用 geo + if 更灵活,但多一层判断;系统级 iptables 最硬核,但脱离 Nginx 上下文。关键看你要控什么、谁在维护、规则变不变。
按层级选配置位置:location > server > http
规则越具体,优先级越高。别把白名单全塞在 http 块里——那样所有站点都受约束,改一处影响全局。
- 只限后台路径? 写在 location /admin/ { ... } 里,不影响首页或 API
- 整个域名只给内网访问? 放 server 块开头,简洁直接
- 全站统一黑白名单(如运维网段)? 才考虑 http 块,但要加注释说明影响范围
小规则用 allow/deny,大名单用 include 分离
如果允许的 IP 少于 10 个,直接写进 location 没问题。一旦超过,硬编码易出错、难同步、没法做版本管理。
- 新建文件 /etc/nginx/conf.d/ip-whitelist.conf,内容只含 allow 和 deny 行
- 在 location 或 server 中写 include /etc/nginx/conf.d/ip-whitelist.conf;
- 更新名单时只需改这个文件,nginx -t && nginx -s reload 即生效
动态策略用 geo 模块,避免 if 嵌套陷阱
geo 不是万能,但它生成变量快、无副作用,比 if ($remote_addr ~ ...) 安全得多。适合做地域分流、分级白名单、或对接外部 IP 列表。
- 在 http 块顶部定义:geo $trusted_ip { default 0; 192.168.10.0/24 1; 2001:db8::/32 1; }
- 在 location 中用:if ($trusted_ip = 0) { return 403; } ——注意,这里 return 比 deny 更明确
- 想把黑名单转白名单?把 default 设为 1,匹配项设为 0,逻辑反转即可
高频攻击场景:别只靠 allow/deny
单纯封 IP 对 CC 或扫描类攻击效果有限——攻击者换 IP 很快。必须叠加限速和连接控制。
- 加限流:用 limit_req_zone $binary_remote_addr zone=perip:10m rate=5r/s; 防暴力刷
- 加连接限制:limit_conn perip 10; 防并发耗尽资源
- 严重时配合系统层:iptables -A INPUT -s 203.0.113.45 -j DROP,绕过 Nginx 直接丢包











