1346 字
7 分钟
CTF院赛平台搭建笔记
这次我们学院要举办CTF比赛,按照老师的意思是要随便搞一下,但是喜欢折腾的我肯定不同意了(虽然我不是信安组的但就是喜欢玩这些东西,刚好早期有部署过GZCTF,我直接跟信安的同学说你们的平台我来处理。
这次部署平台的方案:一台内网CTF主机+一台公网云主机并结合easytier构建虚拟局域网并用caddy自动SSL。
系统版本如下: 公网云主机:Debian GNU/Linux 11 内网CTF主机:openEuler release 25.03
基础设置(云主机 和 内网CTF主机)
$ systemctl stop firewalld && systemctl disable firewalld$ setenforce 0部署easytier(云主机 和 内网CTF主机)
下载easytier
$ wget https://ghfast.top/https://github.com/EasyTier/EasyTier/releases/download/v2.2.4/easytier-linux-x86_64-v2.2.4.zip解压压缩包
$ unzip easytier-linux-x86_64-v2.2.4.zip
# 如果没有unzip下载# dnf install -y unzip# apt install -y unzip移动目录
$ mv easytier-linux-x86_64 /usr/bin/easytier编写service服务
--ipv4 10.144.144.1手动分配虚拟局域网的IP地址
--network-name XXSS虚拟局域网络名称
--network-secret XXSS001虚拟局域网的密码
PS:这里我只展示其中一台的配置文件,其实要改的就是IP地址,因为我要自己分配IP地址所以我就在配置文件里指定IP
$ cat >> /etc/systemd/system/easytier.service << EOF[Unit]Description=EasyTier ServiceAfter=network.target syslog.targetWants=network.target
[Service]Type=simpleExecStart=/usr/bin/easytier/easytier-core --ipv4 10.144.144.1 --network-name XXSS --network-secret XXSS001
[Install]WantedBy=multi-user.targetEOF启动easytier服务
$ systemctl daemon-reload
$ systemctl enable easytier
$ systemctl start easytier
$ systemctl status easytier● easytier.service - EasyTier Service Loaded: loaded (/etc/systemd/system/easytier.service; disabled; preset: disabled) Active: active (running) since Fri 2025-05-16 13:44:41 CST; 7h ago Main PID: 269640 (easytier-core) Tasks: 4 (limit: 98868) Memory: 46.0M () CGroup: /system.slice/easytier.service └─269640 /usr/bin/easytier/easytier-core --ipv4 10.144.144.2 --network-name XXSS --network>......部署GZCTF平台
配置Docker环境
[root@CTFGZ ~]# dnf install -y docker-client docker-engine配置docker-compose
[root@CTFGZ ~]# wget https://ghfast.top/https://github.com/docker/compose/releases/download/v2.36.0/docker-compose-linux-x86_64[root@CTFGZ ~]# mv docker-compose-linux-x86_64 /usr/bin/docker-compose[root@CTFGZ ~]# chmod +x /usr/bin/docker-compose启动docker服务
[root@CTFGZ ~]# systemctl enable docker[root@CTFGZ ~]# systemctl start docker检查docker服务
[root@CTFGZ ~]# systemctl status docker● docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: disabled) Active: active (running) since Thu 2025-05-15 20:37:27 CST; 1 day 1h ago......
[root@CTFGZ ~]# docker versionClient: Version: 18.09.0 EulerVersion: 18.09.0.346 API version: 1.39 Go version: go1.21.4 Git commit: 270f890 Built: Fri Mar 21 10:03:24 2025 OS/Arch: linux/amd64 Experimental: false
Server: Engine: Version: 18.09.0 EulerVersion: 18.09.0.346 API version: 1.39 (minimum version 1.12) Go version: go1.21.4 Git commit: 270f890 Built: Fri Mar 21 10:02:53 2025 OS/Arch: linux/amd64 Experimental: false[root@CTFGZ ~]# docker-compose versionDocker Compose version v2.36.0创建GZCTF项目
[root@CTFGZ ~]# mkdir /opt/GZCTF[root@CTFGZ ~]# cd /opt/GZCTF/配置GZCTF容器端口范围
因为云主机某些端口占用了,我现在需要指定比赛生成的容器端口在指定范围内。(因为我是内网主机映射到云主机上的所以要这么做)
# 指定端口从31000到31099[root@CTFGZ GZCTF]# echo "net.ipv4.ip_local_port_range = 31000 31099" >> /etc/sysctl.conf[root@CTFGZ GZCTF]# sysctl -p编写GZCTF配置文件
<Your_postgres_password>数据库密码
<basexxxxx>加密信息
<Your PUBLIC_ENTRY>地址段或者域名
[root@CTFGZ GZCTF]# vim appsettings.json{ "AllowedHosts": "*", "ConnectionStrings": { "Database": "Host=db:5432;Database=gzctf;Username=postgres;Password=<Your_postgres_password>", "RedisCache": "cache:6379,abortConnect=false" }, "EmailConfig": { "SendMailAddress": "", "UserName": "", "Password": "", "Smtp": { "Host": "localhost", "Port": 587 } }, "XorKey": "<basexxxxx>", //自行配置 "ContainerProvider": { "Type": "Docker", // or "Kubernetes" "PublicEntry": "<Your PUBLIC_ENTRY>", // or "xxx.xxx.xxx.xxx" "PortMappingType": "Default", "EnableTrafficCapture": false, "DockerConfig": { "SwarmMode": false, "Uri": "unix:///var/run/docker.sock" } }, "RequestLogging": false, "DisableRateLimit": true, "RegistryConfig": { "UserName": "", "Password": "", "ServerAddress": "" }, "CaptchaConfig": { "Provider": "None", "SiteKey": "<Your SITE_KEY>", "SecretKey": "<Your SECRET_KEY>", "GoogleRecaptcha": { "VerifyAPIAddress": "https://www.recaptcha.net/recaptcha/api/siteverify", "RecaptchaThreshold": "0.5" } }, "ForwardedOptions": { "ForwardedHeaders": 5, "ForwardLimit": 1, "TrustedNetworks": ["192.168.12.0/8"] }}配置docker compose文件
<初始用户密码>密码需要大写字母
[root@CTFGZ GZCTF]# vim docker-compose.ymlservices: gzctf: image: registry.cn-shanghai.aliyuncs.com/gztime/gzctf:latest restart: always environment: - "LANG=zh_CN.UTF-8" - "GZCTF_ADMIN_PASSWORD=<初始用户密码>" ports: - "80:8080" volumes: - "./data/files:/app/files" - "./appsettings.json:/app/appsettings.json:ro" - "/var/run/docker.sock:/var/run/docker.sock" depends_on: - db - cache
cache: # It is recommended to use garnet, you can also use ghcr.nju.edu.cn/microsoft/garnet-alpine:latest image: redis:alpine command: ["--bind", "0.0.0.0"] restart: always
db: image: postgres:alpine restart: always environment: - "POSTGRES_PASSWORD=<Your_postgres_password>" //记得修改 volumes: - "./data/db:/var/lib/postgresql/data"启动GZCTF
[root@CTFGZ GZCTF]# docker-compose up -d[+] Running 3/3 ✔ Container gzctf-cache-1 Started 0.2s ✔ Container gzctf-db-1 Started 0.3s ✔ Container gzctf-gzctf-1 Started 0.5s备注
初始用户:Admin 密码:yml文件<初始用户密码>配置的密码
如果登录Admin初始用户失败,请按下面步骤进行调整 1、在Web界面创建任意用户 2、回到命令行,给创建的用户赋予管理员权限
[root@CTFGZ GZCTF]# docker-compose exec db psql -U postgrespsql (17.5)Type "help" for help.
postgres=# \c gzctfYou are now connected to database "gzctf" as user "postgres".gzctf=# UPDATE "AspNetUsers" SET "Role"=3 WHERE "UserName"='创建新的用户名';UPDATE 1gzctf=# exitCaddy
现在这个步骤就是在云主机上的操作了,我云主机系统是debian
<easytier_CTF_ip>这个是配置CTF内网主机上easytier的IP。
root@host:~# curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpgroot@host:~# curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.listroot@host:~# apt updateroot@host:~# apt install -y caddy
root@host:~# vi /etc/caddy/Caddyfile# ----------------------# CTF 赛事平台# ----------------------ctf.xxx.xxx { reverse_proxy <easytier_CTF_ip>:80 { # 精简头部传递(Caddy 默认会传递 X-Forwarded-* 头) header_up X-Real-IP {remote} header_up X-Forwarded-Port {server_port} }}刚刚我们说到配置容器范围,现在就要用脚本配置这个端口的映射
<easytier_CTF_ip>这个IP地址要自行修改
root@host:~# cat >> caddy.sh << EOF# 生成31000-31099端口配置echo "# 自动生成端口映射配置" >> /etc/caddy/Caddyfilefor port in {31000..31099}; do cat << EOF >> /etc/caddy/Caddyfilectf.leekk.me:$port { reverse_proxy <easytier_CTF_ip>:$port { header_up X-Real-IP {remote} header_up X-Forwarded-Port {server_port} }}EOFdoneEOF以下是这次部署的样图
graph TB classDef public fill:#FFE8D4,stroke:#FF6B00; classDef private fill:#D5E8D4,stroke:#4CAF50; classDef tunnel stroke:#666,stroke-dasharray:5;
subgraph 公网环境 Internet[互联网] 客户端(客户端) -->|HTTPS请求\n443端口| 云主机B end
subgraph 虚拟局域网 云主机B:::public -.->|easytier隧道\n10.144.144.0/24| 内网主机A:::private end
云主机B -->|反向代理规则\nCaddy: ctf.xxx.com -> 10.144.144.1:80| 内网主机A 内网主机A -->|响应数据| 云主机B 云主机B -->|加密响应| 客户端
style 虚拟局域网 fill:#F0F5FF,stroke:#3366FF linkStyle 2 stroke:#FF6B00,stroke-width:2px linkStyle 3 stroke:#4CAF50 linkStyle 4 stroke:#FF6B00
class 云主机B,Internet,客户端 public class 内网主机A private CTF院赛平台搭建笔记
http://blog.xeu.asia/posts/实验室折腾/ctf院赛平台搭建笔记/