Протокол TAK — це контракт лінії передачі, за яким ATAK, WinTAK, iTAK і TAK Server обмінюються подіями Cursor on Target (CoT). Версія 0 надсилає подію як звичайний XML; версія 1 — як protobuf-повідомлення з префіксом довжини, приблизно вдвічі менше за розміром. Той самий вміст їде трьома транспортами: безсерверним UDP-мультикастом у локальній mesh-мережі, постійними TCP/TLS-потоками до TAK Server (типово порт 8089) та федерацією «сервер–сервер» (9000/9001).

Якщо ви інтегруєте сенсор, БпЛА чи систему C2 з екосистемою TAK, цей поділ важливий одразу: CoT — це модель даних — <event>, <point>, <detail> — тоді як протокол TAK визначає, як ці байти кадруються, версіонуються та узгоджуються на кожному транспорті. Саму XML-схему розібрано в нашому посібнику з формату Cursor on Target та в глибокому зануренні в схему CoT; ця стаття — друга половина питання: лінія передачі.

CoT проти протоколу TAK: модель даних проти контракту на лінії

Розділяйте три рівні — документація екосистеми їх послідовно змішує:

  • Модель події CoT. Один XML-документ на подію: код типу, UID, time/start/stale, точка в WGS-84 і розширюваний <detail>. Смисловий зміст, однаковий на всіх транспортах.
  • Кодування (версія протоколу TAK). Версія 0 кодує подію як XML-текст; версія 1 — як protobuf-повідомлення TakMessage. Обидві несуть ті самі події.
  • Транспорт. UDP-мультикаст у mesh-мережі, постійний TLS-потік до TAK Server або федеративний канал між серверами — кожен кадрує вантаж по-своєму.

Опис протоколу, що постачається з продуктами TAK, задає два базові правила: клієнт, який надсилає версію V, уміє також декодувати версію V, і кожен клієнт досі мусить декодувати XML версії 0. Саме тому змішані парки пристроїв продовжують працювати — усе м'яко деградує до XML.

Діаграма транспортів протоколу TAK: пристрої ATAK, WinTAK та iTAK ділять безсерверний UDP-мультикаст на 239.2.3.1:6969; пристрої або CoT-шлюз ідуть потоком до TAK Server по двосторонньому TLS на порту 8089; сервер федерується з другим TAK Server на портах 9000 і 9001; сенсорні та C2-потоки конвертує в CoT сервіс-шлюз.
Транспорти протоколу TAK: безсерверний mesh-мультикаст, потік до TAK Server по mutual TLS (8089) і федерація «сервер–сервер» (9000/9001); CoT-шлюз живить сервер.

Протокол TAK версії 0: чистий CoT XML

Версія 0 тримала екосистему перше десятиліття й досі лишається запасним режимом усюди. На кожному транспорті вона поводиться інакше:

  • Mesh SA (мультикаст). Оголошення ситуативної обізнаності — це UDP-дейтаграми на добре відому мультикаст-групу 239.2.3.1:6969: одна XML-подія CoT на дейтаграму, без усякого сервера. Кожен пристрій, що приєднався до групи, отримує кожну подію, а ретрансляції немає: загублена дейтаграма — загублений звіт про позицію. Це режим, на якому працює безсерверне відстеження синіх сил у віддільній Wi-Fi- чи MANET-мережі. (ATAK мультикастить GeoChat окремою групою, 224.10.10.1:17012, яку TAK Server може приймати як вхід.)
  • Адресні повідомлення. Повідомлення одному одержувачу йдуть короткоживучим TCP-з'єднанням: під'єднатися, надіслати одну подію, від'єднатися. Пристрій ATAK, що слухає прямих пірів, приймає їх на TCP-порті 4242 — зручно, щоб вкласти подію в один смартфон без сервера.
  • Потік до TAK Server. Постійне з'єднання (зазвичай TLS) несе суцільний потік XML-подій, кожна з XML-декларацією попереду та символом нового рядка після. Одержувач не отримує ані префікса довжини, ані роздільника: він розрізає потік, шукаючи літеральний токен </event> і відрізаючи одразу після нього — наступна декларація починається з наступного ж байта.

