最近把学校的CTFd升级了,把搭建过程重新记录了一下。
大体架构就下面这个样子(乱画的)

架构
架构

系统环境

Ubuntu 18.04 LTS

为了方便编写教程,假定
云服务器公网IP:123.123.123.1
云服务器内网IP:123.123.123.2
内网服务器IP:123.123.123.3
CTFd域名为:ctf.xxx.com
记得修改教程中的域名和IP

设置云服务器

下载frp(https://github.com/fatedier/frp/releases

frps.ini

[common]
bind_port = 6490
bind_addr = 123.123.123.2
token = 设置为随机字符串
vhost_http_port = 80
vhost_https_port = 443
subdomain_host = ctf.xxx.com

#自定义404页面
custom_404_page = /etc/frp/404.html

假设云服务器的80和443已经被Nginx占用,就将Nginx中所有的网站绑定到127.0.0.1,这样frps占用123.123.123.2:80,nginx占用127.0.0.1:80,就不会有冲突了,然后在云服务器上开一个frpc进行转发即可即可

启动frps

nohup frps -c frps.ini &

设置内网服务器

安装docker、docker-compose 启用docker swarm

安装docker:https://docs.docker.com/engine/install/ubuntu/
安装docker-compose:https://docs.docker.com/compose/install/

创建主节点

docker swarm init --advertise-addr 123.123.123.3

docker node ls #获取节点 ID
docker node update --label-add name=linux-1 <节点 ID>

配置CTFd

git clone https://github.com/CTFd/CTFd.git
cd CTFd
git clone https://github.com/frankli0324/ctfd-whale CTFd/plugins/ctfd-whale
makedir frp
vim frp/frpc.ini

frpc.ini

[common]
token = 设置为随机字符串(与服务端相同)
server_addr = 123.123.123.1
server_port = 6490
pool_count = 200
tls_enable = true

admin_addr = 172.1.0.3
admin_port = 7400

下载Frp(https://github.com/fatedier/frp/releases),将frpc放入刚刚创建的frp文件夹

vim docker-compose.yml

version: '3'

services:
  ctfd:
    build: .
    user: root
    restart: always
    ports:
      - "127.0.0.1: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
      - /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.12
    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/
    entrypoint:
        - /conf/frpc
        - -c
        - /conf/frpc.ini
    networks:
        frp:
            ipv4_address: 172.1.0.3
        frp_containers:

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

设置docker镜像加速
https://www.aliyun.com/product/acr

vim /etc/docker/daemon.json

{
  "registry-mirrors": ["https://xxxxxxxxxxxx.mirror.aliyuncs.com"]
}

docker-compose up -d

然后按照架构图,在内网服务器上设置Nginx和frpc即可

Nginx配置文件示例

server {
    listen 127.0.0.1:80;
    listen 127.0.0.1:443 ssl;
    server_name ctf.qust-sec.com;

    if ($server_port !~ 443){
        rewrite ^(/.*)$ https://$host$1 permanent;
    }

    location /events {

      proxy_pass http://localhost:8000/;
      proxy_set_header Connection '';
      proxy_http_version 1.1;
      chunked_transfer_encoding off;
      proxy_buffering off;
      proxy_cache off;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Host $server_name;
    }

    # Proxy connections to the application servers
    location / {
      proxy_pass http://127.0.0.1:8000/;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Host $server_name;
    }

    ssl_certificate /etc/nginx/sslkey/qust-sec/fullchain.crt;
    ssl_certificate_key /etc/nginx/sslkey/qust-sec/private.pem;
    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

}

frpc配置示例

[common]
token = 随机字符串与服务端相同
server_addr = 123.123.123.1
server_port = 6490
pool_count = 200
tls_enable = true


[qustsec_https]
type = https
local_ip = 127.0.0.1
local_port = 443
use_encryption = true
use_compression = true
custom_domains = ctf.xxx.com

[qustsec_http]
type = http
local_ip = 127.0.0.1
local_port = 80
use_encryption = true
use_compression = true
custom_domains = ctf.xxx.com

运行frpc

nohup frpc -c frpc.ini &

设置CTFd-whale

登录CTFd,设置ctfd-whale

请输入图片描述
请输入图片描述

请输入图片描述
请输入图片描述