Тема 11

Автономные сети и синхронизация

Автономные сети и синхронизация

В теме 8 были развернуты базовые локальные службы одиночной вычислительной платформы: DNS-сервер, офлайн-библиотека знаний Kiwix, локальный NTP и git-сервер. В теме 10 подробно исследованы физические законы распространения радиоволн, расчет бюджета радиолинии и специальные цифровые протоколы пакетного обмена. Однако в реальном сценарии автономной эксплуатации (сценарии Б и В из темы 1) возникает задача объединения нескольких пространственно разнесенных вычислительных машин — рабочих мест операторов, шлюзов радиосвязи, контроллеров энергосистемы и датчиков — в согласованно работающий распределенный комплекс без обращения к внешней инфраструктуре провайдеров.

В стандартной сетевой архитектуре сетевые узлы опираются на централизованный маршрутизатор с выходом в интернет, арендуют адреса у вышестоящего DHCP-сервера, разрешают доменные имена через глобальные корневые серверы DNS и синхронизируют локальные базы с облачными репозиториями. В условиях автономного узла исчезает каждое из этих внешних звеньев. Топология сети становится динамической: узлы могут внезапно отключаться для сбережения заряда аккумуляторов (тема 3), каналы между ними подвержены затуханию и радиопомехам, а физический кабель может быть поврежден. Централизованный сервер превращается в классическую единую точку отказа (SPOF).

В этой теме рассматриваются принципы построения отказоустойчивых автономных сетей и распределенной синхронизации. Первая часть посвящена физической кабельной инфраструктуре, энергоэффективному питанию сетевого оборудования (PoE) и сегментации сети на доверенные и гостевые зоны под управлением маршрутизаторов OpenWrt. Во второй части исследуются децентрализованные ячеистые сети (mesh-сети) на основе протокола batman-adv и стандарта IEEE 802.11s. Третья часть разбирает одноранговую P2P-синхронизацию данных утилитой Syncthing на базе векторных часов и механизмы разрешения конфликтов. В четвертой части анализируется специфика передачи трафика стека TCP/IP по узкополосным радиоканалам с высоким RTT и потерями, настройка MTU и правила MSS Clamping. Завершают тему локальный мониторинг параметров автономности и правила безопасности изолированного сетевого периметра.

Сетевая инфраструктура и сегментация автономного узла

Проводная среда против радиоэфира

При проектировании локальной сети автономного узла часто возникает искушение полностью отказаться от кабелей в пользу беспроводной связи Wi-Fi. В условиях автономии этот подход порождает серьезные риски 1.

В таблице представлено сопоставление физических сред передачи данных в стационарном периметре автономного узла:

ПараметрПроводная витая пара (UTP/STP Cat 5e/6)Беспроводной эфир (Wi-Fi 2,4 / 5 ГГц)
Пропускная способностьДетерминированная (100–1000 Мбит/с full duplex)Разделяемая между всеми узлами (half duplex)
Устойчивость к внешним помехамВысокая (симметричная линия, экран в STP)Низкая (чувствительна к экранам, помехам, погоде)
Энергопотребление интерфейса0,2–0,5 Вт на порт коммутатора1,5–4,0 Вт на радиомодуль точки доступа
Радиомаскировка (эмиссия)Отсутствует при качественном экранированииПостоянное радиоизлучение маяков (Beacon frames)
Коллизии в средеОтсутствуют (коммутируемый Ethernet)Коллизии растут экспоненциально с числом узлов

Инженерное правило автономного узла: там, где возможно проложить медный кабель, используется провод. Проводная среда гарантирует выделенную полосу без коллизий, не тратит драгоценные милливатты энергии аккумулятора на радиопередатчики высокой мощности и не создает радиочастотного следа за пределами площадки. Беспроводной канал Wi-Fi резервируется исключительно для мобильных терминалов операторов и полевых датчиков, где кабель невозможен физически 1.

Трехуровневая сегментация периметра

Объединение всех сетевых устройств автономного узла в единое несегментированное адресное пространство (flat network) — грубая архитектурная ошибка. Гостевой смартфон, подключившийся к локальному Wi-Fi, начинает рассылать широковещательные пакеты (mDNS, NetBIOS, ARP), перегружая радиоэфир, а вирусное ПО или скомпрометированный датчик получают прямой доступ к консолям управления накопителями и шиной электропитания.

Сеть автономного узла разделяется на три изолированные зоны безопасности:

Зона 1: Аппаратное ядро (Core / Infra)
        ├── Хранилище данных, Kiwix, локальный git (тема 8)
        ├── Резолвер DNS (unbound), сервер времени NTP
        ├── Шлюзы пакетной радиосвязи LoRa/AX.25 (тема 10)
        └── Контроллер BMS аккумулятора и шина телеметрии (тема 4)

Зона 2: Рабочая зона (Work / Operations)
        ├── Защищенные ноутбуки дежурных операторов
        └── Локальные рабочие терминалы с доступом по SSH-ключам

Зона 3: Гостевой периметр (Guest / Perimeter)
        ├── Личные мобильные устройства и смартфоны
        ├── Недоверенные внешние датчики
        └── Временные узлы соседних площадок
Архитектура трехуровневой сегментации сети автономного узла
Сегментация сети на Core, Work и Guest под управлением OpenWrt с питанием от шины DC

Сегментация реализуется на канальном уровне с помощью виртуальных сетей VLAN (стандарт IEEE 802.1Q) либо разделением физических портов управляемого коммутатора 4:

  • VLAN 10 (Core): подсеть 192.168.10.0/24. Прямой доступ к портам администрирования закрыт для всех, кроме доверенных IP зоны Work по статическим сертификатам.
  • VLAN 20 (Work): подсеть 192.168.20.0/24. Доверенные клиенты имеют доступ к сервисным портам ядра (DNS 53/udp, NTP 123/udp, HTTP Kiwix 8080/tcp, Syncthing 22000/tcp).
  • VLAN 30 (Guest): подсеть 192.168.30.0/24. Зона изолирована: межсетевой экран блокирует любые попытки обращения к адресам VLAN 10 и VLAN 20, за исключением локального DNS-сервера. Внутри беспроводной сети VLAN 30 принудительно включен режим межабонентской изоляции (англ. client isolation), запрещающий прямой обмен кадрами между гостевыми клиентами.

Питание сетевого оборудования и технологии PoE

