CTFd3.x平台部署指南(CTFd+CTFd-Whale)

前言

参考资料

CTFd平台部署指南

新版CTFd-Whale使用指南 - frankli0324

准备阶段

首先,服务器中需要已经安装 docker 和 docker-compose:

docker 安装可以参照官方文档:Install Docker Engine on Debian | Docker Documentation

docker-compose 安装直接 sudo apt install docker-compose 即可。

技术原理

IMG_0441.jpg

主要技术:frp(fast reverse proxy),使 docker 容器中的内部网络穿透到外部网络中。

Frps服务:运行在服务器上的服务,用于将 frpc 的流量向外转发。

文档中使用的是 frps 容器,容器的做法需要一直启用题目的端口映射,当没有题目开启时会造成端口的浪费,而且修改端口范围时需要重启容器,本文沿用了旧版本 CTF 平台部署时使用的 frps 服务。

Frpc容器:与靶机容器同处在一个 docker 网络下,用于将靶机的流量发送到 frps

CTFd-Whale:作为 CTFd 的一个插件,它的作用是调用 docker 的接口生成独立的靶机容器,同时控制 frpc 接口转发靶机端口。

安装步骤

启动CTFd

创建docker集群

首先需要初始化一个 swarm 集群并给节点标注名称。

linux 节点名称需要以 linux- 打头,windows节点则以 windows- 打头

docker swarm init
docker node update --label-add "name=linux-1" $(docker node ls -q)

新版 ctfd-whale 利用 docker swarm 的集群管理能力,能够将题目容器分发到不同的节点上运行。选手每次请求启动题目容器时,ctfd-whale 都将随机选择一个合适的节点运行这个题目容器。

下载CTFd

git clone https://github.com/CTFd/CTFd --depth=1
# --depth=1 只克隆包含最近一次commit的一个分支,这样这个项目文件就不会恨大
# 如果 git clone 速度慢,可以把 https:// 换成 git:// 提速
cd CTFd  # 注:以下全部内容的cwd均为此目录

修改docker-compose.yml文件

2.5.0+版本 CTFd 的 docker-compose.yml 中包含了一个 nginx 反代,占用了80端口,如不需要可注释或删除。

vim docker-compose.yml
version: '3.7' # 修改 docker-compose 版本

services:
  ctfd:
    build: .
    user: root
    restart: always
    ports:
      - "8000:8000" # 服务器端口:容器内端口
    environment:
      - UPLOAD_FOLDER=/var/uploads
      - DATABASE_URL=mysql+pymysql://ctfd:ctfd@db/ctfd
      - REDIS_URL=redis://cache:6379
      - WORKERS=1
      - LOG_FOLDER=/var/log/CTFd
      - ACCESS_LOG=-
      - ERROR_LOG=-
      # - REVERSE_PROXY=true
    volumes:
      - .data/CTFd/logs:/var/log/CTFd
      - .data/CTFd/uploads:/var/uploads
      - .:/opt/CTFd:ro
    depends_on:
      - db
    networks:
        default:
        internal:

  # nginx:
  #   image: nginx:1.17
  #   restart: always
  #   volumes:
  #     - ./conf/nginx/http.conf:/etc/nginx/nginx.conf
  #   ports:
  #     - 80:80
  #   depends_on:
  #     - ctfd
    ···

修改Dockerfile换源

将容器的源换成国内的上交源,提高 build 速度。

vim Dockerfile
FROM python:3.7-slim-buster
WORKDIR /opt/CTFd
RUN mkdir -p /opt/CTFd /var/log/CTFd /var/uploads

# hadolint ignore=DL3008
RUN sed -i "s|http://deb.debian.org/debian|https://mirror.sjtu.edu.cn/debian|g" /etc/apt/sources.list \
    && apt-get update \
    # 修改上面两行
    && apt-get install -y --no-install-recommends \
···

镜像加速可参照:官方镜像加速 - 容器镜像服务 ACR - 阿里云 (aliyun.com)

CTFd平台启动

在进行这一步之前,请确认服务器的时间正确,否则可能导致CTFd平台时间出错,容器连接超时等问题。

docker-compose up -d

若从旧版本平台升级,需要先删除或者 untag 旧版本的 ctfd_ctfd docker 镜像,否则启动时会出错,docker-compose logs ctfd 报错 ctfd_1 | standard_init_linux.go:228: exec user process caused: no such file or directory

