正确设置nginx/php-fpm/apache权限 提高网站安全性 防止被挂木马

本文探讨了网站被挂木马的主要原因及防范措施,强调了正确的Linux网站目录和进程权限设置的重要性,提出了php-fpm/apache/nginx进程不应使用网站文件所有者的用户原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

核心总结:php-fpm/apache 进程所使用的用户,不能是网站文件所有者。 凡是违背这个原则,则不符合最小权限原则。

 

根据生产环境不断反馈,发现不断有 php网站被挂木马,绝大部分原因是因为权限设置不合理造成。因为服务器软件,或是 php 程序中存在漏洞都是难免的,在这种情况下,如果能正确设置 Linux 网站目录权限, php 进程权限,那么网站的安全性实际上是可以得到保障的。

 

那么,造成网站被挂木马的原因是什么?

 

1.  ftp 连接信息被破解,对这个原因,可行的办法就是使用非常复杂的FTP 用户名(不要使用常用的用户名),如果是固定作业,可考虑使用 iptables 防火墙限制来源 IP 。但是一些情景下,可能需要使用 VPN 以便远程维护。 即网站维护者需要使用 FTP 修改网站文件时,必须先登录到 IDC 机房的 VPN 服务器上,再进行后续的操作。

 

2.  网站服务器软件/ 配置 /php 程序存在漏洞,被利用
在讨论这个问题前,先说明文件及进程权限的几个概念:

A.  FTP用户对网站目录具有最大修改权限,那么网站的文件所有者一定属于 FTP,  这是毋庸置疑的 否则如何修改文件呢?

B.  php-fpm/apache/nginx 进程对网站文件至少需要有读取权限,例如,以下命令即可查看这两个进程所使用的账号:



通过上图,我们可以发现,nginxphp-fpm 子进程账号是 nobody

 

我们再查看网站文件目录的权限:

发现网站文件所有者是www 账号,那说明:

nginx和 php 对网站只有读取权限,无写入权限

如果php 程序需要对网站某些文件有写入权限,需要手工将文件或目录权限修改为 777

因为php-fpm 子进程是以 nobody 运行,那么 php-fpm 生成的新文件所有者也是 nobody,  这时 ftp 用户将无法修改这些文件,解铃还需系铃人,当 php 生成文件后,需要调用 chmod("/somedir/somefile", 0777) 将文件权限修改为 777 ,以便 FTP 用户也可以修改这个文件。

经常有开发人员找我请求重设php 生成的文件的权限。

 

如果php-fpm/apache/nginx进程以网站文件所有者用户运行,那意味着 php-fpm/apache/nginx 进程对整个网站目录具有可写权限,噩梦也就由此开始。

 

但是我们发现,有不少系统管理员为了省事,违背了Linux 最小化权限的原则,设置 php-fpm/apache/nginx 进程以网站文件所有者账号运行,当然这样可能会方便 php 开发人员( php-fpm 进程对整个网站目录具有可写权限),但是这样一来, Linux 体系的文件系统权限原则将被打破,所有的安全措施将形同虚设。可以想象的是,万一 php 程序中有漏洞,攻击者上传木马,便可以修改网站的所有文件,网站首页被黑,也就不足为怪了。

 

退一步,如果我们设置了较严格的权限,就算php 程序中存在漏洞,那么攻击者也只能篡改权限为 777 的目录,其它的文件是无法被改写的,网站不就就得更安全了吗?

 

核心总结:php-fpm/apache/nginx进程所使用的用户,不能是网站文件所有者。 凡是违背这个原则,则不符合最小权限原则。

 

经过我参阅网上关于nginx, php-fpm 配置的文章教程和市面上的一些书籍,发现有不少人受这些文章的误导,直接让 php-fpm/apache/nginx进程以网站所有者账号运行,例如张宴的《实战 nginx  取代 apache 的高性能 Web 服务器》一书的 52 页中,存在以下设置:

<value name="user">www</value>

<value name="group">www</value>

 

而在第50 页,设置网站文件所有者也为 www 用户:

