← 返回 README · 简体中文 | English
部署者能看到什么、不能保证什么。 只用标准 SSH 就做不到端到端加密:SSH 的加密在服务器这一端就解开了,聊天室程序必须看到明文才能转发消息,而部署者拥有服务器的 root 权限。本项目能做的,是让程序尽量不留下任何东西,并让用户可以自己核实这一点:
-
用户在聊天室里输入
/privacy,就能看到这台服务器实际运行配置下的数据政策:消息保留多久、封禁是否持久化、有没有开 Tor、管理员能做什么。 -
输入
/forget,立即从服务器的房间历史中删除自己本次连接发过的所有消息。 -
消息只在内存里,过期自动删除;日志里没有 IP、昵称或消息内容;systemd 禁止生成核心转储(
LimitCORE=0),程序崩溃时内存里的聊天内容也不会被写到磁盘。 -
代码开源,Release 由 GitHub Actions 从公开源码构建并附带 SHA256SUMS。但用户无法从远端验证某台服务器跑的就是未经修改的版本,所以最终仍取决于你是否信任部署者。不要在这里发送任何能识别身份的信息。 想对部署者也隐藏 IP,请使用 Tor。
-
SSH 只加密传输,不是端到端加密。 服务器进程能读到消息内容,每次进入都会提醒。
-
不提供 Shell。 没有 exec、SFTP/SCP、端口转发、代理转发、X11。CI 会在真实服务器上验证这一点。
-
不记录 IP。 日志里没有 IP、昵称或消息,第三方库写的日志也会统一过滤掉地址字段。限流和封禁使用“IP 的 HMAC”,密钥只在内存里,每次重启都换;IPv6 按 /64 归并。健康检查接口只返回计数。
-
客户端根本不会发送公钥。 正常情况下,SSH 客户端会把你电脑上的公钥逐个“出示”给服务器。GitHub 上每个人的公钥都是公开的,服务器拿来一比对就能认出你是谁。本服务在 SSH 认证的第一步(
none)就放行普通用户,客户端还没走到出示公钥那一步。只有admin用户名才会进入密钥认证。可以用ssh -v验证:输出里是Authenticated ... using "none",没有Offering public key。CI 里也有对应的测试。 -
封禁持久化是可选的,而且有代价。 默认情况下,计算地址哈希用的密钥只在内存里,磁盘上没有任何能和地址关联的东西,但重启后封禁也会消失。开启
--persist-bans后,这个密钥会和封禁列表一起保存在/var/lib/vivant/(权限 0600,只有服务进程能读),磁盘上只有被封禁地址的哈希,没有 IP,也不涉及其他用户。风险是:如果有人同时拿到了这两个文件,可以穷举 IPv4 地址,反推出被封禁者的 IP。看重匿名性就保持默认关闭。另外,服务启动时如果已经没有仍在生效的封禁,会换一把新密钥,旧密钥(以及它的任何备份)对过去的封禁记录就没用了。 -
消息不落盘。 每个房间只在内存保留最近 500 条、最长 24 小时(私人房间最多 100 条),服务器重启即清空;私人房间清空即销毁;私聊不保存。
-
终端注入防护。 昵称和消息里的控制字符(因此所有 ANSI/OSC/DCS 转义序列,包括读写剪贴板的 OSC 52、让终端回报光标位置的
ESC [6n)、Unicode 双向覆盖字符、零宽空格之类的隐形字符、可以藏一段看不见文字的 Unicode “标签”字符一律剔除;表情组合和波斯语、印度诸文字需要的零宽连接符保留。有测试遍历控制字符、格式字符和标签字符所在的全部码位,确认没有一个能留下来(cargo test,CI 每次都跑)。 -
只用现代 SSH 算法。 密钥交换只接受 mlkem768x25519(抗量子混合)、curve25519 和 ECDH;去掉了 SHA-1 和有限域 Diffie-Hellman(后者在用户认证前就要做 2048–4096 位模幂运算,最容易被用来消耗服务器 CPU)。MAC 不再接受 hmac-sha1。近十年的 SSH 客户端(OpenSSH 6.5+、PuTTY 0.68+、Termius、iSH)都支持。
-
防滥用。 每个地址最多 3 个会话、8 个 TCP 连接、每分钟 10 次新连接;每个连接每秒最多收 32 KB,超出的数据会被放慢(防止有人灌垃圾数据消耗 CPU);消息令牌桶(突发 5 条、每秒 1 条);重复消息拦截;频繁超限自动禁言。不发言挂机、手机锁屏都不会被断开(
-idle-timeout可设上限,默认 0);对方真正掉线时,系统约 15 分钟后关闭连接、释放名额。 -
握手超时与总连接上限。 连上来 30 秒内没有进入聊天的连接(端口扫描器、卡住的握手)会被断开,不会一直占着连接名额。另外全服务器的 TCP 连接总数有上限(会话上限的 2 倍再加 500),来自大量不同地址的连接洪水也耗不尽文件描述符。
-
设计原则:口令在聊天界面里问,不在 SSH 认证层问。 如果将来要做需要口令的私有实例,会先用
none认证放行连接,再在聊天界面里输入口令。原因是:SSH 服务器一旦不放行none认证,客户端就会先把本机所有公钥逐个出示给服务器,用户的身份就暴露了。ssh-chat 的整站口令和 sshoosh 的邀请令牌都在认证层索取,本项目不这样做。 -
Tor 洋葱服务(可选)。 普通连接下,VPS 和云服务商仍然能看到来源 IP,这在应用层无法消除。安装时加
--tor,聊天室会同时发布为.onion地址:通过 Tor 进来的用户,服务器只能看到“来自 Tor”,看不到真实 IP。代价是这些用户无法按地址封禁(/ban会改为踢出),他们共用一组更宽松的限流额度。
即使部署者没开洋葱服务,用 Tor 浏览器直连也可以:服务器会定期下载 Tor 官方公开的出口节点列表,经出口节点连进来的人共用一组宽松的限额,不会因为“同一个 IP 已有 3 人”被挡在门外(有的同类项目拿同一份列表来拒绝 Tor 用户,我们反过来用)。下载这份列表不涉及任何用户信息;部署者可以用 VIVANT_TOR_EXITS=off 关闭。
普通连接下,VPS 和云服务商能看到来源 IP。部署时加 --tor 会同时发布 .onion 地址,用户通过 Tor 连接时,服务器看不到真实 IP。部署方法见部署与配置,用户怎么连见连接与使用。