CTFd-Whale 是本人开发的一个 CTFd 插件, 具有如下优点:
- 可允许用户创建属于自己的独立靶机。(解题时不像共享靶机一样受其他用户对题目操作的影响,体验更好)
- 可快速部署题目(题目镜像在 dockerhub 上有即可,可快速使用他人打包好的题目)
- 可在一台低配置机器上部署成百上千的题目(只要硬盘够大,因为题目是按需启动,不是同时运行的)
为了便于各位安装 CTFd-Whale,部署自己的动态靶机靶场,特作此文阐述几种模式下由一台新机器到靶机能打开为止的全过程。
一、单机 Direct 模式(Frp 转发在一个机器上,只需要一台机器,靶机通过端口号访问,无需配置域名解析)
1、在机器上安装好 Docker 和 Docker-Compose,并且启用 Docker Swarm。
Docker Swarm 参考:https://www.jianshu.com/p/77c4c62d9afe
注意需要用以下命令来标记节点:
docker node ls #检查节点 ID
docker node update --label-add name=linux-1 <节点 ID>
参考链接:
2、在机器上下载代码。
git clone -b single https://github.com/glzjin/CTFd.git
3、进入目录,编辑 frp 两端配置文件,使 token 随机,再使用 docker-compose 启动相关组件。
cd CTFd
vi frp/frps.ini # token 一定要随机
vi frp/frpc.ini # token 一定要随机
git submodule update --init
docker-compose up -d
4、启动完毕,打开 http://ip:8000 安装 CTFd。
5、进入系统后台设置,打开插件设置页面,按照如下指导进行设置。点击可看大图。