Сетевое оборудование автономного узла (коммутаторы, маршрутизаторы, внешние радиомосты) должно питаться непосредственно от шины постоянного тока 12 В, 24 В или 48 В (тема 3) без промежуточного инвертора 230 В. Питание роутера через инвертор и штатный блок «230 В → 12 В» означает два преобразования подряд и вдобавок ток холостого хода инвертора, который течёт и тогда, когда сеть простаивает; сколько это стоит в ватт-часах для конкретного инвертора и нагрузки, считается в теме 3 симулятором energy.py, а не принимается на веру.

Для передачи питания по сетевому кабелю витой пары совместно с данными используется технология PoE (англ. Power over Ethernet):

  1. Пассивный PoE (англ. passive PoE): постоянное напряжение шины (12 или 24 В) подаётся в свободные пары кабеля 100BASE-TX (пара 4–5 — «плюс», пара 7–8 — «минус») через предохранитель. Это простое решение для уличных точек доступа и камер, но без согласования: источник не проверяет, что на другом конце устройство, рассчитанное на это напряжение. Две жилы пары включены параллельно, поэтому сопротивление петли «туда и обратно» на метр кабеля равно сопротивлению одной жилы 24 AWG — 0,0842 Ом/м (стандарт ограничивает его сверху значением 9,38 Ом/100 м, C-11-09). Для нагрузки 6 Вт от шины 12 В по 30 м кабеля на устройстве остаётся 10,57 В (C-11-08), то есть 12 % напряжения теряется в кабеле, а при 50 м — уже 23 % (net.py --poe-m 50). Многие платы с входом «12 В» при 9–10 В перезагружаются под нагрузкой передатчика.
  2. Стандарты IEEE 802.3af и 802.3at (PoE и PoE+): активное питание напряжением около 48 В с мощностью на выходе источника 15,4 и 30 Вт (C-11-11) 3. Источник (PSE) сначала проверяет сигнатурное сопротивление нагрузки и только потом подаёт напряжение. При 48 В ток вчетверо меньше, чем при 12 В той же мощности, и потери в кабеле (P = I^2 R) меньше в 16 раз: на тех же 30 м падение составляет 0,66 % вместо 12 %.
Падение напряжения в пассивном PoE от длины кабеля
Нагрузка 6 Вт, кабель 24 AWG: при 12 В напряжение на устройстве падает на 12 % уже на 30 м, при 24 и 48 В потери невелики (расчёт net.py)

Сетевая операционная система OpenWrt

В качестве ядра маршрутизации автономного узла оптимально применение аппаратных роутеров на архитектурах MIPS или ARM под управлением дистрибутива OpenWrt 4. В отличие от закрытых заводских прошивок, OpenWrt представляет собой полноценный Linux на базе ядра LTS с пакетным менеджером (opkg до версии 24.10, apk начиная с OpenWrt 25.x), подсистемой фильтрации nftables и поддержкой виртуальных сетевых интерфейсов.

Преимущества OpenWrt на автономном узле:

  • Малое энергопотребление: роутер потребительского класса на SoC вроде MediaTek MT7621 потребляет единицы ватт. Это оценка по паспортам подобных устройств, а не измерение: потребление зависит от числа радиомодулей, мощности передатчиков и нагрузки на порты. Для энергобаланса темы 3 его измеряют на своём экземпляре ваттметром постоянного тока в режиме простоя и под нагрузкой.
  • Единый текстовый конфигурационный интерфейс (UCI): все настройки сети хранятся в простых текстовых файлах каталога /etc/config/ (network, wireless, firewall, dhcp), что позволяет версионировать их в git (тема 8) и восстанавливать одной командой.
  • Полная автономность: встроенный демон dnsmasq обеспечивает локальное разрешение DNS и выдачу адресов DHCP без обращения к внешним серверам.

Пример минимальной конфигурации сегмента ядра в /etc/config/network для устройств с драйвером DSA (OpenWrt 21.02 и новее): VLAN описывается секцией bridge-vlan на мосту, а старая запись вида eth0.10 относится к устройствам со встроенным коммутатором без DSA 4:

config device
	option name 'br-lan'
	option type 'bridge'
	list ports 'lan1'
	list ports 'lan2'

config bridge-vlan
	option device 'br-lan'
	option vlan '10'
	list ports 'lan1:u*'

config interface 'core'
	option device 'br-lan.10'
	option proto 'static'
	option ipaddr '192.168.10.1'
	option netmask '255.255.255.0'

Распределенные mesh-сети без центрального шлюза

Архитектура и ограничения ячеистых сетей

Звездообразная топология с единственным маршрутизатором OpenWrt эффективна внутри компактной аппаратной, однако при территориальном рассредоточении узлов (несколько жилых построек, ретранслятор на мачте, полевой пост наблюдения) центральный маршрутизатор становится критической единицей отказа (SPOF) 5. Если мачта с центральным роутером обесточивается или повреждается ветром, связь между периферийными узлами полностью исчезает, даже если они физически видят друг друга по радиоканалу.

Решением является построение децентрализованной ячеистой сети (англ. mesh network). В mesh-сети каждый узел является одновременно и оконечной станцией, и транзитным маршрутизатором (ретранслятором). Пакеты передаются от источника к адресату по цепочке промежуточных узлов (англ. multi-hop forwarding). При выходе из строя любого промежуточного узла топология динамически перестраивается, направляя поток по альтернативным связям.

Однако ячеистые беспроводные сети подчиняются жесткому физическому ограничению: падение эффективной пропускной способности с каждым транзитным скачком (хопом) 5. Поскольку все узлы типовой mesh-сети работают на одном и том же радиоканале в полудуплексном режиме (англ. half-duplex), промежуточный узел-ретранслятор не может одновременно принимать кадр от предыдущего узла и передавать его следующему. Он вынужден сначала принять пакет в буфер, занять радиоканал повторно и передать его дальше.

Если все узлы цепочки слышат друг друга (одна область конкуренции), в каждый момент передаёт только один из них, и полоса цепочки из N одинаковых переходов равна C/N. В длинной цепочке далёкие узлы не мешают друг другу, и при идеальном расписании передачи через каждые три перехода идут одновременно: полоса перестаёт падать и упирается примерно в C/3; реальный MAC 802.11 со скрытыми узлами и коллизиями даёт ближе к C/4 5. Для цепочки из 4 переходов по 20 Мбит/с модель net.py даёт 6,67 и 5,0 Мбит/с в двух предположениях (C-11-02). Число «20 Мбит/с» здесь — условие задачи: номинальные 54 Мбит/с относятся к 802.11g, а реальная полезная скорость одного перехода зависит от стандарта, ширины канала, расстояния и помех и измеряется iperf3. Отсюда инженерное правило: беспроводные mesh-сети проектируются с минимальным числом транзитных скачков (предпочтительно не более 2–3 хопов), а магистральные линки между кластерами прокладываются кабелем или направленными радиомостами на раздельных частотных каналах.

