如何在URL不含~user/时让Apache suexec运行public_html/cgi-bin
让我来帮你搞定这个问题,咱们一步步拆解和修复这两个核心问题~
问题核心
你现在遇到两个关键问题:
- SUEXEC触发500错误:访问
http://billyard.ca/cgi-bin/simpletest.cgi时,SUEXEC日志提示“command not in docroot”,直接拒绝执行脚本 - SELinux权限限制:必须将SELinux设为宽容模式才能避免“premature end of header”错误,这显然不是安全的做法
第一步:修复SUEXEC "command not in docroot"错误
SUEXEC是Apache用来安全切换用户身份执行CGI的工具,它有严格的路径校验规则。咱们先搞清楚它的配置:
1. 查看SUEXEC的核心配置
用root权限运行以下命令,查看SUEXEC的预设参数:
suexec -V
你会看到类似这样的输出,重点关注AP_DOC_ROOT和AP_USERDIR这两行:
-D AP_DOC_ROOT="/var/www/html" -D AP_GID_MIN=100 -D AP_HTTPD_USER="apache" -D AP_LOG_EXEC="/var/log/httpd/suexec.log" -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin" -D AP_UID_MIN=100 -D AP_USERDIR="public_html"
2. 问题原因
当你通过/~jaf/cgi-bin/访问时,SUEXEC触发用户目录模式,允许AP_USERDIR(也就是public_html)下的脚本执行;但当你用根域名的/cgi-bin/访问时,SUEXEC会严格检查脚本路径是否在AP_DOC_ROOT指定的目录范围内。你的/home/jaf/public_html不在默认的/var/www/html里,所以就触发了“command not in docroot”错误。
3. 修复方案(推荐第二种,更安全)
方案一:修改SUEXEC的DOC_ROOT(激进,影响全局)
如果这个站点是服务器的唯一主站,可以修改SUEXEC的AP_DOC_ROOT为/home/jaf/public_html。不过Fedora下需要重新编译Apache或者调整相关配置文件,操作复杂度高,还可能影响其他站点,不推荐。
方案二:用符号链接适配SUEXEC规则(安全且灵活)
我们可以在SUEXEC认可的AP_DOC_ROOT目录下创建一个符号链接指向jaf的cgi-bin,然后调整VirtualHost配置:
- 先创建符号链接(假设
AP_DOC_ROOT是/var/www/html):ln -s /home/jaf/public_html/cgi-bin /var/www/html/cgi-bin - 调整你的VirtualHost配置:
这样SUEXEC会认为脚本在它允许的<VirtualHost *:80> Servername billyard.ca SuexecUserGroup jaf jaf DocumentRoot "/var/www/html" # 把根路径指向jaf的public_html Alias / /home/jaf/public_html/ # 让/cgi-bin指向SUEXEC认可的目录下的符号链接 ScriptAlias /cgi-bin/ /var/www/html/cgi-bin/ </VirtualHost>AP_DOC_ROOT范围内,实际执行的却是jaf目录下的脚本,同时保持以jaf身份运行。
第二步:修复SELinux权限问题
完全不需要把SELinux设为宽容模式,咱们通过调整SELinux规则来解决:
1. 设置正确的文件上下文
首先检查/home/jaf/public_html的SELinux上下文:
ls -Z /home/jaf/public_html
用户目录下的public_html应该是httpd_user_content_t上下文,而CGI脚本需要httpd_user_script_exec_t上下文才能被Apache执行。如果上下文不对,执行以下命令修复:
# 为整个public_html设置用户内容上下文 chcon -R -t httpd_user_content_t /home/jaf/public_html/ # 为cgi-bin下的脚本设置可执行的用户脚本上下文 chcon -R -t httpd_user_script_exec_t /home/jaf/public_html/cgi-bin/
如果希望这个上下文永久生效(避免系统重启或文件恢复后失效),添加SELinux永久规则:
semanage fcontext -a -t httpd_user_content_t "/home/jaf/public_html(/.*)?" semanage fcontext -a -t httpd_user_script_exec_t "/home/jaf/public_html/cgi-bin(/.*)?" restorecon -Rv /home/jaf/public_html
2. 允许Apache访问用户家目录(可选,若上述方法无效)
如果还是有问题,执行以下命令开启Apache访问用户家目录的SELinux布尔值:
setsebool -P httpd_enable_homedirs on
这个布尔值专门控制Apache是否有权限访问用户家目录下的public_html目录。
最后:验证修复
完成所有配置后,重启Apache服务:
systemctl restart httpd
现在访问http://billyard.ca/cgi-bin/simpletest.cgi应该可以正常运行,同时SELinux保持强制模式,安全性不受影响。
内容的提问来源于stack exchange,提问作者jaf0faj

