盲中继滥用防护
AeroNyx 节点如何在不读取密文的前提下抑制重放、循环、速率滥用与故障 peer,并提供隐私安全的运营证据。
盲中继滥用防护是 AeroNyx 去中心化密文转发的安全边界。它限制恶意或不稳定的中继行为,但不解析密文、不建立持久路径历史,也不让节点运营者变成流量观察者。
状态与范围
防护已在 Rust 实现,聚合结果会通过节点健康 metadata 与 Nodeboard 显示。它只负责控制风险并提供诚实证据:显示不透明中继工作是已接受、受防护、降级或过期,而不透露密文内容。
| 控制项 | 状态 |
|---|---|
| Blind payload forwarding | 已实现 |
| Signed freshness and replay suppression | 已实现 |
| Previous-hop rate limiting and quarantine | 已实现 |
| Privacy-safe runtime evidence | 已实现 |
| Nodeboard operator visibility | 已实现 |
| Plaintext or payload inspection | 禁止 |
| User, route, or social-graph analytics | 禁止 |
盲节点不变量
中继可以验证路由 metadata 的签名、执行有界策略、转发不透明 envelope,并返回 terminal 签名 receipt;但不能检查或推导 payload,也不能公开足以重建路径、用户身份或社交关系的 metadata。
- 消息明文、数据包 payload、媒体内容或 MemChain 明文
- DNS 内容、目的地、域名、URL 或浏览记录
- route ID、完整路径、endpoint URL 或 client 公网 IP
- 完整公钥、receiver 身份、message ID 或社交图谱边
- 私钥、voucher secret、wallet-level 流量或解密材料
准入处理流程
每个请求在占用转发容量前都要经过有界检查。以下是概念顺序;所有判定只使用已签名路由 metadata 与本地聚合状态,不使用解密内容。
verify signed previous_hop and envelope
apply in-flight backpressure
check timestamp freshness
check route replay cache
apply previous-hop rate/quarantine decision
validate TTL, loop safety, next-hop descriptor, and endpoint
forward opaque ciphertext or terminate into pending store
重放与时效防护
重放抑制仅存在本机、保存期短且容量有界。签名 envelope timestamp 会拒绝过期或不合理的未来 frame。下表是当前 main 的运行时默认值,不是永久协议承诺;调整时必须同步测试与文档。
| 运行时常量 | 当前默认 |
|---|---|
MAX_BLIND_RELAY_SEEN_ROUTES | 8192 route IDs |
BLIND_RELAY_ROUTE_REPLAY_WINDOW_SECS | 600 seconds |
BLIND_RELAY_PREVIOUS_HOP_RATE_LIMIT | 120 requests / 60 seconds |
BLIND_RELAY_PREVIOUS_HOP_FAILURE_THRESHOLD | 12 scored failures / 300 seconds |
BLIND_RELAY_PREVIOUS_HOP_QUARANTINE_SECS | 300 seconds |
MAX_BLIND_RELAY_PREVIOUS_HOP_BUCKETS | 4096 buckets |
BLIND_RELAY_MAX_ENVELOPE_AGE_SECS | 600 seconds |
BLIND_RELAY_MAX_FUTURE_SKEW_SECS | 120 seconds |
BLIND_RELAY_DELIVERY_RECEIPT_MAX_AGE_SECS | 120 seconds |
MAX_BLIND_RELAY_FORWARD_ATTEMPTS | 3 attempts |
前一跳速率限制与隔离
速率限制按已签名的前一跳身份分桶。60 秒内超过 120 个请求会启动五分钟本地隔离;另一组失败分数会在五分钟内累计 12 次具攻击性的验证失败后启动相同隔离。
invalid_previous_hop | invalid_signature | self_loop | route_loop | ttl_exhausted
只有恶意验证原因会增加失败分数。传输 timeout、ACK 丢失与重复 route 重试不会污染健康前一跳。bucket 存储有容量上限且闲置状态会过期,因此不能演变成持久通信关系图。
幂等与重试语义
重放窗口内重复的 route ID 会获得幂等成功响应:节点增加一次聚合 replay drop,但不会再次投递或转发 envelope。临时性下一跳错误最多尝试三次并加入有界 jitter;永久验证错误不重试。
duplicate route_id -> accepted=true, reason=duplicate_route, no second delivery
transient next-hop failure -> bounded retry with deterministic jitter
permanent validation failure -> no retry
聚合运行时计数
Rust 在下列两个路径提供粗粒度累计计数与 freshness timestamp。这些是节点范围的运营证据,不是消息日志、可计费用户分析,也不能证明某段特定对话发生。
system_stats.discovery_status.peer_store.runtime.blind_relay
system_stats.discovery_status.peer_store.peer_health_summary
| 计数组 | 字段 |
|---|---|
| 接收与处置 | received, terminal, forwarded, rejected |
| 验证与防护 | invalid_signature, envelope_too_large, ttl_exhausted, no_route, invalid_endpoint, loop_detected, replay_dropped, timestamp_rejected, rate_limited, quarantined, quarantine_started |
| 传输与重试 | backpressure_dropped, forward_failed, retry_attempted, retry_succeeded, retry_exhausted |
| Synthetic 证据 | probe_attempted, probe_succeeded, probe_failed, two_hop_probe_attempted, two_hop_probe_succeeded, two_hop_probe_failed |
| 真实投递与 freshness | verified_client_onion_deliveries, last_verified_client_onion_delivery_at, last_accepted_at, last_event_at |
证据质量语义
质量摘要会区分已接受的不透明工作、synthetic 可达性 probe、synthetic 两跳控制 proof,以及 terminal 签名的真实 client delivery receipt。只有预期 terminal 对新鲜、经认证的 client-originated delivery 签名时,real_relay_ready 才成立;synthetic 证据不得宣称为 App/用户流量。
status | 含义 |
|---|---|
idle | 尚无中继或 probe 证据。 |
observing | 已有部分证据,但尚未建立 readiness。 |
stale | 之前成功证据已不新鲜。 |
ready | 有新鲜的已接受工作或合格 proof,且无活动中的传输警示。 |
protecting | 滥用防护计数已触发,但中继仍可运行。 |
degraded | 转发或 probe 失败需要调查。 |
attention | Backpressure 或重试耗尽需要立即处理。 |
proof_scope 进一步区分 client_message_delivery、relay_acceptance、message_delivery、control_plane、single_hop_control_plane、attempted 与 none。历史总量持续累计,但 readiness boolean 必须依赖新鲜证据并计入当前传输故障。
隐私安全的 peer 健康摘要
peer_health_summary 使用缩短的 node identifier 与粗粒度健康 bucket,让运营者能隔离故障或被 quarantine 的 peer,而不看见流量关系。它是带明确隐私边界的控制面诊断信息。
允许:
- 缩短的
node_id_prefix - 粗粒度 health 与 descriptor 状态
- gossip 与 route success freshness bucket
- 聚合 route 成功与失败计数
- 聚合 loop、replay、rate-limit 与 quarantine 计数
- 隔离剩余时间与有界原因 bucket
不允许:
- 完整节点公钥
- route ID 或 endpoint 列表
- 密文 blob 或 payload hash
- message ID 或 receiver 身份
- client IP、目的地或 DNS 数据
- 社交图谱边或谁与谁通信
运营者流程
打开 Nodeboard、选择节点,再进入 Discovery 与 Security / Relay Protection。只按节点健康、可达性、queue 压力及签名 proof freshness 解读趋势。
- 确认 discovery descriptor 与 bootstrap recovery 保持新鲜。
- 声明 runtime ready 前,比较
accepted_total、accepted_percent与最后接受事件的 age。 - 区分
real_relay_ready与 synthetic probe readiness;只有前者证明经认证 client-originated terminal receipt。 - 若出现 protecting、degraded 或 attention,只检查聚合原因 bucket 与传输健康,不要求用户级日志。
源码关系图
文档使用仓库相对路径,因此基础设施迁移主机后规范仍有效。后端与 Nodeboard 位于不同仓库,但只消费 owner-scoped、隐私安全的节点 metadata。
| 层级 | 仓库路径 | 职责 |
|---|---|---|
| Rust 中继 API | crates/aeronyx-server/src/api/chat_peer.rs | 验证 envelope,执行 loop、replay、freshness、rate、quarantine、retry 与 terminal receipt 规则。 |
| Rust PeerStore | crates/aeronyx-server/src/services/peer_store.rs | 保存有界聚合计数、peer health、readiness 与 proof 分类。 |
| Rust 健康 API | crates/aeronyx-server/src/api/vpn_health.rs | 输出本地隐私安全 health JSON。 |
| Rust reporter | crates/aeronyx-server/src/management/reporter.rs | 在节点 heartbeat metadata 传送聚合状态。 |
| 后端可观测性 | privacy_network/api/vpn_observability.py | 向运营控制台返回 owner-scoped system metadata。 |
| Nodeboard types | types/index.ts | 定义 blind relay 与 peer health response type。 |
| Nodeboard 详情与 i18n | app/dashboard/nodes/[id]/page.tsx and lib/i18n/index.ts | 以多语言隐私边界文案呈现 Security / Relay Protection。 |
多跳路由的基础
多跳路由需要抗重放、循环控制、有界重试、peer 隔离,以及不会被误解成用户流量的证据。这套防护为分层加密与后续路径多样性提供基础,同时不削弱盲节点不变量。
开发规则
每个新增字段都必须视为隐私审查。有效的运营指标应回答节点级可靠性问题,却不能识别 payload、sender、receiver、path、endpoint 或 conversation。
- 所有中继路径都必须保持
payload_b64不透明。 - 只新增聚合计数或有界原因 bucket。
- 计数不得与 route ID、endpoint、user、receiver 或 message metadata join。
- Synthetic probe 不得计入加密消息、数据包或 byte 总量。
- 语义变更时同步更新 Rust tests、Nodeboard types 与本页所有语言。