# 踏风 Tafeng
踏风是一个面向 Cloudflare Worker 部署的 WebSSH 工作台,使用 React + Vite + TypeScript 构建。项目采用纯 Worker 架构:前端静态资源、认证、设置、连接管理、命令历史、SFTP 文件管理、WebSocket 终端桥接都由 Cloudflare Worker 承载。
English documentation: [Readme_EN.md](./Readme_EN.md)
## 功能概览
- WebSSH 终端工作台,界面风格接近 macOS Terminal。
- 支持保存 VPS 连接信息:IP / 域名、端口、用户名、密码或私钥。
- 首页管理密码登录,设置中可开启两步验证。
- 中文 / English 双语界面。
- SFTP 文件浏览、文本编辑器、上传和下载。
- 上传接口设计上限为 10G。
- 连接后显示 CPU、内存、Swap、硬盘使用情况和进程列表。
- 全局命令历史记录,所有 VPS 共用,最多保存 100000 条。
- Cloudflare Worker + KV + R2 部署结构。
- 真实 SSH/SFTP 通过 Worker TCP Socket(`cloudflare:sockets`)和 `ssh2` 库接入。
## 当前状态
项目已完成前端、Worker API、认证、设置、连接管理、命令历史、SFTP 文件管理和监控面板。SSH/SFTP 协议通过 Cloudflare Worker 的 `cloudflare:sockets` TCP Socket API 和 `ssh2` 库接入,所有连接在 Worker 内完成协议桥接。
> **⚠️ 重要提示:每次代码更新触发自动重新部署后,需要在 Cloudflare Dashboard 中重新绑定 KV 和 R2。** 因为 `wrangler.toml` 中没有写入 KV/R2 的绑定 ID,每次 `wrangler deploy` 会用本地配置覆盖远程配置,导致之前在 Dashboard 中手动添加的 KV 和 R2 绑定丢失。请参考下方「更新代码后重新绑定」章节。
## 目录结构
```text
tafeng/
├── src/ # React + Vite + TypeScript 前端
├── worker/ # Cloudflare Worker API 与 WebSocket 服务
├── shared/ # 前后端共用类型
├── public/ # 静态资源目录
├── dist/client/ # 前端构建产物,不提交 Git
├── wrangler.toml # Cloudflare Worker 配置
├── package.json # 前端和 Worker 脚本
└── LICENSE # MIT License
```
## 环境要求
- Node.js 18 或更高版本,推荐 Node.js 20+。
- npm 9 或更高版本。
- Cloudflare 账号。
- Wrangler CLI。本项目已把 `wrangler` 放在 devDependencies 中,可以直接使用 `npm run worker:dev` 和 `npm run worker:deploy`。
## 网页部署到 Cloudflare Worker
这是推荐给普通用户的部署方式:从 GitHub Fork 开始,主要在 GitHub 网页和 Cloudflare Dashboard 里完成,不需要在本地运行命令。
### 1. Fork 项目到自己的 GitHub
1. 打开本项目的 GitHub 仓库页面。
2. 点击右上角 `Fork`。
3. Owner 选择你自己的 GitHub 账号或组织。
4. Repository name 可以保持 `tafeng`,也可以改成你喜欢的名字。
5. 点击 `Create fork`。
完成后,你会得到一个自己的仓库,例如:
```text
https://github.com/你的用户名/tafeng
```
后续所有配置都建议改你自己 Fork 出来的仓库,不要直接改上游仓库。
### 2. 在 Cloudflare 创建 KV
踏风需要 KV 保存登录会话、设置、VPS 连接信息和命令历史。
1. 打开 [Cloudflare Dashboard](https://dash.cloudflare.com/)。
2. 进入左侧 `Storage & Databases`。
3. 打开 `KV`。
4. 点击 `Create namespace`。
5. 创建生产 KV,名称建议填写:
```text
tafeng-kv
```
6. 再创建一个预览 KV,名称建议填写:
```text
tafeng-kv-preview
```
7. 记住这两个 Namespace 名称。后面会在 Worker 设置中手动绑定,不需要把 KV ID 写入 `wrangler.toml`。
### 3. 在 Cloudflare 创建 R2 Bucket
踏风使用 R2 作为上传文件和大文件中转存储。
1. 在 Cloudflare Dashboard 左侧进入 `R2 Object Storage`。
2. 点击 `Create bucket`。
3. 创建生产 Bucket:
```text
tafeng-files
```
4. 再创建预览 Bucket:
```text
tafeng-files-preview
```
Bucket 名称可以使用上面的推荐值,也可以自定义。后面会在 Worker 设置中选择 Bucket 并绑定,不需要把 Bucket 名称写入 `wrangler.toml`。
### 4. 在 Cloudflare 连接 GitHub 仓库
Cloudflare Workers 支持从 GitHub 仓库构建和部署。官方入口可能会随 Dashboard 改版微调,但大致路径如下:
1. 打开 Cloudflare Dashboard。
2. 进入 `Workers & Pages`。
3. 点击 `Create` 或 `Create application`。
4. 选择从 Git 仓库导入,通常显示为 `Import a repository`、`Connect to Git` 或类似入口。
5. 选择 `GitHub`。
6. 如果是第一次连接,Cloudflare 会要求授权 GitHub App。
7. 授权时选择你 Fork 的 `tafeng` 仓库。
8. 回到 Cloudflare,选择该仓库和要部署的分支,通常是 `main`。
如果页面让你选择项目类型,选择 `Workers`,不要选择普通静态 Pages 项目。
### 5. 填写构建配置
Cloudflare 会读取 [wrangler.toml](./wrangler.toml) 中的 Worker 入口和静态资源设置。若页面要求手动填写,请使用下面的配置:
```text
Project name: tafeng
Production branch: main
Root directory: /
Build command: npm run build
Deploy command: npm run worker:deploy
Node.js version: 20
```
如果页面要求填写静态资源目录或输出目录,填写:
```text
dist/client
```
如果页面只提供一个命令输入框,优先填写:
```bash
npm run build && npm run worker:deploy
```
注意:不同版本的 Cloudflare Workers Git 集成页面字段可能略有不同。核心原则是先执行 `npm run build` 生成 `dist/client`,再部署 Worker。
### 6. 先完成第一次部署
点击 `Deploy`、`Save and deploy` 或类似按钮,先让 Cloudflare 从 GitHub 拉取代码并完成第一次部署。
第一次部署后,页面可能还不能正常登录,因为还没有给 Worker 绑定 KV 和 R2。这是正常的,继续下一步即可。
### 7. 在网页手动绑定 KV 和 R2
进入刚创建的 `tafeng` Worker:
1. 打开 Cloudflare Dashboard。
2. 进入 `Workers & Pages`。
3. 打开 `tafeng` Worker。
4. 进入 `Settings`。
5. 找到 `Bindings`,有些界面会显示在 `Variables and Secrets` 或 `Resources` 里。
添加 KV Namespace 绑定:
```text
Binding type: KV Namespace
Variable name: TAFENG_KV
KV namespace: tafeng-kv
```
如果页面区分 Preview 环境,也给 Preview 绑定:
```text
Variable name: TAFENG_KV
KV namespace: tafeng-kv-preview
```
添加 R2 Bucket 绑定:
```text
Binding type: R2 Bucket
Variable name: TAFENG_FILES
R2 bucket: tafeng-files
```
如果页面区分 Preview 环境,也给 Preview 绑定:
```text
Variable name: TAFENG_FILES
R2 bucket: tafeng-files-preview
```
绑定名必须完全一致:
```text
TAFENG_KV
TAFENG_FILES
```
代码里通过这两个名字读取 KV 和 R2。名字写错会导致登录、设置、连接信息、命令历史或文件上传失败。
### 8. 设置环境变量和密钥
首次部署可能可以用默认密码 `tafeng` 进入,但生产环境必须设置自己的管理密码。
仍然在 Worker 的设置页面中:
1. 打开 `Variables and Secrets`。
2. 添加 Secret:
```text
名称: ADMIN_PASSWORD
值: 你的强管理密码
```
可选再添加:
```text
名称: SESSION_SECRET
值: 一串随机长字符串
```
如果页面区分 `Production` 和 `Preview` 环境,建议至少在 `Production` 中设置 `ADMIN_PASSWORD`。
### 9. 重新部署
绑定 KV/R2 并设置 Secret 后,建议重新部署一次:
1. 进入 Worker 的 `Deployments` 或 `Builds` 页面。
2. 找到最新一次部署。
3. 点击 `Retry deployment`、`Redeploy` 或类似按钮。
也可以在 GitHub 网页里对 README 做一个很小的修改并提交,触发 Cloudflare 自动重新构建部署。
> **⚠️ 注意:每次重新部署后,KV 和 R2 绑定会被覆盖清空。** 请务必在部署完成后回到 Worker Settings → Bindings,重新添加 `TAFENG_KV` 和 `TAFENG_FILES` 绑定。否则登录、设置、连接信息、命令历史和文件上传功能将无法使用。
### 更新代码后重新绑定
每次从 GitHub 推送代码触发 Cloudflare 自动构建后,都需要执行以下步骤:
1. 等待 Cloudflare 自动构建部署完成。
2. 打开 Cloudflare Dashboard → `Workers & Pages` → `tafeng` → `Settings` → `Bindings`。
3. 重新添加 KV 绑定:
```text
Variable name: TAFENG_KV
KV namespace: tafeng-kv
```
4. 重新添加 R2 绑定:
```text
Variable name: TAFENG_FILES
R2 bucket: tafeng-files
```
5. 点击 `Save` 或 `Deploy` 保存绑定。
> **提示:** 如果你希望避免每次都手动绑定,也可以直接在 `wrangler.toml` 中写入你的 KV Namespace ID 和 R2 Bucket 名称。参见下方「在 wrangler.toml 中固定绑定」章节。
### 在 wrangler.toml 中固定绑定(可选)
在 `wrangler.toml` 中添加以下内容,即可让每次部署自动携带绑定,无需手动操作:
```toml
[[kv_namespaces]]
binding = "TAFENG_KV"
id = "你的KV Namespace ID"
[[r2_buckets]]
binding = "TAFENG_FILES"
bucket_name = "tafeng-files"
```
KV Namespace ID 可以在 Cloudflare Dashboard → `Storage & Databases` → `KV` → 点击你的 namespace 后在页面上找到。添加后提交到 GitHub,后续部署就不需要再手动绑定了。
### 10. 访问踏风
部署成功后,Cloudflare 会给你一个 `workers.dev` 地址,例如:
```text
https://tafeng.你的子域.workers.dev
```
打开地址后:
1. 输入 `ADMIN_PASSWORD` 中设置的管理密码。
2. 进入控制台。
3. 在左侧添加 VPS 连接信息(IP/域名、端口、用户名、密码或私钥)。
4. 点击连接后即可使用 WebSSH 终端、SFTP 文件管理和实时状态监控。
### 11. 配置自定义域名
如果你想使用自己的域名:
1. 打开 Cloudflare Dashboard。
2. 进入 `Workers & Pages`。
3. 打开 `tafeng` Worker。
4. 进入 `Settings`。
5. 打开 `Domains & Routes`。
6. 添加自定义域名或路由。
例如:
```text
ssh.example.com
```
保存后,等待 DNS 和证书生效即可访问。
## 本地开发
安装依赖:
```bash
npm install
```
启动 Vite 前端开发服务:
```bash
npm run dev
```
默认访问地址:
```text
http://localhost:5173/
```
构建前端并启动本地 Worker:
```bash
npm run build
npm run worker:dev
```
Worker 默认访问地址:
```text
http://localhost:8787/
```
本地开发默认管理密码是:
```text
tafeng
```
生产环境不要使用默认密码,请配置 `ADMIN_PASSWORD` Secret。
## Cloudflare 资源准备
踏风部署到 Cloudflare Worker 时需要两个资源:
- KV Namespace:保存设置、会话、VPS 连接信息、命令历史索引和命令历史条目。
- R2 Bucket:保存上传文件或大文件中转数据。
### 1. 登录 Cloudflare
```bash
npx wrangler login
```
如果是在无浏览器的服务器上部署,可以改用 Cloudflare API Token,并设置环境变量:
```bash
export CLOUDFLARE_API_TOKEN="your-cloudflare-api-token"
```
API Token 至少需要 Worker、KV、R2 相关权限。
### 2. 创建 KV Namespace
创建生产 KV:
```bash
npx wrangler kv namespace create TAFENG_KV
```
创建预览 KV:
```bash
npx wrangler kv namespace create TAFENG_KV --preview
```
创建完成后,不需要把 KV ID 写入 [wrangler.toml](./wrangler.toml)。请在 Cloudflare Dashboard 的 Worker 设置中手动添加 KV 绑定:
```text
Variable name: TAFENG_KV
KV namespace: tafeng-kv
```
### 3. 创建 R2 Bucket
创建生产 Bucket:
```bash
npx wrangler r2 bucket create tafeng-files
```
创建预览 Bucket:
```bash
npx wrangler r2 bucket create tafeng-files-preview
```
创建完成后,不需要把 Bucket 名称写入 [wrangler.toml](./wrangler.toml)。请在 Cloudflare Dashboard 的 Worker 设置中手动添加 R2 绑定:
```text
Variable name: TAFENG_FILES
R2 bucket: tafeng-files
```
### 4. 设置管理密码
生产环境必须设置管理密码:
```bash
npx wrangler secret put ADMIN_PASSWORD
```
根据提示输入你的管理密码。
可选:设置会话密钥。当前代码预留了 `SESSION_SECRET`,后续如果你扩展签名会话或加密存储,可以使用它:
```bash
npx wrangler secret put SESSION_SECRET
```
## 构建与部署
### 1. 类型检查
```bash
npm run typecheck
```
### 2. 构建前端
```bash
npm run build
```
构建完成后,静态文件会输出到:
```text
dist/client/
```
### 3. 部署 Worker
```bash
npm run worker:deploy
```
部署成功后,Wrangler 会输出 Worker 访问地址,例如:
```text
https://tafeng.your-subdomain.workers.dev
```
打开这个地址,输入你通过 `ADMIN_PASSWORD` 配置的管理密码即可进入。
## 自定义域名
可以在 Cloudflare Dashboard 中为 Worker 绑定自定义域名:
1. 进入 Cloudflare Dashboard。
2. 打开 Workers & Pages。
3. 选择 `tafeng` Worker。
4. 进入 Settings。
5. 在 Domains & Routes 中添加自定义域名或路由。
## SSH/SFTP 实现架构
SSH 和 SFTP 功能在 Worker 内完整实现,核心代码位于:
```text
worker/sshBridge.ts
```
实现方式:
1. 浏览器通过 WebSocket 连接到 Worker。
2. Worker 使用 `cloudflare:sockets` 的 `connect()` 创建到 VPS `host:22` 的出站 TCP 连接。
3. Worker 使用 `ssh2` 库完成 SSH 协议握手、认证和会话管理。
4. 浏览器 WebSocket 数据和 SSH TCP Socket 数据在 Worker 内双向桥接。
5. SFTP 会话在 SSH 连接建立后自动创建,支持文件浏览、读写、上传和下载。
注意事项:
- Worker 只能创建出站 TCP 连接,不能像传统服务器一样监听任意 TCP 端口。
- SSH 长连接需要注意 Worker 超时、内存和并发连接数量限制。
- SFTP 下载限制为 100MB,文本编辑限制为 2MB。
## 两步验证
踏风已经支持基于 TOTP 的两步验证,并会在网页里提供二维码。
启用步骤:
1. 登录踏风控制台。
2. 点击顶部设置栏中的 `启用两步验证`。
3. 页面会弹出二维码和手动密钥。
4. 使用 Google Authenticator、Microsoft Authenticator、1Password、Bitwarden 等支持 TOTP 的应用扫描二维码。
5. 在弹窗中输入 Authenticator 应用显示的 6 位验证码。
6. 点击 `确认启用`。
启用后,之后登录需要同时输入:
- 管理密码
- Authenticator 应用中的 6 位动态验证码
关闭步骤:
1. 登录踏风控制台。
2. 点击顶部设置栏中的 `两步验证已启用`。
3. Worker 会清除已保存的 TOTP 密钥,并关闭两步验证。
TOTP 密钥会保存在 `TAFENG_KV` 中。生成二维码时会先保存一个 10 分钟有效的待确认密钥,只有验证码校验通过后才会正式启用。
相关入口在:
- [worker/auth.ts](./worker/auth.ts)
- [src/components/SettingsPanel.tsx](./src/components/SettingsPanel.tsx)
## 文件上传下载
踏风支持两种文件传输方式:
### SFTP 文件传输
通过 WebSocket 的 SFTP 会话直接与 VPS 交互:
- **浏览目录**:前端发送 `sftp-ls` 消息,Worker 通过 SFTP 读取远程目录。
- **读取文件**:支持读取最大 2MB 的文本文件进行在线编辑。
- **写入文件**:在线编辑后直接保存到 VPS。
- **上传文件**:浏览器将文件分块(64KB)Base64 编码后通过 WebSocket 流式写入 VPS。
- **下载文件**:Worker 通过 SFTP 流式读取文件(最大 100MB),Base64 编码后发送到浏览器。
### R2 文件上传
上传接口:
```text
POST /api/files/upload
```
Worker 检查 `Content-Length`,超过 10G 返回 `413`。文件内容写入 R2 Bucket `TAFENG_FILES`。
## 命令历史记录
踏风会全局保存所有 VPS 执行过的命令,最多保存 100000 条。
接口:
```text
GET /api/command-history?limit=300&offset=0
DELETE /api/command-history
```
存储方式:
- KV 中保存一个全局索引。
- 每条命令单独保存为 KV 条目。
- 超过 100000 条时自动删除最旧记录。
## 多语言
目前支持:
- 中文
- English
前端语言字典位于:
```text
src/lib/i18n.ts
```
如需增加新语言:
1. 在 `shared/types.ts` 中扩展 `Language` 类型。
2. 在 `src/lib/i18n.ts` 中增加对应字典。
3. 在 `SettingsPanel` 的语言选择器中增加选项。
## 安全建议
生产部署前建议完成以下事项:
- 设置强管理密码:`npx wrangler secret put ADMIN_PASSWORD`。
- 启用两步验证,并妥善保存 Authenticator 恢复方式。
- 不要明文长期保存 SSH 密码或私钥,建议使用加密存储。
- 为 KV 中保存的 VPS 凭据增加加密层。
- 限制 Worker 访问来源或增加额外访问控制。
- 定期清理不需要的命令历史。
- 为 R2 临时上传对象设置清理策略。
- 注意 SSH 连接超时、命令审计和错误处理。
## 常用命令
```bash
# 安装依赖
npm install
# 启动前端开发服务
npm run dev
# 类型检查
npm run typecheck
# 构建前端
npm run build
# 本地运行 Worker
npm run worker:dev
# 部署 Worker
npm run worker:deploy
```
## 常见问题
### 1. 打开页面后无法登录
请确认已经设置生产管理密码:
```bash
npx wrangler secret put ADMIN_PASSWORD
```
本地开发没有设置 Secret 时,默认密码是 `tafeng`。
### 2. 登录或设置接口提示 KV 相关错误
请确认 Cloudflare Dashboard 中已经给 Worker 添加 KV 绑定:
```text
Variable name: TAFENG_KV
KV namespace: tafeng-kv
```
绑定名必须是 `TAFENG_KV`,大小写不能变。
### 3. 文件上传失败
请确认 R2 Bucket 已创建,并且 Cloudflare Dashboard 中已经给 Worker 添加 R2 绑定:
```text
Variable name: TAFENG_FILES
R2 bucket: tafeng-files
```
绑定名必须是 `TAFENG_FILES`,大小写不能变。
### 4. 终端连接 VPS 超时或失败
请检查 VPS 的 IP/域名、端口、用户名和凭据是否正确。Worker 使用出站 TCP 连接到 VPS 的 SSH 端口(默认 22),确保 VPS 防火墙允许来自 Cloudflare IP 段的入站连接。当前 SSH 连接超时为 20 秒。
### 5. 命令历史是否按 VPS 隔离
不是。当前设计是全局历史记录,不管哪个 VPS,所有执行过的命令都会进入同一个历史列表,最多保存 100000 条。
如果这个项目对你有用的话,请我喝罐可乐吧。
## 开源协议
本项目采用 MIT License。你可以自由使用、修改、分发和用于商业项目,但需要保留版权与许可声明。详见 [LICENSE](./LICENSE)。