基础配置

需要一台 x64 的服务器,要提前安装好 Docker 、 Docker-Compose 和 Git

安装过程

docker 集群配置

启用 Docker Swarm,并为生成的 Manager 节点取一个别名

docker swarm init
docker node ls
docker node update --label-add name=linux-1 <节点 ID>

下载 CTFd 修改版

博主 Vicosna 已经对CTFd v3.3.1官方源码进行了更换国内镜像源、添加CTFd-Whale子模块、配置frp网络、设置静态文件CDN加速等工作,可前往使用作者修改的版本进行安装部署。

git clone -b frp https://github.com/vicosna/CTFd.git

但是现在看的时候,不知道为什么,已经找不到了。

我这里还有一份之前下过的,也可以用我的:CTFd.zip

执行如下命令更新CTFd-Whale子模块

cd CTFd
git submodule update --init 

编辑 frp 配置文件

一个是服务端,一个是客户端,主要是修改一个密钥

编辑 frp/frpc.ini

[common]
token = 123456
server_addr = 172.1.0.1
server_port = 6490
pool_count = 200
tls_enable = true

admin_addr = 172.1.0.3
admin_port = 7400

编辑 frp/frps.ini

[common]
bind_port = 6490
token = 123456

确保 token 一样即可

修改 CTFd/themes/core/static/css/fonts.dev.css 和 fonts.min.css

将这两个文件中的 https://use.fontawesome.com/releases/v5.9.0/css/all.css 修改为 https://cdn.bootcss.com/font-awesome/5.13.0/css/all.css

编辑 DockerFile 和 docker-compose.yml

直接按照我的配置复制

DockerFile

FROM python:3.7-alpine
 
WORKDIR /opt/CTFd
RUN mkdir -p /opt/CTFd /var/log/CTFd /var/uploads
 
RUN sed -i 's/dl-cdn.alpinelinux.org/mirror.tuna.tsinghua.edu.cn/g' /etc/apk/repositories && \
    apk update && \
    apk add \
        linux-headers \
        libffi-dev \
        gcc \
        make \
        musl-dev \
        py-pip \
        mysql-client \
        git \
        openssl-dev
 
COPY . /opt/CTFd
 
