# 架設自己的CTF CTFd架設教學 作者: [台中教育大學 白帽社](https://hackmd.io/@ntcuhack/index) -sunfrancis12 ## 前言 ### 伺服器主機 筆者我是在[GCP](https://blog.cloud-ace.tw/google-cloud-platform/products/what-is-gcp/)上面架設環境,並當作網頁伺服器來使用,其實實務上並不建議這樣做,但是當作一個CTFd的平台也已然足夠 但是要注意,GCP最便宜的Computer Engine大概要每月10美(快300台幣)左右,前幾個月可以使用goole提供的抵免額,這點還請讀者自行斟酌 ### 防火牆 如果是跟我一樣是使用GCP的讀者,要記得去**GCP的管理介面設定防火牆**,只有在虛擬機裡面設定(ufw)是沒有用的 關於GCP防火牆的設定,可以參考這篇: > https://ithelp.ithome.com.tw/articles/10263476 ### 網頁伺服器 Nginx 關於nginx設定我並沒有設定的十分嚴謹,像是我沒有限至單一使用者傳輸的數據量,因此建議大家還可以自行添加設定,降低被DDOS的風險 ### Domain 我是從square space上購買domain的,他第一年購買網域的金額為12美(對,作者我超盤),因此會建議大家去Cloud Flare上面買domain 關於如何將domain綁定主機,可以參考這個影片 > [How To Self Configure Your DNS Settings In Google Domains](https://www.youtube.com/watch?v=Ez3lCBSVHQE&ab_channel=Showit) ### HTTPS SSL 憑證 我是用zerossl來申請憑證的,關於SSL的設定我這裡就不加贅述了,日後有機會筆者在補 (我就爛 這邊推薦這篇文章 > [最全SSL憑證免費申請與安裝教學,ZeroSSL申請教學](https://www.mytechgirl.com/tw/how-to/add-ssl-to-website-free-mtg6688.html) ## 環境和使用工具 ### 主機 * [GCP](https://cloud.google.com/) ### CTF平台 * [CTFd](https://github.com/CTFd/CTFd) ### 網頁框架 * [Flask](https://flask.palletsprojects.com/en/2.3.x/) ### 資料庫 * [MariaDB](https://mariadb.org/) or MySQL ### 網頁伺服器 * [nginx](https://www.nginx.com/) * [gunicorn](https://gunicorn.org/) ### 其他 * [gevent](https://www.gevent.org/) ## CTFd 安裝 這裡按照CTFd官方提供的流程 先下載 CTFd的官方檔案 ``` git clone https://github.com/CTFd/CTFd.git cd CTFd ``` 下載完後,執行`prepare.sh`來自動安裝所需檔案 ``` prepare.sh ``` 或者可以使用`requirements.txt`來安裝 ``` pip install -r requirements.txt ``` ### 啟動CTFd 等安裝過程都跑完後,測試CTFd是否安裝順利(Flask 預設會跑在5000 port) ``` flask run ``` 也可以使用`python`執行 ``` python server.py ``` 使用`python3`執行 ``` python3 server.py ``` ## CTFd背景執行 由於上述的啟動方式只適用於Debug,不夠穩定,因此不適合放在伺服器上當作一個服務 要讓他穩定運行,我們需要借助gunicorn ### gunicorn 安裝gunicorn ``` sudo apt install gunicorn ``` 啟動 ctfd ``` sudo gunicorn -w 2 -b 0.0.0.0:8000 "CTFd:create_app()" --daemon ``` `-b` 代表要執行的port,(0.0.0.0代表任何人都可以連線) `-w` 代表使用的[CPU線程](https://zhuanlan.zhihu.com/p/86855590) `--daemon` 移到背景執行 ### gnuicorn debug 查詢 gunicorn 背景執行 ``` ps -ef | grep gunicorn ``` 清除所有 gunicorn ``` sudo pkill gunicorn ``` > 參考自: [[GCP教學-Python] #5使用Gunicorn將API背景執行](https://andy6804tw.github.io/2020/04/10/gcp-gunicorn/#%E7%B5%90%E6%9D%9F%E8%83%8C%E6%99%AF%E5%9F%B7%E8%A1%8C) > ### gevent 為了提高執行效率,建議安裝套件 [gevent](https://hustyichi.github.io/2019/04/14/dive-into-gevent/) ``` pip install gevent ``` 啟動 ctfd ``` sudo gunicorn -w 2 -b 0.0.0.0:8000 --worker-class="gevent" "CTFd:create_app()" --daemon ``` `--worker-class="gevent"` 使用gevent ## 創建資料庫 我們須要創建資料庫,來儲存使用者的資料和題目的資訊 我這裡使用的是MariaDB,其指令和架構都和MySQL一樣 ### MariaDB基本設定 下載 MariaDB ``` sudo apt update sudo apt install mariadb-server mariadb-client ``` 創建資料庫的`root`帳號 ``` mysqladmin -u root password {你的密碼} ``` 接下來他會問你一些權限的設定問題,請讀者自行選擇 登入帳號,指令格式如下 ``` mysql -u {使用者} -p {資料庫名稱} ``` 以`root`帳號為例: ``` mysql -u root -p mysql ``` ### 建立資料庫 我們需要創建一個資料庫,來存放CTFd的設定 ``` create database {資料庫名稱}; ``` 我這邊創立了一個`test`的資料庫 ``` create database ctfd; ``` 可以使用來以下指令列出所有資料庫 ``` show databases; ```  跳到指定的資料庫 ``` use {資料庫名稱}; ``` 我這裡跳到ctfd為例: ``` use ctfd; ```  > 引用自: [mysql命令行的基本用法(通用linux和windows)](https://registerboy.pixnet.net/blog/post/21684093) ### 新增使用者(可選) 登入`root`帳號 ``` mysql -u root -p ``` 建立一個使用者 ``` CREATE USER '使用者'@'localhost' IDENTIFIED BY '使用者密碼'; ``` 以我為例: ``` CREATE USER 'ctfd_user'@'localhost' IDENTIFIED BY 'xxxxxxx'; ``` 給予使用者特定資料庫的所有權限 ``` GRANT ALL PRIVILEGES ON 資料庫名稱.* TO '使用者'@'localhost'; ``` 以我為例: ``` GRANT ALL PRIVILEGES ON ctfd.* TO 'ctfd_user'@'localhost'; ``` 測試是否可以連到`database` ``` mysql -u ctfd_user -p ``` > 引用自: [MySQL 新增使用者及建立資料庫權限](https://registerboy.pixnet.net/blog/post/21684093) ## CTFd 連結資料庫 打開 `CTFd/config.py` ``` cd CTFd/ sudo vim config.py ``` 找到並修改`SQLALCHEMY_DATABASE_URI`的value ``` SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://使用者:密碼@localhost/資料庫名稱?charset=utf8' ``` 以我為例: ``` SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://ctfd_user:xxxxxxxx@localhost/資料庫名稱?charset=utf8' ``` > 參考自: [mariadb 默认root密码_debian10 + mariadb + gunicorn + nginx + CTFd 超详细部署攻略以及易错点](https://blog.csdn.net/weixin_39630140/article/details/110596699) > ### 驗證資料庫 回到`CTFd`資料夾,重啟ctfd ``` python3 serve.py ``` 連線到`database` ``` mysql -u ctfd_user -p ctfd ``` 把資料庫的`table`印出來看是否有內容 ``` show tables; ```  ## Nginx 設定 下載`Nginx` ``` sudo apt-get update sudo apt-get install nginx ``` 啟動`Nginx` ``` systemctl start nginx ``` 查看`Nginx`狀態 ``` systemctl status nginx ```  ### 設定防火牆(視情況) 允許防火牆通過`Nginx`使用的`port`(80,443) ``` sudo ufw allow 'Nginx Full' ``` 或者直接允許`port`(80,443) ``` sudo ufw allow 80 sudo ufw allow 443 ``` 檢查是否開通 ``` sudo ufw status numbered ``` *其他防火牆的設定我這裡就不加贅述了* ### Nginx伺服器設定 先調成`root`權限,之後就指令前就不用加`sudo`了 ``` su - ``` 進到`sites-enabled`資料夾 ``` cd /etc/nginx/sites-enabled/ ``` 讀取`default`,修改內容 ``` vim default ``` 以下是我的nginx設定內容,可以做為參考 ``` listen 80 default_server; listen [::]:80 default_server #root /var/www/html; #填入你的域名,沒有的話就直接default server就好了 server_name www.ntcuhacker.com; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. #try_files $uri $uri/ =404; proxy_pass http://localhost:8000; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; } ``` `proxy_pass`是反向代理,可以將使用者導向其他服務,由於我們當初ctfd是架設在8000`port`,因此這裡將使用者導向至`http://localhost:8000` 下面的設定則是將傳給`/`網址的使用者的IP,協定,封包,完整的傳給`http://localhost:8000` ``` proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; ``` 按`esc`,並輸入`:wq`儲存修改 ### 驗證,以及上架nginx 驗證一下設定檔是否有誤 ``` sudo nginx -t ```  重新reload`nginx`服務,更新設定檔 ``` systemctl reload nginx ``` 或者重啟`nginx`服務 ``` systemctl restart nginx ``` ## 最終測試 試試看在瀏覽器輸入自己主機的外部ip或者domain  
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up