盲中繼濫用防護

AeroNyx8 分鐘閱讀

AeroNyx 節點在轉送加密中繼流量前套用的限制:前一跳速率限制與隔離、重新啟動後仍有效的路由重放抑制、有邊界的重試與 CPU 准入,且只使用經簽署的中繼資料與彙總計數器。

盲中繼濫用防護是 AeroNyx 節點在為其他節點轉送加密中繼流量之前所套用的一組限制。它只使用經簽署的路由中繼資料與本機計數器,來圍堵具濫用行為或不穩定的對等節點。它絕不剖析密文、絕不保存路由歷史,也絕不揭露誰與誰交談。

範圍

控制項狀態
不透明酬載轉送已實作
經簽署的新鮮度檢查與路由重放抑制已實作。當節點的聊天中繼儲存區啟用時,重放狀態在重新啟動後仍可保留
前一跳速率限制與隔離已實作
全程序範圍的請求與加密運算准入限制已實作
節點健康狀態與 Nodeboard 中的彙總執行期證據已實作
檢查明文或酬載依設計不執行
逐使用者、逐路由或社交圖譜分析依設計不執行

盲節點規則

中繼可以驗證路由中繼資料、套用有邊界的政策、轉送不透明信封並回傳經簽署的回執。它絕不可檢查酬載,也絕不可揭露足以重建路由、使用者身分或關係的中繼資料。具體而言,中繼不會記錄或揭露:

  • 訊息、封包、媒體或記憶的明文
  • DNS 查詢、目的地、網域、URL 或瀏覽紀錄
  • 路由 ID、完整路徑、端點 URL 或用戶端 IP 位址
  • 完整公鑰、接收者身分、訊息 ID 或社交圖譜關係
  • 私鑰、票券機密、錢包層級流量或解密素材

准入流程

每個請求在可以使用轉送容量之前,都必須通過以下檢查。步驟 1 到 6 依序執行。在步驟 7 中,以本節點為目標的請求會交由本節點自身的終端或洋蔥處理,而以其他節點為目標的請求則會在解析出下一跳後進行保留。

text
1. request gate: process-wide admission window and in-flight limit (64 requests)
2. crypto admission: a free slot for signature and onion work, or Backpressure
3. authenticate the signed previous hop and envelope
4. previous-hop rate limit and quarantine check
5. envelope metadata: size, age and future-skew limits
6. self-loop check
7. route loop, TTL and next-hop descriptor checks, plus the route replay reservation
8. forward the opaque ciphertext, or peel the terminal layer and deliver

每一項決策都只使用經簽署的路由中繼資料與本機彙總狀態,絕不使用解密後的內容。

執行期限制

以下是節點原始碼中目前的預設值。它們是營運數值,而非永久的協定承諾。

常數預設值
BLIND_RELAY_ROUTE_REPLAY_CAPACITY8192 條有效路由
BLIND_RELAY_ROUTE_REPLAY_TTL_SECS600 秒
PREVIOUS_HOP_RATE_LIMIT 每 PREVIOUS_HOP_RATE_WINDOW_SECS每 60 秒 120 個請求
PREVIOUS_HOP_FAILURE_THRESHOLD 每 PREVIOUS_HOP_FAILURE_WINDOW_SECS每 300 秒 12 次計分失敗
PREVIOUS_HOP_QUARANTINE_SECS300 秒
MAX_PREVIOUS_HOP_BUCKETS4096 個桶
BLIND_RELAY_MAX_ENVELOPE_AGE_SECS600 秒
BLIND_RELAY_MAX_FUTURE_SKEW_SECS120 秒
BLIND_RELAY_DELIVERY_RECEIPT_MAX_AGE_SECS120 秒
DEFAULT_MAX_ATTEMPTS(轉送重試)3 次嘗試
MAX_IN_FLIGHT_BLIND_RELAY_REQUESTS64 個請求

前一跳速率限制與隔離

