把一段文本、一个文件或一段密钥串,用一次性链接交给别人;取一次即销毁。反向也行:开一个带输入框的收件口,让对方把内容投递进来,你取走后即销毁。
它解决的是"私密数据只交接一次"这个场景:不想把凭据留在聊天记录里,也不想开一个需要注册登录的共享空间。链接本身就是凭据,拿到链接即可取件,无需账号。
- 一次性:取件即销毁。状态迁移在 bbolt 写事务内完成,并发下恰好一个成功。
- 路径即凭据:token 由 32 字节 CSPRNG 生成,base62 编码为 43 字符,不可枚举。
- AES-256-GCM 静态加密:内容加密后落盘,密钥文件
<data>/key权限 0600。磁盘被拿走也读不出内容。 - 库内只存 token 哈希:数据库里只有
sha256(token),不存明文 token。 - 到期自动清理:内置 sweeper 默认每 60s 把过期链接置为 expired 并删除内容。
- 审计只记元数据:
ts、link_id、event、kind、name、size、ip_hash、result;不含内容与 token。 - 单二进制、无中间件:Go 标准库
net/http+ 纯 Go 的 bbolt,无 web 框架、无外部依赖服务。
需要 Go 1.24 及以上。
# 终端 A:启动服务。DROP_API_KEY 是引导用的 API Key,会被登记入库,CLI 侧也用它鉴权。
DROP_API_KEY=dev-secret-key go run ./cmd/drop serve# 终端 B:创建一条一次性文本链接,stdout 打印链接。
DROP_API_KEY=dev-secret-key go run ./cmd/drop put --text "hello" --ttl 1h服务默认监听 127.0.0.1:18960,数据目录 ./data。首次启动会生成管理员账号 admin 与随机口令并打印一次(如不想随机,可先设 DROP_ADMIN_PASSWORD)。
docker compose up -d仓库根目录的 docker-compose.yml 会把本机 ./data 挂到容器的 /data,并监听 127.0.0.1:18960。镜像可用 make docker 或 docker build -t drop:latest . 单独构建。
除 serve 外,所有子命令都通过 REST 直连 DROP_SERVER(默认 http://127.0.0.1:18960)。需要鉴权的子命令从 --key-file、DROP_API_KEY 或 DROP_API_KEY_FILE 读取 API Key;明文 Key 不要写进命令行参数。
# 创建出站链接:文件、stdin 或直接文本
drop put ./report.pdf --ttl 2h --name 报告
drop put - --ttl 30m < secret.txt
drop put --text "一次性口令" --ttl 1h
# 创建入站投递链接(带输入框的收件口)
drop req --ttl 1h --name 回执
# 取件:默认输出到 stdout,也可落盘(文件权限 0600)
drop get https://drop.example.com/d/<token> --stdout
drop get <token> -o report.pdf
# 查看链接元数据
drop ls --limit 20
drop ls --json
# 撤销链接(置 revoked 并删除内容)
drop rm <id>
# 查看审计(只含元数据)
drop audit --limit 50
# API Key 管理;明文 Key 只在创建时打印一次
drop key create ci
drop key list
drop key revoke ci
# 重置内置管理员口令(新口令只打印一次)
drop admin reset-password --user admin
# 版本
drop versiondrop ls 输出示例(列:ID / 类型 / 状态 / 名称 / 大小 / 到期):
ID 类型 状态 名称 大小 到期
01M4TP7J16F1QJV98DPDHCFSPB out active 自检 11 2026-10-13T21:16:34+08:00
drop audit 输出示例(列:时间 / 事件 / 链接 / 类型 / 结果):
时间 事件 链接 类型 结果
2026-10-13T21:11:34.469617029+08:00 created 01M4TP7JA5VXXHNDTEX19NWP7W in ok
环境变量提供初值,serve 的命令行 flag 覆盖同名配置。所有项都有默认值。
| 环境变量 | flag | 默认值 | 说明 |
|---|---|---|---|
DROP_ADDR |
-addr |
127.0.0.1:18960 |
监听地址 |
DROP_DATA_DIR |
-data |
./data |
数据目录 |
DROP_BASE_URL |
-base-url |
http://127.0.0.1:18960 |
生成链接用的外部地址(生产填 https 域名) |
DROP_AUTH_MODE |
-auth-mode |
builtin |
builtin 或 sso |
DROP_MAX_SIZE |
-max-size |
25m |
单次提交/上传上限 |
DROP_DEFAULT_TTL |
-default-ttl |
1h |
默认有效期,上限 7d |
DROP_SWEEP_INTERVAL |
-sweep-interval |
60s |
过期清理间隔 |
DROP_TRUST_PROXY |
-trust-proxy |
0 |
置 1 才信任 X-Forwarded-For |
DROP_WEBHOOK_URL |
-webhook-url |
空 | 非空才发事件回调(只含元数据) |
DROP_LOG_LEVEL |
-log-level |
info |
debug / info / warn / error |
DROP_KEY_FILE |
-key-file |
<data>/key |
内容加密密钥文件路径 |
DROP_ADMIN_USER |
无 | admin |
内置管理员用户名 |
DROP_ADMIN_PASSWORD |
无 | 空 | 首启预置管理员口令,空则随机生成并打印一次 |
DROP_SERVER |
无 | http://127.0.0.1:18960 |
CLI 直连的服务地址 |
DROP_API_KEY |
无 | 空 | CLI / serve 引导用的 API Key |
DROP_API_KEY_FILE |
无 | 空 | API Key 文件路径(CLI 侧) |
体积支持 512k / 25m / 1g(二进制单位,1m = 1 MiB);有效期支持 30m / 2h / 7d,上限 7d。
数据目录内容:
<data>/drop.db bbolt 数据库(0600)
<data>/key 内容加密密钥(0600)
<data>/admin.json 内置账号(bcrypt 摘要,0600)
<data>/blobs/<id> 加密后的内容文件
key 丢失后已加密内容无法恢复,备份时请一并保留。
deploy/ 下有可直接改用的样例:
deploy/drop.service:systemd 单元。ExecStart为/opt/drop/drop serve -addr 127.0.0.1:18960 -data /var/lib/drop,Restart=always、NoNewPrivileges=yes、PrivateTmp=yes、LimitNOFILE=65535,并从-/etc/drop/drop.env读取环境变量。deploy/nginx.conf.example:反向代理样例。对外只暴露 HTTPS,回源到127.0.0.1:18960。
反向代理要点:
- 只让应用监听回环,由反代终结 TLS 并对外。
- 生产把
DROP_BASE_URL设为对外 https 地址,否则打印出来的链接指向 127.0.0.1。 - 反代日志必须对
/d/<token>、/r/<token>做脱敏,样例里log_format已把这两类路径统一记为/d/(redacted)、/r/(redacted)。 /healthz只对回环与内网放行。- 确实位于可信反代之后时才设
DROP_TRUST_PROXY=1,否则按 socket 对端 IP 限流。
示例统一使用 drop.example.com / 127.0.0.1,部署时替换成自己的域名即可。
默认 AUTH_MODE=builtin:自带账号密码,首次启动生成管理员账号。设 DROP_AUTH_MODE=sso 即关掉自带入口,身份与未授权时的跳转、401 由服务前面的认证层决定。
- 取件动作是 POST,不是 GET。邮件/IM 网关、浏览器链接预览与安全扫描会预取 GET;页面先 GET(无副作用),点按钮再 POST 取件,避免链接被"用掉"。
- 无效链接统一 404。未知、过期、已用、已撤销返回同一状态码与逐字节相同的响应体,不泄露"这条链接曾经存在过"。
- 日志不记 token 与内容。访问日志里
/d/<token>、/r/<token>统一记成/d/<redacted>、/r/<redacted>,不打印 query 与请求体;debug级别也不打 token 与内容。 - 静态加密。内容用 AES-256-GCM 加密后落盘,取件成功后立即删除内容文件。
- 响应头。
Cache-Control: no-store、Referrer-Policy: no-referrer、X-Robots-Tag: noindex、X-Content-Type-Options: nosniff与严格 CSP;取件页不引任何第三方资源。
MIT,见 LICENSE。