Protection contre les abus du relais aveugle

AeroNyx20 juin 20266 min de lecture50 vues

Comment les nœuds AeroNyx limitent replay, boucles, débit abusif et peers défaillants sans lire le chiffré, avec des preuves opérateur respectueuses de la vie privée.

Blind Relay Abuse Guard est la limite de sécurité du transfert chiffré décentralisé AeroNyx. Il contient les relais abusifs ou instables sans analyser le ciphertext, conserver un historique durable des routes ni transformer l'opérateur en observateur du trafic.

État et périmètre

La protection est implémentée en Rust et ses résultats agrégés sont exposés dans le health metadata et Nodeboard. Elle contient le risque et produit une preuve honnête : travail opaque accepté, protégé, dégradé ou périmé, jamais son contenu.

ContrôleÉtat
Blind payload forwardingImplémenté
Signed freshness and replay suppressionImplémenté
Previous-hop rate limiting and quarantineImplémenté
Privacy-safe runtime evidenceImplémenté
Nodeboard operator visibilityImplémenté
Plaintext or payload inspectionInterdit
User, route, or social-graph analyticsInterdit

Invariant du nœud aveugle

Un relay peut authentifier la metadata de routage, appliquer une politique bornée, transférer une envelope opaque et retourner un receipt signé par le terminal. Il ne doit ni inspecter ou inférer le payload, ni révéler de metadata permettant de reconstruire route, identité ou relation sociale.

  • messages en clair, packet payloads, médias ou MemChain en clair
  • DNS, destinations, domaines, URLs ou historique
  • route IDs, chemins complets, endpoint URLs ou IP client
  • clés publiques complètes, identité receiver, message IDs ou graphe social
  • clés privées, voucher secrets, trafic wallet-level ou matériel de déchiffrement

Pipeline d'admission

Chaque request traverse des contrôles bornés avant de consommer de la capacité. L'ordre ci-dessous est conceptuel ; les décisions utilisent uniquement la metadata signée et l'état agrégé local, jamais le contenu déchiffré.

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

Protection replay et fraîcheur

La suppression replay est locale, courte et limitée en capacité. Les timestamps signés rejettent les frames trop anciennes ou trop futures. Les valeurs sont les defaults actuels de main, pas des promesses permanentes ; toute modification exige tests et documentation.

Constante runtimeValeur actuelle
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

Limite et quarantaine du saut précédent

Le rate limit est indexé par l'identité signée du saut précédent. Plus de 120 requests en 60 secondes déclenche cinq minutes de quarantaine locale. Un score séparé déclenche la même quarantaine après 12 échecs hostiles en cinq minutes.

text
invalid_previous_hop | invalid_signature | self_loop | route_loop | ttl_exhausted

Seules les raisons de validation adversariales comptent. Timeouts de transport, ACK perdus et retry d'une route dupliquée ne pénalisent pas un peer sain. Les buckets sont bornés et l'état inactif expire, empêchant la formation d'un graphe durable.

Idempotence et tentatives

Un route ID répété dans la fenêtre reçoit un succès idempotent : un replay drop agrégé est compté, sans seconde livraison ni transfert. Les erreurs transitoires ont au plus trois tentatives avec jitter borné ; les erreurs permanentes ne sont pas retentées.

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

Compteurs runtime agrégés

Rust expose des compteurs cumulatifs grossiers et timestamps de fraîcheur aux deux chemins suivants. Ce sont des preuves opérationnelles du nœud, pas des logs de messages, analytics facturables ou preuve d'une conversation précise.

text
system_stats.discovery_status.peer_store.runtime.blind_relay
system_stats.discovery_status.peer_store.peer_health_summary
Groupe de compteursChamps
Entrée et issuereceived, terminal, forwarded, rejected
Validation et protectioninvalid_signature, envelope_too_large, ttl_exhausted, no_route, invalid_endpoint, loop_detected, replay_dropped, timestamp_rejected, rate_limited, quarantined, quarantine_started
Transport et retrybackpressure_dropped, forward_failed, retry_attempted, retry_succeeded, retry_exhausted
Preuve synthétiqueprobe_attempted, probe_succeeded, probe_failed, two_hop_probe_attempted, two_hop_probe_succeeded, two_hop_probe_failed
Livraison réelle et fraîcheurverified_client_onion_deliveries, last_verified_client_onion_delivery_at, last_accepted_at, last_event_at

Sémantique de qualité des preuves

