# Vps Security Hardening

> VPS 安全加固自动化 Skill。通过 SSH 登录 VPS 并执行完整的安全策略配置。 触发场景： - "加固VPS安全"、"VPS安全配置"、"新VPS初始化" - "配置SSH安全"、"修改SSH端口"、"禁用root密码登录" - "VPS安全加固"、"服务器安全设置"、"hardening" 功能（7招安全加固）： 1. 创建 sudo 用户，禁用 root 密码登录 2. 修改 SSH 端口（支持 Ubuntu 不同版本） 3. Fail2ban 自动安装配置 4. SSH 密钥登录支持 5. SSH 登录通知（可选） 6. UFW 防火墙配置 7. Docker 安全提醒 Author: github.com/wlzh Version: 1.0.0

- Skill: `wlzh/vps-security-hardening` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add wlzh/vps-security-hardening`
- Raw SKILL.md: https://api.skillmd.com/api/skills/wlzh/vps-security-hardening/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: wlzh (https://skillmd.com/u/wlzh)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/wlzh/vps-security-hardening

---


# VPS 安全加固 Skill

> 版本: 1.0.7 | 作者: github.com/wlzh | 参考: https://x.com/gxjdian/status/2033751314208059507

## 概述

本 Skill 用于自动化 VPS 安全加固流程，基于「7招安全加固」最佳实践，通过 SSH 远程执行一系列安全配置命令。

## ⚠️ 重要警告

**在执行任何操作前，务必确保：**

1. **VPS 平台防火墙已开放新的 SSH 端口** - 否则将被锁死无法登录！
2. 如使用云服务商（AWS/阿里云/腾讯云等），需在安全组/防火墙规则中放行端口
3. 建议先保持原 22 端口连接，新开一个终端测试新端口成功后再关闭 22

## 🔴 前置条件：开启 root 密码登录

**如果 VPS 不支持 root 密码登录，必须先通过 VNC/控制台 开启！**

很多云服务商（AWS、阿里云等）默认禁用 root 密码登录，只允许密钥登录。在运行此 Skill 前，需要先开启：

**通过 VPS 平台控制台（VNC）执行以下命令：**

```bash
# 1. 开启密码认证
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config

# 2. 开启 root 登录
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config

# 3. 重启 SSH 服务
systemctl restart ssh

# 4. 设置 root 密码（会提示输入两次）
passwd root
```

**执行完成后，才能使用此 Skill 进行 SSH 登录和后续配置。**

## 所需信息（执行时收集）

运行此 Skill 时，需要用户提供：

| 参数 | 说明 | 示例 |
|------|------|------|
| `VPS_IP` | VPS 的 IP 地址 | `192.168.1.100` |
| `ROOT_PASSWORD` | root 密码 | `MyP@ssw0rd` |
| `NEW_USER` | 新建的 sudo 用户名 | `admin` |
| `NEW_USER_PASSWORD` | 新用户密码 | `UserP@ss123` |
| `SSH_PORT` | 新的 SSH 端口 | `22222` |

## 执行流程

### Phase 0: 环境检查

```bash
# 检查本地是否安装 sshpass（用于自动输入密码）
which sshpass || echo "需要安装 sshpass: brew install sshpass 或 apt install sshpass"
```

### Phase 1: SSH 连接与系统检测

1. **检测 root 密码登录是否开启**
2. **检测 Ubuntu 版本**（影响 SSH 配置方式）
3. **登录后执行系统更新**

```bash
# 检测 Ubuntu 版本
lsb_release -a

# 更新系统
apt update && apt upgrade -y

# 检查必要工具
which ufw || apt install ufw -y
which sudo || apt install sudo -y
which fail2ban-client || apt install fail2ban -y
```

**Ubuntu 版本与 SSH 配置方式：**

| Ubuntu 版本 | SSH 配置方式 |
|-------------|-------------|
| 22.10, 23.04, 23.10 | socket 激活，需配置 `/etc/systemd/system/ssh.socket.d/` |
| 24.04+ | 直接修改 `/etc/ssh/sshd_config` 或 `sshd_config.d/` |

### Phase 2: 创建 Sudo 用户（第一招）

```bash
# 创建用户
useradd -m -G sudo -s /bin/bash ${NEW_USER}

# 设置密码
echo "${NEW_USER}:${NEW_USER_PASSWORD}" | chpasswd

