====== ZeroTier — оверлей-сеть ====== Self-hosted ZeroTier-сеть, через которую обеспечивается удалённый доступ ко всем домашним сервисам, без необходимости публиковать SSH/админ-порты в интернет. Контроллер свой, не ZeroTier Central. ===== TL;DR — самое важное ===== * **Сеть**: ''c53bc939c1ce37d2'' (имя ''melnoff-main-network''), подсеть ''172.25.30.0/24''. * **Контроллер**: [[https://zt.melnoff.com|zt.melnoff.com]] (ztnet UI), это **не** my.zerotier.com. Авторизация участников делается там. * **Свой moon**: ''c53bc939c1'' @ ''94.103.86.3:9993'' (это и есть контроллер). Файл moon: ''000000c53bc939c1.moon''. * **На каждом новом клиенте** — три команды, см. [[#bootstrap_нового_клиента]]. * **Если ZT «полу-работает»** (онлайн, но трафик не ходит) — первым делом проверить ''allowManaged''. См. [[#типичные_проблемы]]. ===== Архитектура ===== ==== Уровни ==== - **Planets** — публичные корни ZeroTier Inc. Используются для bootstrap. У вас в ''peers'' это адреса с ролью ''PLANET'' (''cafe04eba9'', ''cafe80ed74'' и т.п.). - **Moon** (свой) — ваш корень, добавленный к planets. Дублирует функцию rendezvous и даёт быстрый relay внутри РФ. - **Leaves** — обычные клиенты сети. У них роль ''LEAF''. ==== Роли узлов в сети ==== ^ Узел / Description ^ ZT addr ^ ZT IP ^ Public/LAN endpoint ^ Заметки ^ | Контроллер + moon (хост ''zt.melnoff.com'') | ''c53bc939c1'' | ''172.25.30.225'' | ''94.103.86.3:9993'' | Linux Oracle 10. ZT крутится в Docker (zyclonite/zerotier:1.16.0). Web UI = ztnet. | | Этот мак | ''54dcf8821c'' | ''172.25.30.11'' | ''212.74.229.169:9993'' | macOS, ZT 1.16.1, ''feth2340'' интерфейс. | | Узел "imelnikov" | (см. контроллер) | ''172.25.30.10'' | — | Доступ ''ssh imelnikov@172.25.30.10''. | | PVE-роутер в LAN | (gateway-узел) | ''172.25.30.1'' | — | Бриджит ZT в ''192.168.0.0/24'' и ''172.16.10.0/24''. | | Удалённый peer (sym-NAT) | ''cab282198d'' | ''172.25.30.6'' | ''193.35.100.225'' | За симметричным NAT'ом — для доступа из мака требуется relay через moon. | | Прочие участники | ''31040019d0'', ''35d963a742'', ''73db6c289d'', ''77b9f07f34'', ''7e27e08dd1'', ''c63ddbdfe3'' | — | разное | Разные клиенты сети; точное соответствие ZT-addr↔IP смотреть на ''zt.melnoff.com'' → Members. | ==== Маршруты ==== Контроллер раздаёт клиентам сети (в дополнение к ''172.25.30.0/24''): ^ Target ^ Via ^ Что значит ^ | ''172.25.30.0/24'' | ''(direct)'' | Сама ZT-подсеть | | ''192.168.0.0/24'' | ''172.25.30.1'' | Через ZT-gateway пробрасывается в физический LAN | | ''172.16.10.0/24'' | ''172.25.30.1'' | Доступ к Docker-фабрике на PVE (LXC 107 = ''172.16.10.1'') | ==== Push DNS ==== * Зона: ''homepc.zt'' * Резолвер: ''192.168.0.11'' Push DNS применяется только на клиентах с ''allowDNS=1''. ===== Контроллер на zt.melnoff.com ===== ==== Стек ==== OpenSSH доступен как ''ssh root@zt.melnoff.com''. На хосте Docker-стек: ^ Контейнер ^ Образ ^ Порт ^ Назначение ^ | ''zerotier'' | ''zyclonite/zerotier:1.16.0'' | UDP 9993 (host network) | Сам ZT-демон в режиме контроллера. ZT-addr ''c53bc939c1''. | | ''ztnet'' | ''sinamics/ztnet:latest'' | ''3000'' (HTTP) | Современный web UI/API для управления контроллером. | | ''postgres'' | ''postgres:16-alpine'' | (internal) | БД для ztnet. | Обновлён до 1.16.0 на 2026-04-27 (in-place recreate с named volume ''ztnet_zerotier''; identity и БД members сохранены). Compose-файл: ''/opt/ztnet/docker-compose.yml''. Бэкап volume оставлен в ''/root/zt-volume-backup-*.tgz''. ==== Полезные команды на контроллере ==== # войти на хост ssh root@zt.melnoff.com # на хосте — zerotier-cli работает только через docker exec docker exec zerotier zerotier-cli info docker exec zerotier zerotier-cli listnetworks docker exec zerotier zerotier-cli peers # проверить достижимость члена сети с самого контроллера (тест L3) docker exec zerotier ping -c 3 172.25.30.6 # логи docker logs --tail 100 zerotier docker logs --tail 100 ztnet # REST API контроллера (через токен из контейнера) TOK=$(docker exec zerotier cat /var/lib/zerotier-one/authtoken.secret) docker exec zerotier curl -s -H "X-ZT1-Auth: $TOK" \ http://localhost:9993/controller/network/c53bc939c1ce37d2/member ==== Web UI (ztnet) ==== * Адрес — на порту ''3000'' хоста (либо за nginx). Логин/пароль — у владельца. * Авторизация новых member'ов — там. * Здесь же редактируются: name, ipAssignments, capabilities/tags, routes, dns push, broadcast, multicast limits. ===== Bootstrap нового клиента ===== Минимальный набор шагов на любом новом узле, который должен подключиться к сети: ==== Linux ==== # 1. Установка (Debian/Ubuntu) curl -s https://install.zerotier.com | sudo bash # 2. Присоединение к сети sudo zerotier-cli join c53bc939c1ce37d2 # 3. Подключить свой moon (важно для symmetric-NAT окружений) sudo zerotier-cli orbit c53bc939c1 c53bc939c1 # 4. Разрешить демону применять выданные IP/маршруты sudo zerotier-cli set c53bc939c1ce37d2 allowManaged=1 # 5. Авторизовать узел в zt.melnoff.com → Members → ✓ Auth ==== macOS ==== # 1. Установка через Homebrew или из dmg на zerotier.com brew install --cask zerotier-one # 2-5: те же команды что на Linux. Бинарник в /usr/local/bin/zerotier-cli sudo zerotier-cli join c53bc939c1ce37d2 sudo zerotier-cli orbit c53bc939c1 c53bc939c1 sudo zerotier-cli set c53bc939c1ce37d2 allowManaged=1 ==== Windows ==== - Поставить ZeroTier One MSI с zerotier.com. - В трее → Join Network → ввести ''c53bc939c1ce37d2''. - В админ-cmd: ''zerotier-cli orbit c53bc939c1 c53bc939c1''. - Авторизовать узел в Members на ''zt.melnoff.com''. ==== Через .moon файл (альтернатива orbit) ==== Положить файл ''000000c53bc939c1.moon'' в: * Linux: ''/var/lib/zerotier-one/moons.d/'' * macOS: ''/Library/Application Support/ZeroTier/One/moons.d/'' * Windows: ''%PROGRAMDATA%\ZeroTier\One\moons.d\'' После рестарта демона moon будет загружен. ''zerotier-cli listmoons'' должен показать его. Это полезно если узел стартует в условиях, когда planet'ы недоступны. ===== Зачем нужен свой moon ===== Moon — это ваш собственный root-сервер сети ZeroTier (планета ZT-Inc + ваша «луна» = два корня). ==== Решает три задачи ==== - **Скорость rendezvous и relay.** Публичные planet'ы географически далеко (Амстердам, Сингапур, США — latency 150-240 мс). Свой moon в РФ — 8-11 мс. При невозможности hole-punch'а (см. ниже) трафик идёт через корень — на planet'е это медленно. - **Symmetric-NAT окружения.** Если узел за «строгим» NAT'ом (типа корпоративного или мобильного), p2p-соединения не пробиваются. Без relay через близкий moon связь не работает совсем. Конкретный пример в этой сети — узел ''172.25.30.6'' (''cab282198d'') за симметричным NAT'ом ''193.35.100.225''. - **Независимость от публичной инфраструктуры ZT-Inc.** Если planet'ы временно недоступны (блокировка провайдером, DDoS, downtime), свой moon продолжает работать. ==== Когда moon **не нужен** ==== * На самом узле-moon (он сам и есть root). * Если оба пира за обычным cone NAT-ом — hole-punch через planet'ы работает напрямую, moon не используется. ==== Технически ==== Moon — это подписанный JSON-документ: { "id": "c53bc939c1", "roots": [{ "identity": "c53bc939c1:0:b9b6...<публичный ключ>", "stableEndpoints": ["94.103.86.3/9993"] }], "signature": "...", "timestamp": ..., "updatesMustBeSignedBy": "..." } Создание новой moon: на узле-кандидате ''zerotier-idtool initmoon /var/lib/zerotier-one/identity.public > moon.json'', отредактировать ''stableEndpoints'', потом ''zerotier-idtool genmoon moon.json'' → получится ''.moon''. Распространять на клиентов через ''moons.d/'' или команду ''orbit''. ===== Типичные проблемы ===== ==== 1. ''allowManaged=0'' — IP «висит», но реально не на интерфейсе ==== **Симптом.** ''zerotier-cli info'' = ONLINE, ''listnetworks'' = OK с правильным IP, ''peers'' показывает ''DIRECT'' пира — но любой ICMP/TCP до него падает с ''No route to host'' или просто таймаутится. Под капотом: ''ifconfig '' не показывает inet-адрес, в ''netstat -rn'' нет маршрута на ''172.25.30.0/24''. Трафик уходит через default route (например, на параллельный VPN). **Причина.** Локальная политика клиента запрещает ZT-демону применять IP/маршруты, выданные контроллером. **Лечение.** sudo zerotier-cli set c53bc939c1ce37d2 allowManaged=1 ⚠️ ''leave'' сети **сбрасывает** этот флаг в 0. После любого ''leave''/''join'' цикла — выставить заново. ==== 2. Moon не подхватывается из ''moons.d/'' ==== **Симптом.** Файл ''.moon'' в каталоге есть, но ''zerotier-cli listmoons'' возвращает ''[]''. **Причина.** Демон читает ''moons.d/'' только при старте. **Лечение.** Без рестарта: ''sudo zerotier-cli orbit '' (для нашей сети — ''sudo zerotier-cli orbit c53bc939c1 c53bc939c1''). С рестартом: ''sudo launchctl kickstart -k system/com.zerotier.one'' (macOS) или ''sudo systemctl restart zerotier-one'' (Linux). ==== 3. Узел в Central «онлайн», но ''paths: 0'' и недоступен ==== **Симптом.** На контроллере (''docker exec zerotier zerotier-cli peers'') узел виден как ''DIRECT'' с low latency. На клиенте этот же узел в ''peers'' имеет ''paths: 0, latency: -1''. Пинг не доходит, ARP не resolve'ится. **Причина.** Кэш member-info на клиенте залип — endpoint от moon не получен. **Лечение.** sudo zerotier-cli leave c53bc939c1ce37d2 sudo zerotier-cli join c53bc939c1ce37d2 sleep 5 sudo zerotier-cli set c53bc939c1ce37d2 allowManaged=1 # ← обязательно после join В ZT 1.16 relay-only пути **не показываются** в массиве ''paths'' — поэтому ''paths: 0'' не означает «недоступен», просто «нет p2p». Всегда пробуйте ping реально. ==== 4. ''ACCESS_DENIED'' в ''listnetworks'' ==== **Причина.** Узел не авторизован контроллером. **Лечение.** На ''zt.melnoff.com'' → Members → найти узел по ZT-addr (10 hex) → поставить галку Auth. ==== 5. Дублирование ICMP-ответов (''DUP!'') ==== **Симптом.** При ''ping'' появляются строчки с пометкой ''(DUP!)''. **Причина.** На маке параллельно работает второй TUN-VPN (например, AdGuard на ''utun4'' с ''198.18.0.1'') — он подхватывает копии пакетов. **Лечение.** Не критично, на функциональность не влияет. Если раздражает — проверить, не тащит ли VPN-клиент broadcast/multicast в свой туннель. ===== Диагностический playbook ===== Делать в этом порядке. Каждый шаг предполагает, что предыдущий вернул «зелёный» результат. - **Демон ONLINE?** ''sudo zerotier-cli info'' → ''ONLINE''. Если ''OFFLINE'' — UDP 9993 наружу заблокирован, либо демон не запущен. - **Сеть OK?** ''sudo zerotier-cli listnetworks'' → ''OK'' и осмысленный IP. Если ''ACCESS_DENIED'' — авторизовать в Central. Если ''REQUESTING_CONFIGURATION'' дольше 30 сек — контроллер недоступен. - **''allowManaged=1''?** ''sudo zerotier-cli get allowManaged''. Если ''0'' — фиксить (см. проблема №1). - **Путь до пира.** ''sudo zerotier-cli -j peers'' → достать запись по ZT-addr целевого узла. Смотреть массив ''paths''. Если пусто — это **не** обязательно «недоступен» (см. проблема №3), просто нет p2p. - **Moon загружен?** ''sudo zerotier-cli listmoons'' → должна быть запись с ''id'' = ''000000c53bc939c1''. Если пусто — ''orbit'' (см. проблема №2). - **Stale member cache?** ''leave/join'' цикл (см. проблема №3). - **Последняя надежда:** рестарт демона; апгрейд контроллера до ZT 1.16.x. ===== Полезные ссылки ===== * [[https://zt.melnoff.com|Self-hosted controller (ztnet UI)]] * [[https://docs.zerotier.com/|Официальная документация ZeroTier]] * [[https://github.com/sinamics/ztnet|ztnet (controller UI)]] * [[selfhosted:hardware|Где физически живут участники сети]] ===== Резервная копия moon-файла ===== На случай, если контроллер ''zt.melnoff.com'' будет недоступен (катастрофа / блокировка / порт 9993 закрыт), а нужно поднять новый клиент — вот канонический moon-файл в base64. В файле **нет** приватных ключей — только публичная identity moon-узла, его stable endpoint и подпись world'а. Поэтому хранить его в публичной wiki безопасно. * **Имя файла:** ''000000c53bc939c1.moon'' * **Размер:** 259 байт * **SHA-256:** ''76e8a39807413a5b650c61d133d53285492484af0a7d519cf72a86dd3ce76cf6'' * **Извлечён с:** ''zt.melnoff.com:/var/lib/zerotier-one/moons.d/000000c53bc939c1.moon'' (в Docker-контейнере ''zerotier''). ==== Содержимое (base64) ==== fwAAAMU7yTnBAAABnK+hl0TThMZt6mNZ+M7RQUomXAqP14FfhYP31JFStqq/jyPQcZjitqCMpAHybQcKvbtOW+8oLS2CSNAxzpru31jfdZwqwP1gRqQV7UP6nk+nGmCJcToCv+gF4CUe+JiQaLRXpQEPkeSeSREa4W/4DQ/2NmxR0J7qdLPYWmzZhWknkTbrCzr/9qY6M14n+j2IIPrWKO18x06B6Ed1HZ/Z2KIIlcwVAcU7yTnBALm27ZEIiAep3L8bws8Jwp88Q1I52ZzB8iUyNesmZbJ74rWPvgYpHJq5p66QE4l5x3wAkt0LZ3IqD4TSoVcatj0AAQReZ1YDJwkAAA== ==== Восстановление на новом клиенте ==== === Linux === # 1. Декодировать в правильное имя файла mkdir -p /var/lib/zerotier-one/moons.d echo 'fwAAAMU7yTnBAAABnK+hl0TThMZt6mNZ+M7RQUomXAqP14FfhYP31JFStqq/jyPQcZjitqCMpAHybQcKvbtOW+8oLS2CSNAxzpru31jfdZwqwP1gRqQV7UP6nk+nGmCJcToCv+gF4CUe+JiQaLRXpQEPkeSeSREa4W/4DQ/2NmxR0J7qdLPYWmzZhWknkTbrCzr/9qY6M14n+j2IIPrWKO18x06B6Ed1HZ/Z2KIIlcwVAcU7yTnBALm27ZEIiAep3L8bws8Jwp88Q1I52ZzB8iUyNesmZbJ74rWPvgYpHJq5p66QE4l5x3wAkt0LZ3IqD4TSoVcatj0AAQReZ1YDJwkAAA==' \ | base64 -d > /var/lib/zerotier-one/moons.d/000000c53bc939c1.moon # 2. Проверить (sha256 должен совпасть) sha256sum /var/lib/zerotier-one/moons.d/000000c53bc939c1.moon # ожидаем: 76e8a39807413a5b650c61d133d53285492484af0a7d519cf72a86dd3ce76cf6 # 3. Перезапустить демон sudo systemctl restart zerotier-one # 4. Убедиться что moon подхватился sudo zerotier-cli listmoons === macOS === sudo mkdir -p "/Library/Application Support/ZeroTier/One/moons.d" echo 'fwAAAMU7yTnBAAABnK+hl0TThMZt6mNZ+M7RQUomXAqP14FfhYP31JFStqq/jyPQcZjitqCMpAHybQcKvbtOW+8oLS2CSNAxzpru31jfdZwqwP1gRqQV7UP6nk+nGmCJcToCv+gF4CUe+JiQaLRXpQEPkeSeSREa4W/4DQ/2NmxR0J7qdLPYWmzZhWknkTbrCzr/9qY6M14n+j2IIPrWKO18x06B6Ed1HZ/Z2KIIlcwVAcU7yTnBALm27ZEIiAep3L8bws8Jwp88Q1I52ZzB8iUyNesmZbJ74rWPvgYpHJq5p66QE4l5x3wAkt0LZ3IqD4TSoVcatj0AAQReZ1YDJwkAAA==' \ | base64 -D | sudo tee "/Library/Application Support/ZeroTier/One/moons.d/000000c53bc939c1.moon" > /dev/null # Перезапуск sudo launchctl kickstart -k system/com.zerotier.one sudo zerotier-cli listmoons === Windows (PowerShell, admin) === $b64 = 'fwAAAMU7yTnBAAABnK+hl0TThMZt6mNZ+M7RQUomXAqP14FfhYP31JFStqq/jyPQcZjitqCMpAHybQcKvbtOW+8oLS2CSNAxzpru31jfdZwqwP1gRqQV7UP6nk+nGmCJcToCv+gF4CUe+JiQaLRXpQEPkeSeSREa4W/4DQ/2NmxR0J7qdLPYWmzZhWknkTbrCzr/9qY6M14n+j2IIPrWKO18x06B6Ed1HZ/Z2KIIlcwVAcU7yTnBALm27ZEIiAep3L8bws8Jwp88Q1I52ZzB8iUyNesmZbJ74rWPvgYpHJq5p66QE4l5x3wAkt0LZ3IqD4TSoVcatj0AAQReZ1YDJwkAAA==' $dir = 'C:\ProgramData\ZeroTier\One\moons.d' New-Item -ItemType Directory -Force -Path $dir | Out-Null [IO.File]::WriteAllBytes("$dir\000000c53bc939c1.moon", [Convert]::FromBase64String($b64)) Restart-Service ZeroTierOneService & 'C:\Program Files (x86)\ZeroTier\One\zerotier-cli.bat' listmoons ==== Альтернатива — без файла ==== Если узел может достучаться до публичных planet'ов ZT, можно обойтись без файла — одной командой: sudo zerotier-cli orbit c53bc939c1 c53bc939c1 Демон сам найдёт identity moon-узла через planet'ы. Это проще, но требует, чтобы хотя бы при первом запуске planet'ы были достижимы.