Nginx中实现“白名单IP免密、其他IP需密码”需用satisfy any:先配置allow指定可信IP(如192.168.1.0/24、203.0.113.5),后接deny all兜底;再同级启用auth_basic与auth_basic_user_file,并确保二者与allow/deny共存于同一location块内。

在 Nginx 中,satisfy 指令用于组合多个访问控制条件,实现“满足任一”或“满足全部”的逻辑校验。要同时启用 IP 白名单与密码认证(即:**仅白名单 IP 可免密访问,其他 IP 必须输入正确用户名密码**),核心是使用 satisfy any 配合 allow/deny 和 auth_basic,并确保两者互为备选路径。
1. 基本配置结构:satisfy any 是关键
satisfy any 表示只要满足其中任意一个子条件(IP 允许 或 密码通过),请求即被放行;而默认的 satisfy all(隐式)要求所有条件都满足——这不符合“白名单免密”的需求。
需显式声明:
注意:必须配合 location 块内的 allow/deny 和 auth_basic 同时存在,且二者均为独立校验模块。
- 定义 IP 白名单区域(如内网段、运维固定出口 IP)
- 启用基础认证(
auth_basic+auth_basic_user_file) - 在 location 中写入
satisfy any; - 确保
deny all;放在allow之后,形成“先允后拒”的黑名单兜底
2. 完整可运行配置示例
以下配置允许来自 192.168.1.0/24 和 203.0.113.5 的请求直接访问,其余所有 IP 必须通过 HTTP Basic 认证:
location /admin/ {
satisfy any;
<pre class="brush:php;toolbar:false;"># 白名单 IP 规则(满足其一即可跳过密码)
allow 192.168.1.0/24;
allow 203.0.113.5;
deny all;
# 密码认证(当 IP 不匹配 allow 时触发)
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
重要细节:
– allow 和 deny 必须成对出现,且 deny all 不可省略,否则非白名单 IP 会因无匹配规则而被默认拒绝(Nginx 默认 deny);
– auth_basic_user_file 需提前用 htpasswd 工具生成,例如:htpasswd -c /etc/nginx/.htpasswd admin
3. 常见陷阱与避坑提示
实际部署中容易忽略以下几点,导致逻辑失效:
-
忘记写 satisfy any:默认行为等价于
satisfy all,此时用户既要符合 IP 又要输密码,完全违背设计初衷 -
allow/deny 顺序错误:Nginx 按顺序匹配,
deny all必须放在所有allow之后,否则后续规则不生效 - auth_basic 在 satisfy any 外部或缺失:必须和 allow/deny 同级定义在同一个 location 内,否则不参与校验
-
IPv6 地址未适配:若服务暴露 IPv6,需额外添加
allow 2001:db8::/32;等对应规则,IPv4 和 IPv6 规则相互独立
4. 进阶:结合 geo 或 map 实现动态白名单
当白名单 IP 较多或需按地域/角色分组时,避免在 location 中硬编码大量 allow。可用 geo 指令预定义变量:
geo $is_trusted {
default 0;
192.168.1.0/24 1;
203.0.113.5 1;
2001:db8::/32 1;
}
<p>server {
location /admin/ {
satisfy any;
allow 127.0.0.1;
if ($is_trusted) { allow all; }
deny all;</p><pre class="brush:php;toolbar:false;"> auth_basic "Admin Only";
auth_basic_user_file /etc/nginx/.htpasswd;
}
}
注意:if 在 location 中慎用,此处仅作示意;更稳妥方式是用 map + allow 配合,或直接在 geo 后用 if ($is_trusted = 1) { ... } 做条件分支(需确认 Nginx 版本支持)。










