블라인드 릴레이 악용 방지

AeroNyx2026년 6월 20일7분 읽기44회 조회

AeroNyx 노드가 암호문을 읽지 않고 재전송, 루프, 과도한 요청, 장애 peer를 억제하며 개인정보 보호 운영 증거를 제공하는 방식입니다.

Blind Relay Abuse Guard는 AeroNyx 분산 암호화 전달의 안전 경계입니다. 암호문을 분석하거나 영구 경로 기록을 만들거나 노드 운영자를 트래픽 관찰자로 만들지 않으면서 악의적이거나 불안정한 릴레이 동작을 제한합니다.

상태와 범위

가드는 Rust에 구현되어 있고 집계 결과는 node health metadata와 Nodeboard에 표시됩니다. 목적은 억제와 정직한 증거입니다. 불투명 relay work가 accepted, protected, degraded, stale인지 보여 주되 내용은 보여 주지 않습니다.

제어상태
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금지

블라인드 노드 불변 조건

Relay는 routing metadata 서명을 검증하고 제한된 정책을 적용하며 opaque envelope를 전달하고 terminal signed receipt를 반환할 수 있습니다. 그러나 payload를 검사·추론하거나 경로, 사용자, 사회 관계를 복원할 metadata를 노출해서는 안 됩니다.

  • message plaintext, packet payload, media content, MemChain plaintext
  • DNS content, destination, domain, URL, browsing history
  • route ID, complete path, endpoint URL, client public IP
  • full public key, receiver identity, message ID, social-graph edge
  • private key, voucher secret, wallet-level traffic, decryption material

승인 처리 흐름

각 request는 forwarding capacity를 쓰기 전에 제한된 검사를 통과합니다. 아래 순서는 개념적이며 모든 판단은 signed routing metadata와 local aggregate state만 사용하고 복호화 내용은 사용하지 않습니다.

text
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

재전송 및 시각 보호

Replay suppression은 local, 단기, 용량 제한 방식입니다. Signed envelope timestamp로 오래되었거나 지나치게 미래인 frame을 거부합니다. 표의 값은 현재 main runtime default이며 영구 protocol promise가 아닙니다. 변경 시 test와 docs를 함께 갱신합니다.

런타임 상수현재 기본값
MAX_BLIND_RELAY_SEEN_ROUTES8192 route IDs
BLIND_RELAY_ROUTE_REPLAY_WINDOW_SECS600 seconds
BLIND_RELAY_PREVIOUS_HOP_RATE_LIMIT120 requests / 60 seconds
BLIND_RELAY_PREVIOUS_HOP_FAILURE_THRESHOLD12 scored failures / 300 seconds
BLIND_RELAY_PREVIOUS_HOP_QUARANTINE_SECS300 seconds
MAX_BLIND_RELAY_PREVIOUS_HOP_BUCKETS4096 buckets
BLIND_RELAY_MAX_ENVELOPE_AGE_SECS600 seconds
BLIND_RELAY_MAX_FUTURE_SKEW_SECS120 seconds
BLIND_RELAY_DELIVERY_RECEIPT_MAX_AGE_SECS120 seconds
MAX_BLIND_RELAY_FORWARD_ATTEMPTS3 attempts

이전 홉 속도 제한과 격리

Rate limit는 signed previous-hop identity별로 적용됩니다. 60초에 120 request를 넘으면 5분 local quarantine이 시작됩니다. 별도 failure score는 5분 안에 공격적 validation failure 12회가 쌓이면 같은 격리를 시작합니다.

text
invalid_previous_hop | invalid_signature | self_loop | route_loop | ttl_exhausted

적대적 validation reason만 failure score에 포함됩니다. Transport timeout, ACK loss, duplicate route retry는 정상 previous hop을 오염시키지 않습니다. Bucket store는 제한되고 idle state는 만료되어 영구 communication graph가 되지 않습니다.

멱등성과 재시도 의미

Replay window의 중복 route ID에는 idempotent success를 반환합니다. Aggregate replay drop은 기록하지만 envelope를 다시 전달하거나 forward하지 않습니다. 일시적 next-hop failure는 bounded jitter로 최대 3회 시도하고 영구 validation failure는 retry하지 않습니다.

text
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는 아래 두 path에 coarse cumulative counter와 freshness timestamp를 제공합니다. 이는 node-scoped operational evidence이지 message log, user billing analytics, 특정 대화의 증거가 아닙니다.

text
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
합성 증거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

증거 품질 의미

Quality summary는 accepted opaque work, synthetic reachability probe, synthetic two-hop control proof, terminal-signed client delivery receipt를 구분합니다. real_relay_ready는 expected terminal의 fresh authenticated client-originated receipt에만 사용하며 synthetic evidence를 App/user traffic으로 표시하면 안 됩니다.

