Protección contra abuso del relay ciego
Cómo los nodos AeroNyx contienen replay, bucles, exceso de tráfico y peers fallidos sin leer el cifrado y con evidencia operativa privada.
Blind Relay Abuse Guard es el límite de seguridad del reenvío cifrado descentralizado de AeroNyx. Restringe relays abusivos o inestables sin analizar el ciphertext, crear historiales persistentes de rutas ni convertir al operador en observador del tráfico.
Estado y alcance
La protección está implementada en Rust y sus resultados agregados aparecen en el health metadata del nodo y Nodeboard. Su función es contener y aportar evidencia veraz: indica si el trabajo opaco fue aceptado, protegido, degradado o quedó obsoleto, nunca qué contiene.
| Control | Estado |
|---|---|
| Blind payload forwarding | Implementado |
| Signed freshness and replay suppression | Implementado |
| Previous-hop rate limiting and quarantine | Implementado |
| Privacy-safe runtime evidence | Implementado |
| Nodeboard operator visibility | Implementado |
| Plaintext or payload inspection | Prohibido |
| User, route, or social-graph analytics | Prohibido |
Invariante del nodo ciego
Un relay puede autenticar metadata de ruta, aplicar política acotada, reenviar un envelope opaco y devolver un receipt firmado por el terminal. No puede inspeccionar o inferir el payload ni revelar metadata capaz de reconstruir una ruta, identidad o relación social.
- mensajes en claro, packet payloads, media o MemChain en claro
- DNS, destinos, dominios, URLs o historial de navegación
- route IDs, rutas completas, endpoint URLs o IP pública del cliente
- claves públicas completas, receptores, message IDs o aristas sociales
- claves privadas, voucher secrets, tráfico wallet-level o material de descifrado
Flujo de admisión
Cada request pasa controles acotados antes de consumir capacidad de reenvío. El orden siguiente es conceptual; las decisiones usan metadata de ruta firmada y estado agregado local, no contenido descifrado.
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
Protección contra replay y desfase temporal
La supresión de replay es local, breve y limitada en capacidad. Los timestamps firmados rechazan frames antiguos o excesivamente futuros. La tabla muestra defaults actuales de main, no promesas permanentes del protocolo; cualquier cambio exige tests y documentación.
| Constante de runtime | Default actual |
|---|---|
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 |
Límite y cuarentena del salto anterior
El rate limit se agrupa por identidad firmada del salto anterior. Más de 120 requests en 60 segundos inicia cinco minutos de cuarentena local. Un score separado inicia la misma cuarentena tras 12 fallos de validación hostiles en cinco minutos.
invalid_previous_hop | invalid_signature | self_loop | route_loop | ttl_exhausted
Solo razones de validación adversarial suman al score. Timeouts de transporte, ACK perdidos y retries de una ruta duplicada no penalizan a un peer sano. El almacén de buckets es acotado y expira estado inactivo, por lo que no puede convertirse en un grafo persistente.
Idempotencia y reintentos
Un route ID repetido dentro de la ventana devuelve éxito idempotente: registra un replay drop agregado, pero no entrega ni reenvía de nuevo. Fallos transitorios del next hop tienen hasta tres intentos con jitter acotado; fallos permanentes no se reintentan.
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
Contadores agregados de runtime
Rust expone contadores acumulados gruesos y timestamps de frescura en las dos rutas siguientes. Son evidencia operativa del nodo, no logs de mensajes, analytics facturables ni prueba de una conversación concreta.
system_stats.discovery_status.peer_store.runtime.blind_relay
system_stats.discovery_status.peer_store.peer_health_summary
| Grupo de contadores | Campos |
|---|---|
| Entrada y resultado | received, terminal, forwarded, rejected |
| Validación y protección | invalid_signature, envelope_too_large, ttl_exhausted, no_route, invalid_endpoint, loop_detected, replay_dropped, timestamp_rejected, rate_limited, quarantined, quarantine_started |
| Transporte y retry | backpressure_dropped, forward_failed, retry_attempted, retry_succeeded, retry_exhausted |
| Evidencia sintética | probe_attempted, probe_succeeded, probe_failed, two_hop_probe_attempted, two_hop_probe_succeeded, two_hop_probe_failed |
| Entrega real y frescura | verified_client_onion_deliveries, last_verified_client_onion_delivery_at, last_accepted_at, last_event_at |
Semántica de calidad de evidencia
El resumen distingue trabajo opaco aceptado, probes sintéticos de alcance, proofs sintéticos de dos saltos y receipts de cliente firmados por el terminal. real_relay_ready exige un receipt reciente de entrega originada por cliente y firmado por el terminal esperado. La evidencia sintética nunca se presenta como tráfico de App/usuario.
status | Significado |
|---|---|
idle | Todavía no hay evidencia de relay o probe. |
observing | Existe evidencia parcial, pero readiness no está establecida. |
stale | La evidencia de éxito anterior ya no es reciente. |
ready | Hay trabajo aceptado o proof válido reciente sin alerta activa de transporte. |
protecting | Los contadores de protección están activos y el relay sigue operativo. |
degraded | Fallos de forwarding o probe requieren investigación. |
attention | Backpressure o retries agotados requieren atención inmediata. |
proof_scope separa client_message_delivery, relay_acceptance, message_delivery, control_plane, single_hop_control_plane, attempted y none. Los totales históricos son acumulativos; los booleanos readiness requieren evidencia fresca y consideran fallos de transporte activos.
Salud de peers con privacidad
peer_health_summary usa un identificador abreviado y buckets gruesos para aislar un peer fallido o en cuarentena sin revelar relaciones de tráfico. Es diagnóstico de control-plane con límite de privacidad explícito.
Permitido:
node_id_prefixabreviado- health y estado de descriptor gruesos
- buckets de frescura de gossip y route success
- conteos agregados de éxito y fallo
- conteos agregados de loop, replay, rate limit y quarantine
- segundos restantes de cuarentena y razones acotadas
No permitido:
- claves públicas completas
- route IDs o listas de endpoints
- blobs cifrados o payload hashes
- message IDs o identidad del receptor
- IP del cliente, destinos o DNS
- grafo social o quién habla con quién
Flujo del operador
Abra Nodeboard, elija el nodo y revise Discovery y Security / Relay Protection. Interprete tendencias solo junto con salud del nodo, alcance, presión de cola y frescura de proofs firmados.
- Confirme frescura de descriptors y recuperación bootstrap.
- Antes de declarar ready, compare
accepted_total,accepted_percenty edad del último accepted. - Distinga
real_relay_readyde readiness sintética; solo el primero prueba un receipt terminal originado por cliente y autenticado. - Ante protecting, degraded o attention, revise buckets agregados y transporte sin pedir logs de usuario.
Mapa de código
La documentación usa rutas relativas al repositorio para seguir válida al mover infraestructura. Backend y Nodeboard viven en repositorios separados y consumen únicamente metadata owner-scoped y segura para la privacidad.
| Capa | Ruta de repositorio | Función |
|---|---|---|
| API relay Rust | crates/aeronyx-server/src/api/chat_peer.rs | Autentica envelopes y aplica reglas de loop, replay, frescura, rate, quarantine, retry y terminal receipt. |
| Rust PeerStore | crates/aeronyx-server/src/services/peer_store.rs | Guarda contadores acotados, peer health, readiness y clasificación de proofs. |
| API health Rust | crates/aeronyx-server/src/api/vpn_health.rs | Publica health JSON local y privado. |
| Reporter Rust | crates/aeronyx-server/src/management/reporter.rs | Transporta estado agregado en heartbeat metadata. |
| Observabilidad backend | privacy_network/api/vpn_observability.py | Devuelve metadata owner-scoped a la consola. |
| Tipos Nodeboard | types/index.ts | Define tipos de blind relay y peer health. |
| Detalle e i18n Nodeboard | app/dashboard/nodes/[id]/page.tsx and lib/i18n/index.ts | Muestra Security / Relay Protection con textos localizados de privacidad. |
Base para rutas multi-hop
El multi-hop necesita resistencia a replay, contención de bucles, retries acotados, cuarentena de peers y evidencia que no se confunda con tráfico real. Esta protección sustenta cifrado por capas y diversidad de rutas sin debilitar el invariante ciego.
Reglas de desarrollo
Trate cada campo nuevo como revisión de privacidad. Una métrica útil debe responder una pregunta de fiabilidad del nodo sin identificar payload, emisor, receptor, ruta, endpoint o conversación.
- Mantener
payload_b64opaco en cada ruta relay. - Añadir solo contadores agregados o reason buckets acotados.
- Nunca unir contadores con rutas, endpoints, usuarios, receptores o metadata de mensajes.
- Excluir probes sintéticos de totales de mensajes, paquetes y bytes cifrados.
- Actualizar tests Rust, tipos Nodeboard y todos los idiomas cuando cambie la semántica.