我见过的个人服务器事故,几乎没有一起是被 0day 打穿的。常见剧本是三件事凑齐:22 端口对全网开放、root 允许密码登录、系统半年没更新。
下面 12 条按“先收口、再补洞、最后留证据”的顺序排。全部做完大约一个下午,每条都附验证方法。
背景:先想清楚威胁模型#
加固不是把能关的都关掉。先回答三个问题,后面的选择才有依据。
这台机器暴露在哪?公网、内网、还是只走隧道。谁需要登录?只有你,还是有一个团队。最坏的损失是什么?数据被读、被删,还是被当成跳板。
答案不同,清单的取舍也不同。比如只走内网的机器,可以省掉 fail2ban;但备份和日志外送不能省,因为它们防的是另一类事故。
还有一个现实约束:个人服务器往往没人接手。配置要能被未来的自己看懂,所以宁可少改几项,也别留下一堆没有注释的规则。清单的意义是可持续,不是一次做满分。
12 条清单#
| # | 项目 | 关键动作 |
|---|---|---|
| 1 | SSH 认证 | 只允许密钥,禁 root 密码登录 |
| 2 | 防火墙 | 默认拒绝,只放行必要端口 |
| 3 | 安全更新 | 自动安装安全补丁 |
| 4 | 暴力破解 | fail2ban 或 nftables 限速 |
| 5 | 账号权限 | 独立账号 + sudo 最小授权 |
| 6 | 服务收口 | 关掉不用的服务与监听端口 |
| 7 | 审计日志 | auditd + 日志外送 |
| 8 | 时间同步 | chrony 或 systemd-timesyncd |
| 9 | TLS 证书 | 自动续期 + 到期告警 |
| 10 | 备份 | 3-2-1 + 定期恢复演练 |
| 11 | 容器 | 不暴露 docker.sock,镜像扫描 |
| 12 | 监控告警 | 登录、磁盘、异常出站 |
前六条的核心配置在下面逐条给出,后六条在下一节展开。
修复与缓解:先把六道门关上#
SSH 是最高优先级。密码登录是绝大多数入侵的入口,密钥登录加禁用 root 能挡掉九成自动化攻击。
只改端口号不算加固。扫描器会扫全端口,换个 2222 只能减少日志噪音。真正的门槛是密钥加来源限制。
# /etc/ssh/sshd_config.d/99-hardening.conf
PermitRootLogin prohibit-password
PasswordAuthentication no
KbdInteractiveAuthentication no
MaxAuthTries 3
LoginGraceTime 20
AllowUsers deploy
改之前确认你的公钥已经在 ~/.ssh/authorized_keys 里,并且 PermitRootLogin 不会把你锁在外面。改完先 sshd -t,再 systemctl reload ssh,然后新开一个窗口验证登录,成功后才关掉旧会话。
防火墙 用默认拒绝。下面这段 nftables 只放行 SSH 和 HTTP/HTTPS:
# /etc/nftables.conf(先备份现有规则)
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif lo accept
tcp dport { 22, 80, 443 } accept
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
}
}
nft -c -f /etc/nftables.conf 先做语法检查,再 systemctl reload nftables。远程操作时,规则里必须先放行你自己的 SSH 来源,否则 reload 的瞬间就断了。
改规则前先留一份:nft list ruleset > /root/nft-backup-$(date +%F).rules。这个备份比任何文档都有用,写错时一条命令就能恢复。
自动更新 用 unattended-upgrades(Debian 系)或 dnf-automatic(RHEL 系)。只自动装安全更新,不自动重启,重启窗口自己定。
装完不重启,内核漏洞其实还在。给自己定一个每月重启窗口,比纠结“能不能不重启”更实际。
sudo dpkg-reconfigure --priority=low unattended-upgrades # 交互式开启
sudo unattended-upgrade --dry-run -d | tail -20 # 先空跑看会装什么
fail2ban 负责挡暴力破解。默认的 sshd 规则就够用,重点是别把 bantime 设得太短,也别把自家 IP 封了。
账号权限 上,日常用普通账号,sudo 按命令授权,/etc/sudoers.d/ 里一条条写清楚。别给 ALL=(ALL) NOPASSWD: ALL,那等于把 root 密码贴在门上。
服务收口 用 ss -tulpn 看监听端口,逐个确认用途。很多机器上跑着半年前试用的服务,监听在 0.0.0.0,主人早忘了。
后六条:补洞与留证据#
审计 用 auditd 记录关键目录与提权操作。规则不用多,先覆盖 /etc、/usr/bin、sudoers 和 pkexec 这类敏感路径。
# 监控 /etc 下的改动与提权命令
auditctl -w /etc/passwd -p wa -k identity
auditctl -w /etc/sudoers -p wa -k sudoers
auditctl -a always,exit -F arch=b64 -S execve -F path=/usr/bin/sudo -k sudo_exec
规则写进 /etc/audit/rules.d/,否则重启就没了。日志要外送,本地日志被清是入侵后的常见动作。
时间同步 看起来无关安全,其实关系到日志排序、TLS 校验和 TOTP。timedatectl 确认 System clock synchronized: yes 就行。
顺手把时区统一成 UTC。跨时区排查时少一层换算,日志时间对不上,任何事后分析都要打折扣。
TLS 证书 用 certbot 自动续期,配一条到期提醒。证书过期导致的事故,比大多数漏洞更常见。
备份 按 3-2-1:三份副本、两种介质、一份异地。比备份策略更重要的是恢复演练——没恢复过的备份,只能算心理安慰。
恢复演练不需要等出事才做。每季度挑一个非核心服务,从备份还原到临时目录,确认文件权限、数据库一致性、启动脚本都对。演练记录比备份成功率更有说服力。
容器 方面,别把 /var/run/docker.sock 挂进容器,那等于给了容器 root。镜像用固定 tag 或 digest,别用 latest。镜像扫描工具定期跑一次。
监控 至少覆盖三件事:异常登录(新 IP、新密钥)、磁盘写满、异常出站连接。第三项最能发现被当成跳板的机器。别只装个面板看看,告警要发到你会看的渠道。
验证:逐条对,别凭感觉#
下面这些命令不改变配置,只把“我以为”变成“我确认”。跑完把输出贴进变更记录,三个月后回看能省很多事。
sshd -T | grep -E 'permitrootlogin|passwordauthentication|allowusers'看生效值。ss -tulpn与防火墙规则对一遍,确认没有多余监听。sudo -l检查当前账号的实际权限。systemctl list-timers确认自动更新与证书续期的定时任务在跑。- 从外部扫一次端口(用你信任的工具),确认只开了计划内的端口。
- 恢复演练:从备份还原一个文件或一个数据库,记下耗时。
结论#
- 个人服务器的主要风险是配置疏漏,不是 0day;先收口,再谈检测。
- SSH、防火墙、自动更新三条做完,能挡掉绝大多数自动化攻击。
- 审计与日志外送的价值在事后,别等出事才想起没开。
- 备份的关键指标是恢复耗时,不是备份文件大小。
- 清单每季度过一遍,机器变了,配置就会漂移。
完