Document compact NAT profiles and stable measurement lifetime

This commit is contained in:
evgeny committed 2026-10-12 17:13:22 +02:00
1 parent 5429431567
commit 53c32e5669
3 files changed
+24 -20

No files matched your search

+12 -12
View File
@@ -6,15 +6,13 @@
к протоколу, семейству, фактическому локальному IP:port и поколению сокета. к протоколу, семейству, фактическому локальному IP:port и поколению сокета.
PUBLIC/NAT/PRIVATE/LOCAL — политика конфигурации, а не результат измерения. PUBLIC/NAT/PRIVATE/LOCAL — политика конфигурации, а не результат измерения.
source=ETCP означает измерение рабочего endpoint; source=STUN — резервную оценку source=ETCP означает измерение рабочего endpoint; source=STUN — резервную оценку
по его IP/netif через другой порт. Измеренный ETCP имеет приоритет до истечения TTL. по его IP/netif через другой порт. Успешный ETCP имеет приоритет до явного сброса endpoint.
Модель: src/routing_layer/address_profile.h. Модель: src/routing_layer/address_profile.h.
mapping: UNKNOWN, UNCHANGED, EIM, DEPENDENT. mapping: UNKNOWN, UNCHANGED, EIM, DEPENDENT.
inbound: UNKNOWN, OPEN, CONTACT_REQUIRED. inbound: UNKNOWN, OPEN, CONTACT_REQUIRED.
source: NONE, ETCP, STUN. source: NONE, ETCP, STUN.
evidence_id: случайный 64-битный ID завершённого раунда владельца. round/generation: локальные ID раунда и жизненного цикла endpoint; в NODEINFO не входят.
checked_at: время измерения владельца, Unix microseconds.
generation: случайный 64-битный ID жизненного цикла локального endpoint.
UNCHANGED означает совпадение наблюдаемых и локального адресов на испытанных UNCHANGED означает совпадение наблюдаемых и локального адресов на испытанных
направлениях. Оно не доказывает свободный вход. EIM означает одинаковый внешний направлениях. Оно не доказывает свободный вход. EIM означает одинаковый внешний
@@ -75,11 +73,12 @@ facet не превращается в ложный STRICT. Потери, оши
остаются подсказками для попыток, подтверждение связи даёт handshake с нужным ключом. остаются подсказками для попыток, подтверждение связи даёт handshake с нужным ключом.
Один активный раунд на S. Таймаут пробы — max(1 секунда, 4*RTT), не более 3 секунд; Один активный раунд на S. Таймаут пробы — max(1 секунда, 4*RTT), не более 3 секунд;
три попытки, бюджет раунда 30 секунд. Повтор после ошибки через 30 секунд или три попытки, бюджет раунда 30 секунд. До первого результата повтор после ошибки
после появления подходящего транспорта; штатный refresh через 180 секунд. через 30 секунд или после появления подходящего транспорта; штатный refresh через 30 минут.
Срок фактов — 300 секунд. Таймеры владельца используют monotonic timebase; Успешный профиль не протухает по таймеру. Ошибка перепроверки сохраняет прежний результат
checked_at не обновляется повторным NODEINFO и не зависит от ответа сервера NTP. и редкий период; неизвестный inbound при том же mapping/endpoint сохраняет прежний ETCP inbound.
При несогласованных часах получатель использует осторожные попытки, не отказ. Свойства разных источников не объединяются в один ETCP-профиль. Смена адреса отменяет
старый раунд, сбрасывает профиль и назначает скорую проверку. Таймеры используют monotonic timebase.
TCP и прокси TCP и прокси
------------- -------------
@@ -114,11 +113,12 @@ owner_key и helper_key имеют разные поля и никогда не
--------------- ---------------
Профиль публикуется только владельцем в общей подписанной записи NODEINFO. Профиль публикуется только владельцем в общей подписанной записи NODEINFO.
Списки и их границы входят в подпись; mapping/inbound/evidence/checked_at Списки и их границы входят в подпись; mapping/inbound/source
сохраняются и загружаются вместе. node_addresses — производная проекция: сохраняются и загружаются вместе. node_addresses — производная проекция:
nat_mapping, nat_inbound, nat_evidence, nat_checked, address_kind. nat_mapping, nat_inbound, nat_source, address_kind.
При изменении формата старый кэш адресов пересоздаётся; старый NAT_TYPE не При изменении формата старый кэш адресов пересоздаётся; старый NAT_TYPE не
интерпретируется как новая модель. Подписанные snapshots и записи чата не удаляются. интерпретируется как новая модель. При сокращении SOCKMETA старые snapshots инвалидируются
с сохранением timestamp; адреса и REALITY остаются bootstrap-сведениями. Записи чата не изменяются.
Общий NAT-адрес рекламируется только после EIM. DEPENDENT не рекламирует Общий NAT-адрес рекламируется только после EIM. DEPENDENT не рекламирует
универсальный внешний endpoint. NTP.reachable не управляет рекламой адресов. универсальный внешний endpoint. NTP.reachable не управляет рекламой адресов.
+11 -7
View File
@@ -13,14 +13,14 @@
8-битный `ver` сохраняется как диагностический счётчик; свежесть определяется 8-битный `ver` сохраняется как диагностический счётчик; свежесть определяется
только timestamp. только timestamp.
Профиль endpoint в SOCKMETA содержит независимые `mapping` и `inbound`, источник `source`, Профиль endpoint в SOCKMETA содержит независимые `mapping` и `inbound`, источник `source`.
`evidence_id` и `checked_at`. Последние относятся к измерению владельца, ID и время измерения не передаются: последний успешный профиль действует до
а не к версии всего NODEINFO: повтор записи или изменение имени не продлевает явного изменения endpoint или подтверждённого нового результата. Повторная
измерение. Новые поля профиля на проводе кодируются явными BE-байтами; проверка с тем же результатом не меняет NODEINFO. Все поля SOCKMETA — отдельные байты;
границы списков metadata/адресов/REALITY также входят в каноническую подпись. границы списков metadata/адресов/REALITY также входят в каноническую подпись.
Алгоритм и условия неопределённости описаны в `doc/nat_detection.txt`. Алгоритм и условия неопределённости описаны в `doc/nat_detection.txt`.
`source=ETCP` обозначает измерение рабочего endpoint, `source=STUN` — резервную оценку `source=ETCP` обозначает измерение рабочего endpoint, `source=STUN` — резервную оценку
по IP/netif с другого порта. Source входит в подпись; SOCKMETA занимает 21 байт. по IP/netif с другого порта. Source входит в подпись; SOCKMETA занимает 5 байт.
STUN mapped endpoint не публикуется как внешний адрес рабочего сокета. STUN mapped endpoint не публикуется как внешний адрес рабочего сокета.
Таблица `node_snapshots` хранит полную сериализованную запись без группового Таблица `node_snapshots` хранит полную сериализованную запись без группового
@@ -29,10 +29,14 @@ STUN mapped endpoint не публикуется как внешний адре
snapshot загрузка использует его. Локальная публикация сохраняется до рассылки; snapshot загрузка использует его. Локальная публикация сохраняется до рассылки;
ошибка сохранения не разрешает публикацию новой версии. ошибка сохранения не разрешает публикацию новой версии.
В проекции адресов сохраняются `nat_mapping`, `nat_inbound`, `nat_evidence`, В проекции адресов сохраняются `nat_mapping`, `nat_inbound`, `nat_source`, `address_kind`.
`nat_checked`, `nat_source`, `address_kind`. Уникальность определяется endpoint и видом адреса, Уникальность определяется endpoint и видом адреса,
а не отображаемым классом NAT. Старый производный формат пересоздаётся; а не отображаемым классом NAT. Старый производный формат пересоздаётся;
bootstrap-загрузка без подписанного snapshot не подтверждает NAT-профиль. bootstrap-загрузка без подписанного snapshot не подтверждает NAT-профиль.
При удалении старых `nat_evidence`/`nat_checked` адреса и REALITY сохраняются для bootstrap,
старые профили сбрасываются, сериализованные snapshots инвалидируются.
Максимальные timestamp snapshots сохраняются, чтобы новая локальная публикация
не откатывала версию даже при коррекции часов. Чат и ключи миграция не изменяет.
Timestamp 0 обозначает bootstrap-сведения без подписи (конфиг, приглашение, Timestamp 0 обозначает bootstrap-сведения без подписи (конфиг, приглашение,
начальные адреса). Они могут помочь установить первое соединение, но не начальные адреса). Они могут помочь установить первое соединение, но не
+1 -1
View File
@@ -25,7 +25,7 @@ uint64_t topo_node_sqlite_snapshot_timestamp(sqlite3* db, uint64_t node_id);
struct TOPO_NODE* topo_node_sqlite_snapshot_load(sqlite3* db, struct TOPO_GROUPS* groups, uint64_t node_id); struct TOPO_NODE* topo_node_sqlite_snapshot_load(sqlite3* db, struct TOPO_GROUPS* groups, uint64_t node_id);
/* Персистентная запись адресов узла в node_addresses (источник истины — BGP/topo_group). /* Персистентная запись адресов узла в node_addresses (источник истины — BGP/topo_group).
* DELETE + INSERT из ni->v4_addrs/v6_addrs; mapping/inbound/evidence из подписанного SOCKMETA. */ * DELETE + INSERT из ni->v4_addrs/v6_addrs; mapping/inbound/source из подписанного SOCKMETA. */
int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE* ni); int topo_node_sqlite_addrs_put(sqlite3* db, uint64_t node_id, struct TOPO_NODE* ni);
/* Есть ли у узла запись мембера хотя бы в одной peers_<ch> (реальный мембер с ключами). */ /* Есть ли у узла запись мембера хотя бы в одной peers_<ch> (реальный мембер с ключами). */