教程
PHP 生产环境安全加固指南:php.ini 与 PHP-FPM 配置基线
先说思路
AI 操作示意图·以官网实际界面为准
前阵子 php2shell 那两个高危 RCE 闹得紧,很多人升级完版本就以为万事大吉。其实升级只是把已知漏洞堵上,生产环境的安全基线是另一回事——开发时图方便开的那些东西,到了线上全是攻击面。这篇就是我自己每次新部署 PHP 站点时会过一遍的加固清单,按 php.ini、PHP-FPM、OPcache 三块来,命令都能直接抄。
1. 开发配置 ≠ 生产配置
最常见的翻车点:直接把开发机的 php.ini 复制到生产,或者干脆没动过默认配置。开发环境开着 display_errors、暴露版本号,是为了调试方便;生产环境这些会把报错堆栈、路径、数据库信息直接吐给访问者。
先定位你的配置文件:
php --ini # 看 Loaded Configuration File 指向哪
php -i | grep disable_functions # 看当前禁用了哪些函数
2. php.ini 关键项
下面这几项是我每次必改的,含义和建议值如下(默认值来自官方手册,以官网当前页面为准):
| 配置项 | 作用 | 生产建议 |
|---|---|---|
expose_php |
在 HTTP 响应头 X-Powered-By 里暴露 PHP 版本 |
Off,别让扫描器一眼知道你版本 |
display_errors |
把错误直接输出到页面 | Off,错误只进日志 |
log_errors / error_log |
错误写日志文件 | On,并指定可写日志路径 |
disable_functions |
禁用危险的内部函数 | 见下方说明 |
open_basedir |
限制 PHP 只能访问指定目录树 | 设为站点根目录 + 临时目录 |
upload_max_filesize |
单文件上传上限(默认 2M) | 按业务定,且必须小于 post_max_size |
关于 disable_functions,官方手册明确写了它只能禁用内部函数、必须写在 php.ini 里,而且可以被绕过,不能当成共享主机的唯一安全措施。常见的一组是:
expose_php = Off
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
open_basedir = /var/www/example.com/:/tmp/
upload_max_filesize = 8M
post_max_size = 12M
注意 open_basedir 官方提示它只是"额外的安全网,并不全面",而且开启后会禁用 realpath 缓存带来一点性能损耗——这是用性能换隔离,值不值自己权衡。
3. PHP-FPM 池配置
AI 操作示意图·以官网实际界面为准
FPM 的风险点在于:一个暴露在公网的 FastCGI 端点等于允许任意代码执行(官方手册原话)。所以池配置的核心是"别让别人能连进来"。
[example.com]
user = www-data
group = www-data
listen = /run/php/example.sock # 优先 unix socket,别用 127.0.0.1:9000 裸奔
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 20
几个要点:
- listen 用 unix socket,而不是 TCP 端口。官方建议 web 服务器和 PHP 在同一台机器时优先 socket,权限靠
listen.owner/group/mode控制;实在要用 TCP,必须配listen.allowed_clients限制来源 IP,否则默认接受任意地址连接。 - 运行用户用低权限账号,站点目录权限对应收,别让 PHP 进程以 root 跑。
pm.max_children别拍脑袋。它是同时服务的最大子进程数,按内存估:单进程内存 × max_children 不能超过机器可用内存。官方给的是 mandatory 项,pm有static/dynamic/ondemand三种,小站点用ondemand更省内存。
每个站点都要单独建 FPM 池吗?
不一定。官方手册提醒"池不是安全机制"——所有池共用同一个 OPcache 实例,池之间并不完全隔离。多站点共享一台机器时,分池主要是为了按站点设不同用户和 open_basedir,而不是指望它做强隔离。真要强隔离,得上容器或独立账号体系。
4. OPcache 生产建议
OPcache 默认 opcache.enable = 1,共享内存默认 128MB。生产环境建议保持开启,它是免费的性能提升:
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 16
opcache.revalidate_freq = 60
注意官方手册里那个坑:interned_strings_buffer 的内存是从 opcache.memory_consumption 里扣的,设大了留给字节码缓存的空间就小了。改完配置要重启 FPM 才生效。

5. 一份可直接抄的检查清单
上线前对着过一遍:
- [ ]
php --ini确认改的是生产真正加载的那个文件 - [ ]
expose_php=Off、display_errors=Off、错误进日志 - [ ]
disable_functions已禁用高危执行类函数 - [ ]
open_basedir限定到站点目录 - [ ] FPM listen 用 unix socket 或配了
listen.allowed_clients - [ ] FPM 运行用户非 root,目录权限对应收紧
- [ ]
pm.max_children按内存算过,不是默认值瞎留 - [ ] OPcache 开启,改完重启 FPM 验证
官方资料
资料核对日期:2026-10-25
- PHP 官方手册:php.ini 核心配置项(disable_functions / expose_php / open_basedir / upload_max_filesize):https://www.php.net/manual/en/ini.core.php
- PHP 官方手册:PHP-FPM 池配置(listen / listen.owner / pm.max_children / listen.allowed_clients):https://www.php.net/manual/en/install.fpm.configuration.php
- PHP 官方手册:OPcache 运行时配置:https://www.php.net/manual/en/opcache.configuration.php
最近一周热门文章
按近 7 天访问热度排序,热度积累前优先展示新文章。
当前栏目最新文章
教程 · 继续阅读同栏目的新内容
一起交流
0 条留言LEAVE A NOTE
你的经验,也很重要。
无需注册或登录。请勿公开邮箱密码、证件、银行卡号或其他敏感信息。
















还没有留言,来分享你的想法吧。