У практиці потокова форма виглядає так (скорочено):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<event version="2.0" uid="RAVEN-1" type="a-f-G-U-C" how="m-g" …>…</event><?xml version="1.0" …?><event …>…</event>

Цей сканер-роздільник — поведінка протоколу, а не примха реалізації: власний потоковий кодек TAK Server прямо документує відсутність роздільників і шукає закриваючий тег. Будь-який шлюз мусить випускати події, що чисто розрізаються: цілі події, декларація попереду, нічого зайвого поміж ними. Анотовані повні події дивіться в наших прикладах CoT-повідомлень.

Протокол TAK версії 1: protobuf TakMessage

Версія 1 замінює XML-текст одним proto3-повідомленням — atakmap.commoncommo.protobuf.v1.TakMessage, чиє визначення постачається з дистрибутивами TAK і віддзеркалене в бібліотеках на кшталт Python-пакета takproto. Структура компактна, але строго визначена:

  • TakMessage тримає дві необов'язкові частини: TakControl (службова інформація протоколу — мінімальна й максимальна версії, які відправник декодує, плюс UID контакту) і сам CotEvent.
  • CotEvent несе конверт: type, uid, how, необов'язкові access/qos/opex, три мітки часу в мілісекундах від епохи Unix (sendTime, startTime, staleTime) і поля точки lat, lon, hae, ce, le як double. Невідома висота чи похибка — сентинел 999999, як у XML-конвенції.
  • Detail — тут стає цікаво. Шість добре відомих detail-елементів стали типізованими підповідомленнями: contact (endpoint, callsign), group (з __group: name, role), precisionLocation (geopointsrc, altsrc), status (battery), takv (device, platform, os, version), track (speed, course). Усе інше — remarks, тіла чату, елементи плагінів — пакується в один рядок xmlDetail із сирим XML решти нащадків.

Два правила специфікації рятують від непомітної порчі даних. По-перше, лише цілі елементи: detail-елемент конвертується у типізоване повідомлення повністю або повністю лишається в xmlDetail — ніколи не розрізається навпіл, а якщо він не мапиться чисто, то й залишається в xmlDetail. По-друге, одержувачі зливають типізовані повідомлення назад у XML, і при конфлікті перемагає xmlDetail. Нові поля можна лише додавати в кінець наявних повідомлень; будь-яка смислова зміна вимагає підняття версії. На практиці виграш від protobuf тане в міру зростання нетипізованого detail — рівно те, що видно на трафіку, насиченому чатом чи плагінами.

Кадрування mesh і потоку: конкретні байти

Обидві версії їдуть обома транспортами; кадрування різниться за транспортом, а не за вантажем:

  • Дейтаграма mesh: 0xbf, varint версії протоколу, 0xbf, далі вантаж. Магічний байт 0xbf (191 у десятковій системі) дає приймачеві змогу «понюхати» одну дейтаграму й зрозуміти, protobuf це чи легасі-XML, що починається з < — UDP-входи TAK Server роблять саме цю перевірку на кожній дейтаграмі.
  • Потоковий кадр: 0xbf, varint довжини вантажу в байтах, далі вантаж. Байта версії немає — версію вже одноразово узгоджено на з'єднанні (наступний розділ), тож повторювати її в кожному кадрі було б марнотратством.

Це стандартні беззнакові protobuf-varint: по 7 бітів, від молодших до старших, старший біт позначає продовження, максимум 64 біти (10 байтів). Вантаж на 258 байтів кодується як 82 02; 127 — це 7f, 128 — 80 01.