Frp Config Template,记得修改 token:
[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
其他内容无特殊情况无需修改。
6、添加一个题目,进行测试。点击可看大图。



7、点击 Preview,可以尝试启动靶机。

8、测试成功,配置完成。

二、单机 Direct + Http 模式(Frp 转发在一个机器上,只需要一台机器,靶机通过端口号或者域名访问,需要配置域名解析)
0、准备一个域名,设置如下解析。
- A | *.test.127.0.0.1.nip.io | 你机器 IP
1、在机器上安装好 Docker 和 Docker-Compose,并且启用 Docker Swarm。
Docker Swarm 参考:https://www.jianshu.com/p/77c4c62d9afe
注意需要用以下命令来标记节点:
docker node ls #检查节点 ID
docker node update --label-add name=linux-1 <节点 ID>
参考链接:
2、在机器上下载代码。
git clone -b single-http https://github.com/glzjin/CTFd.git
3、进入目录,编辑 frp 两端配置文件,使 token 随机,使用 docker-compose 启动相关组件。
cd CTFd
vi frp/frps.ini # token 一定要随机
vi frp/frpc.ini # token 一定要随机
git submodule update --init
docker-compose up -d
4、启动完毕,打开 http://ip:8000 安装 CTFd。
5、进入系统后台设置,打开插件设置页面,按照如下指导进行设置。点击可看大图。





Frp Config Template,记得修改 token:
[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
其他内容无特殊情况无需修改。
6、添加一个题目,进行测试。点击可看大图。



7、点击 Preview,可以尝试启动靶机。

8、测试成功,配置完成。

附:如想让 CTFd 也走 80 端口可在 frpc 配置里加一个配置节,也就是 frp/frpc.ini 和 上面的 Frp Config Template 里。
[ctfd]
type = http
local_ip = 172.1.0.2
local_port = 8000
use_encryption = true
use_compression = true
custom_domains = domain.for.your.ctfd.com
三、跨机 Direct 模式(Frp 转发在两个机器上,Frpc 和 CTFd 在一起–下面用机器 A 表示,Frps 单独放一个机器–下面用机器 B 表示,靶机通过端口号访问,无需配置域名解析)
1、在机器上安装好 Docker 和 Docker-Compose,并且启用 Docker Swarm。
Docker Swarm 参考:https://www.jianshu.com/p/77c4c62d9afe
注意需要用以下命令来标记节点:
docker node ls #检查节点 ID
docker node update --label-add name=linux-1 <节点 ID>
参考链接:
2、在机器B上下载代码,编辑 frps 配置文件,随机化 token,并使用 docker-compose 启动相关组件。
git clone https://github.com/glzjin/Frp-Docker-For-CTFd-Whale.git
cd Frp-Docker-For-CTFd-Whale
vi frp/frps.ini
docker-compose up -d
3、在机器A上下载代码。
git clone -b double https://github.com/glzjin/CTFd.git
4、进入目录,编辑 frp 两端配置文件,使 token 随机,并且设置 server_addr 为 机器 B 的 IP,使用 docker-compose 启动相关组件。
cd CTFd
vi frp/frpc.ini # token 一定要随机,并且设置 server_addr 为 机器 B 的 IP
git submodule update --init
docker-compose up -d
5、启动完毕,打开 http://ip:8000 安装 CTFd。
6、进入系统后台设置,打开插件设置页面,按照如下指导进行设置。点击可看大图。





Frp Config Template,记得修改 ip 和 token:
[common]
token = randomme
server_addr = remote_ip
server_port = 6490
pool_count = 200
tls_enable = true
admin_addr = 172.1.0.3
admin_port = 7400
其他内容无特殊情况无需修改。
7、添加一个题目,进行测试。点击可看大图。



8、点击 Preview,可以尝试启动靶机。

9、测试成功,配置完成。

四、跨机 Direct + Http 模式(Frp 转发在两个机器上,Frpc 和 CTFd 在一起–下面用机器 A 表示,Frps 单独放一个机器–下面用机器 B 表示,靶机通过端口号或者域名访问,需要配置域名解析)
0、准备一个域名,设置如下解析。
- A | *.test.127.0.0.1.nip.io | 机器B IP
1、在机器上安装好 Docker 和 Docker-Compose,并且启用 Docker Swarm。
Docker Swarm 参考:https://www.jianshu.com/p/77c4c62d9afe
注意需要用以下命令来标记节点:
docker node ls #检查节点 ID
docker node update --label-add name=linux-1 <节点 ID>
参考链接:
2、在机器B上下载代码,编辑 frps 配置文件,随机化 token,并使用 docker-compose 启动相关组件。
git clone -b double-http https://github.com/glzjin/Frp-Docker-For-CTFd-Whale.git
cd Frp-Docker-For-CTFd-Whale
vi frp/frps.ini # token 一定要随机
docker-compose up -d
3、在机器A上下载代码。
git clone -b double https://github.com/glzjin/CTFd.git
4、进入目录,编辑 frp 两端配置文件,使 token 随机,并且设置 server_addr 为 机器 B 的 IP,使用 docker-compose 启动相关组件。
cd CTFd
vi frp/frpc.ini # token 一定要随机,并且设置 server_addr 为 机器 B 的 IP
git submodule update --init
docker-compose up -d
5、启动完毕,打开 http://ip:8000 安装 CTFd。
6、进入系统后台设置,打开插件设置页面,按照如下指导进行设置。点击可看大图。





Frp Config Template,记得修改 token:
[common]
token = randomme
server_addr = remote_ip
server_port = 6490
pool_count = 200
tls_enable = true
admin_addr = 172.1.0.3
admin_port = 7400
其他内容无特殊情况无需修改。
7、添加一个题目,进行测试。点击可看大图。



8、点击 Preview,可以尝试启动靶机。

9、测试成功,配置完成。

附:如想让 CTFd 也走 80 端口可在 frpc 配置里加一个配置节,也就是 frp/frpc.ini 和 上面的 Frp Config Template 里。
[ctfd]
type = http
local_ip = 172.1.0.2
local_port = 8000
use_encryption = true
use_compression = true
custom_domains = domain.for.your.ctfd.com
85 个评论
zu1k
感谢教程,有个问题:跨机器反代的double分支没有找到
glzjin
再试试,谢谢
手把手教你打造超级CTF平台 | 演道网
[…] https://www.zhaoj.in/read-6333.html […]
手把手教你打造超级CTF平台 – NEWS.ALL
[…] https://www.zhaoj.in/read-6333.html […]
opsafa
感谢教程,配置好泛解析的域名后 创建题目域名无法访问 ,是不是插件有问题呢?
glzjin
检查frpc运行状况 看docker logs
Opsafa
图上写的是插件处填写test.127.0.0.1.nip.io 生成题目后.test前面没有.
插件处配置加上. 后域名也是无法访问
glzjin
是要点的,请加上。
opsafa
[W] [control.go:395] [a5493a9f98fe16d4] new proxy [http_1-f618ac21-2c16-4b0a-bcab-ab00ba3082e1] error: type [http] not support when vhost_http_port is not set
glzjin
………这写的很清楚了….你那个设置项在 frps 没配置…
Opsafa
frps里默认只有端口和token 是需要配置domains吗
glzjin
你分支搞错了…..是有这个配置的 vhost_http_port
opsafa
好的 感谢我看下
anony
安装成功后使用一段时间ctfd容器会报错,frpc容器会挂(docker ps找不到),这个问题应该怎么解决?
glzjin
查日志
glzjin
把日志发上来看看
anony
frpc_1 | 2019/12/05 02:14:19 [I] [admin_api.go:43] Http response [/api/reload], code [200]
frps_1 | 2019/12/05 02:14:22 [W] [control.go:395] [d128895cf640075f] new proxy [direct_1-67b7cb41-b9e8-4b00-a9aa-b71fde99d508_udp] error: port already used
frpc_1 | 2019/12/05 02:14:22 [W] [control.go:142] [direct_1-67b7cb41-b9e8-4b00-a9aa-b71fde99d508_udp] start error: port already used
frpc_1 | 2019/12/05 02:14:29 [I] [admin_api.go:253] Http put request [/api/config]
frpc_1 | 2019/12/05 02:14:29 [I] [admin_api.go:255] Http put response [/api/config], code [200]
frpc_1 | 2019/12/05 02:14:29 [I] [admin_api.go:41] Http request [/api/reload]
frpc_1 | 2019/12/05 02:14:29 [I] [admin_api.go:81] success reload conf
frpc_1 | 2019/12/05 02:14:29 [I] [admin_api.go:43] Http response [/api/reload], code [200]
frpc_1 | 2019/12/05 02:14:39 [I] [admin_api.go:253] Http put request [/api/config]
frpc_1 | 2019/12/05 02:14:39 [I] [admin_api.go:255] Http put response [/api/config], code [200]
frpc_1 | 2019/12/05 02:14:39 [I] [admin_api.go:41] Http request [/api/reload]
frpc_1 | 2019/12/05 02:14:39 [I] [admin_api.go:81] success reload conf
frpc_1 | 2019/12/05 02:14:39 [I] [admin_api.go:43] Http response [/api/reload], code [200]
Exception in thread Thread-7:
Traceback (most recent call last):
File “/usr/lib/python3/dist-packages/urllib3/connectionpool.py”, line 600, in urlopen
chunked=chunked)
File “/usr/lib/python3/dist-packages/urllib3/connectionpool.py”, line 384, in _make_request
six.raise_from(e, None)
File “”, line 3, in raise_from
File “/usr/lib/python3/dist-packages/urllib3/connectionpool.py”, line 380, in _make_request
httplib_response = conn.getresponse()
File “/usr/lib/python3.7/http/client.py”, line 1344, in getresponse
response.begin()
File “/usr/lib/python3.7/http/client.py”, line 306, in begin
version, status, reason = self._read_status()
File “/usr/lib/python3.7/http/client.py”, line 267, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), “iso-8859-1”)
File “/usr/lib/python3.7/socket.py”, line 589, in readinto
return self._sock.recv_into(b)
ConnectionResetError: [Errno 104] Connection reset by peer
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “/usr/lib/python3/dist-packages/requests/adapters.py”, line 449, in send
timeout=timeout
File “/usr/lib/python3/dist-packages/urllib3/connectionpool.py”, line 638, in urlopen
_stacktrace=sys.exc_info()[2])
File “/usr/lib/python3/dist-packages/urllib3/util/retry.py”, line 367, in increment
raise six.reraise(type(error), error, _stacktrace)
File “/usr/lib/python3/dist-packages/six.py”, line 695, in reraise
raise value.with_traceback(tb)
File “/usr/lib/python3/dist-packages/urllib3/connectionpool.py”, line 600, in urlopen
chunked=chunked)
File “/usr/lib/python3/dist-packages/urllib3/connectionpool.py”, line 384, in _make_request
six.raise_from(e, None)
File “”, line 3, in raise_from
File “/usr/lib/python3/dist-packages/urllib3/connectionpool.py”, line 380, in _make_request
httplib_response = conn.getresponse()
File “/usr/lib/python3.7/http/client.py”, line 1344, in getresponse
response.begin()
File “/usr/lib/python3.7/http/client.py”, line 306, in begin
version, status, reason = self._read_status()
File “/usr/lib/python3.7/http/client.py”, line 267, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), “iso-8859-1”)
File “/usr/lib/python3.7/socket.py”, line 589, in readinto
return self._sock.recv_into(b)
urllib3.exceptions.ProtocolError: (‘Connection aborted.’, ConnectionResetError(104, ‘Connection reset by peer’))
glzjin
ctfd那个容器里尝试请求下frpc试试。你内存多大?开了swap吗?
anony
frpc连接不上,内存和swap都是16G,然后尝试修改下frpc配置中的最大连接池上限(pool_count = 5)好像就可以了,感谢教程和帮助
看admin-琴里教你打造超级CTF靶场 - 字节脉搏
[…] https://www.zhaoj.in/read-6333.html […]
ctf.show
请教师傅,CTFd如何配置80端口的ssl?同时如果配置docker里面web服务的ssl?
glzjin
ssl 走 443,请参考 frp 的文档进行配置。
快乐的企鹅
4、启动完毕,打开 http://ip:8000 安装 CTFd。第4步后面走不下去了,注册功能关闭的,怎么打开?
快乐的企鹅
谷歌浏览器有问题,换360的就可以了。
贫困的蚊子
ERROR: for frpc Cannot start service frpc: Could not attach to network ctfd_frp-containers: rpc error: code = PermissionDenied desc = network ctfd_frp-containers not manually attachable
ERROR: Encountered errors while bringing up the project.
glzjin
重新创建一下这个网络,将其设为 attachable.
just
git clone -b single https://github.com/glzjin/CTFd.git
cd CTFd
vi frp/frps.ini # token 一定要随机
vi frp/frpc.ini # token 一定要随机
git submodule update –init
docker-compose up -d
赵师傅ctfd仓库没有这个frp/目录,是要自己创建吗,这个目录下还需要哪些文件
glzjin
我看着应该有的,你再检查下~