你的网站可能比你想象的更脆弱
很多个人站长觉得自己的网站没流量没名气,黑客不会盯上。这个想法大错特错。绝大多数针对个人网站的攻击都是自动化的——扫描器每天都在全网扫描漏洞,根本不是黑客手动挑选目标。你的网站只要有一个漏洞,在二十四小时内就会被扫描到。
我运营网站十五年来,经历过数据库被拖库、首页被篡改为赌博页面、后台被暴力破解等多种安全事件。这篇文章把我踩过的坑和学到的防护经验全部写出来。
一、服务器层面的防护
SSH 安全配置
SSH 是服务器管理的入口,也是被暴力破解的重灾区。查看服务器日志就会发现,每天都有来自全世界的 IP 在尝试登录。下面是必须做的配置:
修改 SSH 默认端口从 22 改成其他高位端口,比如 22222。虽然不能完全防止扫描,但能过滤掉百分之九十九的无差别攻击。禁用 root 远程登录,创建一个普通用户日常使用,需要提权时再 su 或 sudo。配置 SSH 密钥认证,禁止密码登录。这样即使密码泄露也无法远程访问服务器。
# /etc/ssh/sshd_config
Port 22222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers youruser修改后记得重启 SSH 服务并保持原有会话不断开,测试新连接正常后再退出旧会话,避免把自己锁在门外。
防火墙配置
iptables 或 nftables 是 Linux 系统自带的防火墙。对于个人站长,推荐使用 ufw 或 firewalld 这类前端工具。仅开放必要的端口:SSH 端口、HTTP 的 80 端口、HTTPS 的 443 端口。其他端口全部关闭。
对于特定服务,比如 phpMyAdmin 或者后台管理路径,可以限制只允许你的家庭 IP 访问。在 Nginx 层面做 IP 白名单:
location /admin/ {
allow 你的家庭IP;
deny all;
}入侵检测与自动防御
Fail2ban 是站长必备的防御工具。它监控日志文件中的失败登录记录,当某个 IP 在短时间内出现多次失败尝试时,自动将该 IP 加入防火墙黑名单。安装配置简单,资源消耗低,效果立竿见影。
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 86400
findtime = 600
maxretry = 5
[sshd]
enabled = true
port = 22222
logpath = %(sshd_log)s
[nginx-http-auth]
enabled = true
logpath = %(nginx_error_log)s二、网站应用层面的防护
文件权限设置
这是最容易被忽略的问题。很多站长为了省事,直接把网站目录设为 777 权限,相当于把家门敞开。正确的权限策略是:所有文件所有者设为普通用户,目录权限设为 755,普通文件权限设为 644。上传目录单独设置,需要写入权限但不能执行脚本。
find /var/www/html -type f -exec chmod 644 {} \;
find /var/www/html -type d -exec chmod 755 {} \;
chmod 750 /var/www/html/uploads防止 SQL 注入
SQL 注入是最古老也最常见的攻击方式。只要你的网站涉及数据库查询,就面临这个风险。预防的核心原则是永远不要信任用户输入。所有用户输入都应当经过参数化查询处理。
对于 WordPress 用户,使用 prepare 方法确保 SQL 查询安全。对于使用框架的开发者,框架的 ORM 通常已经做好了防注入处理,关键是要始终使用框架推荐的方式操作数据库,不要为了省事直接拼接 SQL。
防止 XSS 跨站脚本攻击
XSS 攻击通过向页面注入恶意脚本窃取用户信息。防护措施包括:输出内容时进行 HTML 实体编码,设置 HttpOnly Cookie,使用 Content-Security-Policy 响应头限制脚本来源。
# Nginx 配置 CSP
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:;";Nginx 安全配置
Nginx 的几项安全配置能挡住大量自动化攻击。隐藏版本号防止针对特定版本的漏洞利用。限制请求频率防止暴力破解。限制请求体大小防止大文件攻击。配置 HTTPS 使用最新 TLS 协议。
# nginx.conf 安全配置
server_tokens off;
client_max_body_size 10m;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
ssl_protocols TLSv1.2 TLSv1.3;三、数据备份策略
没有备份的网站等于随时面临数据归零的风险。服务器硬盘故障、被入侵数据遭删除、升级操作失误——任何一个场景都让你追悔莫及。
备份原则
3-2-1 备份法则是业界的黄金标准:保留三份数据副本,存储在两种不同的介质上,其中一份存放在异地。对于个人站长,具体可以这样执行:服务器上保留一份当天的本地备份,每天自动上传到另一个存储服务,每周手动将关键数据库导出到个人电脑。
自动化备份脚本
一个简单的自动备份脚本可以解决大部分备份需求:
#!/bin/bash
BACKUP_DIR=/backup
DB_NAME=yourdb
DB_USER=dbuser
DB_PASS=dbpass
DATE=$(date +%Y%m%d)
# 备份数据库
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/db_$DATE.sql.gz
# 备份网站文件
tar -czf $BACKUP_DIR/www_$DATE.tar.gz /var/www/html
# 删除30天前的旧备份
DEL_CMD="find $BACKUP_DIR -type f -mtime +30 -delete"
eval $DEL_CMD
# 上传到远程存储
rclone copy $BACKUP_DIR remote:/backups/$DATE/通过 crontab 设置为每天凌晨执行,配合 rclone 同步到其他存储,你的数据安全就有了双重保障。
四、日常安全运维清单
每天登录服务器检查失败登录日志,关注是否有异常的接口请求。检查网站访问日志中的 404 和 500 状态码分布,异常的 404 大量出现说明有人在扫描漏洞。查看服务器磁盘使用率和 inode 使用情况,防止恶意文件写满磁盘。
每周检查网站文件的修改时间,关注是否有近期被修改的核心文件。运行安全扫描工具检查已知漏洞。更新服务器软件包的安全补丁。
每月进行全面的安全审计。检查所有账号和权限是否合规。回顾备份恢复流程是否仍然有效。测试防火墙规则是否正常工作。
五、被入侵后的应急响应流程
即使做好所有防护,也要假设自己终有一天会被攻破。提前准备应急响应流程能最大限度降低损失。
第一步是立即断开服务器网络连接,防止数据继续外泄。然后登录服务器检查系统日志,定位入侵时间和途径。分析被修改的文件,确定攻击者做了什么操作。从备份中恢复数据,修复漏洞。如果无法确定入侵途径,建议重装系统从头部署。
结语
安全不是一个可以一劳永逸的事情,而是一个持续对抗的过程。对个人站长来说,做好基础防护就能挡住百分之九十以上的自动化攻击。记住一句话:你不需要比黑客强,只需要比隔壁网站安全做得更好。把上面提到的基础配置全部落实到位,你的网站就已经超过了绝大多数个人站点。