status의미
idleRelay 또는 probe evidence가 아직 없습니다.
observingEvidence는 있지만 readiness가 확립되지 않았습니다.
stale이전 성공 evidence가 더 이상 fresh하지 않습니다.
readyFresh accepted work 또는 qualifying proof가 있고 active transport attention은 없습니다.
protectingAbuse protection counter가 작동 중이지만 relay는 운영됩니다.
degradedForwarding 또는 probe failure를 조사해야 합니다.
attentionBackpressure 또는 retry exhaustion에 즉시 대응해야 합니다.

proof_scopeclient_message_delivery, relay_acceptance, message_delivery, control_plane, single_hop_control_plane, attempted, none을 구분합니다. Historical total은 누적되지만 readiness는 fresh evidence와 active transport failure를 반영합니다.

개인정보 보호 peer 상태

peer_health_summary는 축약 node identifier와 coarse health bucket으로 traffic relationship을 노출하지 않고 failing/quarantined peer를 격리하게 합니다. 명시적 privacy boundary가 있는 control-plane 진단입니다.

허용:

  • 축약 node_id_prefix
  • coarse health와 descriptor state
  • gossip과 route success freshness bucket
  • aggregate route success/failure count
  • aggregate loop/replay/rate-limit/quarantine count
  • quarantine remaining time과 bounded reason bucket

허용 안 됨:

  • 전체 node public key
  • route ID 또는 endpoint list
  • encrypted blob 또는 payload hash
  • message ID 또는 receiver identity
  • client IP, destination, DNS data
  • social-graph edge 또는 통신 상대 관계

운영자 절차

Nodeboard에서 node를 선택한 뒤 Discovery와 Security / Relay Protection을 엽니다. 추세는 node health, reachability, queue pressure, signed proof freshness 범위에서만 해석합니다.

  1. Discovery descriptor와 bootstrap recovery가 fresh한지 확인합니다.
  2. Runtime ready 선언 전 accepted_total, accepted_percent, last accepted age를 비교합니다.
  3. real_relay_ready와 synthetic probe readiness를 구분합니다. 전자만 authenticated client-originated terminal receipt를 증명합니다.
  4. protecting, degraded, attention이면 aggregate reason bucket과 transport health만 조사하고 user-level log를 요구하지 않습니다.

소스 맵

인프라가 다른 host로 이동해도 유효하도록 repository-relative path를 사용합니다. Backend와 Nodeboard는 별도 repository지만 owner-scoped privacy-safe node metadata만 사용합니다.

계층저장소 경로역할
Rust relay APIcrates/aeronyx-server/src/api/chat_peer.rsEnvelope를 인증하고 loop, replay, freshness, rate, quarantine, retry, terminal receipt rule을 적용합니다.
Rust PeerStorecrates/aeronyx-server/src/services/peer_store.rsBounded aggregate counter, peer health, readiness, proof classification을 저장합니다.
Rust health APIcrates/aeronyx-server/src/api/vpn_health.rsLocal privacy-safe health JSON을 게시합니다.
Rust reportercrates/aeronyx-server/src/management/reporter.rsNode heartbeat metadata로 aggregate status를 전달합니다.
Backend observabilityprivacy_network/api/vpn_observability.pyOwner-scoped system metadata를 operator console에 반환합니다.
Nodeboard typestypes/index.tsBlind relay와 peer health response type을 정의합니다.
Nodeboard detail 및 i18napp/dashboard/nodes/[id]/page.tsx and lib/i18n/index.tsLocalized privacy-boundary copy로 Security / Relay Protection을 표시합니다.

다중 홉 라우팅 기반

Multi-hop routing에는 replay resistance, loop containment, bounded retry, peer quarantine, user traffic과 혼동되지 않는 evidence가 필요합니다. 이 guard는 blind-node invariant를 약화하지 않고 layered encryption과 route diversity의 기반이 됩니다.

개발 규칙

새 field는 모두 privacy review 대상으로 봅니다. Operator metric은 node reliability 질문에는 답해야 하지만 payload, sender, receiver, path, endpoint, conversation을 식별해서는 안 됩니다.

  1. 모든 relay path에서 payload_b64를 opaque로 유지합니다.
  2. Aggregate counter 또는 bounded reason bucket만 추가합니다.
  3. Counter를 route ID, endpoint, user, receiver, message metadata와 join하지 않습니다.
  4. Synthetic probe를 encrypted message, packet, byte total에 포함하지 않습니다.
  5. 의미가 바뀌면 Rust test, Nodeboard type, 모든 언어 문서를 함께 갱신합니다.

노드 탐색과 검증 가능한 암호화 릴레이 전달