节点发现与加密多跳中继

AeroNyx9 分钟阅读

AeroNyx 节点如何通过签名描述符相互发现、维护一份被镜像的目录链,并逐跳转发分层加密的载荷。真实聊天默认使用中心化中继;两跳洋葱路由需主动开启。

AeroNyx 节点通过已签名且会过期的描述符相互发现,并能逐跳转发端到端加密的载荷,每个中继只剥除属于自己的那一层加密。目前,真实的用户聊天默认经过中心化的 AeroNyx 中继(RelayWS)。通过节点路由聊天是应用中需主动开启的设置。

目前运行的功能

功能状态
签名节点发现与节点间 gossip在生产节点上运行
目录链(按节点划分的签名描述符历史,在节点之间镜像)在生产节点上运行
节点之间的两跳洋葱中继在生产节点上运行。在应用中需主动开启,默认关闭
通过洋葱中继访问的匿名信箱在生产节点上可用。普通聊天不使用它们。应用另有一个测试版信箱投递功能
含三个中继跳的路由相关策略和探测已存在于节点源代码中。应用不使用它们
位于网关之后的节点所用的 https:// 主机名端点已包含在当前节点版本中
公共 API 端口上的身份绑定 TLS,无需域名,也无需证书颁发机构在生产节点上运行。当对等节点公布支持时,节点之间使用它。应用端的支持正在开发中
洋葱终端移交至接收方的中继收件箱在生产节点上运行
由运营者固定的种子(discovery.pinned_seeds)已包含在当前节点版本中
默认聊天传输由 AeroNyx 运营的中心化 RelayWS 服务

中心化路径和去中心化路径并行运行。

发现的工作方式

每个节点发布一个用其 Ed25519 身份密钥签名的描述符。描述符包括节点 ID、签发和过期时间、可选的公共端点、能力标志(例如洋葱中间中继或聊天中继)、粗略的容量提示,以及用于洋葱加密的密钥。节点会拒绝已过期或签名无效的描述符。

  • Gossip 有边界。 节点间交换受速率限制和策略管控,消息也有大小限制。
  • 重启恢复。 节点保留一个本地节点缓存,重启后会回退到配置的种子端点。运营者也可以固定种子。
  • 路由选择。 只有具备可用端点和洋葱密钥的新鲜描述符才会被视为中继候选。

描述符可以指定哪些端点

签名能证明是谁发布了描述符,但不能证明其端点可以安全访问。因此,节点只接受两种形式的端点:

  • 通过 http 或 https 访问的公网 IP 地址;环回、私有、链路本地、CGNAT、文档用途、组播和保留地址段均会被拒绝;
  • 带有公共 DNS 名称的 https:// URL。单标签名称、localhost 以及 .local、.internal 和 .home.arpa 等私有后缀均会被拒绝。

主机名在连接时通过一个会丢弃所有非公网地址的解析器进行解析,因此名称无法被指向节点自身、私有网络或云元数据服务。节点客户端还会忽略代理设置,并且从不跟随重定向。

之所以支持主机名形式,是为了让没有自有 IP 地址的节点(例如位于云网关之后的 TEE 节点)也能参与。

固定种子

如果一个节点在启动时没有运营者提供的快照,它只信任自己已持有的身份,因此最终可能只信任它自己。针对这种情况,运营者可以指定某个地址上应有的身份:

toml
[discovery]
pinned_seeds = ["<64-hex node id>@<public ip>:<port>"]
  • 只有在与该身份固定绑定的身份绑定 TLS 上完成一次交换之后,被固定的身份才会被首次接受。
  • 被固定身份此后的每一份描述符,无论来自何处,都必须保持固定的地址,并公布支持身份绑定 TLS。
  • 信任不会传递:种子应答中的其他描述符仍然只是不受信任的候选。
  • 被移除的固定项无法从旧缓存或备份中恢复。

目录链

