之前的文章丢了,重新写一个

这里使用赵师傅开发 ctfd-whale 插件实现动态靶机和动态 flag 功能,要知道的是赵师傅开发的插件是为了适合 buu 的架构,对于普通单服务器搭建靶场的需求对应的是赵师傅博客中的第一个模式。由于赵师傅的博客中有一大部分没有解释清楚的地方,这里写一篇文章做详解。

准备

安装环境

由于动态靶机是使用 docker 实现的,所以首先要准备安装一下 docker

1
2
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun 
sudo usermod -aG docker vaala

然后还要准备 docker-compose

1
sudo apt install docker-compose -y

配置环境

由于插件使用的是集群的模式,所以这里要创建一个单个服务器的集群

1
docker swarm init

然后获得节点 ID

1
docker node ls | awk '{print $1}'

然后将这个 ID 代表的服务器加入集群

1
docker node update --label-add name=linux-1 unvkxf584pwghr2klw******* # 这里换成上一步找到的 ID

最后要准备的是给 docker 更换镜像源,这里推荐将 daocloud 和 aliyun 的源都添加进去,不然会很龟速,也可以给 docker 设置镜像源代理如下

1
2
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo nano /etc/systemd/system/docker.service.d/http-proxy.conf

然后添加内容,这里是我自己的代理

1
2
3
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"

重启生效

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

安装

下载

首先使用赵师傅仓库中的 ctfd,已经做好了镜像换源等工作。

1
git clone -b single https://github.com/glzjin/CTFd.git

由于国内访问 github 会出现速度慢的问题,所以这里我将源码上传到了我的服务器以供高速下载

1
curl -o CTFd.tar https://file.vaa.la/s/Swo9frbkoAMncky/download && tar -xf CTFd.tar

配置

1
2
3
cd CTFd
nano frp/frps.ini # token 一定要随机
nano frp/frpc.ini # token 一定要随机

这里给出 frp 两个配置文件的内容供参考,大致就是只需要修改 token

  • frpc.ini

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [common]
    token = randomme
    server_addr = 172.1.0.1
    server_port = 6490
    pool_count = 200
    tls_enable = true

    admin_addr = 172.1.0.3
    admin_port = 7400
  • frps.ini

    1
    2
    3
    [common]
    bind_port = 6490
    token = randomme

修改好之后我们修改一下 Dockerfile 中的源,之前的 tuna 源有些东西有问题,这里换成阿里的,并且要删除 Dockerfile 中的 python,要修改的部分修改后大概就是这一段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
FROM python:3.7-alpine

WORKDIR /opt/CTFd
RUN mkdir -p /opt/CTFd /var/log/CTFd /var/uploads

RUN echo http://mirrors.aliyun.com/alpine/v3.12/main/ > /etc/apk/repositories && \
apk update

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

RUN apk add \
linux-headers \
libffi-dev \
gcc \
g++ \
make \
musl-dev \
mysql-client \
git \
openssl-dev

删除 requirements.txt 中的 gevent 版本号

1
2
3
datafreeze==0.1.0
gevent
python-dotenv==0.10.3

然后安装插件并启动

1
2
git submodule update --init
docker-compose up -d

不出意外就应该成功了,使用

1
docker ps -a

查看是否有没有正确启动的镜像

平台设置

浏览器访问 8000 端口进入平台,完成平台基本配置,然后进入后台,右上角的插件中进入 ctfd-whale 设置,按下面的内容填写配置

内容
Docker API URL unix://var/run/docker.sock
Frp API IP 172.1.0.3
Frp API Port 7400
Frp Http Domain Suffix None
Frp Http Port 80
Frp Direct IP Address chive.vaala.cloud
Frp Direct Minimum Port 28000
Frp Direct Maximum Port 28100
Max Container Count 100
Max Renewal Times 5
Frp config template 这里填写之前 frpc.ini 的内容
Docker Auto Connect Containers ctfd_frpc_1
Docker Auto Connect Network ctfd_frp_containers
Docker Dns Setting 可留空或填写外部dns
Docker Swarm Nodes linux-1
Docker Multi-Container Network Subnet 173.0.0.0/16
Docker Multi-Container Network Subnet New Prefix 24
Docker Container Timeout 3600

最后点一下更新就可以保存配置了,填写完成后新建题目测试是否成功,按下表新建题目,表中没有提到的保持默认就好

内容
Choose Challenge Type Dynamic docker
Name test
Category test
Initial Value 1
Decay Limit 1
Minimum Value 1
Docker Image vaalacat/push_f12
Frp Redirect Type Direct
Frp Redirect Port 80
Score Type dynamic score

新建题目过后点击启动,然后等待靶机创建,可以在服务器中 docker ps -a 查看是否启动,若启动成功则搭建完成

问题解决

docker ps显示正常但是无法访问

可以使用 docker logs ctfd_ctfd_1 查看输出,如果发现输出类似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/usr/local/lib/python3.7/site-packages/tzlocal/unix.py:158: UserWarning: Can not find any timezone configuration, defaulting to UTC.
warnings.warn('Can not find any timezone configuration, defaulting to UTC.')
Starting CTFd
/usr/local/lib/python3.7/importlib/_bootstrap.py:219: RuntimeWarning: greenlet.greenlet size changed, may indicate binary incompatibility. Expected 144 from C header, got 152 from PyObject
return f(*args, **kwds)
/usr/local/lib/python3.7/importlib/_bootstrap.py:219: RuntimeWarning: greenlet.greenlet size changed, may indicate binary incompatibility. Expected 144 from C header, got 152 from PyObject
return f(*args, **kwds)
/usr/local/lib/python3.7/importlib/_bootstrap.py:219: RuntimeWarning: greenlet.greenlet size changed, may indicate binary incompatibility. Expected 144 from C header, got 152 from PyObject
return f(*args, **kwds)
[2020-10-11 12:31:30 +0000] [1] [INFO] Starting gunicorn 19.9.0
[2020-10-11 12:31:30 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
[2020-10-11 12:31:30 +0000] [1] [INFO] Using worker: gevent
[2020-10-11 12:31:30 +0000] [21] [INFO] Booting worker with pid: 21
[2020-10-11 12:31:31 +0000] [23] [INFO] Booting worker with pid: 23
[2020-10-11 12:31:32 +0000] [25] [INFO] Booting worker with pid: 25
[2020-10-11 12:31:34 +0000] [27] [INFO] Booting worker with pid: 27
[2020-10-11 12:31:35 +0000] [29] [INFO] Booting worker with pid: 29
[2020-10-11 12:31:36 +0000] [31] [INFO] Booting worker with pid: 31
[2020-10-11 12:31:37 +0000] [33] [INFO] Booting worker with pid: 33
[2020-10-11 12:31:39 +0000] [35] [INFO] Booting worker with pid: 35
[2020-10-11 12:31:40 +0000] [37] [INFO] Booting worker with pid: 37

则问题为这篇文章中所提到的问题,只需要删除 requirements.txt 中的 gevent 版本号即可,结果类似下面这样

1
2
3
4
5
redis==3.3.11
datafreeze==0.1.0
gevent
python-dotenv==0.10.3
flask-restplus==0.13.0

然后 docker-compose down 再启动 docker-compose up -d --build 不出意外应该就能解决问题

参考

CTFd-Whale 推荐部署实践