Протокол 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 версії 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.
Оскільки кожен кадр несе власну довжину, потоковий парсер — крихітний автомат станів: чекати 0xbf, накопичити varint, забуферувати рівно стільки байтів, декодувати, повторити — переносячи неповні кадри між читаннями. Версія 0 цього не дає взагалі: ви скануєте текст на </event> і сподіваєтеся, що нічого не обірветься посеред події.
Потокове узгодження: t-x-takp-v, t-x-takp-q, t-x-takp-r
Клієнт не може знати наперед, чи сервер говорить protobuf, тож перемикання узгоджується всередині з'єднання трьома керівними CoT-подіями — самі вони надсилаються як XML:
- Пропозиція (
t-x-takp-v). Сервер, що підтримує протокол TAK, може надіслати одну подію цього типу з<detail><TakControl><TakProtocolSupport version="1"/>— по одному елементу на підтримувану версію, щонайбільше раз на з'єднання, після автентифікації, якщо вхід її вимагає. - Запит (
t-x-takp-q). Клієнт обирає версію з пропозиції й відповідає<TakRequest version="1"/>, після чого мусить припинити надсилати XML (продовжуючи обробляти вхідний XML) і чекати — щонайменше хвилину, перш ніж здатися й перез'єднатися. - Відповідь (
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.
| Порт | Протокол | Роль |
|---|---|---|
8089 | TCP/TLS | Потоковий CoT-вхід — те, до чого з клієнтськими сертифікатами під'єднуються ATAK, WinTAK і шлюзи |
8090 | UDP (QUIC) | Необов'язковий QUIC-вхід потоку, наявний у поточному прикладі конфігурації |
8087 | TCP чи UDP | Незашифрований CoT-вхід (прикладові входи; лише для лабораторії) |
8088 | TCP | Потоковий TCP без TLS (stcp) — лише для тестування |
8443 | TCP/HTTPS | Адміністративний інтерфейс, REST API і WebTAK (автентифікація клієнтським сертифікатом) |
8444 | TCP/HTTPS | HTTPS, звернений до федерації (сховище довіри федерації; отримання mission-пакетів) |
8446 | TCP/HTTPS | Видача сертифікатів (CSR, HTTP Basic auth) та endpoint токенів OAuth2 |
9000 | TCP/TLS | Слухач федерації v1 |
9001 | TCP/TLS | Слухач федерації v2 (gRPC поверх HTTP/2) |
9002 | TCP/TLS | Автентифікація федераційних токенів (якщо увімкнено) |
239.2.3.1:6969 | UDP 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 XML | XML у потоці (з декларацією) | Вантаж protobuf | На лінії (у кадрі) |
|---|---|---|---|---|
| Звіт про власну позицію ATAK | 578 Б | 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 — включно з сертифікатами, групами й федерацією.
Підготували інженери Corvus Intelligence — команди, що будує CoT/TAK-шлюзи, плагіни ATAK та інтеграції TAK Server для оборонних програм (сертифікація ISO 9001/27001, учасник Brave1). Про Corvus Intelligence →