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 个评论
不敢出门
docker.errors.APIError: 403 Client Error: Forbidden (“The network ctfd_frp-containers cannot be used with services. Only networks scoped to the swarm can be used, such as those created with the overlay driver.”)
glzjin
手动把这个网络删了先。
clzd
docker.errors.APIError: 403 Client Error: Forbidden (“The network ctfd_frp-containers cannot be used with services. Only networks scoped to the swarm can be used, such as those created with the overlay driver.”)
clzd
请问这是什么原因呢?
glzjin
手动把这个网络删了先。
手把手教你如何建立一个支持ctf动态独立靶机的靶场 _ 脚本宝典
[…] 建议先去看看官方教程:)本教程对应官方教程第一种模式。https://www.zhaoj.in/read-633… […]
zw
CTFd目录下没有frp文件夹,咋办?是要自己先安装frp吗?
zw
已解决
dOCA
打开题目页面返回了404
frps容器的日志是:[W] [http.go:95] do http proxy request error: no such domain: ******
glzjin
看下 frpc 的日志
auturora
Traceback (most recent call last):
File “manage.py”, line 9, in
app = create_app()
File “/opt/CTFd/CTFd/__init__.py”, line 164, in create_app
upgrade()
File “/usr/local/lib/python3.7/site-packages/flask_migrate/__init__.py”, line 95, in wrapped
f(*args, **kwargs)
File “/usr/local/lib/python3.7/site-packages/flask_migrate/__init__.py”, line 280, in upgrade
command.upgrade(config, revision, sql=sql, tag=tag)
File “/usr/local/lib/python3.7/site-packages/alembic/command.py”, line 298, in upgrade
script.run_env()
File “/usr/local/lib/python3.7/site-packages/alembic/script/base.py”, line 489, in run_env
util.load_python_file(self.dir, “env.py”)
File “/usr/local/lib/python3.7/site-packages/alembic/util/pyfiles.py”, line 98, in load_python_file
module = load_module_py(module_id, path)
File “/usr/local/lib/python3.7/site-packages/alembic/util/compat.py”, line 184, in load_module_py
spec.loader.exec_module(module)
File “”, line 728, in exec_module
File “”, line 219, in _call_with_frames_removed
File “migrations/env.py”, line 99, in
run_migrations_online()
File “migrations/env.py”, line 91, in run_migrations_online
context.run_migrations()
File “”, line 8, in run_migrations
File “/usr/local/lib/python3.7/site-packages/alembic/runtime/environment.py”, line 846, in run_migrations
self.get_context().run_migrations(**kw)
File “/usr/local/lib/python3.7/site-packages/alembic/runtime/migration.py”, line 520, in run_migrations
step.migration_fn(**kw)
File “/opt/CTFd/migrations/versions/b5551cd26764_add_captain_column_to_teams.py”, line 27, in upgrade
op.add_column(“teams”, sa.Column(“captain_id”, sa.Integer(), nullable=True))
File “”, line 8, in add_column
File “”, line 3, in add_column
File “/usr/local/lib/python3.7/site-packages/alembic/operations/ops.py”, line 1929, in add_column
return operations.invoke(op)
File “/usr/local/lib/python3.7/site-packages/alembic/operations/base.py”, line 374, in invoke
return fn(self, operation)
File “/usr/local/lib/python3.7/site-packages/alembic/operations/toimpl.py”, line 132, in add_column
operations.impl.add_column(table_name, column, schema=schema, **kw)
File “/usr/local/lib/python3.7/site-packages/alembic/ddl/impl.py”, line 237, in add_column
self._exec(base.AddColumn(table_name, column, schema=schema))
File “/usr/local/lib/python3.7/site-packages/alembic/ddl/impl.py”, line 140, in _exec
return conn.execute(construct, *multiparams, **params)
File “/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py”, line 982, in execute
return meth(self, multiparams, params)
File “/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/ddl.py”, line 72, in _execute_on_connection
return connection._execute_ddl(self, multiparams, params)
File “/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py”, line 1044, in _execute_ddl
compiled,
File “/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py”, line 1250, in _execute_context
e, statement, parameters, cursor, context
File “/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py”, line 1476, in _handle_dbapi_exception
util.raise_from_cause(sqlalchemy_exception, exc_info)
File “/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py”, line 398, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File “/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py”, line 152, in reraise
raise value.with_traceback(tb)
File “/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py”, line 1246, in _execute_context
cursor, statement, parameters, context
File “/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py”, line 581, in do_execute
cursor.execute(statement, parameters)
File “/usr/local/lib/python3.7/site-packages/pymysql/cursors.py”, line 170, in execute
result = self._query(query)
File “/usr/local/lib/python3.7/site-packages/pymysql/cursors.py”, line 328, in _query
conn.query(q)
File “/usr/local/lib/python3.7/site-packages/pymysql/connections.py”, line 517, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File “/usr/local/lib/python3.7/site-packages/pymysql/connections.py”, line 732, in _read_query_result
result.read()
File “/usr/local/lib/python3.7/site-packages/pymysql/connections.py”, line 1075, in read
first_packet = self.connection._read_packet()
File “/usr/local/lib/python3.7/site-packages/pymysql/connections.py”, line 684, in _read_packet
packet.check_error()
File “/usr/local/lib/python3.7/site-packages/pymysql/protocol.py”, line 220, in check_error
err.raise_mysql_exception(self._data)
File “/usr/local/lib/python3.7/site-packages/pymysql/err.py”, line 109, in raise_mysql_exception
raise errorclass(errno, errval)
sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1060, “Duplicate column name ‘captain_id'”)
[SQL: ALTER TABLE teams ADD COLUMN captain_id INTEGER]
(Background on this error at: http://sqlalche.me/e/2j85)
想请教一下这个怎么解决呀
kmyzsec
先按照教材做一遍,初始化数据库,然后按照下面方法修改文件:
\CTFd\CTFd\__init__.py 164行 upgrade()改成pass,199行run_upgrade()改成exit()
\CTFd\docker-entrypoint.sh 38行注释掉
然后docker-compose build重建docker,docker-compose up -d运行此docker
苏苏
还是没用
SyntaxError: invalid syntax
[2020-07-30 09:41:02 +0000] [18] [INFO] Worker exiting (pid: 18)
[2020-07-30 09:41:02 +0000] [1] [INFO] Shutting down: Master
[2020-07-30 09:41:02 +0000] [1] [INFO] Reason: Worker failed to boot.
Waiting for db: to be ready
db is ready
Starting CTFd
[2020-07-30 09:41:30 +0000] [1] [INFO] Starting gunicorn 19.9.0
[2020-07-30 09:41:30 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
[2020-07-30 09:41:30 +0000] [1] [INFO] Using worker: gevent
[2020-07-30 09:41:30 +0000] [18] [INFO] Booting worker with pid: 18
[2020-07-30 09:41:30 +0000] [18] [ERROR] Exception in worker process
Traceback (most recent call last):
File “/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py”, line 583, in spawn_worker
worker.init_process()
File “/usr/local/lib/python3.7/site-packages/gunicorn/workers/ggevent.py”, line 203, in init_process
super(GeventWorker, self).init_process()
File “/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py”, line 129, in init_process
self.load_wsgi()
File “/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py”, line 138, in load_wsgi
self.wsgi = self.app.wsgi()
File “/usr/local/lib/python3.7/site-packages/gunicorn/app/base.py”, line 67, in wsgi
self.callable = self.load()
File “/usr/local/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py”, line 52, in load
return self.load_wsgiapp()
File “/usr/local/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py”, line 41, in load_wsgiapp
return util.import_app(self.app_uri)
File “/usr/local/lib/python3.7/site-packages/gunicorn/util.py”, line 350, in import_app
__import__(module)
File “/opt/CTFd/CTFd/__init__.py”, line 164
pass()
^
glzjin
你从哪里 pull 的 ctfd-whale 的源码- -||
苏苏
从你的github直接克隆的CTFd
苏苏
我直接在你的github上克隆的CTFd
https://github.com/glzjin/CTFd
cxaqhq
和楼上一样的python报错,求解决,
centos 7
python 2.7
Serene
你好,按照方法三,部署ctfd的机器上,docker里面的ctfd总是在不停的重启,无法进入8000端口配置,看了下日志是这样的
sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1060, “Duplicate column name ‘captain_id'”)
[SQL: ALTER TABLE teams ADD COLUMN captain_id INTEGER]
Serene
删掉这个数据库列以后依然会报同样的错误
苏苏
解决了吗?我的也是这样
Mosa
* Loaded module,
Traceback (most recent call last):
File “wsgi.py”, line 11, in
app = create_app()
File “./CTFd/__init__.py”, line 281, in create_app
init_plugins(app)
File “./CTFd/plugins/__init__.py”, line 196, in init_plugins
module.load(app)
File “./CTFd/plugins/ctfd-whale/__init__.py”, line 216, in load
redis_util = RedisUtils(app=app)
File “./CTFd/plugins/ctfd-whale/redis_utils.py”, line 9, in __init__
self.redis_client = FlaskRedis(app)
File “/opt/pyenv/versions/3.7.5/envs/ctfdenv/lib/python3.7/site-packages/flask_redis/client.py”, line 16, in __init__
self.init_app(app)
File “/opt/pyenv/versions/3.7.5/envs/ctfdenv/lib/python3.7/site-packages/flask_redis/client.py”, line 38, in init_app
redis_url, **self.provider_kwargs
File “/opt/pyenv/versions/3.7.5/envs/ctfdenv/lib/python3.7/site-packages/redis/client.py”, line 638, in from_url
connection_pool = ConnectionPool.from_url(url, db=db, **kwargs)
File “/opt/pyenv/versions/3.7.5/envs/ctfdenv/lib/python3.7/site-packages/redis/connection.py”, line 999, in from_url
‘schemes (%s)’ % valid_schemes)
ValueError: Redis URL must specify one of the followingschemes (redis://, rediss://, unix://)
请问这个报错该怎么解决,我已经装了redis了,也在环境变量中也加了REDIS_URL=”redis://localhost:6379″
KimiX
一直在启动wating ,无法启动组件是什么原因