每个节点还会为其自身的描述符事件保留一份已签名、以哈希链接的历史记录,称为该节点的目录链。其他节点可以镜像该历史记录、获取描述符对象,并为特定描述符请求包含证明。由运营者固定的节点可以对其所见的历史记录签署观察检查点。

不存在全局账本,也不存在单一协调者:每个节点签署自己的历史记录,其他节点负责镜像和检查。

身份绑定 TLS

通过 HTTPS 访问节点通常需要域名和由证书颁发机构签发的证书,而大多数 AeroNyx 节点只能通过 IP 地址访问。为此,节点改用自己的 Ed25519 身份来证明其 HTTPS 端点。

  • 工作方式。 节点创建一个普通的 ECDSA P-256 TLS 密钥和一份自签名证书。证书的某个主体备用名称携带一条绑定信息 aeronyx-tls-binding:v1:<node id>:<expiry>:<signature>,其中的签名由节点身份密钥对一个带域分隔的摘要生成,该摘要涵盖证书自身的公钥、节点 ID 和过期时间。TLS 1.3 握手证明节点持有证书密钥。身份密钥从不对握手进行签名。
  • 客户端检查什么。 验证方只会为其本来要访问的节点接受证书:恰好一条绑定信息、节点 ID 与预期一致、未过期、剩余有效期最多 31 天,并且对本证书的密钥有有效签名。由证书颁发机构签发的证书无法通过这项检查。
  • 同一端口。 公共 API 端口(8422/TCP)同时提供两种服务:以 TLS 握手开头的连接得到 TLS,其他连接照旧得到明文 HTTP。该功能默认开启(discovery.public_api_identity_tls)。
  • 节点之间。 已签名的描述符公布了协议特性 anpf1-ibt1 的节点会提供身份绑定 TLS。看到该特性的对等节点必须通过固定到该节点身份的 TLS 访问它,绝不会回退到明文 HTTP。该特性受描述符签名保护,因此网络攻击者无法将其剥除以强制降级。如果多个身份声称使用同一个端点,则不会生成 TLS 地址,请求会以失败告终。没有该特性的旧节点以及使用 DNS 名称的网关端点保持原有行为。
  • 参考。 源代码与固定的测试向量:aeronyx-node-tls。

其效果是,节点之间的洋葱跳路由信息、gossip、目录同步和见证流量不再能在线路上被读取。应用端连接节点的这种方式的支持正在开发中。

多跳中继的工作方式

  1. 发送方使用每个中继公布的洋葱密钥,为每一跳各包裹一层加密。
  2. 每个中继检查上一跳的签名、时间戳和重放状态,剥除自己的那一层,并转发剩余的不透明数据块。它从不会看到内层。
  3. 最终(终端)节点将消息移交给接收方的中继收件箱(默认为中心化中继),并且只有在该中继接受之后,才返回一份签名回执。该回执绑定了路由 ID、对载荷的承诺、终端节点的身份以及投递时间。它证明的是消息已被接受进入中继托管,而不是接收方已读取。关闭了移交功能的节点会把消息保存在自己的存储中,并签署同类回执,因此仅凭回执无法区分这两种情况。

各方能看到什么

参与方能看到看不到
入口节点发送方的网络地址、一个密封层和下一跳消息发给谁,以及消息内容
终端节点发送方和接收方的密钥以及密文发送方的网络地址,以及消息内容
中心化中继(接收移交)任何一次发送都会让它看到的内容:发送方和接收方的密钥、时间戳和大小发送方的网络地址,以及消息内容

没有任何单个节点能把你的网络地址与你在给谁写信关联起来。终端节点和中心化中继都能看到谁给谁写了信。

协议最多接受三个经过验证的中继跳。应用的隐私路由使用两跳。中继上的滥用限制见 盲中继滥用防护。

