CTFd平台的搭建及加速
笔者近期在忙 Lilac 五一欢乐赛的事。其中过程百般曲折,不过回顾这一段时间折腾 cdn、全站加速、nginx,感觉收获还是很大的,故写一篇博客记录下来。
竞赛平台采用了 CTFd(也没有其他选项,只有 CTFd 可以用)。最初以部署在华为云上,带宽只有 1Mbps,非常卡。于是迁移到了 Vultr 东京节点,虽然国际访问非常流畅,但国内访问又断断续续了。套 Cloudflare 加速之后,国内可用性比较高,至少不会 Timeout 了;但是速度还是上不来,与最初的华为云半斤八两。
最终决定迁移回华为云 VPS,同时采取各种加速手段。本文记载了如何在 VPS 只有 1Mbps 带宽的情况下,把网站加速到用户可以接受的水平。
0x00 安装 CTFd
这是最不用动脑子的部分。docker 即可安装:
docker run --name ctfd -dit -p 8000:8000 ctfd/ctfd
于是就起了一个 CTFd 服务,运行在8000
端口上。如果想要修改源码,可以搞 volume
挂载网站的代码目录,这样直接在实体机上修改,docker 里面的文件就能更新。如果想让它自动启动,加上 --restart=always
就行。
另外,由于 VPS 上有很多个容器(pwn 题的和 web 题的),还是需要一个 docker 管理工具。我以前一直用 DaoCloud 来做这件事,这一次采用 portainer
:
于是可以方便地管理容器、查看负载:
目前为止我们安装好了 CTFd.
0x01 基本配置
首先我们得把主页给改掉。在 Pages 里面改 index
就行。我们放了一张 logo 在首页。代码如下:
<center><img src="/files/xxxx/lilac-white.png" width="750px"/></center>
另外,我们把主题色改成像饿了么那样的蓝色。直接去 element ui 抄配色就行了。注入 header 代码如下:
<style id="theme-color">
:root {--theme-color: #409EFF;}
.navbar{background-color: var(--theme-color) !important;}
.jumbotron{background-color: var(--theme-color) !important;}
</style>
现在我们有了漂亮的首页和 Challenges 界面。
为了不带端口用域名访问,我们采用 nginx 反代 CTFd. 在 sites-enabled
创建一个 train
文件(这不是个好习惯。正常的做法是在 sites-avaliable
创建配置文件,然后用符号链接放进 sites-enabled
,不过我们敏捷开发,就不管那么多了),写进如下内容:
配置好 A 记录之后,访问 train.hitctf.cn
可以访问到 CTFd. 我们基本配置已经完成,这是一个可以拿去用的服务器了。
本次比赛中,我们需要上传一个 5 MB 左右的文件,但是返回了 413 状态码。需要修改 nginx 配置,允许上传大文件:
于是可以顺利上传。来下载一下试试:
所以,我们需要专注于加速了。加速!加速!
0x02 nginx 缓存
首先想到的是用 nginx 来缓存静态文件,分担 CTFd 的服务器负担(CTFd 是 flask 写的)。在 nginx.conf
里面写:
然后在 sites-enabled
把 train
改成:
做完了之后,出现了新的问题:在 admin 修改题目之后,迟迟不能更新。从而我们必须只缓存静态文件。规则改为:
再尝试访问,发现确实 /themes/core/static
里面的文件会加上 Lilac-Proxy: yes
这个头;其余的页面都没有这个头。我们完成了 nginx 层面的配置。
0x03 cdn 与全站加速
CTFd 引用了 fontawesome 等一系列外部库。资源都在国外,访问起来很慢。我们可以利用 cdn 加速。
具体来讲,我是这样干的:在阿里云 OSS 上开一个桶,存下这些信息;建立一个 cdn,源站设为这个 OSS 桶。OSS 本身在国内访问已经很快了,建立 cdn 之后全球访问都很快。于是解决了外部资源问题。
至于内部资源,我们采用了阿里云的 “全站加速”。把 ctf.ruanx.net
CNAME 到阿里云指定的地址,由阿里云申请 https 证书,这样我们的 CTFd 平台就支持了 https.
全站加速分为动态加速和静态加速两个部分。
- 静态加速:对于指定的静态文件,由阿里云缓存到边缘网络。
- 动态加速:直接回源。阿里云会选择最快的路由。
我们主要是利用静态加速功能。设置如下:
现在,静态加速已经做到极致了。直接访问 ctf.ruanx.net
,页面可以在 2s 之内加载出来。
0x04 按量计费的带宽
阿里云的 cdn 和全站加速,虽然帮我们把静态资源加速到飞快,但动态请求还是要回源的。如果阻塞得比较严重,会影响所有人的游戏体验。
我们在华为云弄一个弹性 IP,选择按量计费(0.64元 / GB),带宽放到 300 Mbps. 接下来把这个 IP 绑定到服务器的网卡上,然后配置路由。官方有教程,直接抄官方教程就行了:
现在用新网卡的 IP 地址可以访问到我们的平台。换句话讲,我们的平台有了两条路——一条是 1Mbps,流量免费的;另一条是 300Mbps,流量费很贵的。考虑到 CTFd 不是很耗流量的网站,按量计费是没问题的。
接下来,我们把动态请求交给 300Mbps 的路线。考虑到这条路线的流量费比全站加速更贵,我们仍然由阿里云的全站加速来缓存静态文件(这样也可以降低服务器压力)。
0x05 全站加速的主从切换
把全站加速的源站信息改为:
阿里云会每隔几秒发个包检测服务器状态。在主服务器正常工作的情况下,回源到主服务器;否则回源到备用服务器。这样配置之后,如果遭到 DDOS 攻击,我们卸掉 300Mbps 的网卡,全站加速就开始从 1Mbps 的线路回源,减少我们的损失。
现在 ctf.ruanx.net
高速度、高可用性、全球访问丝滑流畅了。Enjoy the game!
Update 2020-05-01 10:00
我们扛住了大量的访问,而且所有人都很流畅。
Update 2020-05-03 09:00
开赛当晚 20:30 ~ 21:30,有神必壬打了两次 DDoS,有代理池,疯狂访问 scoreboard
和《打工是不可能打工的》附件 che.gif
. 至于是谁打的我暂且蒙在鼓里。打出了一共 1.2GB 流量,峰值带宽大约 60Mbps,可惜全都打在 cdn 上了,对业务没有任何影响 :)