Files
filedrop/plans/phase1-architecture.md
agent 4b34a85599 init: FileDrop phase1 architecture and scaffold
- Rust axum signaling server with WebSocket support
- Lit + TypeScript frontend with Vite
- Redis session storage with TTL
- WebRTC transport and crypto client stubs
- Phase1 architecture plan in plans/
- Deploy directory structure prepared
2026-04-09 10:32:06 +08:00

393 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FileDrop - 安全无痕文件传输 Web App
## 产品定位
免费、无注册、无历史记录的安全文件传输工具。
- 优先局域网,兼顾公网
- WebRTC 直连优先TURN 兜底
- 浏览器端端到端加密
- 传完即销毁,不留痕迹
---
## 第一期范围
### 要做
- 扫码/短码配对
- WebRTC DataChannel 传输
- 浏览器端 AES-GCM 分块加密
- TURN 回退
- 会话超时自动清理
- 小文件传输(<100MB
### 不做
- 用户注册/登录
- 历史记录
- 大文件/断点续传
- 付费/套餐
- Postgres
- WASM
- 对象存储中转
---
## 技术栈
| 层 | 技术 |
|---|---|
| 前端 | Lit + TypeScript + Vite |
| 后端 | Rust + axum + tokio |
| 临时状态 | Redis |
| NAT 穿透 | coturn |
| 反向代理 | Caddy |
| 部署 | Debian 12 + systemd |
---
## 系统架构
```
Browser A Browser B
| |
|---- HTTPS / WSS -------------|
| |
Rust Signaling Server
|
Redis
|
coturn
```
### 职责划分
**浏览器**
- 选文件
- 生成会话密钥
- 二维码/短码配对
- WebRTC 建连
- 文件分块加密
- DataChannel 发送/接收
**Rust 服务端**
- 创建/加入会话
- WebSocket 信令转发
- 临时会话状态
- 过期清理
- 下发 ICE 配置
**Redis**
- 会话临时状态
- 在线状态
- 一次性加入令牌
- TTL 自动过期
**coturn**
- STUN/TURN 服务
---
## 核心流程
### 1. 创建会话
1. 发送端选择文件
2. 浏览器本地生成 `session_secret`
3. 请求 `POST /api/sessions`
4. 服务端返回 `room_id``join_token``ws_url``ice_servers`
5. 前端生成分享信息:
- 短码:`room_id`
- 链接:`/join/{room_id}#k={session_secret}&t={join_token}`
> `#k=` 在 URL fragment 中,不会发给服务端
### 2. 加入会话
1. 接收端扫码进入
2. 前端从 fragment 取出 `session_secret``join_token`
3. 请求 `POST /api/sessions/{room_id}/join`
4. 服务端校验会话状态和 token
5. 成功后建立 WebSocket
### 3. 信令协商
1. 双方连上 `WS /ws`
2. 发送端创建 offer
3. 接收端返回 answer
4. 双方交换 ICE candidate
5. 建立 `RTCDataChannel`
### 4. 文件传输
1. 发送端发送 `file_manifest`
2. 文件切块64KB ~ 256KB
3. 每块独立 AES-GCM 加密
4. 通过 DataChannel 发送
5. 接收端逐块解密并缓存
6. 完成后生成下载文件
7. 双方发送完成确认并关闭会话
### 5. 会话销毁
触发条件:
- 传输完成
- 用户主动取消
- 超时15 分钟)
- WebSocket/RTC 长时间断开
---
## 协议设计
### HTTP API
#### `POST /api/sessions`
创建会话
**请求**
```json
{
"file_count": 2,
"total_size": 1834201
}
```
**响应**
```json
{
"room_id": "8F4K2P",
"join_token": "opaque-token",
"ws_url": "wss://app.example.com/ws",
"expires_at": "2026-04-09T12:00:00Z",
"ice_servers": [
{ "urls": ["stun:turn.example.com:3478"] },
{
"urls": ["turn:turn.example.com:3478?transport=udp"],
"username": "u",
"credential": "p"
}
]
}
```
#### `POST /api/sessions/{room_id}/join`
加入会话
**请求**
```json
{
"join_token": "opaque-token"
}
```
**响应**
```json
{
"ws_url": "wss://app.example.com/ws",
"expires_at": "2026-04-09T12:00:00Z",
"ice_servers": [...]
}
```
#### `GET /health`
健康检查
### WebSocket 消息
统一格式:
```json
{
"type": "offer|answer|ice|ready|cancel|error|ping|pong",
"room_id": "8F4K2P",
"role": "sender|receiver",
"payload": {}
}
```
### DataChannel 消息
控制消息JSON
- `file_manifest` - 文件清单
- `chunk_ack` - 分块确认
- `transfer_complete` - 传输完成
数据面:`ArrayBuffer`(加密分块)
---
## 安全设计
1. 会话密钥只在浏览器生成和持有
2. 文件名和文件内容都加密
3. 服务端只看到 room_id、连接状态、粗粒度元信息
4. 不保存文件内容
5. 不保存传输历史
6. Redis 全部使用 TTL
7. 所有页面和 WS 强制 HTTPS/WSS
8. TURN 使用临时凭证
9. 前端在完成或取消后清空密钥和缓存
**加密方案**
- 会话密钥32 字节随机
- 密钥派生HKDF-SHA-256
- 分块加密AES-GCM
- 摘要校验SHA-256
---
## 前端页面
| 路由 | 说明 |
|---|---|
| `/` | 首页:发送/接收入口 |
| `/send` | 选文件、创建会话、展示二维码 |
| `/join/:roomId` | 扫码进入、确认接收、下载 |
| `/expired` | 会话失效提示 |
---
## Redis 设计
### Key 结构
- `session:{room_id}` - 会话元数据
- `presence:{room_id}:sender` - 发送端在线状态
- `presence:{room_id}:receiver` - 接收端在线状态
- `join_token:{room_id}` - 一次性加入令牌
- `ws:{connection_id}` - WebSocket 连接映射
### TTL
- 会话15 分钟
- 已完成会话:立即删除或保留 1 分钟缓冲
- WebSocket presence30-60 秒心跳续期
---
## 开发里程碑
### P0 原型
- 创建/加入会话
- WS 信令
- DataChannel 建立
- 文本消息互通
### P1 小文件传输
- 文件 manifest
- 分块发送
- 接收后下载
- 进度显示
### P2 安全闭环
- 会话密钥生成
- 文件名/内容加密
- 会话销毁
- Redis TTL 清理
### P3 稳定性
- TURN 兜底验证
- 异常断开处理
- 超时与取消
- Chrome / Safari / iOS 测试
### P4 上线
- Debian 部署
- HTTPS/WSS
- 基础限流
- 基础日志与监控
---
## 项目结构
```
filedrop/
├── Cargo.toml
├── plans/
│ └── phase1-architecture.md
├── server/
│ ├── src/
│ │ ├── main.rs
│ │ ├── config.rs
│ │ ├── api/
│ │ │ ├── mod.rs
│ │ │ ├── sessions.rs
│ │ │ └── health.rs
│ │ ├── signaling/
│ │ │ ├── mod.rs
│ │ │ ├── ws_handler.rs
│ │ │ └── room.rs
│ │ ├── session/
│ │ │ ├── mod.rs
│ │ │ ├── service.rs
│ │ │ └── store.rs
│ │ └── ice/
│ │ ├── mod.rs
│ │ └── config.rs
│ └── Cargo.toml
├── web/
│ ├── package.json
│ ├── tsconfig.json
│ ├── vite.config.ts
│ ├── index.html
│ └── src/
│ ├── main.ts
│ ├── api/
│ │ ├── session-api.ts
│ │ └── signaling.ts
│ ├── webrtc/
│ │ ├── transport.ts
│ │ └── ice.ts
│ ├── crypto/
│ │ └── crypto-client.ts
│ ├── transfer/
│ │ ├── file-transfer.ts
│ │ └── state.ts
│ └── ui/
│ ├── pages/
│ │ ├── home-page.ts
│ │ ├── send-page.ts
│ │ ├── join-page.ts
│ │ └── expired-page.ts
│ └── components/
│ ├── qr-display.ts
│ ├── file-picker.ts
│ ├── progress-bar.ts
│ └── status-indicator.ts
├── deploy/
│ ├── docker-compose.yml
│ ├── Caddyfile
│ ├── coturn.conf
│ └── filedrop.service
└── README.md
```
---
## 部署拓扑
最小部署:
- Caddy/Nginx
- axum app
- Redis
- coturn
域名建议:
- `app.example.com`Web App + API + WS
- `turn.example.com`TURN 服务
---
## 风险与注意事项
1. Safari 对 WebRTC/DataChannel、后台标签页较敏感
2. TURN 成本需监控,大文件应尽快切应用层密文中转
3. 浏览器内存占用,大文件必须按块处理
4. 断点续传复杂度不适合首版
5. 端到端加密需覆盖文件名和文件列表