Протокол B.A.T.M.A.N. Advanced (batman-adv)

В классической маршрутизации (OSPF, RIP, Babel) каждый узел работает на сетевом уровне (Layer 3 OSI), манипулируя IP-пакетами и требуя назначения уникальных IP-подсетей на каждом физическом интерфейсе. Это создает колоссальные сложности в автономных сетях: при смене маршрута IP-адрес шлюза меняется, что приводит к разрыву активных сессий TCP и необходимости переконфигурации служб 5.

Протокол B.A.T.M.A.N. Advanced (Better Approach To Mobile Adhoc Networking, batman-adv) решает эту проблему радикально: он работает на канальном уровне (Layer 2 OSI) в виде модуля ядра Linux 6.

Архитектура модуля ядра batman-adv и стек инкапсуляции кадров
Стек уровней ядра Linux: виртуальный интерфейс bat0, модуль маршрутизации L2 и структура инкапсулированного Ethernet-кадра

С точки зрения операционной системы и прикладных программ batman-adv выглядит как обычный виртуальный Ethernet-интерфейс bat0. Все узлы mesh-сегмента находятся в единой общей IP-подсети (например, 10.0.0.0/24). Компьютеры могут свободно мигрировать между точками доступа, а широковещательные запросы ARP и DHCP прозрачно передаются через всю ячеистую структуру.

Принцип работы алгоритма batman-adv 6:

  1. Каждый узел периодически рассылает во все доступные физические интерфейсы короткие широковещательные пакеты — сообщения инициатора (англ. Originator Messages, OGM).
  2. Сообщение OGM содержит адрес узла-источника и порядковый номер (Sequence Number). Соседи, получив OGM, регистрируют факт приема, пересчитывают метрику качества линка и ретранслируют пакет дальше.
  3. Метрика качества передачи (англ. Transmit Quality, TQ) вычисляется как отношение успешно принятых OGM к общему числу отправленных за скользящее окно (обычно 64 пакета), с учетом асимметрии канала (проверка эхо-ответов от соседа). Значение TQ варьируется от 0 (канал мертв) до 255 (идеальный линк без потерь).
  4. Узел не строит глобальную карту всей сети: для каждого известного адресата узел знает только одно значение — какой из непосредственных физических соседей обеспечивает наилучший интегральный TQ до цели.
  5. При поступлении исходящего Ethernet-кадра ядро упаковывает его в заголовок batman-adv и отправляет в интерфейс выбранного лучшего соседа (next-hop).
Топология ячеистой mesh-сети и динамический обход отказа
При разрыве прямого линка A <-> B протокол batman-adv мгновенно перенаправляет кадры через альтернативный узел E без разрыва TCP-соединений

Настройка интерфейса batman-adv в Linux:

# Добавление физического Wi-Fi интерфейса в mesh-мост
ip link set dev wlan0 down
iw dev wlan0 set type ibss
ip link set dev wlan0 up
iw dev wlan0 ibss join autonomy-mesh 2412

# Подключение wlan0 к batman-adv
batctl if add wlan0
ip link set dev bat0 up
ip addr add 10.0.0.1/24 dev bat0

Стандарт IEEE 802.11s и гибридные топологии

Альтернативой модулю ядра batman-adv является стандарт IEEE 802.11s — официальное расширение стандарта Wi-Fi для ячеистых сетей, поддерживаемое на уровне беспроводного стека mac80211 ядра Linux 7.

В 802.11s узлы (Mesh Points, MP) устанавливают прямые радиосвязи (Mesh Peering) без участия классической точки доступа. Маршрутизация кадров выполняется протоколом HWMP (англ. Hybrid Wireless Mesh Protocol), сочетающим реактивный поиск маршрутов по запросу (по аналогии с AODV) и проактивное построение дерева до корневого узла (Root Node) 7.

Сравнение batman-adv и IEEE 802.11s:

  • 802.11s работает только поверх радиоинтерфейсов Wi-Fi и не умеет напрямую объединять разнородные каналы в одну сеть без внешнего сетевого моста (bridge).
  • batman-adv не привязан к Wi-Fi: он объединяет в один интерфейс bat0 любые интерфейсы, передающие кадры Ethernet (радио в режиме ad-hoc или mesh point, витая пара, VLAN, туннель уровня L2), и выбирает путь с лучшей метрикой TQ — например, кабель, а при его обрыве радио. Последовательный радиомодем со SLIP в этот список не входит: SLIP переносит только IP-пакеты (уровень L3), а batman-adv работает с кадрами Ethernet (L2). Поверх такого канала маршрутизируют на уровне IP (Babel, статические маршруты).

Направленные линки, AREDN и грозозащита мачт

Между зданиями и постами, разнесёнными на сотни метров и километры, полудуплексную цепочку mesh заменяют направленными радиомостами точка — точка на отдельных каналах: каждый мост — отдельный переход, не мешающий соседям, и формула C/N к ним не применяется. Расчёт такого моста — бюджет линии из темы 10: усиление направленных антенн, потери фидера, свободная первая зона Френеля над препятствиями посередине трассы. Типичная ошибка — проверить «прямую видимость в бинокль» и не проверить зону Френеля: на трассе 2 км на 5 ГГц её радиус посередине 5,2 м, и крыша соседнего сарая уже ощутимо ослабляет сигнал (расчёт linkbudget.py --freq 5500 --dist 2 из темы 10).

AREDN (Amateur Radio Emergency Data Network) — готовая прошивка на основе OpenWrt для любительских mesh-сетей на частотах Wi-Fi, работающих в любительских диапазонах: узлы сами находят друг друга, маршрутизация (OLSR, в новых версиях Babel) и локальные службы настроены заранее. Ограничение то же, что у любой любительской связи: работа в любительских полосах требует позывного у каждого оператора, а шифрование трафика правилами любительской службы обычно запрещено. Для автономного узла без любительских позывных AREDN — образец архитектуры, а не готовое решение; в нелицензируемых полосах Wi-Fi ту же роль играют OpenWrt с batman-adv или 802.11s.

Мачта с антенной — самая высокая проводящая точка площадки. Мачту заземляют отдельным проводником кратчайшим путём, оплётку кабеля снижения заземляют у входа в здание, на ввод ставят грозоразрядник; кабель Ethernet с крыши заводят через устройство защиты от перенапряжений, а не напрямую в коммутатор ядра. Механизмы перенапряжений и выбор защиты разобраны в теме 12; в этой теме важен вывод для топологии: уличные точки доступа и мосты подключают к ядру через отдельный порт и предохранитель цепи PoE, чтобы удар в мачту не вывел из строя всю сеть.