若不幸在删除旧的镜像之前启动,则可能遇到数据库连接不上的问题,docker-compose logs ctfd 停留在 ctfd_1 | Waiting for mysql+pymysql://ctfd:ctfd@db to be ready,解决方法是把整个 .data 文件夹删除,或者重新git clone。

访问 http://localhost:8000,对CTFd进行初始配置。

安装启动frp服务

配置frps服务

下载安装frps

cd
wget https://github.com/fatedier/frp/releases/download/v0.36.2/frp_0.36.2_linux_amd64.tar.gz
tar -zxvf frp_0.36.2_linux_amd64.tar.gz
cd frp_0.36.2_linux_amd64
sudo cp systemd/* /etc/systemd/system/
sudo mkdir /etc/frp
sudo cp frpc.ini frps.ini /etc/frp/
sudo cp frpc frps /usr/bin/
sudo chmod a+x /usr/bin/frpc /usr/bin/frps
sudo systemctl enable frps

配置frps.ini

sudo vim /etc/frp/frps.ini
#frps.ini
[common]
bind_port = 7897
bind_addr = 0.0.0.0
token = thisistoken
# vhost_http_port = 80 # 如果要配置http动态域名则需要这个。80端口开启需要systemd使用root权限启用frp,在这里不需要

启动frps服务

sudo systemctl start frps

配置frpc容器

修改 docker-compose.yml 文件,添加一个 frpc 服务,并添加一个 frp 网络和题目容器网络;把 frpc 加入 ctfd 默认网络、frp 网络和题目容器网络,设置 frpc 在 frp 网络中的 ip 为 172.1.0.4,也就是 admin_addr。

vim docker-compose.yml
services:
  ···
  frpc:
    image: glzjin/frp:latest
    restart: always
    volumes:
      - ./conf/frp:/conf/
    entrypoint:
      - /usr/local/bin/frpc
      - -c
      - /conf/frpc.ini
    networks:
        default:
        frp_containers:
        frp_connect:
            ipv4_address: 172.1.0.4

networks:
    ···
    frp_connect:
        driver: overlay
        internal: true
        ipam:
            config:
                - subnet: 172.1.0.0/16
    frp_containers:
        driver: overlay
        internal: true  # 如果允许题目容器访问外网,则可以去掉
        attachable: true
        ipam:
            config:
                - subnet: 172.2.0.0/16

配置frpc.ini

mkdir ./conf/frp
vim ./conf/frp/frpc.ini
[common]
token = thisistoken
server_addr = 172.17.0.1    # 这里填写服务器ip addr之后docker0的ip地址
server_port = 7897          # 这里需与前面frps.ini的bind_port匹配
admin_addr = 172.1.0.4      # 这里填写frpc服务在frp网络中的ip
admin_port = 7400
# 这里需要留至少一行空行,因为新的 Whale 会把容器的转发代理写到这个文件里,没留空行的话会影响 admin_port。

检查frp配置

更新 docker-compose 配置后使用 logs 命令查看 frpc 服务日志。

docker-compose up -d
docker-compose logs frpc

出现下面的日志说明配置正常,frpc 与 frps 连接正常。

[service.go:224] login to server success, get run id [****], server udp port [****]
[service.go:109] admin server listen on 172.1.0.4:7400
CTFd
├── conf
│   └── frp
│       └── frpc.ini
├── docker-compose.yml
├── Dockerfile
│

配置CTFd

修改docker-compose.yml文件

映射 docker 启动接口,并把 ctfd 服务添加到 frp 网络中。

services:
    ctfd:
        ...
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
        depends_on:
            - frpc #frpc需要先运行
        networks:
            ...
            frp_connect:

下载 CTFd-Whale

git clone https://github.com/frankli0324/CTFd-Whale CTFd/plugins/ctfd-whale --depth=1
docker-compose build # 需要安装依赖
docker-compose up -d

进入 CTFd 平台之后,在 admin 页面选择 Whale

IMG_0765(20220305-002754)

IMG_0766(20220305-002755)

CTFd动态容器题目部署指南

IMG_0767(20220305-002755)

IMG_0768(20220305-002755)

点击 Finish 即可发布题目。