日本IIJ线路服务器网站报403,如何检查服务身份、目录权限并按最小权限修复

网站首页、静态文件和后台是否都报403,是排查日本IIJ线路服务器访问故障的第一个分界点。如果只有目录首页报错,可能是首页文件或目录访问规则问题;如果部署后整站突然报错,更应检查发布目录、文件属主和服务运行身份。403表示某个HTTP处理层拒绝了请求,不能仅凭状态码认定是线路或文件权限故障。
建议按“确认403由谁返回 → 核对实际服务身份 → 检查完整路径权限 → 排查服务规则与安全策略 → 最小范围修复”的顺序处理。先取日志证据,再修改权限;不要把整站改成777,也不要为了消除报错让Web服务以root身份运行。
先确认:请求在哪里被拒绝
以下以Linux上的Nginx站点为例;动态页面如经PHP-FPM处理,还需单独核对PHP-FPM池的身份。操作前准备有sudo权限的维护账户、实际域名、站点配置和错误发生时间。示例域名、路径、用户名都应替换为现场值。
先对同一个URL发起GET请求,避免只用HEAD请求造成判断偏差:
curl -sS -D - -o /dev/null https://www.example.com/
如果站点前面存在代理或缓存,可在源站上保留域名与TLS主机名,直接请求本机监听地址:
curl --resolve www.example.com:443:127.0.0.1 \
-sS -D - -o /dev/null https://www.example.com/
该命令只适用于Nginx在本机对应地址监听443的情况;否则应换成实际监听地址。连接失败或证书验证失败,不等于确认了403原因,也不应直接跳过证书校验来作判断。
| 观察结果 | 优先判断 | 下一步 |
|---|---|---|
| 公网403,直连源站正常 | 前置代理、访问策略或两条请求路径的配置差异 | 对照前置层日志与源站日志 |
| 两条路径都403,源站记录文件访问失败 | 源站权限或安全策略问题 | 检查服务身份与路径 |
/报403,已知静态文件正常 | 首页缺失、首页配置或目录访问规则问题 | 核对index与实际文件 |
| 静态文件正常,动态接口403 | 应用鉴权、访问规则或动态服务身份问题 | 查上游和应用日志 |
对比时还应保持请求方法、路径及登录状态一致。源站日志没有记录,也可能是查错了虚拟主机或访问日志被关闭,不能据此直接归因网络。
从日志建立分支:哪些403才需要改权限
对Nginx,可以先读取当前磁盘上的完整配置并检查语法:
sudo nginx -T
重点核对命中的server_name、root或alias、index、location,以及该站点的access_log、error_log位置。输出可能包含敏感配置,不宜原样公开。该命令读取的是磁盘配置;若配置修改后尚未重载,还需结合运行日志判断当前生效状态。
按配置中的实际路径读取错误日志:
sudo tail -n 100 /实际路径/error.log
常见线索有以下区别:
Permission denied:文件访问被系统拒绝,继续检查传统权限、ACL、SELinux或服务隔离;它并不只代表缺少某个chmod权限位。directory index ... is forbidden:请求落到目录,且没有按配置找到可用首页、目录列表又未开启。应检查首页文件和映射,不是直接放开目录写权限。access forbidden by rule:优先检查匹配到的访问规则,例如deny、allow或显式返回403的配置。- 应用记录了鉴权失败并返回403:检查登录状态、角色、令牌及业务规则;修改文件权限通常无效。
如果是首页文件缺失,应通过发布流程恢复首页或修正index、root。不要用开启目录列表的方式掩盖问题,否则可能暴露站点文件名。
核对服务身份:谁真正读取这些文件
Nginx主进程可能以root运行,但通常由非特权worker读取静态文件。只看主进程身份,容易误判。
ps -eo user,group,pid,args | grep -E '[n]ginx|[p]hp-fpm'
同时核对Nginx配置中的user,以及实际PHP-FPM池配置中的user、group。不要假定所有系统都使用www-data或nginx。
若要确认某个worker实际持有的UID、GID和补充组,可用查到的PID执行:
sudo grep -E '^(Uid|Gid|Groups):' /proc/实际PID/status
id 用户名显示的是当前账户数据库信息,不一定等于已运行进程的组集合。刚调整用户组后,旧进程可能仍持有旧组权限,需要通过该服务适用的重载或重启方式重新创建工作进程,并再次检查。
Nginx与PHP-FPM不必使用同一身份。 Nginx读取静态文件,PHP-FPM读取并执行PHP代码;缓存、会话、上传目录的写权限应给实际执行写入的身份,而不是笼统给所有Web进程。
沿完整路径检查:文件可读不代表能访问
假设日志显示目标文件是:
/srv/www/site/public/index.html
检查整个路径,而不是只看最后一个文件:
namei -l /srv/www/site/public/index.html
sudo getfacl -p /srv /srv/www /srv/www/site \
/srv/www/site/public /srv/www/site/public/index.html
namei可展示逐级目录的属主和权限;getfacl用于查看ACL,需系统已安装相应工具。如果路径经过软链接,还要检查软链接实际指向的完整路径。
权限判断遵循以下规则:
- 读取已知路径下的文件,需要对每一级父目录有搜索权限
x,并对文件有读权限r。 - 目录的
r用于列出目录项,不能替代进入目录所需的x。 - 静态文件通常不需要执行权限,提供静态访问也不要求目录可写。
- 普通权限按属主、匹配组、其他人的对应类别判断,不是把所有类别权限累加。
- ACL中的命名用户或组权限可能受
mask限制,应关注getfacl输出中的有效权限。
因此,即使index.html是644,上层目录若为700且属于部署账户,Web worker仍可能无法读取。
可用实际服务账户做初步验证:
sudo -u 实际服务用户 -- test -x /srv/www/site/public
echo $?
sudo -u 实际服务用户 -- test -r /srv/www/site/public/index.html
echo $?
返回0表示该项测试通过,非零表示未通过。但这只能模拟账户访问,不能完整复现运行中服务的补充组、SELinux域、容器挂载或systemd隔离环境;最终仍以真实请求为准。
定位后修复:只开放所需路径与操作
单个读取身份缺权限:可以考虑定点ACL
下面适用于一个明确场景:已确认Nginx worker为非文件属主,目标只是读取首页,文件系统支持ACL,相关路径不存在需要特殊保留的复杂ACL。示例中假设核验后的账户是www-data,其他环境必须替换。
先保存所有待修改对象的权限与ACL,再授权:
WEBUSER=www-data
ACL_BACKUP=$(mktemp /var/tmp/site-acl.XXXXXX)
sudo getfacl -p /srv /srv/www /srv/www/site \
/srv/www/site/public /srv/www/site/public/index.html \
> "$ACL_BACKUP"
printf '权限备份:%s\n' "$ACL_BACKUP"
确认备份成功、内容完整后再执行:
sudo setfacl -m "u:${WEBUSER}:--x" \
/srv /srv/www /srv/www/site /srv/www/site/public
sudo setfacl -m "u:${WEBUSER}:r--" \
/srv/www/site/public/index.html
这只给予目录搜索和目标文件读取权限,不赋予写入权限。需要注意两项影响:
- 父目录搜索权限可能使该身份能够到达其他原本可读的子项,应先检查同层目录边界。
setfacl可能重算ACL的mask,进而改变其他已有ACL条目的有效权限;复杂ACL不能直接套用示例,应先比较现有条目及有效权限。
修改后用getfacl复核。需要回滚时,使用刚才记录的备份文件:
sudo setfacl --restore="$ACL_BACKUP"
回滚会恢复备份时这些对象的权限状态,可能覆盖其后的合法权限调整,应在同一维护窗口内操作。上述示例只修复该首页的读取条件;CSS、图片等资源需按实际公开文件集合核对,不能视为整站已修复。
长期权限布局:部署者可写,服务按需读写
对于整站,应把代码所有权保留给部署账户或受控维护账户,再通过专用读取组或ACL给服务必要权限。只读目录可采用750、普通文件可采用640,但成立条件是服务身份确实匹配读取组,且所有父目录都可搜索;这些数字不是通用修复答案。
写权限仅限应用确认需要的缓存、会话或上传目录。代码目录、配置文件和密钥不应因Web访问失败而一并变成可写。涉及递归权限调整前,应先盘点文件、备份权限,并明确哪些目录需要不同策略,不要执行整站chmod -R 777或把全部代码递归交给Web用户。
普通权限正常:继续检查安全策略与服务隔离
启用SELinux的系统可以先做只读检查:
getenforce
ls -Zd /srv/www/site/public
sudo ausearch -m AVC -ts recent
这些命令适用于已安装对应工具的SELinux环境。若存在与本次访问关联的拒绝记录,应核对该发行版的Web内容标签策略;不要直接关闭SELinux。可先预览标准标签恢复是否会改变目标:
sudo restorecon -nRv /srv/www/site/public
非标准站点路径可能需要先建立正确的持久标签映射,不能认为直接运行restorecon必然有效。实际调整前应保存原标签与映射配置,并限定到站点所需范围。
如果使用AppArmor或systemd服务隔离,还需检查相关拒绝日志、InaccessiblePaths、RootDirectory等设置。进程根本看不到该路径时,主机上的文件权限正确也不足以恢复访问。
验证恢复,并盯住下一次发布
修复后应重复最初的请求,确认预期公开页面返回正常响应,同时观察同一时间段的错误日志。文件权限和ACL变更通常即时生效,无需为此重启Nginx;若修改了配置,应先完成语法检查,再对已核验的服务单元执行重载,并保留原配置以便回退。
至少验证以下项目:
1. 首页、嵌套目录文件、CSS或图片,以及动态页面分别符合预期。
2. 日志不再出现本次相关的权限拒绝,新出现的403另按请求路径分析。
3. 私有配置、密钥和非公开目录仍不能通过HTTP读取。
4. 服务账户能读取所需内容,但不能修改代码;应用只在指定目录内可写。
若当前恢复、下一次发布又复发,应检查部署工具是否保留ACL、发布账户的umask、新目录属组,以及软链接切换后的真实路径。将“worker身份变化、发布目录权限变化、权限拒绝日志、403比例异常”纳入监控,比反复扩大目录权限更能稳定地解决日本IIJ线路服务器上的此类故障。