Динамическая перемаршрутизация при отказах промежуточных узлов

Ключевое эксплуатационное свойство mesh-сети — скорость обнаружения аварии и сходимости топологии (англ. convergence time).

Если узел B внезапно обесточивается:

  1. Соседние узлы A и C фиксируют прекращение поступления сообщений OGM от узла B.
  2. Через несколько пропущенных интервалов OGM (по умолчанию OGM рассылается раз в секунду) метрика соседа B падает до нуля. Точное время зависит от версии алгоритма (B.A.T.M.A.N. IV или V) и параметров; в ЛР 11 время восстановления измеряется, а не берётся из текста.
  3. В таблице транзитной пересылки маршрут к удаленным узлам переключается на альтернативного соседа с наилучшим из оставшихся TQ (например, через транзитный узел E на рисунке топологии).
  4. Адреса конечных хостов не изменились, поэтому соединения TCP не рвутся: TCP видит паузу (одну или несколько повторных передач по RTO) и продолжает поток по новому пути. Это верно не только для batman-adv: при смене маршрута на уровне L3 (Babel, OSPF) адреса концов соединения тоже не меняются, и TCP переживает перестройку, если она укладывается в его таймауты. Рвётся соединение тогда, когда меняется адрес самого хоста (NAT на другом шлюзе, новый адрес по DHCP).

Статическая маршрутизация такого не умеет: если сосед B завис или потерял радиосвязь дальше, а его интерфейс к A остался поднят, ядро A продолжает отправлять пакеты в B. Отказ соседа без потери несущей замечает только протокол, который регулярно проверяет соседа. Именно это сравнивается в ЛР 11.

Распределенная синхронизация данных между узлами

Архитектура протокола Syncthing (BEP)

Когда сетевая связность между узлами налажена, возникает задача репликации файлов: базы оперативных заметок, журналов телеметрии, актуальных карт и конфигураций. Использование традиционных протоколов клиент-серверного доступа (SMB, NFS, HTTP) в автономных сетях неэффективно: если сервер файлов выключен или недоступен из-за радиопомех, работа остальных узлов останавливается 8.

Современным стандартом одноранговой децентрализованной репликации является Syncthing 8. Это открытая распределенная система синхронизации файлов, не требующая центрального сервера и функционирующая по протоколу обмена блоками (англ. Block Exchange Protocol, BEP).

Ключевые принципы архитектуры Syncthing:

  1. Криптографическая идентификация узлов: у каждого узла нет логина и пароля; идентификатором узла служит Device ID — строка из 56 символов в формате Base32, представляющая собой SHA-256 хэш открытого ключа сертификата TLS, сгенерированного при первом запуске узла 8.
  2. Взаимная аутентификация и сквозное шифрование: все сетевые соединения между узлами устанавливаются строго по протоколу TLS 1.3 с взаимной проверкой сертификатов (mTLS). Подмена данных или прослушивание пакетов в незащищенном радиоэфире mesh-сети криптографически исключены.
  3. Блочная синхронизация: файл разбивается на блоки фиксированного размера (от 128 КиБ до 16 МиБ в зависимости от размера файла), каждый блок индексируется хешем SHA-256 8. Если в файле заменить байты на месте, передаётся только изменённый блок. Но границы блоков стоят на фиксированных смещениях: вставка одной строки в начало файла сдвигает все последующие байты, хеши всех следующих блоков меняются, и передаётся весь хвост файла. Резервные копии в теме 9 используют другую схему — нарезку по содержимому (англ. content-defined chunking, CDC), где границы блоков привязаны к самим данным и вставка затрагивает один-два блока. Для журнала, дописываемого в конец, фиксированные блоки работают хорошо; для текста, правящегося в начале, — плохо.
Одноранговый кластер Syncthing и разрешение конфликтов параллельного изменения
Syncthing в изолированном сегменте: поиск соседей через UDP broadcast, обмен блоками по TLS и сохранение конфликтных версий

Обнаружение соседей в изолированной сети

В стандартной заводской конфигурации Syncthing полагается на глобальные серверы обнаружения (Global Discovery) и общедоступные узлы ретрансляции трафика (Relay Servers), расположенные в сети Интернет.

В условиях автономного узла внешние серверы недоступны. Более того, включенные по умолчанию попытки отправить запросы к глобальным discovery-серверам засоряют локальный канал бесполезным трафиком и вызывают постоянные задержки сетевого стека по таймаутам DNS.

Настройка Syncthing для полностью автономной работы:

  1. Отключение глобального обнаружения: в конфигурации config.xml отключаются параметры globalAnnounceEnabled и relaysEnabled.
  2. Активация локального обнаружения (Local Discovery): узлы находят друг друга автоматически путем периодической отправки широковещательных пакетов (IPv4 Broadcast на порт 21027/udp) и групповых пакетов (IPv6 Multicast на адрес ff12::8384). Пакет содержит Device ID отправителя и порт прослушивания (стандартно 22000/tcp).
  3. Статические адреса для радиоканалов: если узлы соединены через медленный радиомодем или маршрутизатор, фильтрующий широковещательный трафик, адрес соседа задается статически в явном виде: tcp://10.0.0.2:22000.

Векторные часы и разрешение конфликтов параллельной правки

В распределенной системе без общего источника точного времени (тема 8) невозможно определить, какая версия файла новее, просто сравнивая метки времени операционной системы (mtime): часы на двух изолированных ноутбуках могут расходиться на минуты или часы 8.

Syncthing использует векторы версий (англ. version vectors) — разновидность векторных часов, предложенных Фиджем и Маттерном в 1988 году 9; скалярные часы Лампорта (1978) упорядочивают события, но не позволяют отличить «после» от «одновременно». Каждый файл сопровождается версионным вектором — списком пар вида:

V = \{ (\text{Device}_1, c_1), (\text{Device}_2, c_2), \dots, (\text{Device}_k, c_k) \}

где c_i — монотонно возрастающий локальный счетчик модификаций файла на узле \text{Device}_i.

Правило доминирования версий:

  • Версия V_A признается более новой, чем V_B (V_A > V_B), если для всех узлов счетчики V_A не меньше счетчиков V_B (\forall i: c_i^A \ge c_i^B), и существует хотя бы один узел, где счетчик строго больше (c_j^A > c_j^B). В этом случае файл на узле B молча и безопасно обновляется содержимым файла A.
  • Если же на узле 1 счетчик увеличился (c₁ = 5, c₂ = 2), а на узле 2 одновременно файл был изменен локально (c₁ = 4, c₂ = 3), ни один из векторов не доминирует над другим. Это состояние называется параллельным конфликтом (англ. concurrent conflict) 9.