应用中的聊天

  • 默认: 消息经过中心化的 RelayWS 服务。消息内容经过端到端加密,但该服务会处理投递元数据。请参阅 聊天中继客户端集成。
  • 隐私路由(需主动开启,默认关闭): 开启后且路由已就绪时,应用会优先通过两跳洋葱路由发送一对一消息。如果没有任何洋葱路由接受该消息,应用会将其保留在设备上;除非你针对该条消息予以批准,否则不会改用标准中继。
  • 匿名信箱(测试版): 一个独立的投递功能,仅在连接到隐私网络时可用。普通对话不使用它。

匿名信箱拉取大小

过去,无论条目大小,一次信箱拉取结果都是一个固定的 163,130 字节的镜像,因此一条短消息要产生约 160 KiB 的响应。拉取版本 2 通过已签名的协议特性 anpf1-ampc1 协商,会把密封条目填充到五个大小档位中最小的那一档(4,204、16,492、65,644 或 131,180 字节,或编解码器允许的最大值)。现在,一个 4,096 字节的条目以 4,518 字节传输。

TEE 节点

有一个生产节点运行在 Phala Cloud 的可信执行环境(基于 Intel TDX 的 dstack)中。它只充当匿名信箱和洋葱中继:其 VPN 已禁用,MemChain 已关闭,其身份密钥来自 dstack 密钥服务。只能通过网关上的 TLS 主机名访问它,这也是新增主机名端点的原因。应用目前不验证该节点的 TEE 远程证明。

实时状态

网络汇总状态发布在:

text
GET https://api.aeronyx.network/api/privacy_network/vpn/public/network-stats/

中继和发现的汇总数据出现在 data.protocol_status 下,例如 peer_store.blind_relay 和 peer_store.peer_quorum。阅读时请注意两点:

  • 节点级汇总数据只统计最近 120 秒内有心跳的节点,因此离线节点会从 protocol_status.reported_nodes 等计数中移除。network.total_nodes 和 network.vpn_nodes 仍统计已注册的活动节点,无论是否在线。
  • 合成探测计数器(probe_*、two_hop_probe_*)衡量的是路径健康状况,不是用户流量。

公开响应只包含计数、状态分桶和时间戳。它从不包含节点 ID、端点、路由 ID、载荷、接收方、客户端 IP 地址、DNS 数据或社交图谱关系。请参阅 网络统计与隐私边界。

<!-- faq:start -->

常见问题

我的 AeroNyx 聊天消息会经过去中心化节点吗?

默认不会。消息经过中心化的 RelayWS 服务。你可以在应用中开启隐私路由,开启后,当路由就绪时,一对一消息会通过经过节点的两跳洋葱路由发送。如果没有任何路由接受某条消息,应用会保留该消息,直到有可用路由,或你批准通过标准中继发送该条消息。

中继节点能读取它转发的消息吗?

不能。中继只剥除属于自己的加密层,并转发一个不透明数据块。消息内容还在对话参与者之间进行了端到端加密。

什么是目录链?

目录链是每个节点自身描述符的已签名、以哈希链接的历史记录。其他节点会镜像它,并可以请求包含证明。它没有全局协调者。

位于网关之后的节点如何加入网络?

它可以发布一个 https:// 主机名作为其端点。其他节点在连接时解析该名称,并且只使用公网地址,因此该名称无法被重定向到私有或内部目标。

为什么公开统计页面显示的已注册节点数多于在线节点数?

network.total_nodes 和 network.vpn_nodes 统计已注册的活动节点,无论是否在线。请与 network.online_vpn_nodes 对比。协议和转发计数只包含心跳新鲜的节点。

节点的 HTTPS 需要域名或证书颁发机构吗?

不需要。节点可以用自己的身份密钥证明其 HTTPS 端点:其 TLS 证书携带节点身份对证书密钥所作的签名,知道节点 ID 的客户端或对等节点即可验证。位于网关之后的节点仍然可以改用 https:// 主机名。

签名的投递回执证明了什么?

它证明终端节点已将消息接受进入中继托管,实际上就是接收方的中继收件箱。它不能证明接收方已经看到或读过该消息。如需此类证明,请使用聊天协议的送达回执和已读回执。

<!-- faq:end -->