Діаграма байтової розкладки кадрування протоколу TAK: mesh-дейтаграма UDP — 0xbf, varint версії, 0xbf, далі вантаж protobuf TakMessage; потоковий кадр TCP або TLS — 0xbf, varint довжини вантажу, далі вантаж; а події версії 0 — чистий XML, що ріжеться по закриваючому токені event.
Кадрування протоколу TAK v1: заголовок mesh повторює магічний байт, версію, магічний байт; заголовок потоку — магічний байт плюс varint довжини; версія 0 несе сирий XML, що ріжеться по закриваючому токені event.

Оскільки кожен кадр несе власну довжину, потоковий парсер — крихітний автомат станів: чекати 0xbf, накопичити varint, забуферувати рівно стільки байтів, декодувати, повторити — переносячи неповні кадри між читаннями. Версія 0 цього не дає взагалі: ви скануєте текст на </event> і сподіваєтеся, що нічого не обірветься посеред події.

Потокове узгодження: t-x-takp-v, t-x-takp-q, t-x-takp-r

Клієнт не може знати наперед, чи сервер говорить protobuf, тож перемикання узгоджується всередині з'єднання трьома керівними CoT-подіями — самі вони надсилаються як XML:

  1. Пропозиція (t-x-takp-v). Сервер, що підтримує протокол TAK, може надіслати одну подію цього типу з <detail><TakControl><TakProtocolSupport version="1"/> — по одному елементу на підтримувану версію, щонайбільше раз на з'єднання, після автентифікації, якщо вхід її вимагає.
  2. Запит (t-x-takp-q). Клієнт обирає версію з пропозиції й відповідає <TakRequest version="1"/>, після чого мусить припинити надсилати XML (продовжуючи обробляти вхідний XML) і чекати — щонайменше хвилину, перш ніж здатися й перез'єднатися.
  3. Відповідь (t-x-takp-r). Сервер відповідає <TakResponse status="true"/> або "false". При true обидві сторони переводять усе з'єднання на вантажі версії 1 з префіксом довжини — та сама версія в обидва боки — і більше жодного XML не тече. При false з'єднання лишається на XML, і клієнт може спробувати пізніше.

Усі три події поділяють один UID транзакції (protouid із специфікації), і цей танець суворий: protobuf, надісланий до відповіді true, ламає з'єднання з еталонним сервером. У mesh рукостискання немає: кожен пристрій транслює повідомлення TakControl щонайменше що 60 секунд, заявляючи мінімальну й максимальну версії, які він декодує; контакти, мовчазні дві хвилини, повертаються до версії свого останнього декодованого повідомлення; і всі передають на найвищій версії, яку декодує всім відомі контакти, вертаючись до XML, щойно з'являється легасі-пристрій. Навантажте узгодження тестами, перш ніж вважати, що парк переключився, — важелі тюнінгу описано в нашому посібнику з продуктивності TAK Server.

Порти TAK Server: типова карта

Типові значення з посібника з конфігурації TAK Server 5.7 та його прикладового CoreConfig.xml; кожен порт налаштовується, тож сприймайте це як те, що відкриває дистрибутив «з коробки», а не як контракт. Власна порада посібника щодо брандмауера мінімальна: відкрити 8089 і 8443.

ПортПротоколРоль
8089TCP/TLSПотоковий CoT-вхід — те, до чого з клієнтськими сертифікатами під'єднуються ATAK, WinTAK і шлюзи
8090UDP (QUIC)Необов'язковий QUIC-вхід потоку, наявний у поточному прикладі конфігурації
8087TCP чи UDPНезашифрований CoT-вхід (прикладові входи; лише для лабораторії)
8088TCPПотоковий TCP без TLS (stcp) — лише для тестування
8443TCP/HTTPSАдміністративний інтерфейс, REST API і WebTAK (автентифікація клієнтським сертифікатом)
8444TCP/HTTPSHTTPS, звернений до федерації (сховище довіри федерації; отримання mission-пакетів)
8446TCP/HTTPSВидача сертифікатів (CSR, HTTP Basic auth) та endpoint токенів OAuth2
9000TCP/TLSСлухач федерації v1
9001TCP/TLSСлухач федерації v2 (gRPC поверх HTTP/2)
9002TCP/TLSАвтентифікація федераційних токенів (якщо увімкнено)
239.2.3.1:6969UDP multicastГрупа mesh SA (типовий клієнт; можна мостити як вхід сервера)

