Ubuntu服务器部署LNMP环境后,默认配置往往只满足“能跑起来”,离生产环境的安全标准还有很大差距。很多站点被入侵并不是因为漏洞多高明,而是权限给太大、日志没人看、危险函数没禁用、备份没做隔离。下面直接针对Nginx、PHP-FPM、MySQL、系统层和运维流程给出可落地的加固方案。
一、系统基础层加固:先把地基打牢Ubuntu刚装完第一件事不是装软件,而是更新和最小化。执行 apt update && apt upgrade -y 把所有补丁打上,然后检查 /etc/ssh/sshd_config。把 PermitRootLogin 改成 no,PasswordAuthentication 改成 no,只允许密钥登录。如果必须保留密码,至少把 Port 从22改成一个不常用的高位端口,同时安装 fail2ban 自动封禁暴力破解IP。
创建普通用户并加入sudo组,日常操作一律用普通用户,需要提权时再sudo。不要用root直接跑任何服务。接着启用UFW防火墙,只放行SSH端口、80和443,其他全部拒绝。命令如下:
ufw default deny incoming ufw default allow outgoing ufw allow 22/tcp ufw allow 80/tcp ufw allow 443/tcp ufw enable
系统层还要限制共享内存、禁止无用模块加载。编辑 /etc/fstab 加入 tmpfs /dev/shm tmpfs defaults,noexec,nosuid 0 0,防止攻击者利用共享内存执行恶意程序。内核参数方面,在 /etc/sysctl.conf 里开启 SYN洪水防护、禁用ICMP重定向、开启反向路径过滤,这些能有效缓解DDoS和IP欺骗。
二、Nginx加固:从配置上堵住信息泄露和非法访问Nginx默认会暴露版本号,攻击者可以针对性找对应版本的漏洞。在 nginx.conf 的 http 块里加上 server_tokens off; 隐藏版本信息。同时设置 client_body_timeout、client_header_timeout 为10秒左右,限制慢速连接占用资源。限制请求体大小 client_max_body_size 根据业务实际设置,比如10m,防止上传大文件耗尽磁盘。
每个站点配置文件里,要明确禁止访问隐藏文件和敏感目录。在 server 块中加入:
location ~ /\. {
deny all;
}
location ~* \.(sql|log|ini|conf|sh|bak|tar|gz|zip)$ {
deny all;
}
这样能防止源码包、数据库备份、配置文件被直接下载。如果站点有上传目录,必须在该目录的location里加 location ~* \.(php|php5|phtml)$ { deny all; },禁止上传目录执行PHP脚本。同时关闭目录浏览 autoindex off。
HTTPS是必须的,不要再用HTTP明文传输。配置TLS时禁用旧协议,只保留TLSv1.2和TLSv1.3,加密套件用强加密组合。启用HSTS头 add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; 防止降级攻击。再配合 add_header X-Frame-Options SAMEORIGIN; 和 add_header X-Content-Type-Options nosniff; 减少点击劫持和MIME嗅探风险。
如果Nginx作为反向代理,要确保 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; 正确传递,避免后端PHP获取到错误的客户端IP导致IP限制失效。
三、PHP-FPM加固:禁用危险函数,隔离站点权限PHP是LNMP里最容易被利用的环节。打开 php.ini,把 expose_php 设为 Off,不暴露PHP版本。disable_functions 必须配置,至少禁用以下函数:exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,phpinfo。注意curl_exec如果业务需要远程请求,可以保留,但其他命令执行类函数必须全部禁用。
同时设置 allow_url_fopen = Off 和 allow_url_include = Off,禁止远程文件包含。open_basedir 限制PHP只能访问指定目录,比如 /var/www/site1:/tmp,这样即使某个站点被上传了webshell,也无法读取其他站点的文件。memory_limit 设置合理值,比如128M或256M,防止单个进程吃光内存。
PHP-FPM的进程池配置同样关键。每个站点使用独立的用户和组运行,不要全部用www-data。在 /etc/php/8.1/fpm/pool.d/ 下为每个站点创建独立pool,配置 user 和 group 为站点专属用户,listen.owner 和 listen.group 也对应设置。这样站点A被入侵后,攻击者无法直接读写站点B的文件。listen 模式建议使用Unix socket而非TCP端口,减少网络暴露面。
还要开启 php-fpm 的慢日志和错误日志,slowlog 路径指定好,request_slowlog_timeout 设为5秒,方便发现异常执行。pm.max_children 根据服务器内存合理设置,防止进程数过多导致OOM。
四、MySQL/MariaDB加固:最小权限和审计并重数据库默认安装后有几个匿名用户和测试库,必须清理。执行 mysql_secure_installation 脚本,删除匿名用户、禁止root远程登录、删除test库、刷新权限。然后修改root默认认证插件,使用强密码。
业务上不要用root连接数据库。为每个站点创建独立数据库用户,只授予该库的SELECT、INSERT、UPDATE、DELETE权限,不授予FILE、PROCESS、SUPER等全局权限。授权语句示例:
CREATE USER 'site1_user'@'localhost' IDENTIFIED BY '强密码'; GRANT SELECT,INSERT,UPDATE,DELETE ON site1_db.* TO 'site1_user'@'localhost'; FLUSH PRIVILEGES;
如果应用和数据库在同一台服务器,绑定地址设为127.0.0.1,不要监听0.0.0.0。在 /etc/mysql/mysql.conf.d/mysqld.cnf 里设置 bind-address = 127.0.0.1。如果必须远程连接,用SSH隧道或内网专线,不要直接暴露3306端口到公网。
开启MySQL的通用查询日志或慢查询日志,至少开启慢查询日志,long_query_time 设为2秒。定期检查日志里是否有异常的SELECT、UNION、INTO OUTFILE等操作。同时开启 error log,记录启动、关闭和错误信息。数据库备份要定期做,备份文件不能放在web可访问目录下,最好用mysqldump加密后同步到异地。
五、文件权限与目录结构:让入侵者寸步难行很多站点被篡改是因为文件权限设置成777。正确的做法是:网站根目录属主为站点用户,属组为www-data,目录权限750,文件权限640。上传目录如果需要写权限,设置为770,但禁止执行PHP。配置文件如 .env、config.php 权限设为600,属主为站点用户。
用 find 命令批量修正权限:
find /var/www/site1 -type d -exec chmod 750 {} \;
find /var/www/site1 -type f -exec chmod 640 {} \;
chown -R site1_user:www-data /var/www/site1
对于需要写入的目录如 runtime、cache、uploads,单独设置 chmod -R 770 并确认属组为www-data。不要为了方便把所有目录都设成777,那等于把钥匙挂在门上。
另外要监控文件变化。安装 aide 或 tripwire 做文件完整性检查,每天生成报告,发现核心文件被改动立即告警。也可以写个简单的cron脚本,用 find -mtime -1 找出24小时内被修改的php文件,配合邮件通知。
六、日志与监控:看不见的攻击最危险日志是安全加固的最后一环,也是最容易被忽视的一环。Nginx的access log和error log必须开启,格式里要包含真实客户端IP、请求时间、请求方法、URI、状态码、响应时间。PHP-FPM的错误日志和慢日志同样要保留。MySQL的慢查询和错误日志也要集中收集。
建议用 logrotate 对日志做轮转,防止单个日志文件过大。配置 /etc/logrotate.d/nginx 和 php-fpm,按天切割,保留30天。同时把关键日志同步到远程日志服务器或对象存储,避免入侵者删日志掩盖痕迹。
实时监控方面,安装 netdata 或 prometheus + node_exporter 监控CPU、内存、磁盘IO、网络流量。当出现异常流量突增、CPU长时间100%、磁盘写入异常时,能第一时间发现。再配合 fail2ban 监控Nginx日志里的404、502、恶意扫描特征,自动封禁IP。
最后是备份。再强的安全措施也无法保证100%不被入侵,所以备份是底线。用 rsync 或 rclone 把网站文件和数据库每天备份到异地,保留至少7天版本。备份文件加密存储,恢复流程要定期演练,确保真出问题时能快速恢复。
七、安全加固后的验证清单完成以上步骤后,用以下清单逐项验证:SSH是否已禁止root密码登录;防火墙是否只开放必要端口;Nginx是否隐藏版本号并禁止敏感文件访问;PHP危险函数是否全部禁用;每个站点是否使用独立用户运行;MySQL是否删除匿名用户并限制root远程登录;文件权限是否没有777;日志是否开启并轮转;备份是否自动化并异地存储。
安全加固不是一次性工作,而是持续过程。每周检查系统更新,每月审查日志和权限变化,每季度做一次渗透测试。Ubuntu的LNMP环境只要按上述方案落实,就能抵御绝大多数自动化攻击和常见入侵手法。