速率限制以前一跳的簽署身分為鍵。若同一前一跳在 60 秒內發出超過 120 個請求,就會對該跳點啟動五分鐘的本機隔離。另有一項獨立的失敗計分,會在五分鐘內累積 12 次計分失敗後啟動相同的隔離。只有以下原因會計入分數:

text
invalid_previous_hop | invalid_signature | self_loop | route_loop | ttl_exhausted

傳輸逾時、遺失的確認、重複重試與重放衝突都不會計入分數,因此健康的對等節點不會因網路問題而遭到隔離。桶儲存區有容量上限,閒置的桶會被逐出,因此此防護機制不會累積成長期的通訊圖譜。

路由重放與重試

每個中繼請求都帶有一個路由 ID。當節點的聊天中繼儲存區啟用時([memchain.chat_relay] enabled = true),路由保留與已完成的回應會保存在其 SQLite 資料庫中,因此重放保護在重新啟動後仍然有效。否則,節點會使用具有相同容量與時間窗的記憶體內登錄表。若全部 8192 個槽位都被有效路由佔用,新路由會以 replay_capacity 遭到拒絕,直到槽位到期為止。

重複的路由 ID 會有以下四種結果之一:

情況回應對前一跳的影響
相同請求;第一次嘗試已完成重放已儲存的回應,包括任何由終端簽署的回執。不會進行第二次遞送或轉送(duplicate_route)計為成功
相同請求;第一次嘗試仍在執行中HTTP 503 route_in_flight。傳送者可以重試無
同一路由 ID 下的不同請求HTTP 400 replay_conflict記錄於對等節點健康狀態中。不計入隔離分數
相同請求,但已儲存的回應超過 120 秒HTTP 409 replay_response_expired。該路由在其 600 秒時間窗的剩餘期間內仍保持保留,因此無法再次執行無

最後一種結果適用於持久儲存區。經簽署的回執只有作為新鮮證據時才有效,因此節點在 120 秒後不會再重放回執。

當轉送至下一跳時因逾時、連線錯誤或請求錯誤而失敗,節點最多會重試至總共三次嘗試。每次重試前的短暫延遲,是從路由 ID、下一跳與嘗試次數衍生而來。下游節點回報為明確拒絕的失敗不會重試。

加密運算准入(營運者容量說明)

簽章檢查、洋蔥剝除與回執簽署都受 CPU 限制,因此每個節點程序都會加以限制:

  • 總槽位:主機回報之 CPU 執行緒數的一半,無條件進位,最少 4 個、最多 8 個,因此即使只有一兩個執行緒的主機也有 4 個槽位。
  • 傳入請求:比總數少一個槽位,讓傳出路由建立與回執完成始終能夠推進。因此在最小的主機上,傳入請求也有 3 個槽位。
  • 所有槽位都忙碌時:請求會立即以 HTTP 429 與 backpressure 原因遭到拒絕。它不會在佇列中等候。

因此,在小型主機上,中繼會在流量突增時提早卸除負載。backpressure_dropped 計數器持續上升,表示節點需要更多 CPU 或更少的中繼流量。

彙總執行期計數器

節點會在心跳中,於以下路徑回報概略的累計計數器與新鮮度時間戳記:

text
system_stats.discovery_status.peer_store.runtime.blind_relay
system_stats.discovery_status.peer_store.blind_relay_quality
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
合成探測probe_attempted、probe_succeeded、probe_failed、two_hop_probe_attempted、two_hop_probe_succeeded、two_hop_probe_failed
真實遞送與新鮮度verified_client_onion_deliveries、last_verified_client_onion_delivery_at、last_accepted_at、last_event_at

這些計數器描述的是節點的運作情況。它們不是訊息日誌或計費資料,也無法證明任何特定對話曾經發生。

證據品質

品質摘要將四類證據分開處理:已接受的不透明中繼工作、合成可達性探測、合成兩跳探測,以及針對用戶端發起之遞送的終端簽署回執。real_relay_ready 需要一份新鮮且經驗證的用戶端遞送回執。合成證據絕不會被回報為使用者流量。

