Files
.pouch/skills/host-sec-check/references/hardening.md
T

74 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 分阶段加固
本参考只在用户明确同意「加固 / 配置 / 修复」后使用。默认先做检查,不改变远端主机。
## 0. 变更前闸门
1. 确认目标主机、系统、维护窗口、业务端口和允许的管理来源。
2. 确认有云控制台/VNC/串口等带外回滚入口;没有就不要同时改 SSH 和防火墙。
3. 保留当前 SSH 会话,再准备第二条测试会话。先验证新会话成功,再关闭旧入口。
4. 记录 `sshd -T`、`ss -lntup`、`ufw status verbose` 或 nftables/iptables 状态、Docker/k8s 入口。
5. 将待改配置复制到受限的备份目录,记录时间和校验值;备份中可能有敏感信息,不要贴进聊天。
不要要求用户把 root 密码发给 Agent,也不要使用 `sshpass`、命令行密码、`SSHPASS` 或关闭 host-key 校验。优先复用现有 SSH key;必须创建临时密码时,用控制台或交互式 `passwd` 设置,并在密钥验证后删除/锁定。
## 1. 账号和 SSH
先创建并验证一个非 root 管理账号,再收紧 root 和密码登录:
- 用户加入发行版正确的管理组(Debian/Ubuntu 通常是 `sudo`,RHEL 系通常是 `wheel`)。
- 用户的 `~/.ssh` 为 `0700`,`authorized_keys` 为 `0600`,目录和文件归属正确;只记录 key 指纹,不复制私钥或完整 key 内容。
- 配置应放在发行版支持的 drop-in 中,例如 `/etc/ssh/sshd_config.d/60-host-sec-check.conf`,不要删除或改名所有现有 drop-in。
- 基线建议:`PermitRootLogin no`、`PasswordAuthentication no`、`KbdInteractiveAuthentication no`(启用 MFA/键盘交互时例外)、`PermitEmptyPasswords no`、`PubkeyAuthentication yes`、`MaxAuthTries 3`。
- `X11Forwarding`、TCP 转发、Agent 转发和 `AllowGroups` 要按业务需要逐项确认,不能为了“看起来更安全”无条件关闭。
- 改端口不是必需项;如果确实改,先放行云安全组和本机防火墙,再在第二条会话中用新端口测试。IPv4 和 IPv6 规则都要确认。
每次变更都按这个顺序:
```bash
sshd -t
sshd -T | grep -iE '^(port|permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|permitempty passwords|maxauthtries) '
systemctl reload ssh 2>/dev/null || systemctl reload sshd
# 从另一条终端测试新用户/新端口,成功后才关闭旧登录路径
```
不要按 Ubuntu 版本号猜 SSH socket 模式。先看 `systemctl is-enabled ssh.socket`、`systemctl status ssh.socket ssh.service` 和 `ss -lntp`,按实际监听单元配置;改动后再次用 `sshd -T` 和 `ss` 验证。
## 2. 防火墙和暴露面
- 先识别实际后端:UFW、nftables、firewalld 和 Docker 规则可能同时存在;不能在不了解现有规则时直接 `default deny incoming` 或 reset。
- 保留已有业务白名单,最小化放行管理来源;明确处理 IPv6,避免只收紧 IPv4。
- 防火墙只解决入站路径,不代表云安全组已收紧。云平台规则查不到就写「未验证」。
- Docker 默认会安装自己的转发规则,不能仅凭 `daemon.json` 中没有 `iptables` 就认定需要写入 `"iptables": false`。先检查现有规则、发布端口和业务依赖;优先修正 compose 的绑定(内部服务不发布、回源绑 loopback/VPN),必要时在 `DOCKER-USER`/nftables 设计明确策略。
- 关闭 `rpcbind`、数据库、Docker API、Portainer、Cockpit、k8s API 等入口前,先确认没有业务或编排依赖,并从外部验证端口确实消失。
## 3. Fail2ban、补丁和日志
- 安装/启用 Fail2ban 前确认日志后端(`systemd` journal 或 `/var/log/auth.log`/`secure`),配置 `ignoreip` 为可信管理网段/VPN,而不是只写 loopback。
- 变更后检查 `fail2ban-client status`、对应 jail、过滤器命中和当前封禁;避免把维护网段封掉。
- 按发行版包管理器修补安全更新,并记录是否需要重启;不要把“执行了 apt upgrade”当成补丁覆盖证明。
- 检查时间同步、journal 持久化和日志轮转;日志缺失本身是审计结果,不要静默当作正常。
- `auditd`、自动安全更新和登录通知属于按业务选择的增强项,不是所有机器都应无条件启用。通知脚本必须避免泄露 token、密码和完整环境变量。
## 4. 验证和回滚
加固完成后至少验证:
1. 第二条会话可用:新用户、密钥、预期端口、预期来源均成功。
2. `sshd -t`、`sshd -T`、服务状态、监听端口和防火墙规则与目标一致。
3. 从外部探测 IPv4/IPv6:应关闭的端口不可达,业务域名和必要入口仍可用。
4. Fail2ban jail 正常;Docker/k8s 业务仍能启动,关键容器没有意外变成公网监听。
5. 记录未验证项、重启需求和回滚命令。SSH 或防火墙失败时,优先从带外控制台恢复备份,不要在失联状态下反复猜配置。
## 与“一键加固脚本”的边界
一键脚本可以提供检查清单,但以下做法不能作为本 skill 的默认行为:
- 在命令行、环境变量或最终报告打印密码;
- `StrictHostKeyChecking=no` / `UserKnownHostsFile=/dev/null`;
- 先要求开启 root 密码登录,再自动收紧;
- 删除/改名整个 `sshd_config.d`;
- 无条件开启密码认证或把 root 保留为 `prohibit-password`;
- 用 `sed` 拼接 JSON,或无条件把 Docker `iptables` 设为 `false`;
- 只 `sleep` 几秒后重启 SSH/防火墙,未通过第二会话和外部探测验证。