换手机后的第一次登录,正是只走 VPN 的保险库显露代价的时刻:应用没有缓存,服务器在隧道后面,而隧道的凭据可能就在你打不开的保险库里。这是设计问题,不是故障,在部署前回答比部署后回答更便宜。三个条件决定私有保险库对用户是否可行。只要其中任何一个不成立,正确的答案通常是把暴露面收窄,而不是筑一道 VPN 墙。

条件 1:用户在第一天就能到达服务器

新设备没有缓存、没有会话,也没有信任。它需要解析服务器的主机名、找到通往它的路由,并且在用户尝试登录之前就安装好 VPN 配置。如果这三件事里有任何一件要等到首次登录之后才到位,部署就会在最糟的时刻失败。数一数新员工要完成多少步骤,才能打开自己的保险库。

分流隧道通常更合适:只承载保险库的端点以及它需要的 DNS 路径,剩下的用户流量照旧。这是要与 VPN 所有者一起做的路由决策,而不是假定每个移动客户端都遵守同一套策略。两种地址族和服务的主机名都必须与这个选择一致。

如果用户在拿到可用凭据之前到不了服务器,这个条件就不成立,VPN 墙的形状也就错了。

条件 2:缓存访问是只读的,而这已经够用

Bitwarden 客户端无需连接服务器就能显示已经解锁的保险库,而那份离线副本是只读的。它适合在故障期间读取密码;它不是新的登录,也不是编辑。在设计方案之前,先决定只读对你的用户是否可接受。

curl -sI https://vault.example.com/alive
openssl s_client -connect vault.example.com:443 -servername vault.example.com </dev/null

锁定和登出是不同的状态,这里的差别很重要。锁定的客户端保持本地保险库加密,并可用主密码或生物识别再次解锁;登出会删除那份本地副本,并且需要服务器。如果支持脚本让用户登出再登录来修复同步问题,它同时也带走了他们的离线访问。逐个检查客户端上的超时动作,不要假定默认值。

缓存副本不是备份。它只活在一台设备上,绑定一个账户,登出或抹除就会消失。

条件 3:恢复不经过保险库本身

循环情形很容易无意中造出来:VPN 凭据存在保险库里,保险库在 VPN 后面,而唯一有缓存的设备正是丢失的那台。这时恢复就取决于系统之外的文档或人。把那条引导路径写下来,并在有人需要之前用可恢复的账户测试它。没人演练过的应急流程只是希望。

以受控方式测试整个顺序:先确认哪些现有条目离线仍可读,再恢复网络路径,验证新的登录和同步都能工作。除非另有一条退路,不要把登出唯一缓存副本当作实验。记下你观察到的结果,包括客户端版本。

如果恢复需要保险库,这个条件就不成立。解决办法是记录在案的带外路径,而不是入职文档里更严厉的警告。

无论如何都要保留的:HTTPS、备份和更新

即使放在 VPN 后面,HTTPS 仍然保留。它给 Web 服务一个浏览器可以校验的身份,并让应用连接的保护不依赖隧道在何处终止。私有端点不该教用户点掉证书警告,因为这种习惯会跟着他们去公开网站。

备份是与可用性分开的一门功课。Vaultwarden 把数据存在数据库里,在服务停止时取一份一致的副本,或者做数据库层面的备份,比从运行中的进程里复制文件更有价值。把副本放在保险库主机之外,并测试恢复。导出的保险库材料需要与原件同样的保护,因为导出并不像服务器存储那样加密。

sqlite3 /data/db.sqlite3 ".backup '/backup/vault-2026-11-03.sqlite3'"
docker compose ps

然后让服务器和客户端保持更新。只走 VPN 能减少暴露,但不会让有漏洞的实现变无害,也保护不了已被攻破的端点。三个条件决定访问模型,而维护决定这个模型能不能撑过这一年。

相关文章