Nginx 如何实现访问控制?有哪些访问控制方法?
Nginx 如何实现访问控制?有哪些访问控制方法?
Nginx 的访问控制是后端面试高频考点,核心思路是"在反向代理层拦截非法请求,减轻后端压力"。主要方法有五种:IP 黑白名单、HTTP 基本认证、请求方法限制、基于请求头的鉴权、地理/时间条件控制,实战中往往组合使用。下面逐一拆解原理和配置要点。
一、IP 黑白名单:最基础的网络层控制
Nginx 通过 allow / deny 指令按 IP 或 CIDR 段做访问控制,规则从上到下依次匹配,命中即生效:
nginxlocation /admin { allow 192.168.1.0/24; # 内网放行 allow 10.0.0.0/8; # VPN 段放行 deny all; # 其余全部拒绝 proxy_pass http://backend; }
注意事项:
- 当客户端经过代理时,
$remote_addr拿到的是代理 IP 而非真实客户端 IP,需要配合$http_x_forwarded_for或realip模块获取真实地址 - 白名单优先于黑名单是安全最佳实践——默认拒绝,显式放行
二、HTTP 基本认证:用户名密码验证
使用 auth_basic + auth_basic_user_file 实现,密码文件通过 htpasswd 工具生成:
nginxlocation /admin { auth_basic "Admin Area"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_pass http://backend; }
生成密码文件:
bashhtpasswd -c /etc/nginx/.htpasswd admin_user
关键点: Basic Auth 的凭据是 Base64 编码而非加密,生产环境务必搭配 HTTPS 使用,否则密码可被中间人截获。
三、请求方法限制:只允许特定 HTTP 方法
用 limit_except 指令比 if ($request_method) 更规范,它在 location 级别做方法白名单:
nginxlocation /api { limit_except GET POST { deny all; # 只允许 GET 和 POST,其他方法返回 403 } proxy_pass http://api_backend; }
与 if 写法的区别: limit_except 是 Nginx 官方推荐的方式,不会触发 "if is evil" 问题,且与 satisfy 指令配合更好。
四、基于请求头的鉴权:API Key、Referer、User-Agent
API Key 校验:
nginxmap $http_x_api_key $api_valid { default 0; "sk_prod_abc123" 1; "sk_prod_def456" 1; } location /api { if ($api_valid = 0) { return 401; } proxy_pass http://api_backend; }
用 map 比 if 直接比较更灵活,支持多 key 映射且可集中管理。
防盗链(Referer 校验):
nginxlocation /images/ { valid_referers none blocked server_names *.example.com; if ($invalid_referer) { return 403; } root /var/www/images; }
UA 过滤: 屏蔽恶意爬虫
nginxif ($http_user_agent ~* (bot|crawler|spider|scraper)) { return 403; }
五、地理与时间条件控制
地理位置限制(基于 geo 模块):
nginxgeo $allowed_country { default no; CN yes; US yes; } server { location / { if ($allowed_country = no) { return 403; } proxy_pass http://backend; } }
如需精确到城市级,可用 geoip 模块配合 MaxMind 数据库。
时间条件限制:
nginxmap $time_iso8601 $business_hours { default 0; ~^(\d{4}-\d{2}-\d{2}T(09|1[0-9]|2[0-1])) 1; } location /admin { if ($business_hours = 0) { return 403; } proxy_pass http://backend; }
适合管理后台只在工作时段开放的场景。
六、组合策略:satisfy 指令与多层防护
satisfy any 表示满足任一条件即可访问,satisfy all 表示必须全部满足:
nginxlocation /admin { satisfy any; # IP 白名单 或 密码认证,满足其一即可 allow 192.168.1.0/24; deny all; auth_basic "Admin Area"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_pass http://backend; }
实战建议: 管理后台常用 satisfy any——内网 IP 免密码,外网需要认证;API 接口常用 satisfy all——IP + Key 双重验证。
七、安全加固:敏感文件与目录防护
nginx# 禁止访问隐藏文件(如 .git、.env) location ~ /\. { deny all; access_log off; log_not_found off; } # 禁止访问敏感后缀文件 location ~* \.(htaccess|htpasswd|ini|log|sh|sql|bak|swp)$ { deny all; access_log off; } # 禁止目录遍历 autoindex off;
这些规则应作为 Nginx 配置的基线安全策略,防止信息泄露。
面试追问与核心要点
Q:Nginx 访问控制的执行顺序是什么?
allow/deny 按配置顺序从上到下匹配,先命中先生效。location 内的规则优先于 server 级别,server 级别优先于 http 级别。
Q:satisfy any 和 satisfy all 的区别?
any 是"或"逻辑——IP 白名单和认证满足其一即可;all 是"与"逻辑——两者都必须通过。默认是 all。
Q:代理场景下 IP 限制为什么不生效?
因为 $remote_addr 拿到的是上一层代理的 IP。解决方案:使用 ngx_http_realip_module 设置 set_real_ip_from 和 real_ip_header X-Forwarded-For 还原真实客户端 IP。
Q:if 指令在 location 中有什么陷阱?
Nginx 的 if 在 location 中属于 rewrite 阶段,可能导致非预期行为("if is evil")。能用 map、limit_except、allow/deny 替代的就避免用 if。