Le résumé distingue travail opaque accepté, probes synthétiques, proofs synthétiques two-hop et receipts client signés par le terminal. real_relay_ready exige un receipt récent, authentifié, initié par client et signé par le terminal attendu. Une preuve synthétique n'est jamais du trafic App/utilisateur.

statusSignification
idleAucune preuve relay ou probe.
observingUne preuve existe, readiness non établie.
staleLa preuve de succès n'est plus fraîche.
readyTravail accepté ou proof frais sans alerte transport active.
protectingLes protections sont actives et le relay reste opérationnel.
degradedÉchecs forwarding ou probe à examiner.
attentionBackpressure ou retries épuisés exigent une action immédiate.

proof_scope distingue client_message_delivery, relay_acceptance, message_delivery, control_plane, single_hop_control_plane, attempted et none. Les totaux historiques restent cumulatifs, mais readiness exige une preuve fraîche et tient compte des pannes actives.

Santé des peers respectueuse de la vie privée

peer_health_summary emploie un identifiant abrégé et des buckets grossiers pour isoler un peer défaillant ou en quarantaine sans exposer les relations de trafic. C'est un diagnostic control-plane avec limite de confidentialité explicite.

Autorisé:

  • node_id_prefix abrégé
  • health et descriptor state grossiers
  • buckets de fraîcheur gossip et route success
  • comptes agrégés de succès et échec
  • comptes agrégés loop, replay, rate-limit, quarantine
  • temps de quarantaine restant et raisons bornées

Interdit:

  • clés publiques complètes
  • route IDs ou listes d'endpoints
  • blobs chiffrés ou payload hashes
  • message IDs ou identité receiver
  • IP client, destinations ou DNS
  • graphe social ou relations de communication

Parcours opérateur

Ouvrez Nodeboard, choisissez le nœud, puis Discovery et Security / Relay Protection. Interprétez les tendances uniquement avec santé, accessibilité, pression de file et fraîcheur des proofs signés.

  1. Vérifier la fraîcheur des descriptors et du bootstrap recovery.
  2. Comparer accepted_total, accepted_percent et l'âge du dernier accepted avant de déclarer ready.
  3. Distinguer real_relay_ready du synthetic readiness ; seul le premier prouve un receipt terminal authentifié initié par client.
  4. En protecting, degraded ou attention, examiner les buckets agrégés et le transport sans demander de logs utilisateur.

Carte du code source

Les chemins sont relatifs au dépôt afin de rester valides après migration d'hôte. Backend et Nodeboard sont séparés et ne consomment que de la metadata owner-scoped respectueuse de la vie privée.

CoucheChemin du dépôtRôle
API relay Rustcrates/aeronyx-server/src/api/chat_peer.rsAuthentifie les envelopes et applique loop, replay, fraîcheur, rate, quarantine, retry et terminal receipt.
Rust PeerStorecrates/aeronyx-server/src/services/peer_store.rsStocke compteurs bornés, peer health, readiness et classification des proofs.
API health Rustcrates/aeronyx-server/src/api/vpn_health.rsPublie le health JSON local et privé.
Reporter Rustcrates/aeronyx-server/src/management/reporter.rsTransporte le statut agrégé dans le heartbeat.
Observabilité backendprivacy_network/api/vpn_observability.pyRetourne la metadata owner-scoped à la console.
Types Nodeboardtypes/index.tsDéfinit les types blind relay et peer health.
Détail et i18n Nodeboardapp/dashboard/nodes/[id]/page.tsx and lib/i18n/index.tsAffiche Security / Relay Protection avec textes localisés de confidentialité.

Socle du routage multi-hop

Le multi-hop requiert anti-replay, confinement des boucles, retries bornés, quarantaine et preuve non confondue avec le trafic utilisateur. Cette protection prépare le chiffrement en couches et la diversité des routes sans affaiblir l'invariant aveugle.

Règles de développement

Traitez chaque nouveau champ comme une revue de confidentialité. Une métrique doit répondre à une question de fiabilité du nœud sans identifier payload, émetteur, destinataire, route, endpoint ou conversation.

  1. Garder payload_b64 opaque sur chaque chemin relay.
  2. Ajouter uniquement compteurs agrégés ou reason buckets bornés.
  3. Ne jamais joindre compteurs avec routes, endpoints, utilisateurs, receivers ou metadata message.
  4. Exclure les probes synthétiques des totaux messages, paquets et octets chiffrés.
  5. Mettre à jour tests Rust, types Nodeboard et toutes les langues lors d'un changement de sens.

Découverte des nœuds et livraison chiffrée vérifiable