Дві примітки. FreeTAKServer — Python-сервер відкритої екосистеми (див. наш огляд відкритої екосистеми TAK) — тримає 8089 для CoT поверх TLS, але використовує 8087 для чистого TCP CoT. А федерація заслуговує на окреме прочитання: канал v1 обмінюється protobuf-повідомленнями FederatedEvent за чотирибайтовим префіксом довжини, тоді як v2 працює як gRPC-сервіс із потоковими RPC і перевірками здоров'я — це розібрано в нашому посібнику з налаштування федерації та огляді архітектури Federation Hub.

Розмір повідомлень і смуга: XML проти protobuf

Ми закодували дві репрезентативні події обома способами — звіт про власну позицію в стилі ATAK (типізований detail плюс нетипізований елемент uid) і трек БпЛА від невеликого моста MAVLink; protobuf-бік кодував еталонний Python-енкодер:

ПодіяCoT XMLXML у потоці (з декларацією)Вантаж protobufНа лінії (у кадрі)
Звіт про власну позицію ATAK578 Б634 Б258 Б261 Б
Трек від моста БпЛА363 Б419 Б171 Б174 Б

Це 52–59 % економії для таких форм — узгоджується з 55–65 %, які ми наводили в нашій статті про інтеграцію телеметрії дронів, і з польовими вимірюваннями Isode 2025 року для TAK над HF-радіо: приблизно 530-байтові XML-події проти 376–380-байтових федеративних protobuf-повідомлень до стиснення. Protobuf допомагає найбільше там, де XML — чистий конверт: декларації, імена атрибутів, закриваючі теги; а detail, припаркований у xmlDetail, зберігає свій XML-розмір.

Чому це важливо на радіо: сорок користувачів, що самопозиціються кожні десять секунд, коштують приблизно 20 kbps у потоковому XML (по 634 Б кожна) проти приблизно 8 kbps у protobuf — без урахування накладних витрат TLS-запису на кожне повідомлення. На вузькосмугових каналах ефект жорсткий: на 75 bps Isode виміряла 29–33 секунди наскрізної затримки для однієї події. Ще одна поведінка щодо розмірів: потоковий вихід TAK Server відмовляється надсилати protobuf TakMessage більший за 65 536 байтів; таку подію замінює маленький вказівник на передачу файлу, що кличе клієнта забрати повний XML по HTTPS. Чатовий трафік розібрано в нашій статті про стратегію роботи з чатовими даними.

Надсилання CoT із Python: TLS, сертифікати, protobuf

Усе сказане вище стискається в маленьку програму — самої стандартної бібліотеки вистачає, щоб відкрити TLS-з'єднання до входу 8089 з клієнтським сертифікатом і лити події XML версії 0, без жодних залежностей:

import asyncio
import datetime as dt
import ssl
import xml.etree.ElementTree as ET

TAK_HOST, TAK_PORT = "tak.example.org", 8089      # TLS streaming input
CA_FILE, CERT_FILE, KEY_FILE = "takserver-ca.pem", "client.pem", "client.key"

def ts(t):  # CoT time: ISO 8601, UTC, millisecond precision
    return t.strftime("%Y-%m-%dT%H:%M:%S.") + f"{t.microsecond // 1000:03d}Z"

def cot_event(uid, cot_type, lat, lon, hae, callsign, stale_s=60):
    now = dt.datetime.now(dt.timezone.utc)
    ev = ET.Element("event", version="2.0", uid=uid, type=cot_type, how="m-g",
                    time=ts(now), start=ts(now),
                    stale=ts(now + dt.timedelta(seconds=stale_s)))
    ET.SubElement(ev, "point", lat=f"{lat:.7f}", lon=f"{lon:.7f}",
                  hae=f"{hae:.1f}", ce="10.0", le="9999999.0")
    ET.SubElement(ET.SubElement(ev, "detail"), "contact", callsign=callsign)
    return ET.tostring(ev, encoding="utf-8", xml_declaration=False)

