emirhankaplan/kalkan-cyber-range
GitHub: emirhankaplan/kalkan-cyber-range
一个自托管的网络安全靶场平台,提供动态 flag、浏览器内攻击终端和隔离容器编排,支持 CTF 与渗透测试练习。
Stars: 0 | Forks: 0
🛡️ KALKAN — 自主网络靶场
一个自托管的 网络靶场(CTF / 渗透测试练习)。选择一台故意留有漏洞的
机器 → 平台将为你启动一个 隔离的容器 → 发起攻击 → 找到
基于会话的动态 flag → 提交它。精神上类似于 HackTheBox / TryHackMe,但每次
会话的 flag 都是唯一的(攻略 write-up 毫无用处),并且它内置了一个 真正的浏览器内攻击
shell,让你无需任何设置即可开始黑客攻击。
## ✨ 亮点
- **基于会话的动态 flag** — 为每个会话生成并注入 `Kalkan{<32 hex>}`,**仅在服务端存储**,使用恒定时间(constant-time)验证。共享 / 旧的 / 互联网上的 flag 永远无效。
- **真正的浏览器内攻击 shell** — 直接连接到一个已经处于目标网络中的攻击者盒子(box)的实时 PTY(xterm.js ↔ WebSocket ↔ `docker exec`)。客户端零设置。同时提供 WireGuard。
- **经过强化的隔离编排** — 每个会话使用一个无出口网络 + `cap-drop ALL` 以及资源受限的容器;配置过程实时流式传输;在停止/到期时自动销毁。
- **8 个可用的漏洞实验环境**,涵盖不同类别 — 每一个都通过真实引擎验证了端到端的 rooting 过程。
- **实时运营感** — 全局“谁在线”状态 + 基于 WebSocket 的 rooting 实时动态,每台机器的任务简报,行动后报告,以及忠实还原的终端级设计移植。
## 状态 — 所有阶段均已实现 ✅
| 阶段 | 范围 | 状态 |
| ----- | ----------------------------------------------------------- | :---: |
| 0 | 框架搭建 + 从设计中移植的完整前端 | ✅ |
| 1 | 引擎:经过强化的 Docker 编排 + 实时 WS 日志 | ✅ |
| 2 | 动态 flag + 服务端验证 + 防作弊 | ✅ |
| 3 | 浏览器内的攻击者终端(PTY ↔ WS ↔ xterm.js) | ✅ |
| 4 | JWT 认证、真实目录、排行榜 + 积分系统 | ✅ |
| 5 | WireGuard VPN(“自带 Kali”) | ✅¹ |
¹ 第 5 阶段始终签发真实的基于会话的 `.conf` 文件;当在 WireGuard 网关主机上设置 `KALKAN_WG_ENABLED=true` 时,将激活实时的主机配置(`wg`/`ip`)。
**端到端验证:** 所有 **8 个实验环境**(命令注入、SQLi、LFI、SSRF、反序列化、SSTI、IDOR、JWT-bypass)均可成功预置 → 从攻击者盒子发起利用 → 泄露**精确的**基于会话的 flag → 提交 → **ROOTED** + 获得积分,然后进行彻底的销毁。错误/旧的 flag 会失败;暴力破解受到限制(HTTP 429);WS 升级需要有效的 token + origin;引擎内置了单元测试。
## 架构
```
┌─────────────────────────────────────────────┐
browser ──HTTPS/WSS──▶│ Caddy (TLS, security headers, routing) │
└───────────────┬───────────────┬─────────────┘
│ / │ /api/* /ws/*
┌─────▼─────┐ ┌──────▼───────┐ ┌────────┐
│ web │ │ engine (Go) │──▶│ Redis │
│ Next.js │ │ chi + WS │ │sessions│
└───────────┘ └──────┬───────┘ │ flags │
│ Docker SDK └────────┘
▼
┌──────────────────────────────────────────┐
│ per-session isolated bridge networks │
│ kalkan-sess-
(internal, no egress) │
│ ┌──────────┐ ┌────────────────┐ │
│ │ target │◀──────▶│ attacker shell │ │
│ │ (lab) │ │ (PTY ↔ browser)│ │
│ └──────────┘ └────────────────┘ │
└──────────────────────────────────────────┘
```
平台服务(Caddy、web、engine、Redis)通过 docker-compose 运行。**实验环境
容器由 engine 动态启动,绝不通过 compose 启动。**
## 技术栈
- **Frontend** (`web/`):Next.js 14 (App Router) · TypeScript (strict) · Tailwind v3 ·
Zustand · xterm.js · 原生 WebSocket。
- **Engine** (`engine/`):Go 1.22+ · chi · Docker Engine SDK · coder/websocket ·
golang-jwt v5 · go-redis(后备:内存数据库)。架构分层为 `core`(端口/模型) +
叶子包(store/flag/auth/ratelimit/lab/vpn) + 集成层(orchestrator/ws/
session/api)。
- **Infra**:Docker + docker-compose(仅限平台) · Caddy(TLS + 反向代理) ·
WireGuard。
## 仓库布局
```
web/ Next.js frontend (ported from the design — visual source of truth)
engine/ Go orchestration API + WebSocket
internal/core domain model + port interfaces (the contract)
internal/{store,flag,auth,ratelimit,lab,vpn} leaf implementations
internal/{orchestrator,ws,session,api} Docker / WS / lifecycle / HTTP
labs/ Vulnerable target machines — one folder per machine (folder == codename)
_template/ copy-paste-ready lab: Dockerfile + metadata.json + flag-inject entrypoint
AVCI/ demo lab — a "network tools" panel with a command-injection RCE
gateway/ WireGuard server bootstrap + per-session peer manager (Phase 5)
deploy/ docker-compose.yml, Caddyfile, attacker image, .env.example
Makefile make dev / dev-engine / attacker-image / build / lint / up / down
```
## 快速开始
### 本地开发
`make dev` 启动 Web 应用;`make dev-engine` 运行 engine(内存存储,
实验环境使用真实的 Docker)。它们通过 `web/.env.development` 进行跨域通信。
```
make install # web deps
make attacker-image # build kalkan/attacker:latest once (needs Docker)
# terminal 1 — engine 在 :8080 上(需要 Docker 访问权限;内存存储)
make dev-engine
# terminal 2 — web 在 :3000 上
make dev
```
打开 http://localhost:3000 并使用预置的操作员登录:
| 字段 | 值 |
| -------- | ----------- |
| Operatör | `n0xferatu` |
| Anahtar | `kalkan` |
### 完整平台(docker-compose)
```
cp deploy/.env.example deploy/.env # then edit secrets (JWT, domain, …)
make attacker-image
make up # caddy + web + engine + redis
make logs ; make down
```
## 质量
```
make lint # web eslint + tsc --noEmit, engine go vet + gofmt
make test # engine unit tests
```
单元测试覆盖了安全关键的不变量:存储记录的往返过程
(针对 Redis `json:"-"` flag/密码哈希错误的回归防护)、flag 格式 +
恒定时间验证、JWT 的签发/验证(包括 alg-confusion + 过期拒绝)、
速率限制器、原子化的首次解题计分以及实验环境注册表。
## 独创之处
- **基于会话的动态 flag** — write-up 攻略毫无用处;每个会话的 flag 都不同。
- **真正的浏览器内攻击 shell** — 直接连接到目标网络中攻击者盒子的 PTY;
客户端零设置(WireGuard 是“自带 Kali”的替代方案)。
- **任务简报** — 每台机器一个用于展示任务背景的简报面板。
- **实时动态** — 全局的“谁在线”状态 + 基于 WS 的实时 rooting 滚动播报。
- **行动后报告** — ROOTED 横幅会报告获取 root 的时间 + 获得的积分。
## 工作原理(循环流程)
1. `POST /api/labs/AVCI/start` → engine 生成 `Kalkan{<32 hex>}`,构建
实验环境镜像,创建一个**内部**(无出口)网络,启动经过强化的
目标(flag 通过 `KALKAN_FLAG` 注入)+ 攻击者盒子,并通过 `GET /ws/sessions/:id` 流式传输带有样式的预置日志。
2. 操作员从**浏览器终端**(直接连接到攻击者容器的真实 PTY,已处于目标网络中)或他们自己的 Kali 通过 WireGuard `.conf` 发起攻击。在 AVCI 上的示例:`host=127.0.0.1; cat /root/root.txt`。
3. `POST /api/sessions/:id/flag` **仅在服务端**通过恒定时间比较进行验证。正确 → 状态变为 `rooted`,获得积分,通过 WS 广播 → UI 触发 ROOTED 庆祝动画。
## 安全模型
这是一个黑客攻击平台,因此它本身不能被黑客攻击。
- **目标实验容器**:仅有内部网络且**无出口**(已验证
`internal=true`),512 MiB / 1 CPU / 256-pid 限制,`--cap-drop ALL` + 仅保留所需的那一个 cap(目标为 `NET_BIND_SERVICE`,攻击者为 `NET_RAW`),`no-new-privileges`
(可切换),tmpfs `/tmp`。防范主机 DoS 和从盒子内部进行的数据渗漏。
- **Flags**:基于会话的 `Kalkan{<32 hex>}`(crypto/rand),注入到容器中,
**仅在服务端存储**(`json:"-"` — 永远不会序列化到客户端),使用 `crypto/subtle` 恒定时间比较进行验证。共享/旧的/互联网上的 flag 永远无法通过验证。
- **防作弊 / 防滥用**:在 flag 提交(基于会话 AND
基于 IP)和登录(基于 IP)上应用令牌桶速率限制 → 暴力破解时返回 HTTP 429。
- **AuthZ**:带过期的 JWT (HS256);每个会话路由都会检查所有权(404/403);
WebSockets 通过 `?token=` 进行身份验证,并强制执行 Origin 白名单。
- **传输层**:Caddy 终止 TLS;WS over WSS;HSTS, X-Frame-Options, nosniff,
Referrer-Policy, 以及 CSP 集中在 `deploy/Caddyfile` 中设置。密钥通过环境变量传递
(附带 `deploy/.env.example`;`.env` 被 gitignored)。
### 信任假设 — Docker socket
Engine 直接与 **Docker daemon 通信**(Engine SDK)以构建镜像并
创建网络 + 容器。对 Docker socket 的访问权限等同于主机上的 root 权限,因此:
- **在您控制的专用、隔离的 VM/VPS 上运行 Kalkan** — 而不是共享/生产主机。
- socket 仅挂载到 engine 中(见 `deploy/docker-compose.yml`),永远不会
通过网络暴露。实验容器永远不会获得 socket,也永远没有出口。
## API
| 方法 | 路径 | 备注 |
| ------ | ----------------------------- | -------------------------------------- |
| POST | `/api/auth/login` | → `{token, user}`(受速率限制) |
| GET | `/api/me` | 当前操作员 |
| GET | `/api/labs` | 目录(rooted 数量 + 每位用户解题数) |
| POST | `/api/labs/{codename}/start` | 预置会话 |
| GET | `/api/sessions/{id}` | 会话状态(仅限所有者) |
| POST | `/api/sessions/{id}/stop`·`/restart`·`/extend` | 生命周期 |
| POST | `/api/sessions/{id}/flag` | 验证 flag(受速率限制) |
| GET | `/api/sessions/{id}/vpn` | WireGuard `.conf` |
| GET | `/api/leaderboard` | 排名靠前的操作员 |
| WS | `/ws/sessions/{id}` | 预置日志 + 状态 + rooted |
| WS | `/ws/sessions/{id}/terminal` | 攻击者 PTY |
## 添加实验环境
```
cp -r labs/_template labs/ # folder name MUST equal the codename
# 编辑 labs//metadata.json + Dockerfile,然后重启 engine
```
有关文件夹约定和基于会话的
flag 注入机制,请参阅 [`labs/README.md`](labs/README.md)。您提供/选择易受攻击的应用程序(自定义,或者是
已有的程序,如 DVWA / OWASP Juice Shop);Kalkan 负责对其进行编排。`labs/AVCI`
是一个完整且可用的示例。
## 设计来源
前端是最终设计(`Kalkan Siber Poligon.html`)的忠实移植。
手工编写的设计系统(`web/src/styles/`)是**视觉上的唯一事实来源**,
被逐字移植;Tailwind 配置了匹配的 token 以供编写新代码使用。UI 有意**没有**被重新设计。标签:Docker, EVTX分析, Go, OPA, Ruby工具, 安全防御评估, 搜索引擎查询, 日志审计, 网络安全, 请求拦截, 隐私保护, 靶场