Fork project
This commit is contained in:
268
docs/advanced.zh-cn.md
Normal file
268
docs/advanced.zh-cn.md
Normal file
@ -0,0 +1,268 @@
|
||||
# 高级部署
|
||||
|
||||
## 前提
|
||||
|
||||
请确认你有过单机部署的经验,不建议第一次就搞这样分布架构
|
||||
|
||||
建议有一定Docker部署及操作经验者阅读此文档
|
||||
|
||||
在进行以下步骤之前,你需要先安装好ctfd-whale插件
|
||||
|
||||
## 目的
|
||||
|
||||
分离靶机与ctfd网站服务器,CTFd通过tls api远程调用docker
|
||||
|
||||
## 架构
|
||||
|
||||
两台vps
|
||||
|
||||
- 一台作为安装CTFd的网站服务器,称为 `web` ,需要公网IP
|
||||
- 一台作为给选手下发容器的服务器,称为 `target` ,此文档用到的服务器是有公网IP的,但如果没有,可也在 `web` 服务器用 `frps` 做转发
|
||||
|
||||
本部署方式的架构如图所示
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 配置Docker的安全API
|
||||
|
||||
参考来源:[Docker官方文档](https://docs.docker.com/engine/security/protect-access/#use-tls-https-to-protect-the-docker-daemon-socket)
|
||||
|
||||
|
||||
### target服务器配置
|
||||
|
||||
建议切换到 `root` 用户操作
|
||||
|
||||
### 克隆本仓库
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/frankli0324/ctfd-whale
|
||||
```
|
||||
|
||||
### 开启docker swarm
|
||||
|
||||
```bash
|
||||
$ docker swarm init
|
||||
$ docker node update --label-add "name=linux-target-1" $(docker node ls -q)
|
||||
```
|
||||
|
||||
把 `name` 记住了,后面会用到
|
||||
|
||||
创建文件夹
|
||||
```bash
|
||||
$ mkdir /etc/docker/certs && cd /etc/docker/certs
|
||||
```
|
||||
|
||||
设置口令,需要输入2次
|
||||
```bash
|
||||
$ openssl genrsa -aes256 -out ca-key.pem 4096
|
||||
```
|
||||
|
||||
用OpenSSL创建CA, 服务器, 客户端的keys
|
||||
```bash
|
||||
$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
|
||||
```
|
||||
|
||||
生成server证书,如果你的靶机服务器没有公网IP,内网IP理论上也是可以的,只要web服务器能访问到
|
||||
```bash
|
||||
$ openssl genrsa -out server-key.pem 4096
|
||||
$ openssl req -subj "/CN=<target_ip>" -sha256 -new -key server-key.pem -out server.csr
|
||||
```
|
||||
|
||||
配置白名单
|
||||
```bash
|
||||
$ echo subjectAltName = IP:0.0.0.0,IP:127.0.0.1 >> extfile.cnf
|
||||
```
|
||||
|
||||
将Docker守护程序密钥的扩展使用属性设置为仅用于服务器身份验证
|
||||
```bash
|
||||
$ echo extendedKeyUsage = serverAuth >> extfile.cnf
|
||||
```
|
||||
|
||||
生成签名证书,此处需要输入你之前设置的口令
|
||||
```bash
|
||||
$ openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
|
||||
-CAcreateserial -out server-cert.pem -extfile extfile.cnf
|
||||
```
|
||||
|
||||
生成客户端(web服务器)访问用的 `key.pem`
|
||||
```bash
|
||||
$ openssl genrsa -out key.pem 4096
|
||||
```
|
||||
|
||||
生成 `client.csr` ,此处IP与之前生成server证书的IP相同
|
||||
```bash
|
||||
$ openssl req -subj "/CN=<target_ip>" -new -key key.pem -out client.csr
|
||||
```
|
||||
|
||||
创建扩展配置文件,把密钥设置为客户端身份验证用
|
||||
```bash
|
||||
$ echo extendedKeyUsage = clientAuth > extfile-client.cnf
|
||||
```
|
||||
|
||||
生成 `cert.pem`
|
||||
```bash
|
||||
$ openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
|
||||
-CAcreateserial -out cert.pem -extfile extfile-client.cnf
|
||||
```
|
||||
|
||||
删掉配置文件和两个证书的签名请求,不再需要
|
||||
```bash
|
||||
$ rm -v client.csr server.csr extfile.cnf extfile-client.cnf
|
||||
```
|
||||
|
||||
为了防止私钥文件被更改以及被其他用户查看,修改其权限为所有者只读
|
||||
```bash
|
||||
$ chmod -v 0400 ca-key.pem key.pem server-key.pem
|
||||
```
|
||||
|
||||
为了防止公钥文件被更改,修改其权限为只读
|
||||
```bash
|
||||
$ chmod -v 0444 ca.pem server-cert.pem cert.pem
|
||||
```
|
||||
|
||||
打包公钥
|
||||
```bash
|
||||
$ tar cf certs.tar *.pem
|
||||
```
|
||||
|
||||
修改Docker配置,使Docker守护程序可以接受来自提供CA信任的证书的客户端的连接
|
||||
|
||||
拷贝安装包单元文件到 `/etc` ,这样就不会因为docker升级而被覆盖
|
||||
```bash
|
||||
$ cp /lib/systemd/system/docker.service /etc/systemd/system/docker.service
|
||||
```
|
||||
|
||||
将第 `13` 行
|
||||
```
|
||||
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
|
||||
```
|
||||
改为如下形式
|
||||
```
|
||||
ExecStart=/usr/bin/dockerd --tlsverify \
|
||||
--tlscacert=/etc/docker/certs/ca.pem \
|
||||
--tlscert=/etc/docker/certs/server-cert.pem \
|
||||
--tlskey=/etc/docker/certs/server-key.pem \
|
||||
-H tcp://0.0.0.0:2376 \
|
||||
-H unix:///var/run/docker.sock
|
||||
```
|
||||
|
||||
重新加载daemon并重启docker
|
||||
```bash
|
||||
$ systemctl daemon-reload
|
||||
$ systemctl restart docker
|
||||
```
|
||||
|
||||
**注意保存好生成的密钥,任何持有密钥的用户都可以拥有target服务器的root权限**
|
||||
|
||||
---
|
||||
|
||||
### Web服务器配置
|
||||
|
||||
在`root`用户下配置
|
||||
|
||||
```bash
|
||||
$ cd CTFd
|
||||
$ mkdir docker-certs
|
||||
```
|
||||
|
||||
先把刚才打包好的公钥 `certs.tar` 复制到这台服务器上
|
||||
|
||||
然后解压
|
||||
```bash
|
||||
$ tar xf certs.tar
|
||||
```
|
||||
|
||||
打开 `CTFd` 项目的 `docker-compose.yml` ,在`CTFd` 服务的 `volumes` 下加一条
|
||||
```
|
||||
./docker-certs:/etc/docker/certs:ro
|
||||
```
|
||||
|
||||
顺便把 `frp` 有关的**所有**配置项删掉,比如`frp_network`之类
|
||||
|
||||
|
||||
然后执行 `docker-compose up -d`
|
||||
|
||||
打开`CTFd-whale`的配置网页,按照如下配置docker
|
||||
|
||||

|
||||
|
||||
注意事项
|
||||
|
||||
- `API URL` 一定要写成 `https://<target_ip>:<port>` 的形式
|
||||
- `Swarm Nodes` 写初始化 `docker swarm` 时添加的 `lable name`
|
||||
- `SSL CA Certificates` 等三个路径都是CTFd容器里的地址,不要和物理机的地址搞混了,如果你按照上一个步骤更改好了 `CTFd` 的 `docker-compose.yml` ,这里的地址照着填就好
|
||||
|
||||
对于单容器的题目,`Auto Connect Network` 中的网络地址为`<folder_name>_<network_name>`,如果没有改动,则默认为 `whale-target_frp_containers`
|
||||
|
||||

|
||||
|
||||
*多容器题目配置 未测试*
|
||||
|
||||
---
|
||||
|
||||
## FRP配置
|
||||
|
||||
### 添加泛解析域名,用于HTTP模式访问
|
||||
|
||||
可以是这样
|
||||
```
|
||||
*.example.com
|
||||
*.sub.example.com (以此为例)
|
||||
```
|
||||
|
||||
### 在target服务器上配置
|
||||
|
||||
进入 `whale-target` 文件夹
|
||||
```bash
|
||||
$ cd ctfd-whale/whale-target
|
||||
```
|
||||
|
||||
修改 `frp` 配置文件
|
||||
```bash
|
||||
$ cp frp/frps.ini.example frp/frps.ini
|
||||
$ cp frp/frpc.ini.example frp/frpc.ini
|
||||
```
|
||||
|
||||
打开 `frp/frps.ini`
|
||||
|
||||
- 修改 `token` 字段, 此token用于frpc与frps通信的验证
|
||||
- 此处因为frps和frpc在同一台服务器中,不改也行
|
||||
- 如果你的target服务器处于内网中,可以将 `frps` 放在 `web` 服务器中,这时token就可以长一些,比如[生成一个随机UUID](https://www.uuidgenerator.net/)
|
||||
- 注意 `vhost_http_port` 与 [docker-compose.yml](/whale-target/docker-compose.yml) 里 `frps` 映射的端口相同
|
||||
- `subdomain_host` 是你做泛解析之后的域名,如果泛解析记录为`*.sub.example.com`, 则填入`sub.example.com`
|
||||
|
||||
|
||||
|
||||
#### 打开 `frp/frpc.ini`
|
||||
|
||||
- 修改 `token` 字段与 `frps.ini` 里的相同
|
||||
|
||||
- 修改 `admin_user` 与 `admin_pwd`字段, 用于 `frpc` 的 basic auth
|
||||
|
||||
---
|
||||
|
||||
### 在WEB服务器上配置
|
||||
|
||||
打开whale的设置页面,按照如下配置参数
|
||||
|
||||

|
||||
|
||||
网页中,
|
||||
|
||||
- `API URL` 需要按照 `http://user:password@ip:port` 的形式来设置
|
||||
- `Http Domain Suffix` 需要与 `frps.ini` 中的 `subdomain_host` 保持一致
|
||||
- `HTTP Port` 与 `frps.ini` 的 `vhost_http_port` 保持一致
|
||||
- `Direct Minimum Port` 与 `Direct Maximum Port` 与 `whale-target/docker-compose.yml` 中的段口范围保持一致
|
||||
- 当 API 设置成功后,whale 会自动获取`frpc.ini`的内容作为模板
|
||||
|
||||
---
|
||||
|
||||
至此,分离部署的whale应该就能用了,可以找个题目来测试一下,不过注意docker_dynamic类型的题目似乎不可以被删除,请注意不要让其他管理员把测试题公开
|
||||
|
||||
你可以用
|
||||
```bash
|
||||
$ docker-compose logs
|
||||
```
|
||||
来查看日志并调试,Ctrl-C退出
|
||||
Reference in New Issue
Block a user