status意義
idle尚無任何中繼或探測活動
observing已有部分證據,但尚未確立就緒狀態
stale先前的成功證據已不再新鮮
ready有新鮮的已接受工作或符合資格的證明,且沒有進行中的傳輸問題
protecting濫用防護已觸發,而中繼仍持續運作
degraded轉送或探測失敗需要調查
attention背壓或重試耗盡需要營運者立即處理

proof_scope 標示所見過的最強證據:client_message_delivery、relay_acceptance、message_delivery、control_plane、single_hop_control_plane、attempted 或 none。

不含流量關係的對等節點健康狀態

peer_health_summary 讓營運者能找出故障或遭隔離的對等節點,而不會看到誰與誰通訊。

包含:縮短的節點 ID 前綴、概略的健康與描述元狀態、gossip 與路由成功的新鮮度、彙總的路由成功與失敗次數、隔離狀態、剩餘時間,以及概略的原因分組。

絕不包含:完整的節點公鑰、路由 ID、端點清單、加密資料塊或酬載雜湊值、訊息 ID、接收者身分、用戶端 IP 位址、目的地、DNS 資料或社交圖譜關係。

原始碼對照

層級節點儲存庫中的路徑角色
中繼協調crates/aeronyx-server/src/api/chat_peer/blind_relay.rs請求閘門、加密運算准入、驗證、迴圈與 TTL 檢查、重放結果、轉送與終端處理
HTTP 介面與限制crates/aeronyx-server/src/api/chat_peer.rs路由、主體與進行中請求限制、錯誤代碼與原因分組
濫用政策crates/aeronyx-server/src/api/chat_peer_abuse_guard.rs前一跳速率限制、失敗計分與隔離
重放登錄表crates/aeronyx-server/src/api/chat_peer_replay.rs記憶體內登錄表與已儲存回應的格式
持久重放儲存區crates/aeronyx-server/src/services/chat_relay_blind_route_store.rsSQLite 路由保留與回應
重試政策crates/aeronyx-server/src/api/chat_peer_retry.rs可重試與明確失敗的區分,以及重試時機
計數器與品質crates/aeronyx-server/src/services/peer_store.rs 與 services/peer_store/status.rs彙總計數器、就緒狀態與證明分類
健康狀態回報crates/aeronyx-server/src/api/vpn_health.rs 與 management/reporter.rs本機健康狀態 JSON 與心跳酬載

節點軟體以 AGPL-3.0 授權開源於 github.com/AeroNyxNetwork/AeroNyx。路由如何建立,請參閱 節點探索與加密多跳中繼。

<!-- faq:start -->

常見問題

中繼節點能讀取或記錄它所轉送的流量嗎?

不能。中繼檢查經簽署的路由中繼資料,並轉送不透明的信封。它只保留彙總計數器,絕不保留酬載、路由歷史或接收者身分。

當節點重試同一條路由時會發生什麼事?

若第一次嘗試已完成,節點會重放其已儲存的回應,不會進行第二次遞送。若第一次嘗試仍在執行中,節點會回傳可重試的 route_in_flight。同一路由 ID 下的不同請求會以 replay_conflict 遭到拒絕。

重放保護在節點重新啟動後仍然有效嗎?

是的,前提是節點的聊天中繼儲存區已啟用。此時路由保留與已完成的回應會保存在 SQLite 中。若沒有該儲存區,節點會使用在重新啟動時清空的記憶體內登錄表。

對等節點為什麼會遭到隔離?

對等節點若在 60 秒內傳送超過 120 個請求,或在五分鐘內累積 12 次計分驗證失敗,就會被隔離五分鐘。逾時、遺失的確認與重複重試不會計為失敗。

為什麼我的節點在負載下會回傳 backpressure?

因為它所有的中繼加密運算槽位都在忙碌中。節點約以其 CPU 執行緒數的一半(最少 4 個、最多 8 個)用於簽章與洋蔥處理,並會立即拒絕多出的請求,而不是將其排入佇列。

<!-- faq:end -->