# 验证用户创建成功
id ${NEW_USER}
```

### Phase 3: 配置 SSH 安全设置（第二招）

**方式A：Ubuntu 24.04+ / 传统方式**

创建专用配置文件 `/etc/ssh/sshd_config.d/99-hardening.conf`：

```ssh
# VPS Security Hardening - generated by vps-security-hardening skill
# Author: github.com/wlzh
# Version: 1.0.0

Port ${SSH_PORT}
PermitRootLogin prohibit-password
PasswordAuthentication yes
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
```

**方式B：Ubuntu 22.10/23.04/23.10（socket 激活）**

```bash
# 创建 socket 覆盖配置
mkdir -p /etc/systemd/system/ssh.socket.d
cat > /etc/systemd/system/ssh.socket.d/listen.conf << EOF
[Socket]
ListenStream=
ListenStream=${SSH_PORT}
EOF

# 禁用 socket 激活，改用传统服务
systemctl disable --now ssh.socket
systemctl enable --now ssh.service
```

**配置说明：**
- `Port`: 自定义 SSH 端口，避开默认 22
- `PermitRootLogin prohibit-password`: root 仅允许密钥登录（比 without-password 更严格）
- `PasswordAuthentication yes`: 普通用户允许密码登录（配置密钥后可改为 no）
- `PubkeyAuthentication yes`: 启用密钥认证
- `MaxAuthTries 3`: 最多尝试 3 次认证
- `ClientAliveInterval/CountMax`: 5 分钟无活动断开

### Phase 4: 配置 Fail2ban（第三招）

```bash
# 安装 fail2ban
apt install fail2ban -y

# 创建自定义配置
cat > /etc/fail2ban/jail.local << 'EOF'
[sshd]
ignoreip = 127.0.0.1/8
enabled = true
filter = sshd
port = ${SSH_PORT}
maxretry = 5
findtime = 300
bantime = 600
logpath = /var/log/auth.log
action = %(action_)s
EOF

# 启动服务
systemctl enable fail2ban
systemctl start fail2ban
```

**配置说明：**
- `ignoreip`: 白名单 IP，不会被封
- `maxretry`: 允许失败 5 次
- `findtime`: 5 分钟内
- `bantime`: 封禁 10 分钟（设为 -1 永久封禁，但不推荐）

### Phase 5: 验证 SSH 配置

```bash
# 检查配置语法
sshd -t

# 验证配置生效（重启前）
sshd -T | grep -iE "^(port|permitrootlogin|passwordauthentication|pubkeyauthentication) "

# 预期输出：
# port ${SSH_PORT}
# permitrootlogin prohibit-password
# passwordauthentication yes
# pubkeyauthentication yes
```

### Phase 6: 配置 UFW 防火墙（第六招）

```bash
# 设置默认策略
ufw default deny incoming
ufw default allow outgoing

# 允许新 SSH 端口（必须在启用前配置！）
ufw allow ${SSH_PORT}/tcp comment 'SSH custom port'

# 如果有网站服务
# ufw allow 80/tcp
# ufw allow 443/tcp

# 启用防火墙
ufw --force enable

# 删除默认 22 端口（确认新端口可用后）
ufw delete allow 22/tcp 2>/dev/null || ufw status numbered

# 查看状态
ufw status verbose
```

### Phase 7: 重启服务

```bash
# 重载配置
systemctl daemon-reload
systemctl restart ssh.service
systemctl restart fail2ban

# 验证服务状态
systemctl is-active ssh.service
systemctl is-active fail2ban
```

### Phase 8: SSH 登录通知（第五招，可选）

如需配置登录通知（企业微信/Telegram/钉钉）：

```bash
# 编辑 PAM 配置
vim /etc/pam.d/sshd
# 添加：session optional pam_exec.so /usr/local/bin/notify_ssh_login.sh

# 创建通知脚本
vim /usr/local/bin/notify_ssh_login.sh
chmod +x /usr/local/bin/notify_ssh_login.sh
```

**企业微信通知脚本示例：**

```bash
#!/bin/bash
if [ "$PAM_TYPE" != "open_session" ]; then
    exit 0
fi

ip=$PAM_RHOST
date=$(date +"%e %b %Y, %a %r")
name=$PAM_USER
webhook_url="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的webhook密钥"

curl -s -X POST "$webhook_url" \
    -H "Content-Type: application/json" \
    -d "{
        \"msgtype\": \"markdown\",
        \"markdown\": {
            \"content\": \"**SSH登录提醒**\n> 登录用户: $name\n> 客户端IP: $ip\n> 登录时间: $date\"
        }
    }"
