LNMP是Linux、Nginx、MySQL、PHP的组合简称,是目前非常主流的Web服务架构。相比手动逐个编译安装,一键部署脚本能大幅节省时间,同时避免依赖缺失、版本不匹配等常见坑。不过装好只是第一步,如果默认配置直接上线,很容易被扫描器盯上成为攻击目标。本文先讲一键部署的完整流程,再从Nginx、PHP、MySQL三个层面给出加固清单,最后附上验证方法。

一、使用lnmp一键安装包完成部署
目前社区维护最活跃的是lnmp.org提供的一键安装包,它用Shell脚本封装了Nginx、MySQL/MariaDB、PHP的编译安装流程,还自动处理了systemd服务注册、开机自启等细节。整个安装过程只需要下载脚本、解压、执行三条命令。
安装前建议先确认系统是CentOS 7以上或Ubuntu 18.04以上,并且磁盘剩余空间不少于5GB,内存最好在1GB以上,否则编译MySQL时可能因为内存不足而失败。如果机器内存偏小,可以先创建交换分区再执行安装。
# 下载并解压一键安装包 wget http://soft.lnmp.com/lnmp/lnmp2.0.tar.gz tar zxf lnmp2.0.tar.gz cd lnmp2.0 # 执行安装脚本,进入交互式选择界面 ./install.sh lnmp
脚本会让你依次选择MySQL版本、PHP版本以及是否安装InnoDB引擎等选项。生产环境建议MySQL选8.0或5.7,PHP根据程序需求选7.4或8.1,不建议选择已经停止维护的老版本。整个编译安装大约需要30分钟到1小时,取决于机器性能。安装完成后执行lnmp status可以查看各组件运行状态,浏览器访问服务器IP出现默认页面即表示部署成功。
二、Nginx层面的安全加固
Nginx的默认配置为了兼容性牺牲了不少安全性,上线前至少要做以下几项调整。第一是隐藏版本号,默认情况下响应头会暴露Server: nginx/1.x.x,攻击者可以根据版本号查找对应漏洞。在http块中加入一行配置即可关闭。
http {
# 隐藏Nginx版本号
server_tokens off;
# 禁止不安全的HTTP方法
if ($request_method ~* ^(TRACE|TRACK)$) {
return 405;
}
}第二是限制访问敏感目录和文件。很多程序会在Web根目录下留有.git目录、备份文件、配置文件,这些一旦被直接下载就会导致源码或数据库密码泄露。可以在server块中用location规则统一拦截。
server {
listen 80;
server_name www.ipipp.com;
root /home/wwwroot/default;
# 禁止访问隐藏文件和敏感目录
location ~ /\. {
deny all;
}
location ~* /(data|temp|upload)/.*\.(php|py|sh)$ {
deny all;
}
# 限制单IP连接数和请求速率,缓解CC攻击
limit_conn addr 20;
limit_req zone=req_limit burst=10 nodelay;
}第三是启用访问控制和传输加密。管理后台目录建议加一层Basic认证,全站尽快启用HTTPS,可以用脚本自带的lnmp ssl add命令申请Let's Encrypt免费证书。此外还应该配置合理的超时时间和请求体大小限制,例如client_max_body_size 10m,避免被恶意大文件请求拖垮服务。
三、PHP与MySQL的加固清单
PHP是整个链条中最容易被利用的一环,尤其是WebShell问题。打开php.ini(一般位于/usr/local/php/etc/php.ini),重点调整以下几项。disable_functions用于禁用危险函数,open_basedir用于将PHP的文件访问范围限制在站点目录内,即使被上传了木马文件也无法读取其他目录。
; php.ini 关键安全配置 disable_functions = passthru,exec,system,shell_exec,proc_open,popen expose_php = Off display_errors = Off log_errors = On open_basedir = /home/wwwroot/default/:/tmp/ cgi.fix_pathinfo = 0 session.cookie_httponly = 1
其中cgi.fix_pathinfo设为0是为了防止经典的解析漏洞,攻击者上传一张包含PHP代码的图片,再通过特殊URL让Nginx把它交给PHP执行。修改后记得执行lnmp php-fpm restart让配置生效。
MySQL方面,安装脚本生成的root默认只允许本机登录,这一点已经比较安全,但仍需做三件事:一是给root设置强密码,删除空密码账号;二是网站程序不要用root连接,单独创建一个只授权指定库的账号;三是删除test数据库和匿名用户。用mysql命令行操作如下。
-- 删除匿名用户和test库 DELETE FROM mysql.user WHERE User=''; DROP DATABASE IF EXISTS test; -- 创建网站专用账号,只授权单个库 CREATE DATABASE webdb DEFAULT CHARACTER SET utf8mb4; CREATE USER 'webuser'@'localhost' IDENTIFIED BY '复杂密码'; GRANT SELECT,INSERT,UPDATE,DELETE ON webdb.* TO 'webuser'@'localhost'; FLUSH PRIVILEGES;
另外建议在my.cnf中把skip-symbolic-links打开,关闭3306端口的远程监听(bind-address设为127.0.0.1),Web和数据库同机部署时完全没有必要对外暴露数据库端口。
四、系统层加固与验证
除了三个组件本身,操作系统层面也有几件事值得做。首先是配置防火墙,只放行80、443和SSH端口,CentOS用firewalld,Ubuntu用ufw,一键脚本安装时如果选了开启防火墙选项则会自动配置。其次是修改SSH默认端口并禁用root密码登录,改用密钥认证,这是拦截爆破攻击最有效的手段。
# 只放行必要端口 firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --reload # 安装fail2ban自动封禁暴力破解IP yum install -y epel-release && yum install -y fail2ban systemctl enable --now fail2ban
所有配置完成后需要进行一轮验证。用curl -I http://127.0.0.1检查响应头是否还暴露版本信息,尝试访问http://IP/.git/config确认返回403,写一个包含system()函数的测试页确认被禁用,用mysql -h 外网IP -u root确认远程连接被拒绝。每一项都通过后,这套LNMP环境才算真正达到可上线的状态。最后提醒一点,加固不是一次性工作,定期执行lnmp update升级组件版本、关注安全公告,才能让服务器长期保持安全。