async def drain(reader):
    # Keep reading the server (its t-x-takp-v offer, other users' SA),
    # or TCP flow control eventually stalls its writes to you.
    while await reader.read(65536):
        pass

async def main():
    ctx = ssl.create_default_context(cafile=CA_FILE)   # verify server cert + name
    ctx.load_cert_chain(CERT_FILE, KEY_FILE)           # our client identity
    reader, writer = await asyncio.open_connection(TAK_HOST, TAK_PORT, ssl=ctx)
    rx = asyncio.create_task(drain(reader))
    try:
        while not rx.done():
            writer.write(cot_event("gw-demo.uav-12", "a-f-A-M-F-Q",
                                   50.4501234, 30.5234567, 640.0, "UAV-12"))
            await writer.drain()
            await asyncio.sleep(5)                     # report well inside stale
    finally:
        writer.close()

asyncio.run(main())

Три деталі тут тримають усе на собі. Сокети asyncio типово вимикають алгоритм Нагла, тож кожна подія виходить негайно — на сирих сокетах увімкніть TCP_NODELAY самостійно. Задача drain — не прикраса: сервер, що пише клієнтові, який ніколи не читає, зрештою застрягає на керуванні потоком TCP. Сертифікати мусять бути у форматі PEM: TAK Server видає PKCS#12 .p12 (те, що споживає ATAK), який OpenSSL конвертує в три рядки:

openssl pkcs12 -in gateway-01.p12 -clcerts -nokeys -out client.pem -passin pass:SECRET
openssl pkcs12 -in gateway-01.p12 -nocerts -nodes -out client.key -passin pass:SECRET
openssl pkcs12 -in truststore-root.p12 -nokeys -out takserver-ca.pem -passin pass:SECRET

Для protobuf пакет takproto (PyPI) конвертує CoT XML у вантажі версії 1 і назад та додає кадрування; бібліотека PyTAK загортає цілісного клієнта — COT_URL приймає tls://host:8089 або udp+wo://239.2.3.1:6969, TAK_PROTO=1 вибирає protobuf, а сертифікати імпортуються просто з TAK data package .zip. Дилему «зроби сам чи візьми бібліотеку» розвинено в нашій статті про патерни інтеграції C2 з TAK.

Саме тут прототип вихідного дня стикається з операційною реальністю: видача сертифікатів на масштабі всього парку, protobuf-узгодження між змішаними версіями клієнтів, мультикаст, який має реально маршрутизуватися. Ми будуємо шлюзи CoT/протоколу TAK, мігруємо потоки з XML на protobuf, інтегруємо та зміцнюємо TAK Server. Розкажіть, що вам потрібно з'єднати →

Семантика доставки, захист і підступи, що кусають

Без підтверджень — роботу робить stale

CoT — це «вистрелив і забув» на кожному рівні: без підтверджень на кожне повідомлення, без номерів послідовності, без сесій. Свіжістю керує мітка часу stale — споживачі старять або скидають події, що її минули, — і частотою: надсилайте всередині власного вікна stale або змиріться з привидами на карті. TAK Server пом'якшує перез'єднання буфером latest SA (новим клієнтам одразу надсилаються останні відомі позиції досяжних користувачів), а ATAK тримає з'єднання живим пінгом (t-x-c-t), на який сервер відповідає понгом (t-x-c-t-r). Після будь-якого перез'єднання пересилайте свою поточну картину, а не сподівайтеся, що сервер її запам'ятав.

Сертифікати, групи, канали