chown -R www:www /data0/htdocs/blog

显然,此书的这部分内部,对初学者有误导,针对这个问题,我已经向本书作者发邮件,希望其能在第二版中进行强调声明,以免由于过度宽松的权限配置,造成一些安全隐患。

 

官方提供的配置文件中,php-fpm 子进程使用 nobody 用户,这完全是合理的,无须修改。

 

那么nginx 的子进程用户,如何设置合理? 我的建议是也使用 nobody (对错误日志写入等无影响),设置方法如下:

nginx.conf文件第一行设置为 user    nobody; ,  再执行 nginx -s reload 即可。

 

php-fpm子进程用户设置方法:

编辑文件php-fpm.conf (一般位于 /usr/local/php/etc/php-fpm.conf,  视安装参数为准),找到 user group 两个参数的定义,将其设置为nobody( 默认已经是 nobody) ,再重启 php-fpm 进程即可。

 

 

网站可写目录的特殊注意

这里的可写,是相对php-fpm 子进程而言。一个网站最容易出安全问题的即是可写目录,如果可写目录权限能控制严格,安全系数也将大大提高。

我们认为,一个网站可写目录主要分为以下几种:

1.  php 数据缓存目录,如 discuzforumdata 目录,就存放了大量数据缓存文件。此类目录一般会禁止用户直接访问,但是 discuz 在这个目录下又存放了不少 js, css 文件,我们并不能简单地拒绝用户访问这个目录。显然,这个目录下的所有文件,不能直接交给 php 解析,我们后面会给出解决方案。

2.  附件上传目录。显然此类目录需要开启访问,但不能交由php 引擎解析(即这个目录下的所有文件均视为普通静态文件)。

3.  静态文件生成目录,这类目录下的文件全部应视为静态文件。

4.  日志目录, 一般都会拒绝用户直接访问之。

 

也就是说对网站开发人员而言,需要对可写目录实现动静分离,不同性能的文件,应该区别对待之,这样也就方便系统管理员,设置合理的nginx 规则,以提高安全性。

 

简单地去掉php 文件的执行权限,并不能阻止 php-fpm 进程解析之。

 

接下来,根据以上总结,系统管理员如何配置nginx 的目录规则,才更安全呢?

1.  数据缓存目录 /cache/
这个目录的特点是需要777 权限,无须提供给用户访问,那么可以按以下参考配置 nginx

location ~ "^/cache" {

return 403;

}

 

location ~ "\.php$" {

fastcgi_pass 127.0.0.0:9000;

....................

}

 

这时,任何用户将无法访问/cache/ 目录内容,即使

2. 附件上传目录  attachments

此目录的特点是需要开放访问权限,但所有文件不能由php 引擎解析(包括后缀名改为 gif 的木马文件)

location ~ "^/attachments" {

 

}

 

location ~ "\.php$" {

fastcgi_pass 127.0.0.0:9000;

....................

}

 

注意,上面对attachments 目录的 location 定义中是没有任何语句的。 nginx 对正则表达式的 location 匹配优先级最高,任何一个用正则表达式定义的 location,  只要匹配一次,将不会再匹配其它正则表达式定义的 location

 

现在,请在attachments 目录下建立一个 php 脚本文件,再通过浏览器访问安,我们发现浏览器提示下载,这说明 nginxattachments 目录下的文件当成静态文件处理,并没有交给 php fastcgi 处理。这样即使可写目录被植入木马,但因为其无法被执行,网站也就更安全了。

 

显然,重要的php 配置文件,请勿放在此类目录下。

 

3.  静态文件生成目录 public
这些目录一般都是php 生成的静态页的保存目录,显然与附件目录有类似之处,按附件目录的权限设置即可。

可以预见的是,如果我们设置了较严格的权限,即使网站php 程序存在漏洞,木马脚本也只能被写入到权限为 777 的目录中去,如果配合上述严格的目录权限控制,木马也无法被触发运行,整个系统的安全性显然会有显著的提高。

 

