Linux 下做 PHP 安全加固,真正难的地方不是写几条配置,而是把系统、运行时、Web 服务器和传输链路连成一套完整防护。下面按实际部署顺序整理一遍,既保留能直接落地的命令和配置,也说明每一步主要解决什么问题,方便你判断哪些是必须项、哪些需要按业务场景调整。
先把系统和服务栈更新到可维护状态
很多线上风险并不是“高明攻击”造成的,而是系统组件长期不更新,继续暴露已知漏洞。Linux、PHP、Apache 或 Nginx、数据库这些基础组件,至少都要保持在官方仍提供维护的版本范围内。
在 Debian 或 Ubuntu 系系统里,可以先执行:
sudo apt update && sudo apt upgrade -y
这一步看起来基础,但它决定了后面所有配置是否建立在一个仍被官方修复漏洞的环境上。如果底层版本已经过旧,单独修改 php.ini 的意义会明显下降。
PHP 版本怎么选才更安全
PHP 版本并不是越新越好,但一定要选官方仍在维护的稳定版本。停止维护的旧版本通常会继续保留已公开的安全缺陷,除非项目存在明确的兼容性约束,否则不建议继续使用。
原文给出的示例版本是 7.4 或 8.x,安装命令如下:
sudo apt install php7.4 php7.4-cli php7.4-fpm php7.4-mysql
如果你的业务运行在 PHP-FPM 模式下,还要注意 Web 服务器配置中的 FPM socket 路径是否与实际安装版本一致,例如后文 Nginx 配置里使用的是:
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
也就是说,升级 PHP 版本后,Web 层联动配置也要一起检查。
围绕 php.ini 收紧 PHP 运行时权限
php.ini 是 PHP 安全策略的核心位置。这里的重点不是把选项“堆满”,而是围绕报错暴露、危险函数、上传限制和缓存行为做约束。
错误显示与危险函数
生产环境应避免把报错直接输出给访问者,否则路径、变量名甚至 SQL 相关信息都可能被暴露出来。同时,具备命令执行能力的函数如果业务不依赖,应该直接禁用。
; 启用错误报告,生产环境关闭显示错误
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
; 禁用危险函数,坚决禁用eval、exec、passthru、shell_exec、system等
disable_functions = eval,exec,passthru,shell_exec,system
其中 display_errors = Off 和 log_errors = On 的组合,适合线上环境:对外不暴露细节,对内保留排障记录。
上传限制与 OPcache
上传能力本身不是漏洞,但无限制的上传尺寸和请求体大小会扩大滥用空间。另一方面,启用 OPcache 主要是性能优化,但稳定的缓存设置也有助于减少不必要的运行时抖动。
; 文件上传限制,根据实际需求调整大小
upload_max_filesize = 2M
post_max_size = 8M
file_uploads = On
; 启用OPcache,提升性能
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
这里没有统一标准值,关键在于“按业务最小够用”去设定,而不是默认放宽。
安全响应头的作用
原文还给出了一组安全头配置,用来降低 XSS、点击劫持和类型嗅探带来的风险:
; 安全头,防止XSS、点击劫持等攻击
headers.append = "X-Content-Type-Options: nosniff"
headers.append = "X-Frame-Options: SAMEORIGIN"
headers.append = "X-XSS-Protection: 1; mode=block"
headers.append = "Strict-Transport-Security: max-age=31536000; includeSubDomains"
需要注意的是,这类头信息很多时候也可以在 Apache 或 Nginx 层统一下发。若你的站点已经在 Web 服务器层集中管理响应头,就要避免重复配置或相互冲突。
HTTPS 是上线环境的基础项
只要站点有登录、表单、Cookie 或任何用户数据传输,就不应该再以明文 HTTP 暴露。使用 Let's Encrypt 配合 certbot,可以用较低成本完成证书签发和续期。
sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d yourdomain.com
HTTPS 的价值不只是“浏览器不报不安全”,更重要的是把认证信息、会话数据和后台管理流量都放到加密通道里。同时,后续配置 HSTS 时,站点会进一步收紧回退到 HTTP 的可能性。
Apache 与 Nginx 的安全配置重点
PHP 安全不能只盯着解释器本身,真正对外提供服务的是 Web 服务器。这里最关键的两件事,是把 HTTP 强制跳转到 HTTPS,以及正确加载 SSL 证书和 PHP-FPM 处理规则。
Apache 示例
编辑 /etc/apache2/apache2.conf 或站点配置文件,可以按下面的方式完成跳转和 SSL 配置:
<VirtualHost *:80>
ServerName yourdomain.com
Redirect permanent / https://yourdomain.com/
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName yourdomain.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
SSLHonorCipherOrder on
SSLCipherSuite HIGH:!aNULL:!MD5
</VirtualHost>
</IfModule>
这段配置的核心含义有三层:80 端口统一跳转、443 启用证书、禁用弱加密组合。
Nginx 示例
如果使用 Nginx,编辑 /etc/nginx/sites-a vailable/yourdomain,同样遵循“先跳转、再启用 SSL、最后对接 PHP-FPM”的思路:
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
root /var/www/html;
index index.php index.html index.htm;
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
这里要特别确认 root 目录、index 顺序以及 fastcgi_pass 所指向的 PHP-FPM socket 是否与当前环境一致,否则容易出现 404、502 或 PHP 文件无法被正确解析的问题。
别漏掉防火墙和备份这两道底线
应用层配置做得再细,也不能替代主机级防护和故障恢复能力。对外端口暴露越少,攻击面就越小;而一旦发生误删、入侵或升级失败,备份是否可用往往决定恢复成本。
用 UFW 收紧端口暴露
在 Linux 环境中,UFW 是相对直接的防火墙工具。原则很简单:只开放业务必须的端口,例如 80 和 443,其余默认不开放。
sudo ufw allow 'Nginx Full'
sudo ufw enable
定期备份网站文件和数据库
备份不是“有空再做”的附加项,而是安全体系里的最后一道恢复机制。网站目录和数据库至少都应纳入自动化备份范围。
sudo tar -czvf /backup/yourdomain_$(date +%F).tar.gz /var/www/html
mysqldump -u root -p yourdatabase > /backup/yourdatabase_$(date +%F).sql
如果条件允许,建议再配合 cron 任务做周期化执行,并额外验证一次备份文件是否真的能恢复,而不是只看任务有没有成功生成文件。
依赖库也要持续更新
很多 PHP 项目的风险并不来自你自己写的业务代码,而来自框架、组件和第三方库。即使系统、PHP 和 Nginx 都是新版本,依赖层长期不更新,仍然可能暴露已知漏洞。
因此,除了定期执行 composer update 或同类更新操作,还应持续关注相关安全公告,确认是否存在需要优先修补的组件版本问题。
整体来看,Linux 下的 PHP 安全配置不是一次性动作,而是一套持续维护机制:先保证版本可维护,再收紧 php.ini 和 Web 服务器配置,用 HTTPS、防火墙和备份把边界补齐,最后把依赖更新和日志检查纳入日常运维流程。
