Операційний TAK-трафік — це двосторонній TLS: клієнт перевіряє сервер за CA розгортання, сервер перевіряє клієнтський сертифікат від того самого CA, а CN сертифіката стає іменем користувача для розподілу по групах. Членство в групах — на вході, за сертифікатом або через LDAP/файлові бекенди — це й уся модель контролю доступу до того, чиї треки хто бачить; невідповідні з'єднання потрапляють до __ANON__. Федерація свідомо користується окремим сховищем довіри, тож CA партнера ніколи мовчки не авторизує клієнтські з'єднання, а видача сертифікатів живе на порту 8446 за HTTP Basic auth. Якщо розгортанню потрібні HTTP-API замість сирих сокетів, цей контур описано в нашому посібнику з інтеграції CloudTAK API.

Типові режими відмов

  • Мультикаст, що не доходить: мультикаст іде далі лише поки дозволяє TTL (типовий TTL 1 тримає дейтаграми в межах локального сегмента; прикладова конфігурація TAK Server піднімає його до 5), неправильний IGMP snooping мовчки скидає групи, а мультикаст ніколи не перетинає NAT. Mesh SA — технологія однієї підмережі.
  • Розсинхронізація часу: зі старінням за stale неправильний годинник або випаровує чиїсь треки, або лишає їх назавжди. Синхронізуйте час (GNSS або NTP), перш ніж дебажити що-небудь інше.
  • Тертя форматів сертифікатів: сервер говорить JKS, клієнти PKCS#12, ваш сервіс PEM — а сертифікати без розширеного використання ключа client-auth відхиляються ще на рукостисканні. Конвертуйте свідомо і тестуйте точну ланку.
  • Алгоритм Нагла: затримка батчингу в 200 мс непомітна на каналі до дата-центру й смертельна на тактичному. Вимкніть його або батчіть явно.
  • Бурі перез'єднань: сотня шлюзів, що перез'єднуються разом після обриву радіо, виглядає як DDoS. Використовуйте джиттерований експоненційний відкат, реавтентифікуйтеся, відтворюйте поточний стан.
  • Припущення про змішані версії: один легасі-клієнт у mesh скидає всіх назад до XML, а сервер, що ніколи не надсилає t-x-takp-v, ніколи не отримає protobuf. Інструментуйте, яким кодуванням осіли ваші лінки, — байти на лінії за хвилину говорять правду.

Еталонна архітектура: сервіс CoT-шлюзу

Витривалий патерн живлення TAK-мережі з не-TAK-систем — маленький виділений сервіс-шлюз, а не код, вбудований у кожне джерело:

  • Вхідні адаптери — MAVLink, радар, AIS, GPS-трекери, REST/WebSocket-потоки — кожен нормалізується до внутрішньої моделі треку.
  • Конструктор CoT — одне місце, що володіє політикою UID (стабільні, просторові імена, стійкі до колізій), мапингом типів, кодами how і вікнами stale на джерело та випускає XML чи protobuf за одними правилами detail.
  • Наглядач виходу — пул автентифікованих TLS-з'єднань з узгодженням (protobuf, коли пропонують, інакше XML), джиттерованим перез'єднанням, обмеженням швидкості на лінк для вузькосмугових шляхів і відтворенням поточного стану.
  • Операційна поверхня — здоров'я лінків, чинне кодування, байти за хвилину та моніторинг терміну дії сертифікатів; на тактичних мережах протокол першим підозрюють і останнім інструментують.

Саме така форма — протокольно-вірний рубіж між чужими даними та TAK Server — і є компонентом, який ми будуємо для оборонних програм, пліч-о-пліч із копілотом TAKpilot на тій самій інфраструктурі. Якщо ваша програма малює цю діаграму просто зараз — покличте команду, яка вже відправляла таке в експлуатацію.

Потрібно це у вашій мережі?

Ми будуємо шлюзи протоколу CoT/TAK, мігруємо потоки з XML на protobuf, інтегруємо та зміцнюємо TAK Server — включно з сертифікатами, групами й федерацією.

Збудуйте ваш CoT-шлюз → Дивіться TAKpilot →

Підготували інженери Corvus Intelligence — команди, що будує CoT/TAK-шлюзи, плагіни ATAK та інтеграції TAK Server для оборонних програм (сертифікація ISO 9001/27001, учасник Brave1). Про Corvus Intelligence →