K8s部署ret2shell

1176 字
6 分钟
K8s部署ret2shell

1. 背景#

前段时间看到信安协会的同学去打了西电的MoeCTF,感觉他们的哪个平台(Ret2shell)在颜值和功能上都挺不错的,于是想把现在使用的 GZCTF 升级成 Ret2shell

2. 部署环境#

目前 GZCTF平台 部署在一个三节点的K8S集群上,由于学校局域网对外端口封禁非常严重,于是使用MetalLB提供的LoadBlancer对上层的反向代理服务器进行暴露。

  • 系统:Debian GNU/Linux 12 (bookworm)

  • 集群:K8s v1.25.0 + Helm v3.11.2

  • 存储:使用宿主机目录

  • 镜像仓库:使用外部的Harbor作为镜像仓库

3. 部署#

3.1 创建命名空间#

apiVersion: v1
kind: Namespace
metadata:
name: ret2shell-platform
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/part-of: ret2shell

3.2 给节点打标签#

Terminal window
# 负责运行平台的节点
kubectl label node master1 ret.sh.cn/workload=platform
# 负责运行题目容器的节点
kubectl label node master2 ret.sh.cn/workload=challenge
kubectl label node master3 ret.sh.cn/workload=challenge

3.3 创建PV#

Important

因为集群的空间吃紧,所以我在master1节点新加了一块硬盘并挂载到了 /opt/ret2shell-data ,这里手动创建PV和PVC并在 values.yaml 里面手动引用

  • 创建 nats 的 PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: ret2shell-nats-data
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: nats
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: ret2shell-local
hostPath:
path: /opt/ret2shell-data/nats
type: DirectoryOrCreate

这个PV用于nats的JetStream消息持久化,分配1G

  • 创建 postgres 的 PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: ret2shell-postgresql-data
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: postgresql
spec:
capacity:
storage: 15Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: ret2shell-local
hostPath:
path: /opt/ret2shell-data/postgresql
type: DirectoryOrCreate

这个PV用于平台数据库的数据存储,考虑到需要长期使用,分配15G

  • 创建 valkey 的 PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: ret2shell-valkey-data
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: valkey
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: ret2shell-local
hostPath:
path: /opt/ret2shell-data/valkey
type: DirectoryOrCreate

这个是键值对数据库的数据持久化PV,分配1G

  • 创建 victoria 的 PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: ret2shell-victoria-logs-data
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: victoria-logs
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: ret2shell-local
hostPath:
path: /opt/ret2shell-data/victoria-logs
type: DirectoryOrCreate

这个PV用于平台日志存储,分配3G

  • 创建 platform 的 PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: ret2shell-platform-data
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: platform
spec:
capacity:
storage: 70Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: ret2shell-local
hostPath:
path: /opt/ret2shell-data/platform
type: DirectoryOrCreate

这个PV存储bucket 仓库、附件、媒体文件、题目环境捕获文件、平台本地日志,分配70G

3.4 创建对应的PVC#

  • 创建 nats 的 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ret2shell-nats-data
namespace: ret2shell-platform
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: nats
spec:
accessModes:
- ReadWriteOnce
storageClassName: ret2shell-local
volumeName: ret2shell-nats-data
resources:
requests:
storage: 1Gi
  • 创建 postgres 的 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ret2shell-postgresql-data
namespace: ret2shell-platform
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: postgresql
spec:
accessModes:
- ReadWriteOnce
storageClassName: ret2shell-local
volumeName: ret2shell-postgresql-data
resources:
requests:
storage: 10Gi
  • 创建 valkey 的 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ret2shell-valkey-data
namespace: ret2shell-platform
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: valkey
spec:
accessModes:
- ReadWriteOnce
storageClassName: ret2shell-local
volumeName: ret2shell-valkey-data
resources:
requests:
storage: 1Gi
  • 创建 victoria 的 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ret2shell-victoria-logs-data
namespace: ret2shell-platform
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: victoria-logs
spec:
accessModes:
- ReadWriteOnce
storageClassName: ret2shell-local
volumeName: ret2shell-victoria-logs-data
resources:
requests:
storage: 3Gi
  • 创建 platform 的 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ret2shell-platform-data
namespace: ret2shell-platform
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: platform
spec:
accessModes:
- ReadWriteOnce
storageClassName: ret2shell-local
volumeName: ret2shell-platform-data
resources:
requests:
storage: 25Gi

3.5 使用 Helm 进行安装#

  • 编写 values.yaml
