Nginx自定义403页面需单独配置location = /403.html并显式放行,否则因deny规则拦截或文件不可读导致空白页;须设root、allow all、internal,且确保文件存在、权限正确、SELinux上下文合规。

直接加 error_page 403 /403.html 很可能无效,页面仍是空白或默认白页——根本原因不是配置没写,而是 Nginx 在触发 403 后,会用当前 location 的 root 去找 /403.html,而该路径往往被 deny 规则拦住,或文件压根不可读。
必须单独配置 location = /403.html 并显式放行
Nginx 处理 error_page 是发起一次内部子请求,这个请求仍受外层 location / 的 allow/deny 控制。所以哪怕你写了 deny all,也得为错误页 URI 单独开一个“绿色通道”:
- 用
location = /403.html精确匹配,避免正则或前缀干扰 - 必须加
allow all;(或按需限制),否则照样被拒 - 显式指定
root目录,例如root /usr/share/nginx/html;(注意是目录,不是完整路径) - 推荐加上
internal;,防止用户绕过规则直击/403.html
确保文件真实存在且权限正确
配置再对,/403.html 文件本身打不开,Nginx 就会 fallback 到内置白页:
- 检查文件路径:比如
root /usr/share/nginx/html;+location = /403.html→ 实际路径是/usr/share/nginx/html/403.html - 确认文件可读:
ls -l /usr/share/nginx/html/403.html,Nginx worker 进程用户(如nginx或www-data)要有读权限 - SELinux 启用时,还需检查上下文:
ls -Z /usr/share/nginx/html/403.html,必要时执行restorecon -Rv /usr/share/nginx/html
拦截扫描 IP 后返回自定义页的典型写法
以基于 IP 拦截(如用 geo + map 或第三方模块)或简单 deny 为例,完整配置片段如下:
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
http {
# 示例:用 geo 定义恶意 IP 段(实际中可对接实时黑名单)
geo $bad_ip {
default 0;
192.168.100.0/24 1;
203.0.113.5 1;
}
<pre class="brush:php;toolbar:false;">map $bad_ip $blocked {
1 1;
default 0;
}}
server { location / { if ($blocked) { return 403; }
其他正常逻辑...
error_page 403 /403.html;
}
location = /403.html {
internal;
root /usr/share/nginx/html;
allow all;
}}
注意:if 在 location 中慎用,生产环境更推荐用 geo+map 预处理变量,或使用 ngx_http_geoip2_module 等成熟方案。
安全加固:让 403 不暴露路径存在性
扫描器看到 403,就知道路径真实存在。若想隐藏,可统一返回 404 或跳转通用页:
- 对敏感路径(如
/.git、/config.php)直接return 404;,不走 403 流程 - 关闭版本泄露:
server_tokens off; - 自定义页面 HTML 内容里不要含服务器、路径、Nginx 版本等信息
- 反向代理场景下,加
proxy_hide_header Server;防止后端暴露

