```

### Phase 9: 生成报告

执行完成后，生成包含以下内容的报告：

```
════════════════════════════════════════════════════════════
                    VPS 安全加固报告
════════════════════════════════════════════════════════════
执行时间: $(date)
VPS IP: ${VPS_IP}
系统版本: $(lsb_release -ds)

[✓] 系统更新: apt update && apt upgrade 完成
[✓] 新用户: ${NEW_USER} 已创建并加入 sudo 组
[✓] SSH 端口: ${SSH_PORT}
[✓] Root 登录: 仅允许密钥登录 (prohibit-password)
[✓] 密码认证: 已启用（普通用户）
[✓] Fail2ban: 已安装并启动
[✓] UFW 防火墙: 已启用

防火墙状态:
$(ufw status verbose)

Fail2ban 状态:
$(fail2ban-client status sshd)

SSH 配置验证:
$(sshd -T | grep -iE "^(port|permitrootlogin|passwordauthentication) ")

════════════════════════════════════════════════════════════
                    登录信息
════════════════════════════════════════════════════════════
新登录命令: ssh -p ${SSH_PORT} ${NEW_USER}@${VPS_IP}

⚠️ 重要提醒:
1. 请确保 VPS 平台防火墙已开放端口 ${SSH_PORT}
2. 建议配置 SSH 密钥登录后禁用密码认证
3. 保存好新用户密码: ${NEW_USER_PASSWORD}
4. 如使用 Docker，注意配置端口映射安全（见第七招）
════════════════════════════════════════════════════════════
```

## 执行脚本

完整的自动化脚本见 `scripts/harden-vps.sh`，支持以下参数：

```bash
./scripts/harden-vps.sh \
  --ip <VPS_IP> \
  --root-pass <ROOT_PASSWORD> \
  --user <NEW_USER> \
  --user-pass <NEW_USER_PASSWORD> \
  --port <SSH_PORT>
```

## Docker 安全提醒（第七招）

如果 VPS 上运行 Docker，需要注意：

1. **内部服务不暴露端口** - 数据库、Redis 等只在容器内部通信
   ```yaml
   services:
     redis:
       image: redis:alpine
       # 不需要 ports 配置！
   ```

2. **需要反代的服务只监听 127.0.0.1**
   ```yaml
   services:
     app:
       ports:
         - "127.0.0.1:3000:3000"  # 只在本地监听
   ```

3. **需要公网访问的服务才暴露端口**
   ```yaml
   services:
     web:
       ports:
         - "80:80"
         - "443:443"
   ```

**原因**：Docker 会直接修改 iptables 规则，绕过 UFW！

## 常见问题

### Q: sshpass 未安装怎么办？

A: 手动安装：
- macOS: `brew install hudochenkov/sshpass/sshpass`
- Ubuntu/Debian: `sudo apt install sshpass -y`
- CentOS/RHEL: `sudo yum install sshpass -y`

### Q: root 密码登录未开启怎么办？

A: 需要通过 VPS 控制台（VNC/控制台）执行：

```bash
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
systemctl restart ssh
passwd root  # 设置 root 密码
```

### Q: 被防火墙锁死怎么办？

A: 通过 VPS 平台控制台（VNC）登录，执行：

```bash
ufw disable
# 或添加规则
ufw allow 22/tcp
ufw allow ${SSH_PORT}/tcp
```

### Q: 如何配置 SSH 密钥登录？

```bash
# 本地生成密钥
ssh-keygen -t ed25519 -C "your@email.com"

# 复制公钥到服务器
ssh-copy-id -p ${SSH_PORT} ${NEW_USER}@${VPS_IP}

# 测试密钥登录成功后，禁用密码认证
# 修改 /etc/ssh/sshd_config.d/99-hardening.conf
PasswordAuthentication no
systemctl restart ssh
```

## 安全检查清单

- [ ] 系统已更新 (`apt update && apt upgrade`)
- [ ] sudo 用户已创建
- [ ] SSH 端口已修改
- [ ] root 密码登录已禁用
- [ ] Fail2ban 已安装并运行
- [ ] UFW 防火墙已配置
- [ ] 云平台防火墙已开放新端口
- [ ] SSH 密钥已配置（推荐）
- [ ] SSH 登录通知已配置（可选）
- [ ] Docker 端口映射已检查（如适用）

## 版本历史

- **v1.0.0** (2026-03-17): 初始版本
  - 7 招安全加固完整实现
  - 支持 Ubuntu 多版本检测
  - Fail2ban 自动安装配置
  - SSH 登录通知支持
  - Docker 安全提醒