values.yaml
global:
labels: {}
platform:
image:
repository: ghcr.io/ret2shell/ret2shell
tag: 3.12.2
exposure:
type: nodePort
service:
nodePort: 30307
config:
auth:
signingKey: "strong-password"
server:
externalDomain: ctf.example.com
externalHttps: true
corsOrigins: "https://ctf.example.com"
cluster:
enabled: true
nodeSelector: "challenge"
enableCapture: true
nodeSelector:
ret.sh.cn/workload: platform
persistence:
enabled: true
accessMode: ReadWriteOnce
existingClaim: "ret2shell-platform-data"
postgresql:
mode: internal
image:
repository: docker.jiaxin.site/library/postgres
tag: 18-alpine
auth:
password: "strong-password"
nodeSelector:
ret.sh.cn/workload: platform
persistence:
enabled: true
accessMode: ReadWriteOnce
existingClaim: "ret2shell-postgresql-data"
valkey:
mode: internal
image:
repository: docker.jiaxin.site/valkey/valkey
tag: 8-alpine
auth:
enabled: true
password: "strong-password"
nodeSelector:
ret.sh.cn/workload: platform
persistence:
enabled: true
accessMode: ReadWriteOnce
existingClaim: "ret2shell-valkey-data"
nats:
mode: internal
image:
repository: docker.jiaxin.site/library/nats
tag: 2-alpine
auth:
enabled: true
token: "strong-password"
nodeSelector:
ret.sh.cn/workload: platform
persistence:
enabled: true
accessMode: ReadWriteOnce
existingClaim: "ret2shell-nats-data"
registry:
mode: disabled
victoriaLogs:
mode: internal
image:
repository: docker.jiaxin.site/victoriametrics/victoria-logs
tag: v1.43.1
nodeSelector:
ret.sh.cn/workload: platform
persistence:
enabled: true
accessMode: ReadWriteOnce
existingClaim: "ret2shell-victoria-logs-data"
Important

使用 existingClaim 字段引用刚刚创建的PVC

我们使用外部的Harbor作为比赛使用的镜像仓库,所以不使用ret2shell部署的受控registry,将 registry.mode 设置为 disabled

  • 开始部署
Terminal window
# 安装jq
sudo apt install -y jq
# 创建配置文件夹
mkdir -p ~/ret2shell-deploy
cd ~/ret2shell-deploy
# 获取最新版本
R2S_VERSION="$(curl -fsSL https://api.github.com/repos/ret2shell/ret2shell/releases/latest | jq -r '.tag_name')"
# 下载最新版本的Chart和签名
curl -fLO "https://github.com/ret2shell/ret2shell/releases/download/${R2S_VERSION}/helm-chart-${R2S_VERSION}.tgz"
curl -fLO "https://github.com/ret2shell/ret2shell/releases/download/${R2S_VERSION}/helm-chart-${R2S_VERSION}.tgz.sha256"
# 校验一下sha256
EXPECTED_SHA256="$(awk '{print $1}' "helm-chart-${R2S_VERSION}.tgz.sha256")"
ACTUAL_SHA256="$(sha256sum "helm-chart-${R2S_VERSION}.tgz" | awk '{print $1}')"
test "$EXPECTED_SHA256" = "$ACTUAL_SHA256"
# 安装
helm upgrade --install ret2shell helm-chart-3.12.2.tgz -n ret2shell-platform -f values.yaml

4. 暴露服务#

4.1 使用MetalLB#

  • 创建IP地址池
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ret2shell-ips
namespace: metallb-system
spec:
addresses:
- 192.168.1.119/32
autoAssign: false
  • 创建负载均衡的 SVC
apiVersion: v1
kind: Service
metadata:
name: ret2shell-loadblancer
namespace: ret2shell-platform
labels:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: platform
annotations:
metallb.universe.tf/address-pool: ret2shell-ips
spec:
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: http
protocol: TCP
selector:
app.kubernetes.io/name: ret2shell
app.kubernetes.io/component: platform

4.2 配置反向代理#

server {
include common.d/listen.conf;
include ssl/main.conf;
server_name ctf.example.com;
location / {
proxy_pass http://192.168.1.119;
include common.d/proxy_pass.conf;
}
}

5. 添加镜像仓库的凭据#

Terminal window
kubectl create secret docker-registry harbor-secret \
--docker-server=<你的仓库地址> \
--docker-username=<用户名> \
--docker-password=<密码或访问令牌> \
--namespace=ret2shell-challenge
Important

ret2shell拉取镜像时使用的凭据是 docker-registry 形式的,需要提前在集群内配置,在创建题目时设置,启动题目环境时平台会自动使用该凭据拉取Harbor内的镜像

6. 结尾#

没了喵,谢谢欣赏

gopher
gopher

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

K8s部署ret2shell
https://blog.tuf3i.cc/posts/ret2shell-deploy/
作者
TuF3i
发布于
2026-10-09
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
TuF3i
一只区,什么也不想写
分类
标签
站点统计
文章
19
分类
11
标签
20
总字数
50,652
运行时长
0 天
最后活动
0 天前

目录