安全设计
它凭什么敢在你家 Wi-Fi 里传文件
这一页讲它怎么守住你的文件: 三把钥匙、两个开关、以及手机那头到底能看到什么。 看完你会知道该怎么按场合挑设置。
先记住这一句
兔本本快传在你电脑上开一个局域网 HTTP 服务, 监听所有网卡(0.0.0.0)。 安全边界完全由凭据保证,不由绑定地址保证 —— 「连着同一个 Wi-Fi」本身不是一道门。
三把钥匙
凭什么认出来「这部手机可以用」
三条独立的路径,有效期和用途都不一样。
① 启动令牌
每次启动应用都会重新生成。 二维码里带着它(前提是没有密码)。 重启之后,上一次扫出来的链接一律失效。
这是最短命的一把:只在本次运行里有用。
② 6 位密码
不随启动轮换,自动生成 6 位数字。 想换只能手动重置 —— 「保持不变才方便」。
⚠️ 有密码的时候,令牌不再是入口凭据: 二维码里不带令牌,扫码也要输密码。
③ 设备凭据
给以后可能有的手机 App用: 配对成功一次,30 天内不用再扫。
⛔ App 现在还不可用(依赖未装、从未构建)。 这条路目前是地基,不是功能。
设备凭据是唯一一处「安全姿态被降低」的改动
前两把钥匙的边界是「这次运行」或「这次配置」, 设备凭据把边界拉长到 30 天。 这不是「又加了一道防线」,而是把防线拉长了 —— 我们把它单独写出来,不混在「新增功能」里。
配套约束:设备凭据不享受免确认 —— 永远要在电脑上点一次「允许」;电脑上那个「重置令牌」按钮 会一并吊销全部设备,否则它写着「断开所有手机」就是假的。
两个开关
「密码」和「电脑端确认」是叠加的,不是互斥的
pinEnabled 管第一道(要不要输那 6 位数字), autoAccept 管第二道(要不要在电脑上点「允许」)。 两个都是独立开关,四种组合都成立。
| 密码 | 自动接受 | 几道门 | 扫码之后会怎样 | 适合 |
|---|---|---|---|---|
| 开 | 关 | 两道 | 输密码 → 电脑上点「允许」 → 连上 | 家里来客人、公司 |
| 开 | 开 | 一道 | 输密码 → 连上 | 自己家、自己手机 |
| 关 | 关 | 一道 | 电脑上点「允许」→ 连上 | 临时用、不设密码 |
| 关 | 开 | 零道 | 直接连上 | 只在你完全信任这个 Wi-Fi 时 |
最后一行是「零门槛」,不是「更方便」
密码关、自动接受开 —— 同一局域网里的任何设备,扫到码就能传文件进来。 桌面设置里对这一档有红字警示。在家用默认设置(两道门)就够了; 在外面、在公司,不要开这一档。
「有几副面孔」和「有几道门」是两回事
手机配对页是密码框还是敲门按钮, 只由「密码开不开」决定 —— 两副面孔永远互斥,不会同时出现。
而「有几道门」是密码和自动接受叠加算出来的(见上表)。 别把这两件事搞混:门是几道,脸是一张。
那个 6 位密码
它到底有多强
100 万种组合。我们不把「6 位」说成「很安全」。
它挡得住什么
随手试。 同一局域网里有人瞎点、误连、拿着旧链接想碰运气 —— 挡得住。
配合限流,连错几次就锁一小会儿,也挡得住「死循环猜」。
它挡不住什么
铁了心要试的人。 6 位数字只有 1 000 000 种组合,理论上限就在那。
还有:能看到你电脑屏幕的人 —— 密码和二维码印在同一块屏幕上,他两个都读得到。 这个密码挡的是「只拿到链接 / 截图、看不到屏幕」的人。
| 限流桶 | 上限 | 作用 |
|---|---|---|
| 同一来源 IP · 令牌桶 | 20 次 / 60 秒 | 防单台设备狂发请求 |
| 同一来源 IP · 密码桶 | 5 次 / 10 分钟 | 防单台设备狂试密码 |
| 跨 IP · 密码桶 | 60 次 / 5 分钟 | 防多台设备分摊着试 |
所有限流都按来源 IP 分桶,不退回全局单计数器 —— 否则任何一台设备连错几次,就能把所有手机一起锁死。 ⚠️ 已知副作用:IPv6 会被压到 /64, 同一局域网走 IPv6 的设备共用那几格。
密码只存在你自己电脑上
存在本机的设置文件里,不上传、不同步、不进任何云端。 原因很直白:它必须显示在屏幕上给你看, 加密了也得能解出来显示,那就不是加密。
影响面:拿到你电脑上那个设置文件的人能读到它。 我们不假装这是银行保险箱,只说它挡什么、不挡什么。
手机那头能看到什么
说清楚「下发」和「回传」的区别
会下发到手机的
- ✅ 你自己显式添加过的目标文件夹: { id, 备注, 真实路径 }
- ✅ 这批文件的落盘预览(目录名会叫什么)
- ✅ 端点配置(分块上限、阈值等传输参数)
⚠️ 真实路径包含你的用户名和目录结构。 这是为了消歧(两个文件夹可以重名)而做的主动取舍, 已登记为一处「为可用性降低信息隔离」的改动。
绝不会下发 / 绝不会回传
- ⛔ 默认保存目录 saveDir 不发
- ⛔ 手机只显示、不回传任何路径 —— 回传的只有不透明的 id
- ⛔ 免认证的那五个门里,一个字节的路径都不含
- ⛔ 文件内容不上传到任何外部服务
所有带路径的接口都要求已认证会话。 「能看到路径」= 拿着有效凭据的浏览器,不是「网上任何人都能」。
怎么用最省心
在家里用,它就是最顺手的那个
兔本本快传走的是局域网直连: 文件从手机直接走到电脑,不绕任何服务器。 所以在自己家的 Wi-Fi 下用,又快又省事。
- 在家:随便传。 路由器是你的、网络是你的。 照片、视频、文档,想传多少传多少,没有账号、没有限速、没有「本月流量用完」。
- 在外面:连自己的手机热点。 公司、咖啡厅、酒店、学校宿舍这些地方人多网杂。 想在外面传,开手机热点让电脑连上来,就和在家一样放心。
- 为什么选局域网直连。 不上云、不托管、不排队。 传多快取决于你家路由器,不取决于谁的服务器; 而且文件一个字节都不出你的门。
家里用默认设置就很好。到外面,换个网络,和在家里一样简单。
常见误解
「连着同一个 Wi-Fi」不是一道安全门
事实是
服务监听 0.0.0.0, 接受来自局域网内任意设备的入站连接。 这是本项目与「纯本地应用」最大的不同。
咖啡厅的 Wi-Fi、公司的 Wi-Fi、宿舍的 Wi-Fi, 在这个模型下都算「同一局域网」。 门不在网络上,门在凭据上。
所以
别把「在家用着挺好」理解成「在哪都行」。 出门前想一想:这条网络里,有没有你不认识的设备?
真要跨网络传,那是另一个产品形态(要公网、要域名、要 TLS), 不是这个工具。
免认证面
有五个门不需要凭据,每一个都有理由
我们把它们数出来写在官网上,而不是让你去猜。 如果哪天变成六个,这一页该跟着变。
| # | 门 | 它需要免认证的理由 |
|---|---|---|
| 1 | 入口页 GET /(配对入口) | 手机还没拿到凭据,这一步就是为了拿凭据 |
| 2 | 配对模式 GET /api/pair/mode | 让手机决定显示密码框还是敲门按钮;不含任何用户数据 |
| 3 | 发起配对 POST /api/pair | 交密码 / 等允许的那一步;密码校验在建队列之前 |
| 4 | 配对状态轮询 GET /api/pair/status | 手机等电脑点「允许」时轮询用;只回自己的状态 |
| 5 | 手机静态资源 /m/* | 页面本身必须能打开,否则配对都无从谈起 |
五个,不是四个,也不是六个。 每一个的职责都写在项目内部的接口契约文档里。 超出这五个的任何接口,都要求已认证会话。
认证先于处理
每一个需要凭据的接口,第一句就是验凭据 —— 验完才看请求体、才碰磁盘。 这条顺序不是「我们记得这么做」,而是被验证脚本盯着的硬性质。
你的数据去了哪
纯本地。唯一的出站,默认是关的。
不会出去的
- ✅ 你传的文件 —— 直接落在你指定的文件夹
- ✅ 设置、密码、目标文件夹配置 —— 本地 JSON
- ✅ 去重账本 —— 本地 JSON
- ✅ 没有分析、没有统计、没有崩溃上报
- ✅ 没有账号体系,也就没有「上传到你的账号」
唯一一条出站
手机页更新通道:电脑出站拉取一个已签名的手机页资源包。
三个硬约束:
- 默认关闭 —— 没配更新源就功能不可用,而且不出网
- 验签后落盘 —— 拉回来的东西只被当静态文件发给手机
- 永不 require / eval / import —— 被投毒的内容也只能在手机的浏览器沙箱里跑,碰不到电脑
⛔ 生产签名密钥目前未生成,信任表是空的 —— 空表等于一律验不过。这是安全的方向。
能力一览
现在就能用的,和我们特意这样设计的
上半是你今天就能用上的能力; 下半是我们特意这样设计的取向 —— 让它保持简单、保持本地。
① 现在就很好用
- 扫码用浏览器传,手机不装 App
- 同名文件自动改名,绝不覆盖
- 存到你指定的文件夹,带日期与备注
- 大文件分块、断了能续(同一运行内)
- 相册按时间 / 类型归档
- 选完先看图 / 看视频再传
- 被时间筛掉的文件看得见、捞得回
- 传过的内容可以跳过(需开启去重)
② 还在路上 / 未验证
- Windows 实机验证 —— 从未在 Windows 上跑过
- 代码签名 —— 未做,SmartScreen 可能拦
- macOS 官网测试版 —— 无 Developer ID 签名、未公证;首次安装仍需验收
- 传输加密(HTTPS / TLS)
- iOS 息屏后继续传
- 手机 App(依赖未装、从未构建)
- 相册同步的真机表现(HEIC / 视频编码 / 几千行内存)
③ 我们特意这样设计
- 只做 手机 → 电脑这一个方向
- 没有账号、没有云端存档
- 不保存传输历史(内存、200 条、关掉即清)
- 应用本体不做自动更新
- 不碰你手机上的文件(不会自动删)
逐条对照
| 能力 | 现在的真实状态 | 为什么 |
|---|---|---|
| 手机 → 电脑 传文件 | 已实现 | 核心功能。扫码、选文件、落盘,全链路在跑。 |
| 电脑 → 手机 传文件 | 专注一个方向 | 定位是「手机内容的出口」,把手机→电脑这一条做顺。 |
| 手机不装 App | 已实现 | 扫码打开的是完整功能的网页。不装 App 也能传完。 |
| 手机 App(长期凭据) | 在做了 | 服务端地基已打(30 天设备凭据),但 app/ 依赖未装、从未构建。 |
| 局域网内传输 | 已实现 | 同一 Wi-Fi 直传,不经过任何第三方服务器。 |
| 跨网络传输(人在外面连家里) | 专注局域网 | 需要公网入口与 TLS,是另一个产品形态。在家 / 连自己的热点就够顺。 |
| 大文件分块续传 | 已实现 | 同一运行内断点续传;重启应用会清暂存。 |
| iOS 息屏后续传 | 未验证 | 机制在(服务端 60 秒停滞看门狗),真机表现没测过。 |
| 同名文件保护 | 已实现 | 自动改名 xxx (1).jpg,绝不覆盖。 |
| 按拍摄时间归档 | 已实现 | EXIF / 容器元数据;取不到会回退并标「推测」。 |
| 内容去重(跳过已有) | 已实现 | 需在电脑上开启;默认关。判据是内容指纹。 |
| 传输加密(HTTPS) | 在做了 | 现在是局域网直连,文件不出家门。见上文使用建议。 |
| 代码签名 | 测试版未签名 | Mac 测试版没有 Developer ID 签名、未公证。首次打开可能被拦,见安装指引;不是 Apple 已审核的应用。 |
| Windows 安装包可用 | 未验证 | 只证到「能在开发机上产出 .exe」,从未在 Windows 真机执行。 |
| 自动更新(应用本体) | 不做 | 只有手机页有更新通道,且默认关闭、签名密钥未生成。 |
| 云端存档 / 账号 | 不做 | 设计取向:文件一个字节都不出你的电脑。 |
| 传输历史 / 回看 | 不做 | 内存、上限 200 条、关掉即清。文件本身是留下的。 |
标签各有含义:已实现 是已经在跑的机制; 在做了 / 正式版会做 是我们正在补上的; 未验证 是代码在但真机没验过; 设计取向 是我们特意这样选的,不是没做完。
我们的口径
每一项能力,都实测过才写进来
页面上列出的每一项,都是在真实环境里跑通过的。 没跑通的不写,跑通了才会出现在你面前。
- 已验证 = 在真实环境跑过并取到证据。 比如传输停滞看门狗:在进程外跑过 22 条取证 + 负控, 能明确说出「60 秒内一个字节都没有就会被判死」。
- 已实现、未验证 = 代码在,但我们不知道真机上会怎样。 比如 iOS 息屏后续传、HEIC 缩略图、视频编码兼容、 几千行的真实内存占用。这些只有你拿着真手机才能确认。
- 我们禁止自己写的词。 「基本上没问题」「理论上可以用」「应该可以」「一般不会」—— 这些词在我们这里是禁用的。 要么「已验证」,要么「未验证,我们不知道」。
这一页所有「未验证」的条目,都等着你去验。 验出来了告诉我们可以;验出问题更要告诉。