项目简介

本项目旨在开发一个基于Docker的AWD比赛平台,通过Docker搭建靶场,提供管理端和用户端,管理端可以管理平台各种资源,快速布置题目,启动靶机,选手端可以查看靶机信息,提交flag。本文介绍了项目当前设计的程度,刚开始起步开发,后面肯定会有很多地方要调整,本人在项目中负责系统设计和后端开发(小菜鸡)后续我会不断发博客记录我的开发过程。另外本系统的设计参考了vider-team开发的Cardinal,对开发这个系统的师傅们表示感谢。

项目背景

实验室的攻防同学对线下AWD赛制都不熟,只会做题,所以我们希望开发这样一个比赛平台,可以给ctf选手进行训练,后续也可以支撑我们校赛。

系统设计

系统架构设计

(我也不太懂这玩意儿怎么画,所以就这样了)

架构图:

docker 搭建并启动dtm docker启动项目_字段

我们设计的思路就是用Docker容器做靶机,后端去管理这些容器,在AWD赛制中,每一台靶机对应一个队伍一道题目。

系统的核心部分和难点

系统的核心在于:

  • 启动靶机,配置靶机
    启动容器,配置容器完全通过代码实现,不需要进入命令行敲命令。
  • 如何进行CheckDown
    AWD比赛中需要检测选手靶机的服务是否挂掉,因为选手可以通过删掉自己靶机上的服务来让其他人不能攻击他,拿不到flag,因此主办方要检测选手的服务有没有down掉,如果down掉了要扣分。
  • 如何快速恢复容器状态,刷新flag
    每轮比赛结束后都要将靶机恢复掉,并要刷新flag(需要动态flag的题目)。

数据库设计:

管理员表:

admin

字段

类型

说明

备注

id

int unsigned

管理员编号

主键

name

varchar(20)

管理员用户名

pwd

varchar(255)

密码

队伍表:

team

字段

类型

说明

备注

id

int unsigned

队伍编号

主键

name

varchar(50)

队伍名

pwd

varchar(255)

密码

logo

varchar(30)

logo文件名

score

double

分数

公告表:

notification

字段

类型

说明

备注

id

int unsigned

通知编号

主键

title

varchar(100)

通知标题

content

varchar(255)

通知正文

题目表

challenge

字段

类型

说明

备注

id

int unsigned

题目编号

主键

title

varchar(100)

题目名

description

varchar(255)

题目描述

score

double

题目基础分数

auto_refresh

tinyint(1)

是否自动刷新flag

command

varchar(255)

刷新flag的命令

visible

tinyint(1)

是否可见

Flag表:

flag

字段

类型

说明

备注

id

int unsigned

flag编号

主键

team_id

int unsigned

所属队伍

box_id

int unsigned

靶机编号

challenge_id

int unsigned

题目编号

round

int unsigned

第几轮

flag

varchar(255)

flag内容

靶机表:

box

字段

类型

说明

备注

id

int unsigned

靶机编号

主键

challenge_id

int unsigned

题目编号

外键

team_id

int unsigned

队伍编号

外键

ip

varchar(30)

ip地址

port

varchar(20)

服务端口号

ssh_user

varchar(20)

ssh用户名

ssh_pwd

varchar(50)

ssh密码

score

double

分数

is_down

tinyint(1)

是否宕机

is_attacked

tinyint(1)

是否被攻击成功

Webhook表:

webhook

字段

类型

说明

备注

id

int unsigned

编号

主键

url

varchar(255)

url

type

varchar(30)

触发类型

retry

int unsigned

重复次数

timeout

int unsigned

时限

attack表:

attack

字段

类型

说明

备注

id

int unsigned

攻击编号

主键

team_id

int unsigned

被攻击队伍id

外键

attacker_id

int unsigned

攻击队伍id

外键

box_id

int unsigned

被攻击靶机id

challenge_id

int unsigned

题目id

外键

round

int unsigned

轮次

config 设置表

config

字段

类型

说明

备注

id

int unsigned

设置编号

主键

key

varchar(255)

设置名

val

varchar(255)

设置值

kind

tinyint

val的类型

请求返回的格式

我这里定义了请求返回的格式,其实这个系统没什么复杂的逻辑,所以就很简单地定义了一下

{
    "code":200,
    "data":{
        "xxx":"xxx",
        "xxxx":"xxx",
    },
    "msg":"success"
}

code:状态码,200表示成功,400表示请求失败,500表示服务器内部错误

data:后端返回的具体数据

msg:是后端返回的信息,一般成功返回success,失败返回错误信息

关键模块设计

这里我介绍下系统关键模块当前的设计

镜像构建

添加前要添加镜像,这里由出题人将构建镜像的文件整理好放到一个文件夹,然后上传

  1. 上传打包镜像的相关文件
  2. 后台打包镜像
  3. 前端可查出镜像。

添加靶机

  1. 选择使用哪个镜像
  2. 选择添加给哪个队伍
  3. 设置靶机服务暴漏的端口号
  4. 设置ssh端口号,账号和密码
  5. 设置是否需要刷新flag

题目check

比赛中题目的check比较复杂,因为涉及的面很广,然后但一个服务端很难实现,所以我们就把check的任务交给出题人,由出题人维护自己的check程序,然后向系统提交哪些靶机挂了

flag刷新

添加完靶机后,我们直接在数据库中生成好flag,然后到需要刷新的时候取出来,到靶机里执行shell命令去替换就完事了。

技术选型

后端采用gin做web框架,使用gorm操作数据库,使用docker-sdk连接docker进程,前端使用vue

后面使用了jwt做鉴权,用viper读配置文件。

当前开发进度

现在就是把项目的大体框架搭出来了,定义了一下前端请求的接口。

项目目录长这样子

Evo/
├── auth                             这里是权限相关的内容
│   ├── jwt.go
│   ├── jwt_test.go
│   ├── pwd.go
│   └── pwd_test.go
├── config                         这里是系统启动时初始化设置的模块
│   ├── config.go
│   ├── config_test.go
│   └── config.yml
├── ctrl                            controller,不用多说
│   ├── accountCtrl.go
│   ├── adminCtrl.go
│   ├── boxCtrl.go
│   ├── challengeCtrl.go
│   ├── configCtrl.go
│   ├── flagCtrl.go
│   ├── imageCtrl.go
│   ├── noticeCtrl.go
│   ├── resp.go
│   ├── starryCtrl.go
│   ├── teamCtrl.go
│   └── webhookCtrl.go
├── db                           数据库相关
│   └── mysql.go
├── docker                          这里写docker相关的东西
├── dto                              数据传输对象,不一定会用到
├── game                             比赛相关的,比如计分,验证flag之类的
├── go.mod
├── go.sum
├── main.go
├── middleware                         这里是中间件
│   └── authMW.go
├── model                              模型
│   ├── admin.go
│   ├── attack.go
│   ├── box.go
│   ├── challenge.go
│   ├── flag.go
│   ├── notification.go
│   ├── team.go
│   └── webhook.go
├── router                            路由
│   └── router.go
└── util                                工具包

最后

我给这个项目命名为Evo,取应为单词evolution(进化)的前三个字母,我希望这个平台开发好之后能一直维护改进下去,不断进化。
开发环境:

  • Ubuntu 20.04
  • docker 20.10.14
  • go 1.17.3
  • vim 8.1.2269