penicili/ctf-proxmoxer
GitHub: penicili/ctf-proxmoxer
一个基于 FastAPI 和 Ansible 的 CTF 挑赛实例自动化部署后端,与 CTFd 集成,在 Proxmox VE 上为每支队伍按需创建和管理隔离的虚拟机环境。
Stars: 0 | Forks: 0
# CTF Proxmoxer 平台
用于通过 Proxmox VE 管理基于虚拟机的 CTF 挑赛的后端服务。与 CTFd 插件 [CTFd-proxmoxer-client](https://github.com/penicili/ctfd-proxmoxer-client) 配合使用
## 架构
```
flowchart TB
subgraph CTFd["CTFd"]
core["CTFd Core\n(Challenges, Teams, Flags)"]
plugin["ctfd-proxmoxer-client\n(Plugin)"]
plugin -- "baca/tulis data" --> core
end
plugin -- "HTTP REST API" --> backend
subgraph Backend["ctf-proxmoxer (FastAPI Backend)"]
backend["/api/v1/levels\n/api/v1/challenges"]
end
backend -- "Ansible (SSH)" --> builder
backend -- "Ansible (SSH)" --> vms
backend -- "Proxmox API" --> pve_api[("Proxmox VE")]
subgraph PVE["Proxmox VE"]
pve_api
builder["Image Builder\n10.10.10.110\n(docker build + push)"]
registry["Docker Registry\n10.10.10.5:5000"]
vms["Challenge VMs\n(per tim)"]
builder -- "push image" --> registry
registry -- "pull image" --> vms
end
```
## 技术栈
- **后端**: Python, FastAPI
- **数据库**: SQLite (via SQLAlchemy)
- **虚拟化**: Proxmox VE (`proxmoxer`)
- **自动化**: Ansible (`ansible-runner`)
- **容器**: Docker, Docker Registry (`registry:2`)
## 安装
```
git clone https://github.com/penicili/ctf-proxmoxer.git
cd ctf-proxmoxer
python -m venv .venv
source .venv/bin/activate # Linux/Mac
# .venv\Scripts\activate # Windows
pip install -r requirements.txt
cp .env.example .env # isi sesuai environment
uvicorn app:app --host 0.0.0.0 --port 8000 --reload
```
## 所需的基础设施设置
在使用后端之前,请确保在 Proxmox VE 中已准备好以下组件:
| 组件 | 类型 | IP | 功能 |
|---|---|---|---|
| Base Template VM | QEMU Template | — | 作为所有 challenge VM 的克隆源 |
| Docker Registry | LXC | 10.10.10.5 | 存储 challenge 的 Docker image |
| Image Builder | QEMU VM | 10.10.10.110 | 构建并推送 challenge 的 Docker image |
所有组件均在内部网络 `vmbr1` (`10.10.10.0/24`) 中运行。
## Challenge 创建指南
Challenge 以包含存在漏洞的 Web 应用程序的 Git repository 形式创建。后端会自动为参赛者构建、推送并将 challenge 部署到 VM 中。
### Repository 结构
```
challenge-repo/
├── Dockerfile # build image aplikasi challenge
├── docker-compose.yml # wajib ada
├── public-images.txt # opsional, list image publik yang dibutuhkan
└── app/
└── ...
```
### 1. Dockerfile
构建 challenge 应用程序的 image。Flag 通过环境变量 `FLAG` 注入。
```
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
```
在应用程序内部,从环境中读取 flag:
```
import os
FLAG = os.environ.get("FLAG", "CTF{placeholder}")
```
### 2. docker-compose.yml
必须使用系统在部署时注入的环境变量 `REGISTRY_HOST`、`IMAGE_TAG` 和 `FLAG`。
**单服务:**
```
services:
app:
image: ${REGISTRY_HOST}/${IMAGE_TAG}:latest
ports:
- "80:5000"
environment:
- FLAG=${FLAG}
```
**多服务(以 MySQL 为例):**
```
services:
app:
image: ${REGISTRY_HOST}/${IMAGE_TAG}:latest
ports:
- "80:5000"
environment:
- FLAG=${FLAG}
- DB_HOST=db
depends_on:
- db
db:
image: ${REGISTRY_HOST}/mysql:8
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=challenge
```
### 3. public-images.txt (可选)
如果 challenge 需要公共 image(MySQL、Redis 等),请在此文件中列出。系统将在准备阶段把此类 image 镜像同步到内部 registry,从而使部署不依赖互联网。
```
mysql:8
redis:7-alpine
```
`docker-compose.yml` 中的公共 image 必须以 `${REGISTRY_HOST}/` 为前缀编写,以便从内部 registry 而不是 Docker Hub 拉取。
## 系统流程
### 准备阶段
管理员触发准备 → 后端在 Image Builder 上运行 Ansible:
1. `git clone` challenge repository
2. `docker build` 应用程序 image
3. `docker push` 到内部 registry (`10.10.10.5:5000`)
4. 将 `public-images.txt` 中的公共 image 镜像同步到 registry(如果有)
5. `level.template_url` 被设置为 image tag (`level-{id}`)
### 部署 Challenge
管理员为团队部署 challenge → 后端:
1. 在 Proxmox 中克隆 base template VM
2. 等待 VM 启动 + cloud-init(约 30 秒)
3. 在 PVE 主机上设置 iptables 端口转发
4. Ansible 通过 SSH 连接到 VM(通过 PVE 的 ProxyJump):
- `git clone` challenge repo(用于获取 `docker-compose.yml`)
- 写入包含 `FLAG`、`REGISTRY_HOST`、`IMAGE_TAG` 的 `.env` 文件
- `docker compose up -d --pull always`
5. Challenge 状态 → `RUNNING`
6. 通过 API 在 CTFd 中创建 challenge 条目 + flag
### 终止 Challenge
管理员终止 → 后端:
1. 运行 `post_challenge.yml`(在 VM 中清理)
2. 删除 iptables 端口转发规则
3. 在 Proxmox 中停止 VM
## 环境变量
请查看 `.env.example` 获取完整列表。重要变量:
| 变量 | 说明 |
|---|---|
| `PROXMOX_HOST` | Proxmox VE 的 IP |
| `TEMPLATE_VMID` | base template VM 的 VMID |
| `REGISTRY_HOST` | 内部 Docker Registry 的 Host:port |
| `CI_RUNNER_IP` | Image Builder VM 的 IP |
| `CTFD_URL` | CTFd 实例的 URL |
| `CTFD_API_TOKEN` | 用于完成 challenge 的 CTFd API token |
| `SSH_KEY_PATH` | 用于访问 PVE 和 VM 的 SSH key 路径 |
| `VM_SSH_USERNAME` | challenge VM 中的 cloud-init 用户名 |
标签:Ansible, AV绕过, Docker, FastAPI, 安全防御评估, 系统提示词, 自动化运维, 虚拟化, 请求拦截, 逆向工具