Правило разрешения конфликта (описание в документации Syncthing, раздел «Conflicting Changes» 14). Вектор версий решает только вопрос «есть ли конфликт»; какая версия уступит, решает время изменения:

  1. Версия с более старым временем изменения (mtime) переименовывается в конфликтную копию, под исходным именем остаётся более новая.
  2. Только если mtime равны, конфликтной становится версия устройства с большим значением Device ID (сравниваются первые 63 бита).
  3. Имя копии содержит дату, время и короткий ID устройства, которое последним изменило эту версию:
notes.sync-conflict-20261020-143015-V7XQ4KM.txt
  1. Копия синхронизируется на все узлы как обычный файл; оператор сливает правки вручную (diff, редактор) и удаляет копию.

Из правила 1 следует практический вывод: разрешение конфликта всё же зависит от часов. Если часы одного ноутбука ушли на сутки вперёд (тема 8), его версия будет «побеждать» в каждом конфликте. Обе версии при этом сохраняются, поэтому данные не теряются, но под исходным именем может оказаться не та версия, которую ожидали. Если одна сторона файл изменила, а другая удалила, побеждает изменение: файл восстанавливается.

Синхронизация не заменяет резервную копию

Синхронизация реплицирует любое изменение — в том числе удаление, перезапись мусором и шифрование файлов вредоносной программой. Удалённый на одном узле файл через секунды исчезает на всех. Резервная копия (тема 9), наоборот, хранит состояние на моменты в прошлом и не меняется от того, что происходит с рабочими данными; поэтому её точка восстановления (RPO) — время последнего снимка, а у синхронизации «точки в прошлом» нет вовсе. Механизм версий файлов Syncthing (File Versioning) хранит прежние версии на принимающем узле и спасает от части ошибок, но живёт на том же диске, с той же папкой, и не защищает от отказа узла и от удаления самих версий. Поэтому на Полигоне синхронизация отвечает за доступность данных на нескольких машинах, а резервное копирование (restic или borg по теме 9) — за возможность вернуться назад; опыт «удаление реплицируется» входит в ЛР 11.

Что нельзя синхронизировать в P2P-сети

Попытка использовать Syncthing для синхронизации любых произвольных каталогов операционной системы приведет к сбоям и разрушению данных.

Через P2P-синхронизацию не передают:

  1. Активные файлы баз данных (SQLite, PostgreSQL, MySQL): СУБД непрерывно пишут в файлы страниц и журналов упреждающей записи (WAL — Write-Ahead Log). Попытка поблочно реплицировать открытый файл .db во время активных транзакций приведет к записи на удаленном узле несогласованного состояния («разорванной страницы», англ. torn page), что необратимо разрушит базу данных. Синхронизировать можно только заблаговременно снятые дампы (например, файл, созданный командой sqlite3 data.db ".backup backup.sq3").
  2. Виртуальные диски и образы ВМ (raw, qcow2): файлы размером в десятки гигабайт с постоянной случайной записью блоков создают непрерывную нагрузку на радиоканал и процессор.
  3. Системные каталоги ОС (/etc, /var, /dev): Syncthing работает в пространстве пользователя и не сохраняет специфические права суперпользователя, расширенные атрибуты безопасности (SELinux/xattr) и специальные файлы устройств (пайпы, сокеты).

Для синхронизации текстовых конфигураций и программного кода лучшим инструментом остается Git 10. В условиях отсутствия онлайн-хостингов Git функционирует через локальные bare-репозитории либо отчуждаемые пакетные архивы git bundle (тема 8). Команда git bundle create updates.bundle master упаковывает всю историю коммитов и веток в единый файл, который переносится на соседний узел через Syncthing или на флеш-карте и распаковывается командой git pull updates.bundle.

Радиоканал как транспорт для протоколов стека TCP/IP

Инкапсуляция IP в радиопакеты: SLIP, PPP, AX.25

Когда требуется передать IP-трафик между удаленными автономными узлами, разделенными десятками километров, единственным физическим носителем становится УКВ или КВ радиостанция (тема 10) 11.

Для передачи IP-пакетов через последовательные интерфейсы радиомодемов применяются протоколы инкапсуляции:

  1. SLIP (Serial Line Internet Protocol, RFC 1055): предельно простой протокол кадрирования. Каждый IP-пакет обрамляется байтом 0xC0 (END). Если байт 0xC0 встречается внутри данных, он заменяется двухбайтовой последовательностью 0xDB 0xDC. Протокол не имеет механизмов согласования адресов, проверки контрольных сумм и сжатия заголовков.
  2. PPP (Point-to-Point Protocol, RFC 1661): стандарт двухточечной связи. Включает контроль целостности кадра (FCS — 16-битный CRC), согласование сетевых параметров по протоколу IPCP и возможность аутентификации.
  3. AX.25 (Amateur Packet Radio Protocol): радиолюбительский протокол канального уровня, поддерживающий аппаратные и программные модемы TNC (Terminal Node Controller, утилита direwolf, тема 10). Ядро Linux содержит встроенную поддержку AX.25: утилита kissattach связывает последовательный порт радиомодема с сетевым интерфейсом ax0, поверх которого операционная система способна маршрутизировать стандартные IPv4-пакеты 11.

Проблема высокого RTT, потерь и деградация TCP

Протокол TCP разрабатывался для проводных сетей с низкой задержкой (RTT единицы миллисекунд) и крайне низкой вероятностью битовых ошибок (BER < 10⁻⁹). В проводном Ethernet практически единственной причиной потери пакета является переполнение очереди коммутатора (англ. buffer overflow) при перегрузке 12.

При передаче через радиоэфир физическая реальность меняется кардинально 12:

  • Круговая задержка велика из-за низкой скорости и полудуплекса. Кадр 1500 + 18 байт на 1200 бит/с передаётся 10,12 с (C-11-05); с подтверждением и задержкой включения передатчика 300 мс RTT одного радиоперехода не меньше 11,1 с (C-11-06) — и это нижняя граница, без ожидания свободного канала. Начальное значение таймера повторной передачи TCP — 1 с (C-11-07) 13: первый сегмент будет повторён раньше, чем могло прийти подтверждение.
  • Ошибки бит в радиоканале на порядки чаще, чем в проводе. Значение BER зависит от запаса линии (тема 10); в примерах этого раздела взято BER = 2 \cdot 10^{-4} как условие задачи.
Временная диаграмма TCP на радиоканале 1200 бит/с
Кадр 1500 байт занимает эфир 10,1 с, а таймер RTO истекает через 1 с: повторы начинаются до прихода подтверждения и занимают тот же полудуплексный канал