RUN pip install -r requirements.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/
RUN for d in CTFd/plugins/*; do \
      if [ -f "$d/requirements.txt" ]; then \
        pip install -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com -r $d/requirements.txt; \
      fi; \
    done;
 
RUN chmod +x /opt/CTFd/docker-entrypoint.sh
RUN adduser -D -u 1001 -s /bin/sh ctfd
RUN chown -R 1001:1001 /opt/CTFd /var/log/CTFd /var/uploads
 
USER 1001
EXPOSE 8000
ENTRYPOINT ["/opt/CTFd/docker-entrypoint.sh"]

docker-compose.yml

version: '2.1'

services:
  ctfd:
    build: .
    user: root
    restart: always
    ports:
      - "8000:8000"
    environment:
      - UPLOAD_FOLDER=/var/uploads
      - DATABASE_URL=mysql+pymysql://root:ctfd@db/ctfd
      - REDIS_URL=redis://cache:6379
      - WORKERS=1
      - LOG_FOLDER=/var/log/CTFd
      - ACCESS_LOG=-
      - ERROR_LOG=-
    volumes:
      - .data/CTFd/logs:/var/log/CTFd
      - .data/CTFd/uploads:/var/uploads
      - .:/opt/CTFd:ro
      - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      - db
    networks:
        default:
        internal:
        frp:
            ipv4_address: 172.1.0.2

  db:
    image: mariadb:10.4
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=ctfd
      - MYSQL_USER=ctfd
      - MYSQL_PASSWORD=ctfd
      - MYSQL_DATABASE=ctfd
    volumes:
      - .data/mysql:/var/lib/mysql
    networks:
        internal:
    # This command is required to set important mariadb defaults
    command: [mysqld, --character-set-server=utf8mb4, --collation-server=utf8mb4_unicode_ci, --wait_timeout=28800, --log-warnings=0]

  cache:
    image: redis:4
    restart: always
    volumes:
    - .data/redis:/data
    networks:
        internal:

  frpc:
    image: glzjin/frp:latest
    restart: always
    volumes:
      - ./frp:/conf/
    depends_on:
      - frps
    entrypoint:
        - /usr/local/bin/frpc
        - -c
        - /conf/frpc.ini
    networks:
        frp:
            ipv4_address: 172.1.0.3
        frp_containers:

  frps:
    image: glzjin/frp:latest
    restart: always
    volumes:
      - ./frp:/conf/
    entrypoint:
        - /usr/local/bin/frps
        - -c
        - /conf/frps.ini
    network_mode: host

networks:
    default:
    internal:
        internal: true
    frp:
        driver: bridge
        ipam:
            config:
                - subnet: 172.1.0.0/16
    frp_containers:
        driver: overlay
        internal: true
        ipam:
            config:
                - subnet: 172.2.0.0/16

编辑 requirements.txt

替换为如下内容

alembic==1.12.1
aniso8601==10.0.1
APScheduler==3.10.4
attrs==24.2.0
backports.zoneinfo==0.2.1
banal==1.0.6
bcrypt==3.1.7
boto3==1.10.39
botocore==1.13.50
certifi==2025.1.31
cffi==1.15.1
chardet==5.2.0
charset-normalizer==3.4.1
click==8.1.8
datafreeze==0.1.0
dataset==1.1.2
docker==4.1.0
docutils==0.15.2
Flask==1.1.2
Flask-APScheduler==1.11.0
Flask-Caching==1.4.0
flask-marshmallow==0.10.1
Flask-Migrate==2.5.2
flask-redis==0.4.0
flask-restplus==0.13.0
Flask-Script==2.0.6
Flask-SQLAlchemy==2.4.1
gevent==21.12.0
greenlet==1.1.3.post0
gunicorn==19.9.0
idna==3.10
importlib-metadata==6.7.0
importlib-resources==5.12.0
itsdangerous==1.1.0
Jinja2==2.11.3
jmespath==0.10.0
jsonschema==4.17.3
Mako==1.2.4
MarkupSafe==1.1.1
marshmallow==2.20.2
marshmallow-sqlalchemy==0.17.0
mistune==0.8.4
netaddr==0.7.19
normality==2.0.0
passlib==1.7.2
pathlib2==2.3.5
pkgutil_resolve_name==1.3.10
pycparser==2.21
PyMySQL==0.9.3
pyrsistent==0.19.3
python-dateutil==2.9.0.post0
python-dotenv==0.10.3
pytz==2025.2
PyYAML==6.0.1
redis==3.3.11
requests==2.31.0
s3transfer==0.2.1
six==1.13.0
SQLAlchemy==1.3.11
SQLAlchemy-Utils==0.36.0
text-unidecode==1.3
typing_extensions==4.7.1
tzlocal==5.1
urllib3==1.25.11
websocket-client==1.6.1
Werkzeug==0.16.0
zipp==3.15.0
zope.event==5.0
zope.interface==6.4.post2

部署并启动

直接部署并启动

docker-compose up -d

这里很可能会遇到下面这个错误

查看一下 frpc 的容器 ID

docker ps -a

删除然后用 --attachable 参数重新创建这个网络

docker network rm ctfd_frp_containers
docker network create --driver overlay --attachable ctfd_frp_containers

然后再启动就可以了

docker start 容器ID

如果发现 CTFd 容器出现以下报错:

Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: exec: "/opt/CTFd/docker-entrypoint.sh": permission denied: unknown

给予脚本执行权限即可,然后重新启动 CTFd 即可

chmod +x docker-entrypoint.sh

如果 frpc 容器一直显示连接不到 frps 容器,看看是不是 docker 的 iptables 关掉了,要打开才能连上。

编辑 CTFd Whale 配置

参考下面的截图配置即可

这里填本机地址或自己的域名

这里直接复制 ftpc 的配置内容,注意全部复制过来

创建动态靶机

参考下图创建挑战

第一次启动的时候会很慢,因为要去下载镜像

然后去访问,应该就会有题目了

泥嚎~