但是网站可写目录的作用及权限,只有开发人员最为清楚。这方面需要php 开发人员和系统管理员积极沟通。我们使用的方式是:项目上线前,开发人员根据以文档形式提供网站可写目录的作用及权限,由系统管理员针对不同目录进行权限设置。任何一方修改了网站目录权限,但未体现到文档中,我们认为是违反工作流程的。

<think>好的,我现在要帮用户理解Nginx中的upstream配置,特别是针对PHP-FPM的部分。首先,用户给出的配置是: upstream php-fpm { server unix:/run/php-fpm/www.sock; } 我需要先回忆一下Nginx的upstream模块的作用。upstream主要用于定义后端服务器组,实现负载均衡和代理。这里用户使用的是Unix套接字,而不是IP地址,说明PHP-FPM是通过本地socket通信的,这通常比TCP更快,因为没有网络开销。 接下来,我需要分析这个配置的具体作用。用户可能是在配置NginxPHP-FPM的通信,所以需要解释upstream块在这里的意义。首先,upstream定义了一个名为php-fpm的后端服务器组,里面只有一个server条目,指向Unix套接字文件。这个名称php-fpm在之后的fastcgi_pass指令中会被引用,比如fastcgi_pass php-fpm;。 然后,要解释为什么使用Unix套接字而不是IP。可能的原因包括性能更好,安全性更高,因为不需要开放网络端口。同时,需要确认套接字文件的路径是否正确,通常路径是/run/php-fpm/www.sock,但不同的系统或安装方式可能会有差异,比如有些可能在/var/run/目录下。 接下来,用户可能需要了解如何扩展这个配置,比如添加多个后端服务器实现负载均衡。比如可以添加多个server行,每个指向不同的socket或IP,并设置权重或其他参数。但当前配置只有一个,所以可能用户的环境是单机部署,不需要负载均衡。 还要提到高可用性的考虑,虽然当前只有一个server,但如果有多个,Nginx会自动处理故障转移。不过用户可能现在只是基础配置,暂时不需要复杂设置。 然后,需要指出常见的配置错误,比如套接字文件路径不正确,或者权限问题。Nginx的工作进程(通常是www-data或nginx用户)必须有权限访问该套接字文件。可能需要检查文件权限和所属用户组,确保Nginx可以读写。 另外,配置中的upstream名称php-fpm是自定义的,用户可以根据需要改名,但要保证在fastcgi_pass中引用一致。比如如果upstream叫backend,那么fastcgi_pass backend;。 可能还需要提到健康检查的相关配置,虽然默认情况下Nginx没有主动的健康检查,但可以手动设置max_fails和fail_timeout等参数来检测后端状态。不过在这个例子中,用户可能还没涉及到这些高级设置,所以暂时不需要深入,但可以作为扩展知识提及。 最后,总结这个配置的作用:定义了一个名为php-fpm的后端服务,使用本地Unix套接字与PHP-FPM进程通信,提升性能,并确保Nginx正确代理请求到PHP处理器。同时,提醒用户注意路径和权限问题,以及可能的扩展选项。</think>--- ### **一、核心作用解析** ```nginx upstream php-fpm { server unix:/run/php-fpm/www.sock; } ``` 这是Nginx用于定义反向代理后端服务的标准配置模块,在PHP-FPM场景中实现**进程间通信路由**。具体作用分解: | 配置元素 | 功能说明 | |------------------------|--------------------------------------------------------------------------| | `upstream php-fpm` | 定义名为"php-fpm"的后端服务组(逻辑分组) | | `server unix:...` | 指定使用Unix域套接字(非TCP)进行通信 | | `/run/php-fpm/www.sock`| PHP-FPM监听的套接字文件路径(需与PHP-FPM配置中的`listen`参数绝对一致) | --- ### **二、通信架构示意图** ```bash Nginx Worker进程 ⇩ [unix:/run/php-fpm/www.sock] # 内核级IPC通道 ⇩ PHP-FPM Master进程 ⇩ PHP-FPM Worker进程池 ``` **性能优势**:相比`127.0.0.1:9000`的TCP连接方式: - 减少TCP三次握手/四次挥手开销 - 避免端口号冲突风险 - 内核直接处理数据拷贝,吞吐量提升约30% --- ### **三、配置深度验证** #### 1. **套接字文件存在性检查** ```bash ls -l /run/php-fpm/www.sock # 预期输出: # srw-rw---- 1 www-data www-data 0 Jul 15 10:00 /run/php-fpm/www.sock ``` **关键指标**: - 文件类型为`s`(socket) - 所属用户/组需与Nginx worker进程一致(通常为`www-data`或`nginx`) #### 2. **PHP-FPM配置对应验证** 检查`php-fpm.conf`或`www.conf`: ```ini ; 确保监听路径完全一致 listen = /run/php-fpm/www.sock ; 权限设置需允许Nginx进程访问 listen.owner = www-data listen.group = www-data listen.mode = 0660 ``` #### 3. **Nginx连接测试** ```bash sudo -u www-data curl --unix-socket /run/php-fpm/www.sock http://localhost/status ``` 预期返回PHP-FPM状态信息(需开启`pm.status_path`配置) --- ### **四、负载均衡扩展配置** #### 基础负载均衡 ```nginx upstream php-fpm-cluster { server unix:/run/php-fpm/node1.sock weight=3; # 权重占比3/7 server unix:/run/php-fpm/node2.sock weight=4; # 权重占比4/7 least_conn; # 可选负载均衡算法 } ``` #### 健康检查机制 ```nginx server unix:/run/php-fpm/bak.sock backup; # 定义备用服务器 check interval=3000 rise=2 fall=3 timeout=1000 type=http; check_http_send "GET /health-check HTTP/1.0\r\n\r\n"; check_http_expect_alive http_2xx http_3xx; ``` --- ### **五、故障排查指南** #### 1. **连接拒绝错误** ```log connect() to unix:/run/php-fpm/www.sock failed (2: No such file or directory) ``` **解决方案**: - 确认PHP-FPM服务已启动:`systemctl status php-fpm` - 检查套接字文件生成路径是否正确 #### 2. **权限被拒绝错误** ```log connect() to unix:/run/php-fpm/www.sock failed (13: Permission denied) ``` **权限修复流程**: ```bash chown www-data:www-data /run/php-fpm/www.sock chmod 660 /run/php-fpm/www.sock setsebool -P httpd_unified 1 # SELinux环境专用 ``` #### 3. **资源耗尽问题** ```log upstream timed out (110: Connection timed out) ``` **优化方向**: - 调整PHP-FPM池配置: ```ini pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 2 pm.max_spare_servers = 8 ``` - 增加Nginx的`fastcgi_read_timeout`值 --- ### **六、生产环境最佳实践** #### 1. 专用socket目录 ```nginx upstream php-fpm { server unix:/dev/shm/php-fpm.sock; # 使用内存文件系统 } ``` 优势:完全避免磁盘I/O,提升约15%的QPS #### 2. 多进程组隔离 ```nginx upstream api-fpm { server unix:/run/php-fpm/api.sock; } upstream web-fpm { server unix:/run/php-fpm/web.sock; } ``` 对应PHP-FPM配置: ```ini [api] listen = /run/php-fpm/api.sock [web] listen = /run/php-fpm/web.sock ``` #### 3. 内核参数优化 ```bash # 提高套接字缓冲区 sysctl -w net.core.rmem_max=16777216 sysctl -w net.core.wmem_max=16777216 ``` --- **最终推荐配置示例**: ```nginx upstream php-fpm { server unix:/dev/shm/php-fpm.sock weight=5; server unix:/run/php-fpm/backup.sock backup; keepalive 50; # 维持长连接 keepalive_requests 10000; # 单个连接最大请求数 keepalive_timeout 60s; } server { location ~ \.php$ { fastcgi_pass php-fpm; fastcgi_keep_conn on; # 启用keepalive } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值