Защита слепого relay от злоупотреблений
Как узлы AeroNyx сдерживают replay, циклы, перегрузку и сбойные peers, не читая шифротекст и сохраняя приватность операционных доказательств.
Blind Relay Abuse Guard — граница безопасности децентрализованной передачи шифротекста AeroNyx. Она ограничивает злоупотребления и нестабильность, не анализируя ciphertext, не создавая постоянную историю маршрутов и не превращая оператора в наблюдателя трафика.
Статус и область
Защита реализована в Rust, агрегированные результаты доступны в health metadata и Nodeboard. Её задача — сдерживание и честное доказательство: opaque relay work принято, защищается, деградировало или устарело, но не раскрывается его содержимое.
| Контроль | Состояние |
|---|---|
| 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, позволяющую восстановить маршрут, личность или социальную связь.
- plaintext сообщений, packet payload, media или MemChain plaintext
- DNS, destinations, domains, URLs или browsing history
- route IDs, полные пути, endpoint URLs или client public IP
- полные public keys, receiver identity, message IDs или social graph
- private keys, voucher secrets, wallet-level traffic или decryption material
Конвейер допуска
Каждый request проходит ограниченные проверки до расходования forwarding capacity. Порядок ниже концептуальный; решения используют только signed routing 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
Защита от replay и по времени
Replay suppression локальна, краткосрочна и ограничена по объёму. Подписанные timestamps отклоняют старые и чрезмерно будущие frames. Таблица отражает текущие defaults main, а не вечные обещания протокола; изменения требуют tests и docs.
| Runtime-константа | Текущее значение |
|---|---|
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 |
Лимит и карантин предыдущего hop
Rate limit привязан к подписанной identity предыдущего hop. Более 120 requests за 60 секунд запускают локальный карантин на пять минут. Отдельный score запускает тот же карантин после 12 враждебных validation failures за пять минут.
invalid_previous_hop | invalid_signature | self_loop | route_loop | ttl_exhausted
В score входят только adversarial validation reasons. Transport timeout, потерянный ACK и retry дубликата маршрута не штрафуют здоровый peer. Bucket store ограничен, idle state истекает, поэтому постоянный communication graph не возникает.
Идемпотентность и повторы
Повторный route ID в окне получает idempotent success: учитывается один aggregate replay drop без повторной доставки или пересылки. Временная ошибка next hop имеет максимум три попытки с bounded jitter; постоянная validation error не повторяется.
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
Агрегированные runtime-счётчики
Rust публикует грубые cumulative counters и freshness timestamps по двум путям. Это node-scoped operational evidence, а не message logs, биллинговая аналитика или доказательство конкретного разговора.
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 |
| Транспорт и retry | 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 probes, synthetic two-hop proofs и terminal-signed client receipts. real_relay_ready требует свежий authenticated client-originated receipt от ожидаемого terminal. Synthetic evidence нельзя показывать как App/user traffic.
status | Значение |
|---|---|
idle | Доказательств relay или probe ещё нет. |
observing | Частичные доказательства есть, readiness не установлена. |
stale | Предыдущее успешное доказательство устарело. |
ready | Есть свежая принятая работа или proof без активной transport alert. |
protecting | Счётчики защиты активны, relay продолжает работать. |
degraded | Forwarding или probe failures требуют проверки. |
attention | Backpressure или exhausted retries требуют немедленного действия. |
proof_scope разделяет client_message_delivery, relay_acceptance, message_delivery, control_plane, single_hop_control_plane, attempted и none. Исторические totals накопительные; readiness требует свежих доказательств и учитывает активные transport failures.
Приватная сводка здоровья peers
peer_health_summary использует сокращённый node identifier и грубые health buckets, позволяя изолировать failing/quarantined peer без раскрытия traffic relationships. Это control-plane диагностика с явной privacy boundary.
Разрешено:
- сокращённый
node_id_prefix - грубые health и descriptor state
- freshness buckets gossip и route success
- aggregate route success/failure counts
- aggregate loop/replay/rate-limit/quarantine counts
- остаток карантина и bounded reason buckets
Запрещено:
- полные node public keys
- route IDs или endpoint lists
- encrypted blobs или payload hashes
- message IDs или receiver identity
- client IP, destinations или DNS
- social graph или связи собеседников
Рабочий процесс оператора
Откройте Nodeboard, выберите узел, затем Discovery и Security / Relay Protection. Тенденции интерпретируются только вместе с node health, reachability, queue pressure и freshness подписанных proofs.
- Проверьте свежесть descriptors и bootstrap recovery.
- До объявления ready сравните
accepted_total,accepted_percentи age последнего accepted. - Отличайте
real_relay_readyот synthetic readiness; только первое доказывает authenticated client-originated terminal receipt. - При protecting, degraded или attention исследуйте aggregate buckets и transport health без user-level logs.
Карта исходного кода
Используются repository-relative paths, чтобы спецификация переживала перенос инфраструктуры. Backend и Nodeboard находятся в разных репозиториях и потребляют только owner-scoped privacy-safe metadata.
| Слой | Путь репозитория | Роль |
|---|---|---|
| Rust relay API | crates/aeronyx-server/src/api/chat_peer.rs | Аутентифицирует envelopes и применяет loop, replay, freshness, rate, quarantine, retry и terminal receipt rules. |
| Rust PeerStore | crates/aeronyx-server/src/services/peer_store.rs | Хранит bounded counters, peer health, readiness и proof classification. |
| Rust health API | crates/aeronyx-server/src/api/vpn_health.rs | Публикует локальный privacy-safe health JSON. |
| Rust reporter | crates/aeronyx-server/src/management/reporter.rs | Передаёт aggregate status в heartbeat metadata. |
| Backend observability | privacy_network/api/vpn_observability.py | Возвращает owner-scoped metadata в консоль. |
| Nodeboard types | types/index.ts | Определяет blind relay и peer health types. |
| Nodeboard detail и i18n | app/dashboard/nodes/[id]/page.tsx and lib/i18n/index.ts | Показывает Security / Relay Protection с локализованной privacy boundary. |
Основа multi-hop маршрутизации
Multi-hop требует anti-replay, сдерживания циклов, bounded retry, карантина peer и доказательств, не смешиваемых с user traffic. Guard создаёт основу layered encryption и route diversity без ослабления blind-node invariant.
Правила разработки
Каждое новое поле проходит privacy review. Метрика должна отвечать на вопрос о надёжности узла, не идентифицируя payload, sender, receiver, path, endpoint или conversation.
- Сохранять
payload_b64opaque на всех relay paths. - Добавлять только aggregate counters или bounded reason buckets.
- Не соединять counters с routes, endpoints, users, receivers или message metadata.
- Не включать synthetic probes в totals сообщений, packets и bytes.
- При смене семантики обновлять Rust tests, Nodeboard types и все языки страницы.