deny 放在 location 块内无效,因该指令仅在 http、server 或 limit_except 上下文中合法;正确位置是 server 块顶层、所有 location 外,且需重载配置生效。

直接在网站配置文件里加 deny 语句是可行的,但必须写在 server 块顶层(location 外),否则完全不生效。
为什么 deny 放在 location 里没用
Nginx 的 deny 指令只在 http、server 或 limit_except 上下文中合法;放进 location 块会导致 Nginx 启动报错或静默忽略规则。宝塔用户常误以为“在配置文件里随便找个位置粘贴就行”,结果测试时发现 IP 还能正常访问,就是栽在这个点上。
- 错误写法:
location / { deny 203.0.113.5; }→ 规则无效 - 正确位置:在
server { ... }开头大括号内、任何location块之前 - 验证是否生效:改完保存后必须点【重载配置】,不是重启 Nginx,也不是只点保存
怎么写 deny 才支持 CIDR 和单 IP
deny 原生命令天然支持 CIDR 表示法,无需额外模块,语法简洁且性能高。它比宝塔后台「网站 → 安全 → IP 黑名单」生成的 if ($remote_addr = ...) 更底层、开销更低。
- 屏蔽单个 IP:
deny 203.0.113.5; - 屏蔽网段:
deny 192.168.100.0/24;(注意末尾分号不能漏) - 可叠加多条:
deny 203.0.113.0/28;、deny 2001:db8::/32;(IPv6 需确认 Nginx 编译时启用了 IPv6 支持) - 顺序重要:Nginx 自上而下匹配,先写的规则优先;
deny all;应放在最后作为兜底
容易被忽略的拦截干扰源
你加了 deny 却发现某 IP 访问失败,未必是你刚配的规则在起作用——更可能是其他层提前拦截了。
- 检查系统防火墙:
iptables -L INPUT -n | grep :80或firewall-cmd --list-all,看是否有REJECT规则针对该 IP - 云厂商安全组(阿里云/腾讯云)优先级最高,若入方向放行了
0.0.0.0/0,Nginx 根本收不到包,deny就是摆设 - CDN 或反向代理(如 Cloudflare)会把真实 IP 替换为节点 IP,此时
$remote_addr是 CDN 的 IP,需配合real_ip模块和可信代理列表使用 - 宝塔「网站 → 安全 → IP 黑名单」和你手写的
deny可共存,但重复屏蔽同一 IP 不叠加效果,以最先匹配的server块内规则为准
真正生效的黑名单,是层层校验后最后一道由 Nginx 执行的 deny;只要写错位置、没重载、或被更高层截断,就等于没设。











