5分钟极速部署CTFd动态靶场:Docker+Whale插件实战指南
为什么需要动态靶场?
在网络安全竞赛或教学场景中,传统静态靶场存在明显的局限性——所有参赛者共享同一套题目环境,容易导致Flag被复制传播、解题思路被窥探等问题。动态靶场技术通过为每位用户实时生成独立隔离的题目环境,从根本上解决了这些痛点:
- 环境隔离性:每个队伍获得专属容器实例
- Flag唯一性:系统自动生成差异化Flag
- 资源可控性:按需分配计算资源,结束后自动回收
CTFd-Whale作为官方推荐的动态靶场插件,通过与Docker深度集成,实现了开箱即用的动态环境管理能力。下面我们将用最简洁的步骤完成整套系统的部署。
1. 环境准备
1.1 基础组件安装
确保系统已安装以下核心组件(以Ubuntu 20.04为例):
# 更新软件源 sudo apt-get update && sudo apt-get upgrade -y # 安装Docker引擎 curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER # 安装Docker Compose sudo curl -L "https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose验证安装结果:
docker --version && docker-compose --version1.2 网络配置优化
动态靶场需要特殊的网络架构支持,建议提前规划以下网络配置:
| 网络名称 | 用途说明 | IP段示例 |
|---|---|---|
| ctfd_network | CTFd核心服务通信 | 172.16.0.0/24 |
| whale_network | 动态靶机容器间通信 | 172.17.0.0/24 |
| frp_network | FRP反向代理通信 | 172.18.0.0/24 |
创建基础网络:
docker network create ctfd_network docker network create whale_network2. 快速部署CTFd核心
2.1 一键启动基础服务
创建docker-compose.yml文件:
version: '3' services: ctfd: image: ctfd/ctfd:latest ports: - "8000:8000" volumes: - ctfd_data:/var/ctfd - /var/run/docker.sock:/var/run/docker.sock networks: - ctfd_network environment: - UPLOAD_FOLDER=/var/uploads - DATABASE_URL=mysql+pymysql://root:ctfd@db/ctfd - REDIS_URL=redis://redis:6379 db: image: mariadb:10.5 environment: - MYSQL_ROOT_PASSWORD=ctfd - MYSQL_DATABASE=ctfd volumes: - db_data:/var/lib/mysql networks: - ctfd_network redis: image: redis:6 networks: - ctfd_network volumes: ctfd_data: db_data: networks: ctfd_network: driver: bridge启动服务:
docker-compose up -d提示:首次启动可能需要2-3分钟初始化数据库,访问http://服务器IP:8000即可进入安装向导
2.2 管理员账户配置
完成网页端的初始化设置后,建议通过命令行创建超级用户:
docker exec -it ctfd_ctfd_1 flask create_admin3. Whale插件集成
3.1 插件安装与配置
进入CTFd容器安装插件:
docker exec -it ctfd_ctfd_1 bash cd /opt/CTFd/plugins git clone https://github.com/glzjin/CTFd-Whale.git exit修改docker-compose.yml增加Whale所需配置:
ctfd: environment: - WHALE_ENABLED=true - WHALE_FRPC_API=http://frpc:7400 - WHALE_DOCKER_BASE_URL=unix://var/run/docker.sock - WHALE_SUBNET=172.18.0.0/243.2 FRP服务部署
添加FRP服务到docker-compose.yml:
services: frpc: image: glzjin/frp volumes: - ./frpc.ini:/etc/frp/frpc.ini networks: - frp_network - ctfd_network restart: always networks: frp_network: driver: bridge创建frpc.ini配置文件:
[common] server_addr = 172.18.0.1 server_port = 6490 token = your_secure_token admin_addr = 0.0.0.0 admin_port = 7400重启服务使配置生效:
docker-compose down && docker-compose up -d4. 动态题目实战配置
4.1 题目环境构建
以简单的Web题目为例,准备Docker镜像:
FROM nginx:alpine COPY flag /flag COPY src /usr/share/nginx/html RUN chmod 444 /flag && \ echo "<?php echo system(\$_GET['cmd']); ?>" > /usr/share/nginx/html/shell.php构建并推送镜像:
docker build -t your_registry/web_challenge:latest . docker push your_registry/web_challenge:latest4.2 CTFd后台配置
- 进入Admin Panel → Whale → Settings
- 填写Docker连接参数:
- Docker API URL:
unix://var/run/docker.sock - FRP API URL:
http://frpc:7400
- Docker API URL:
- 创建新题目时选择"Dynamic"类型
- 配置题目容器参数:
image: your_registry/web_challenge ports: - "80" memory: 128m cpu: 0.54.3 访问测试
参赛者点击"Start Instance"后,系统将自动:
- 从指定镜像创建独立容器
- 分配随机端口并通过FRP暴露
- 生成唯一Flag注入容器
- 在题目页面显示访问入口
5. 运维与监控技巧
5.1 资源监控命令
查看当前运行的动态容器:
docker ps --filter "label=whale=true"监控资源使用情况:
docker stats $(docker ps -q --filter "label=whale=true")5.2 日志排查方法
查看特定容器的运行日志:
docker logs -f 容器ID检查FRP连接状态:
curl http://localhost:7400/api/status5.3 自动清理策略
设置Cron任务定期清理闲置实例:
0 * * * * docker ps -q --filter "label=whale=true" --filter "status=exited" | xargs docker rm -f对于资源占用过高的容器,可以通过API强制回收:
import docker client = docker.from_env() for container in client.containers.list(filters={"label": "whale=true"}): if container.attrs['State']['Memory']['usage'] > 512*1024*1024: container.kill()