2人参与 • 2026-09-22 • 硬盘
在 centos 7 上用 nginx 部署一个静态站点,root 指向非标准目录 /data/www,监听自定义端口 12000。过程中连续踩了两个坑:
bind() to 0.0.0.0:12000 failed (13: permission denied)"/data/www/index.html" is forbidden (13: permission denied)两个错误的共同点都是 13: permission denied,但根因都是 selinux,而不是普通的文件权限或端口占用。本文把整个排查过程整理出来,供遇到类似问题的同学参考。
/data/www12000127.0.0.1:180systemctl status nginx.service nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: [emerg] bind() to 0.0.0.0:12000 failed (13: permission denied) nginx: configuration file /etc/nginx/nginx.conf test failed
12000 虽然是高于 1024 的端口,普通用户理论上可以绑定,但在 selinux enforcing 模式下,selinux 策略默认只允许 http 服务绑定 http_port_t 类型里的端口。12000 不在允许列表中,所以 nginx 的 worker 进程(非 root)绑定该端口时被 selinux 拒绝。
把 12000 加入 http_port_t 类型:
semanage port -a -t http_port_t -p tcp 12000 # 验证 semanage port -l | grep http_port_t
如果 semanage 不存在,先安装:
yum install -y policycoreutils-python
然后重启 nginx:
systemctl restart nginx
setenforce 0 后重启,能启动即确认是 selinux 问题,但不推荐长期关闭。httpd_can_network_connect:可以解决绑定问题,但这个布尔值本来是放行出站连接的,用它解决绑定问题会放宽不必要权限,有安全风险。推荐方案一:只放行单个端口,最小化改动。
nginx 启动正常,访问 http://10.2.2.240:12000/ 有请求日志,但返回 403:
"/data/www/index.html" is forbidden (13: permission denied), client: 10.2.2.240, server: localhost, request: "get / http/1.1", host: "10.2.2.240:12000"
同时另一条日志:
connect() to 127.0.0.1:180 failed (13: permission denied) while connecting to upstream
配置里有:
satisfy any; allow 192.168.34.0/24; deny all; auth_basic "restricted access"; auth_basic_user_file /etc/nginx/.htpasswd;
satisfy any 表示 ip 限制 和 basic 认证 满足任意一个即可通过。
用 curl 分别测试:
# 密码错误 → 401 curl -v -u admin:admin123 http://10.2.2.240:12000/ # http/1.1 401 unauthorized # 密码正确 → 403 curl -v -u admin:admin@123 http://10.2.2.240:12000/ # http/1.1 403 forbidden
从 401 变成 403 说明认证已通过,403 是认证之后的文件访问被拒,与登录凭据无关。错误日志里也明确写了:
user "admin": password mismatch # 之前密码错 "/data/www/index.html" is forbidden (13: permission denied) # 认证通过后读文件被拒
namei -l /data/www
输出:
dr-xr-xr-x root root / drwxr-xr-x root root data drwxrwxrwx gtdata sftpg www
ls -l /data/www/index.html # -rwxrwxrwx. 1 gtdata sftpg 194818 sep 1 13:57 /data/www/index.html
路径每一级都有 x 权限,文件本身也是 777。普通 linux 权限完全没问题,所以排除。
既然普通权限没问题,而报错又是 13: permission denied,同时还有对 127.0.0.1:180 的出站连接也被拒,两个现象高度一致地指向 selinux。
getenforce # enforcing ls -z /data/www/index.html # 上下文不是 httpd_sys_content_t
/data/www 不在标准 web 目录下,selinux 没有给它 httpd_sys_content_t 上下文,nginx 读文件就被拦。
# 1. 添加永久上下文规则 semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?" # 2. 应用规则 restorecon -rv /data/www # 3. 验证 ls -z /data/www/index.html
执行后再访问,返回 200,页面正常。问题解决。
针对本次的两个问题,最终执行的命令:
# 端口:允许 nginx 绑定 12000 semanage port -a -t http_port_t -p tcp 12000 # 文件:给 /data/www 打上 httpd_sys_content_t 上下文 semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?" restorecon -rv /data/www # 上游:若 nginx 需要反代本机其他端口,放行出站连接 setsebool -p httpd_can_network_connect 1 # 重启 systemctl restart nginx
验证:
curl -v -u admin:admin@123 http://10.2.2.240:12000/ # http/1.1 200 ok
普通权限用 ls -l、namei -l 一看便知,如果这些都没问题,但日志仍报 permission denied,基本就是 selinux。用 getenforce 和 ls -z 确认。
selinux 不会因为端口 > 1024 就自动放行,必须把端口加入 http_port_t,否则 nginx 启动阶段就会失败。
/data/www 这类自定义路径不在 selinux 预定义的 web 目录里,需要 semanage fcontext + restorecon 显式指定 httpd_sys_content_t。
httpd_can_network_connect 控制 nginx 能否主动发起网络连接。反代 127.0.0.1:180 这类上游时,如果没开,会看到:
connect() to 127.0.0.1:180 failed (13: permission denied)
tail -f /var/log/nginx/error.log — 看具体报错namei -l <路径> — 排除普通权限getenforce — 确认 selinux 状态ls -z <路径> — 看 selinux 上下文semanage port -l | grep http_port_t — 看端口是否放行按这个顺序走,绝大多数 nginx 的 permission denied 都能快速定位。
setenforce 0 只适合临时验证。生产环境应通过 semanage、restorecon、setsebool 精确放行,既解决问题又不牺牲安全性。
到此这篇关于centos 7下nginx访问自定义目录报403的完整排查过程的文章就介绍到这了,更多相关centos 7下nginx访问自定义目录报403内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论