Когда пакет теряется из-за помехи, алгоритм управления перегрузкой TCP (Reno, CUBIC) принимает эту потерю за перегрузку сети 12. Реакция зависит от того, как потеря обнаружена. Если пришли три повторных подтверждения (сегменты после потерянного дошли), окно перегрузки (англ. congestion window, cwnd) уменьшается примерно вдвое и включается быстрое восстановление. Если же подтверждений нет вовсе и истёк таймер RTO, cwnd сбрасывается до одного сегмента, начинается медленный старт, а RTO удваивается при каждом следующем истечении. На медленном радиоканале с длинными кадрами срабатывает как раз второй случай: окно мало, повторным подтверждениям неоткуда взяться.

Итог: скорость падает почти до нуля, а повторы занимают тот же полудуплексный канал, по которому должны прийти подтверждения. Подробно механизмы TCP разобраны в курсе «Компьютерные сети», тема 13; здесь важно следствие для автономного узла: по радиоканалу передают короткие сообщения поверх UDP с собственным подтверждением (CoAP — RFC 7252, протоколы store-and-forward из темы 10) или используют TCP с увеличенными таймаутами и малым MSS, а большие файлы переносят носителем или ночным окном связи.

Алгоритм BBR (net.ipv4.tcp_congestion_control=bbr) не считает каждую потерю перегрузкой и на каналах со случайными потерями ведёт себя лучше Reno и CUBIC, но таймер RTO и полудуплекс он не отменяет.

Оптимизация MTU и MSS Clamping

Стандартный размер максимального блока передачи (англ. Maximum Transmission Unit, MTU) в сетях Ethernet составляет 1500 байт 1.

В радиоканале с высокой вероятностью битовой ошибки MTU 1500 байт почти не работает. Вероятность успешного прохождения кадра длиной L бит при вероятности ошибки в одном бите BER рассчитывается по формуле Бернулли:

P_{success} = (1 - BER)^L

Соответственно, вероятность искажения хотя бы одного бита (и, как следствие, сброса всего пакета контрольной суммой CRC32):

P_{loss} = 1 - (1 - BER)^L

Числовой пример: расчет потерь пакетов от размера MTU

Сравним поведение двух пакетов при передаче по радиоканалу с типичным уровнем шума, обеспечивающим вероятность битовой ошибки BER = 2 \cdot 10^{-4} (один сбойный бит на каждые 5000 бит):

  • Пакет 1: Стандартный Ethernet MTU = 1500 байт (1500 · 8 = 12 000 бит).
  • Пакет 2: Оптимизированный радио-MTU = 256 байт (256 · 8 = 2048 бит).

Вероятность потери пакета 1 (MTU 1500): P_{loss}(1500) = 1 - (1 - 2 \cdot 10^{-4})^{12\,000} = 1 - (0,9998)^{12\,000} \approx 1 - 0,0907 = 0,9093 \text{ (то есть } 90,93 \% \text{)}

Вероятность потери пакета 2 (MTU 256): P_{loss}(256) = 1 - (1 - 2 \cdot 10^{-4})^{2048} = 1 - (0,9998)^{2048} \approx 1 - 0,6638 = 0,3362 \text{ (то есть } 33,62 \% \text{)}

Таким образом, при BER = 2 \cdot 10^{-4} кадр 1500 байт теряется с вероятностью 90,9 % (C-11-01, расчёт net.py).

Кадр 256 байт при той же BER теряется с вероятностью 33,6 % (C-11-03): доля доставленных с первой попытки растёт с 9 % до 66 %. Уменьшать MTU бесконечно тоже нельзя: заголовки IP и TCP (40 байт) занимают всё большую долю кадра. Если считать полезную долю с учётом повторов, \eta = \frac{L - 40}{L}(1 - P_{loss}), то её максимум при BER = 2 \cdot 10^{-4} достигается при MTU 179 байт и равен 58,3 % (C-11-04). Оптимум зависит от BER: при 10^{-4} он около 244 байт, при 10^{-3} — около 93 байт (net.py --ber 1e-3). Формула предполагает независимые ошибки бит; в радиоканале ошибки идут пачками, и это ограничение названо в шапке net.py.

Вероятность потери кадра от MTU и BER
Потеря кадра растёт с длиной кадра тем быстрее, чем выше BER; при BER 2·10⁻⁴ кадр 1500 байт теряется в 90,9 % случаев (расчёт net.py)

