服务器安全不是装个防火墙就万事大吉的事。一个暴露在公网的 Linux 服务器,如果没有经过系统性的加固,从上线到被扫描器盯上可能只需要几个小时。这篇文章从 Linux 系统层、Nginx 中间层到 MySQL 数据层,给出一份可直接落地的安全加固清单,同时覆盖 XSS 和 SQL 注入这两个最常见的 Web 攻击面。
一、Linux 服务器安全加固清单
1. SSH 加固
SSH 是服务器最重要的入口,也是最常被暴力破解的目标。
- 禁用 root 远程登录:在
/etc/ssh/sshd_config中设置PermitRootLogin no,日常操作使用普通用户 +sudo。 - 改用密钥认证:设置
PasswordAuthentication no,彻底关闭密码登录。配合ssh-keygen生成密钥对,公钥放到服务器的~/.ssh/authorized_keys。 - 修改默认端口:将 22 端口改为非标准端口(如 22022),能过滤掉绝大部分自动化扫描。
- 限制登录来源:如果服务器只服务于特定 IP 段,用
AllowUsers或防火墙规则限制来源。 - 安装 fail2ban:自动封禁多次登录失败的 IP,配置简单且效果显著。
2. 防火墙与端口管理
遵循最小开放原则——只开放必要的端口。
# 使用 ufw 的典型配置
ufw default deny incoming
ufw default allow outgoing
ufw allow 22022/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
定期用 ss -tlnp 检查监听端口,关闭不需要的服务。很多安全事件源于一个被遗忘的测试端口。
3. 系统更新与权限
- 开启自动安全更新:Ubuntu/Debian 用
unattended-upgrades,CentOS 用yum-cron。 - 检查 SUID 文件:
find / -perm -4000 -type f 2>/dev/null,确认没有异常提权入口。 - 关键目录权限:
/etc/shadow应为640,/root应为700。 - 启用 SELinux 或 AppArmor,为服务提供额外的访问控制层。
4. 日志与监控
部署 auditd 记录关键系统调用,用 logwatch 或集中式日志方案(如 ELK)定期审查异常行为。至少确保 /var/log/auth.log 有人看——或者有工具帮你看。
二、Nginx 安全配置要点
Nginx 作为反向代理和 Web 服务器,是攻击者接触应用的第一层。
隐藏版本信息
server_tokens off;
避免在响应头和错误页面中暴露 Nginx 版本号,减少被针对性利用的可能。
安全响应头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'" always;
其中 Content-Security-Policy(CSP)是防御 XSS 的重要补充手段,后文会展开。
限制请求与连接
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_conn addr 10;
}
这能有效缓解暴力破解和简单的 CC 攻击。
其他关键项
- 禁用不需要的 HTTP 方法:
if ($request_method !~ ^(GET|HEAD|POST)$) { return 405; } - 禁止访问敏感文件:
location ~ /\.(git|env|htaccess) { deny all; } - 上传目录禁止执行 PHP:
location /uploads/ { location ~ \.php$ { deny all; } }
三、XSS 的常见方式与前端防御
XSS(跨站脚本攻击)的本质是攻击者让恶意脚本在受害者的浏览器中执行。常见类型有三种:
- 存储型 XSS:恶意脚本被存入数据库(如评论区),所有访问该页面的用户都会中招。危害最大。
- 反射型 XSS:恶意脚本通过 URL 参数传入,服务器直接回显在页面中。通常需要诱导用户点击特制链接。
- DOM 型 XSS:前端 JavaScript 直接从
location.hash、document.URL等来源取数据并插入 DOM,不经过服务器。
前端防御的核心原则
永远不信任用户输入,永远对输出进行编码。
具体做法:
- 输出编码:将
<转为<、>转为>、"转为"。根据输出上下文选择编码方式——HTML 内容、HTML 属性、JavaScript 字符串、URL 各自的编码规则不同。 - 避免危险的 DOM 操作:用
textContent替代innerHTML,用setAttribute替代直接拼接属性。如果必须用innerHTML,先经过 DOMPurify 等库净化。 - CSP 作为纵深防御:通过
Content-Security-Policy头限制脚本来源,禁止内联脚本执行。即使编码出现疏漏,CSP 也能阻断大部分 XSS 利用。 - Cookie 加 HttpOnly:让 JavaScript 无法读取会话 Cookie,即使 XSS 成功也无法直接窃取会话。
四、MySQL 防止 SQL 注入的几种写法
SQL 注入的根源是将用户输入拼接进 SQL 语句。防御的核心是让数据和指令分离。
1. 参数化查询(首选)
// PDO 预处理
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $email]);
# Python + MySQL Connector
cursor.execute("SELECT * FROM users WHERE email = %s", (email,))
参数化查询让数据库驱动负责转义和类型处理,是防御 SQL 注入最可靠的方式。
2. 使用 ORM
Laravel 的 Eloquent、Django ORM、SQLAlchemy 等默认使用参数化查询,只要不手写原生 SQL 拼接,基本不会引入注入漏洞。
# Django ORM 自动参数化
User.objects.filter(email=email)
3. 输入验证与白名单
对于无法参数化的场景(如动态表名、排序字段),使用严格白名单:
$allowed = ['name', 'created_at', 'email'];
$orderBy = in_array($_GET['sort'], $allowed) ? $_GET['sort'] : 'name';
4. 最小权限原则
应用连接数据库的账号不应拥有 DROP、FILE、GRANT 等权限。只授予必要的 SELECT、INSERT、UPDATE、DELETE,并且只限于特定数据库。
5. 额外加固
- 关闭
local_infile,防止通过LOAD DATA LOCAL读取服务器文件。 - 开启慢查询日志,监测异常查询模式。
- 使用 WAF(如 ModSecurity)作为补充层,但绝不能替代代码层的参数化查询。
结语
安全加固是一个持续的过程,不是一次性的配置任务。Linux 层控制入口,Nginx 层过滤流量,应用层防御 XSS 和 SQL 注入,数据库层限制权限——每一层都不完美,但叠加起来能大幅提高攻击成本。建议将上述清单转化为自动化脚本或配置管理工具(如 Ansible)中的检查项,定期审计,持续更新。
未经允许不得转载:任鹏个人博客 » 服务器安全加固清单:Linux、Nginx 与 MySQL 实战指南


朋友圈点赞图在线生成源码