kin · rendezvous
会合服务
它只做一件事:让两个都在 NAT 后面的朋友互相知道对方当前的外部地址。 之后它就无事可做了 —— 隧道是两台设备之间直接建立的,一个字节都不经过这里。
为什么需要它
kin 是朋友之间互相提供网络出口的 VPN。要让两台设备直接相连,双方必须 同时 知道对方此刻的外部地址,才能同时朝对方发包、把 NAT 上的洞打开。
麻烦在于:双方都在 NAT 后面,谁也不可达 —— 没有人能把这个地址直接递给对方。 所以需要一个在公网上的、双方都能连上的撮合方,把两张名片放进同一个抽屉里。 这就是这个服务,也仅此而已。
它看得到什么,看不到什么
✓ 它看得到
- 一个随机的一次性
token(配对码里带的,不含任何身份信息) - 一个公钥指纹和一个 base64 公钥
- 最多 16 个
ip:port候选地址 - 一个你自己填的显示名,比如「哥哥的台式机」
✕ 它看不到
- 你的流量内容 —— 它不在数据路径上
- 你访问了什么网站、流量去了哪里
- 你是谁:没有账号、没有注册、没有用户表
- 这次握手最后成没成 —— 打洞是两端之间的事
它不留什么
每条记录的 TTL 是 300 秒,到点自己消失。会合是短暂的,不该留痕。
它不记录客户端 IP,不写访问日志,没有分析脚本 —— 这一页连 JavaScript 都没有。 服务端的全部状态就是一个 KV namespace:没有数据库,没有队列,没有一个 secret, 因为它不需要知道任何需要保密的东西。
它也不能偷偷变成中继:这个服务只有一个端点,只收发 JSON, 不具备转发 UDP 的能力。流量要么直连,要么根本不通。
接口
两条,就这些。超额或畸形的输入一律拒绝。
POST /api/rv
→ {"token":"…","endpoint":{"peer_id":…,"pub_key":…,
"candidates":["203.0.113.7:51820"],"name":…}}
← 200 {"ok":true}
GET /api/rv?token=…&self=…
← 200 {"ready":true,"endpoint":{…}} // 该 token 下不是你自己的那条
← 200 {"ready":false} // 对端还没来,等一会儿再问
自己跑一个
这个服务是开源的,也刻意做得很小 —— 小到你可以读完全部代码,
然后部署成你自己的那一个:只需要一个 Cloudflare 账号和一条
wrangler pages deploy。
不用相信别人的会合服务,是这件事里最重要的一部分。