Однако простого уменьшения MTU на сетевом интерфейсе радиомодема (ip link set dev ax0 mtu 256) недостаточно: удаленные клиенты в сети Ethernet не знают об узком месте и продолжают отправлять пакеты размером 1500 байт с установленным флагом «Не фрагментировать» (DF — Don't Fragment). Пакеты отбрасываются, а сообщения ICMP «Destination Unreachable, Fragmentation Needed» часто блокируются некорректно настроенными экранами (проблема «черной дыры Path MTU Discovery», PMTUD Black Hole) 1.

Решение: принудительная перезапись максимального размера сегмента (MSS Clamping) на пограничном маршрутизаторе OpenWrt с помощью nftables 4:

# Правило nftables: перехват рукопожатия TCP SYN и принудительное ограничение MSS
nft add rule inet fw4 forward tcp flags syn tcp option maxseg size set 216

(При MTU = 256 байт вычитание 20 байт заголовка IP и 20 байт заголовка TCP даёт MSS = 256 − 40 = 216 байт.)

Локальный мониторинг и телеметрия узла

Метрики автономности: питание, температура, дисковый износ

В автономной системе мониторинг решает принципиально иную задачу, чем в корпоративном ЦОД. Вместо загрузки очередей веб-сервера первостепенными становятся метрики живучести аппаратной платформы и энергосистемы:

  1. Энергетические метрики (от контроллера заряда и BMS, тема 4):
    • Напряжение главной шины питания (U_шины, В) с точностью до 0,05 В.
    • Ток заряда/разряда (I_шины, А).
    • Расчетная глубина разряда и оставшаяся емкость (SOC, %).
  2. Температурные метрики (от датчиков I²C/1-Wire и термозон процессора):
    • Температура аккумуляторного блока (критично для LiFePO4: заряд ниже 0 °C разрушает структуру электродов).
    • Температура радиатора пассивного охлаждения процессора и контроллера SSD.
  3. Состояние накопителей (по данным демона smartd):
    • Рост атрибутов дефектных секторов (Reallocated / Pending).
    • Свободное дисковое пространство на корневом и архивном разделах (порог тревоги: менее 15 % остатка).
  4. Сетевые метрики:
    • Доступность шлюзов и ключевых узлов кластера.
    • Уровень шума в эфире (RSSI / SNR) и статистика потерянных пакетов.

Легковесный сбор телеметрии без внешних облаков

Развертывание тяжелых промышленных систем мониторинга (Zabbix, стек ELK) на автономном узле нерационально: они потребляют гигабайты оперативной памяти и сотни мегабайт дисковой записи в сутки, расходуя ресурс флеш-памяти и батарей.

Архитектура локального сбора телеметрии строится на легковесных компонентах:

  • Периодический сбор скриптами (Cron / Systemd Timers): легковесный скрипт на Bash или Python опрашивает интерфейсы /sys/class/thermal/ и /sys/class/power_supply/ раз в 60 секунд.
  • Хранилище временных рядов (TSDB): использование локальной базы данных SQLite с кольцевой перезаписью или компактного экземпляра VictoriaMetrics в режиме одного бинарника без внешних зависимостей.
  • Кольцевые журналы в оперативной памяти (tmpfs): оперативные логи пишутся в RAM-диск /run, сбрасываясь на энергонезависимый накопитель только при аварийных событиях, что предотвращает износ SSD.

Локальные оповещения и аварийная сигнализация

Поскольку отправка email-уведомлений или push-сообщений в Telegram без интернета невозможна, каналы оповещения оператора реализуются физическими и локальными средствами:

  1. Аппаратный звуковой сигнализатор (пьезоэлектрический зуммер / buzzer): подключен к контактам GPIO одноплатного компьютера. При критическом падении напряжения шины (например, U < 11,8 В) звучит прерывистый сигнал тревоги, пробуждающий дежурного оператора.
  2. Светодиодная шкала статуса: дискретная индикация уровней деградации узла (зеленый — Уровень 0–1, желтый — Уровень 2, мигающий красный — авария питания).
  3. Локальный пейджинг через XMPP/IRC (тема 8): бот рассылает текстовые предупреждения в локальный групповой чат автономного узла.

Распределение ролей между машинами и координация людей

Службы темы 8 (DNS, время, справочные материалы, файлы, мониторинг) не обязаны жить на одной машине, но и разносить их на все машины подряд вредно: каждая лишняя копия службы — лишний потребитель энергии и лишний источник рассинхронизации. Рабочее разбиение для Полигона: «сервер» (одноплатный компьютер или ноутбук с наименьшим потреблением) держит DNS, DHCP, время, мониторинг и основную копию данных; рабочие места хранят свои рабочие папки и синхронизируют их с сервером; резервная машина выключена большую часть времени, получает резервные копии по расписанию (тема 9) и умеет за известное время взять на себя роль сервера. Что именно и за сколько минут переносится на резервную машину, записывается в регламент темы 13 и проверяется учением.

Организационная часть ломается раньше технической: два оператора правят один документ, никто не знает, кто сейчас дежурит, сообщение по радио принято, но не передано дальше. Поэтому на сервере держат простые локальные инструменты координации: доску задач (текстовый файл или вики wiki.polygon.internal), общий календарь окон связи и дежурств, журнал смен, куда каждый записывает принятые решения и изменения конфигурации. Правило записи «кто — что — когда — почему» дешевле любого протокола разрешения конфликтов.

Безопасность изолированного сетевого сегмента

Защита периметра и изоляция клиентов (Client Isolation)

Изолированная сеть тоже нуждается в межсетевом экране, хотя у неё нет выхода в интернет. Внутри автономного периметра угрозы безопасности возникают из-за подключения гостевых смартфонов, использования непроверенных флеш-накопителей и возможных ошибок конфигурации.

Базовые правила фильтрации трафика nftables на шлюзе OpenWrt:

# Создание таблицы фильтрации автономного шлюза
nft add table inet autonomy_filter
nft add chain inet autonomy_filter forward '{ type filter hook forward priority 0; policy drop; }'

# 1. Разрешить установленные и связанные соединения
nft add rule inet autonomy_filter forward ct state established,related accept

# 2. Разрешить трафик из рабочей зоны (Work) к службам ядра (Core)
nft add rule inet autonomy_filter forward iifname "veth-rw" oifname "veth-rc" accept

# 3. Разрешить гостям (Guest) доступ ТОЛЬКО к локальному DNS и Kiwix на ядре
nft add rule inet autonomy_filter forward iifname "veth-rg" oifname "veth-rc" ip daddr 192.168.10.2 udp dport 53 accept
nft add rule inet autonomy_filter forward iifname "veth-rg" oifname "veth-rc" ip daddr 192.168.10.2 tcp dport 8080 accept

# Все остальные попытки пересылки из Guest в Core и Work блокируются политикой drop

В беспроводной точке доступа гостевого периметра в обязательном порядке активируется опция isolate:

# /etc/config/wireless
config wifi-iface 'guest_ui'
	option device 'radio0'
	option mode 'ap'
	option ssid 'Autonomy-Guest'
	option network 'guest'
	option isolate '1'

Флаг isolate '1' запрещает радиомодулю Wi-Fi пересылать кадры между беспроводными клиентами одной и той же сети. Зараженный смартфон гостя не сможет атаковать соседние телефоны или сканировать порты других пользователей.

Предотвращение утечек трафика и принудительный перехват DNS

Мобильные операционные системы и браузеры проверяют наличие интернета: запрашивают по HTTP служебные адреса (детектор адаптивного портала, англ. captive portal detection: у Android — http://connectivitycheck.gstatic.com/generate_204, у устройств Apple — http://captive.apple.com/hotspot-detect.html) и могут шифровать DNS-запросы: DNS-over-TLS (DoT) работает на порту 853 (C-11-10) 2, DNS-over-HTTPS (DoH) — на порту 443 вместе с обычным HTTPS.

В изолированной сети такое поведение приводит к зависанию приложений и ложным сообщениям «Сеть без доступа к интернету, отключиться?».

Для нейтрализации утечек на маршрутизаторе настраивается принудительный перехват (DNS Hijacking):

# Перенаправление всех запросов на 53 порт любого внешнего IP на локальный DNS узла
nft add table inet nat
nft add chain inet nat prerouting '{ type nat hook prerouting priority -100; }'
nft add rule inet nat prerouting udp dport 53 redirect to :53
nft add rule inet nat prerouting tcp dport 53 redirect to :53

# DoT (853/tcp) отклоняется сразу: клиент переходит на обычный DNS,
# а не ждёт таймаута
nft add rule inet autonomy_filter forward tcp dport 853 reject with tcp reset

Перехват обычного DNS (порт 53) прост; DoT отклоняется по порту; DoH по порту отличить от HTTPS нельзя, его можно ограничить только списком адресов известных резолверов, и полностью это не удаётся. Без интернета это не утечка, а задержка: клиент ждёт ответа резолвера, которого нет.

Чтобы детектор адаптивного портала счёл сеть исправной, нужны две службы. DNS не умеет отвечать кодом HTTP: он лишь возвращает адрес. Поэтому локальный резолвер (dnsmasq или unbound, тема 8) отвечает на имена проверочных узлов адресом шлюза, а на шлюзе работает HTTP-ответчик, который на /generate_204 отдаёт пустой ответ с кодом 204, а на страницу Apple — ожидаемую страницу «Success». Если ответчика нет, устройство пишет «сеть без доступа к интернету» — для автономного узла это честное сообщение, и многие операторы оставляют его. Если же нужна страница с правилами для гостей, ответчик отдаёт её вместо 204, и устройство само откроет окно портала. Обе ветки собираются в ЛР 11.

Обновления только из локального зеркала

Узел, не смотрящий наружу, обновляется только из своего зеркала пакетов с проверенной подписью (тема 7). На уровне сети это одно правило: машинам сегментов Work и Guest разрешено обращаться к зеркалу на сервере ядра по HTTP, но не наружу, даже если внешний канал временно появился; роутеры OpenWrt получают пакеты (apk в 25.x) из того же локального зеркала. Тогда появление канала связи не превращается в неконтролируемое обновление всех машин сразу, а обновление проходит тот же путь проверки подписи, что и в теме 7.

Что эта модель не учитывает

  1. Преднамеренные помехи радиоканалу не рассматриваются: от них нет сетевой защиты, есть только провод там, где он возможен (раздел о проводной среде) и запасной канал (тема 10).
  2. Модель не учитывает византийские отказы (англ. Byzantine faults) в mesh-сети: ситуацию, когда скомпрометированный или неисправный узел намеренно транслирует фиктивные сообщения OGM с максимально возможным TQ, затягивая весь транзитный трафик сети на себя («черная дыра» маршрутизации).
  3. Модель протокола Syncthing предполагает достаточный объем дискового пространства на каждом принимающем узле: при исчерпании свободного места репликация блокируется для всей общей папки.
  4. Сети с длительными разрывами связности (DTN, RFC 9171) не рассматриваются: при разрывах на часы и сутки TCP/IP неприменим, нужен перенос сообщений с хранением (тема 10).
  5. net.py считает ошибки бит независимыми, цепочку mesh — однородной, а RTT — без ожидания канала и очередей; реальные значения хуже по задержке и могут быть лучше по потерям (пачки ошибок).
  6. Падение напряжения PoE посчитано для холодного кабеля без разъёмов; при +40 °C сопротивление меди выше примерно на 8 %.

Итоги темы

Сеть автономного узла строится без провайдера, центрального шлюза и облачных служб. Провод там, где его можно проложить, надёжнее и экономнее радио; сегменты Core, Work и Guest с проверенной матрицей доступа защищают службы ядра от ошибок и от гостевых устройств. Питание сетевого оборудования от шины постоянного тока убирает лишние преобразования, но пассивный PoE от 12 В на десятках метров теряет заметную долю напряжения, и это считается, а не угадывается.

Mesh-сеть устраняет единую точку отказа, но платит полосой: в одной области конкуренции цепочка даёт C/N, в длинной цепочке — около C/3–C/4. Отказ соседа без потери несущей статическая маршрутизация не замечает; это делает только протокол, регулярно проверяющий соседей, и время восстановления у него — измеримая величина, а не обещание. Смена маршрута не рвёт TCP, пока адреса концов соединения не меняются.

Syncthing обнаруживает конфликт по векторам версий, а уступающую версию выбирает по времени изменения, поэтому часы узлов всё равно важны. Блоки фиксированного размера экономны для дописывания и расточительны для вставки. Синхронизация реплицирует и удаление, поэтому не заменяет резервную копию из темы 9.

Радиоканал как транспорт IP требует малого MTU, учёта RTT в секундах и осторожности с TCP: потеря кадра растёт с его длиной, а оптимальный MTU определяется BER. Детектор адаптивного портала удовлетворяется только HTTP-ответчиком, а не DNS. Обновления приходят только из локального зеркала, а роли машин и правила координации людей записываются заранее и проверяются учениями темы 13.

Литература

  1. Perahia E., Stacey R. Next Generation Wireless LANs: 802.11n and 802.11ac. — 2nd ed. — Cambridge University Press, 2013.
  2. RFC 7858. Specification for DNS over Transport Layer Security (TLS). — IETF, 2016. https://www.rfc-editor.org/rfc/rfc7858
  3. IEEE Std 802.3bt-2018. IEEE Standard for Ethernet — Amendment 2: Physical Layer and Management Parameters for Power over Ethernet over 4 Pairs. — IEEE, 2019.
  4. OpenWrt Documentation: Network configuration (UCI, DSA). — https://openwrt.org/docs/guide-user/network/dsa/dsa-mini-tutorial
  5. Akyildiz I. F., Wang X. A survey on wireless mesh networks // IEEE Communications Magazine. — 2005. — Vol. 43, No. 9. — P. S23–S30.
  6. Seither D., König A., Hollick M. Routing performance of Wireless Mesh Networks: A practical evaluation of BATMAN advanced // IEEE 36th Conference on Local Computer Networks (LCN). — IEEE, 2011.
  7. IEEE Std 802.11s-2011. Amendment 10: Mesh Networking. — IEEE, 2011.
  8. Syncthing Project. Block Exchange Protocol v1. — https://docs.syncthing.net/specs/bep-v1.html
  9. Mattern F. Virtual Time and Global States of Distributed Systems // Parallel and Distributed Algorithms. — North-Holland, 1989. — P. 215–226.
  10. Chacon S., Straub B. Pro Git. — 2nd ed. — Apress, 2014. https://git-scm.com/book
  11. Beech W. A., Nielsen D. E., Taylor J. AX.25 Link Access Protocol for Amateur Packet Radio. Version 2.2. — Tucson Amateur Packet Radio (TAPR), 1998.
  12. Fall K., Floyd S. Simulation-based Comparisons of Tahoe, Reno, and SACK TCP // ACM SIGCOMM Computer Communication Review. — 1996. — Vol. 26, No. 3. — P. 5–21.
  13. RFC 6298. Computing TCP's Retransmission Timer. — IETF, 2011. https://www.rfc-editor.org/rfc/rfc6298
  14. Syncthing Documentation. Understanding Synchronization (раздел Conflicting Changes). — https://docs.syncthing.net/users/syncing.html