Het TAK-protocol is de wire-overeenkomst waarmee ATAK, WinTAK, iTAK en TAK Server Cursor on Target-events (CoT) uitwisselen. Versie 0 stuurt het event als gewone XML; versie 1 als een protobuf-bericht met lengteprefix, ongeveer half zo groot. Dezelfde payload reist over drie transporten: serverloze UDP-multicast op de lokale mesh, persistente TCP/TLS-streams naar TAK Server (standaard poort 8089) en server-naar-serverfederatie (9000/9001).

Wie een sensor, drone of C2-systeem met het TAK-ecosysteem integreert, voelt dit onderscheid meteen: CoT is het datamodel — <event>, <point>, <detail> — terwijl het TAK-protocol bepaalt hoe die bytes op elk transport geframed, geversioneerd en onderhandeld worden. Het XML-schema zelf staat in onze gids over het Cursor on Target-formaat en de diepe duik in het CoT-schema; dit artikel is de andere helft: de verbinding.

CoT versus het TAK-protocol: datamodel versus verbindingsovereenkomst

Houd drie lagen gescheiden — de documentatie van het ecosysteem vermengt ze regelmatig:

  • Het CoT-eventmodel. Eén XML-document per event: typecode, UID, time/start/stale, een WGS-84-punt, een uitbreidbaar <detail>. De semantische inhoud, op elk transport identiek.
  • De codering (TAK-protocolversie). Versie 0 codeert het event als XML-tekst; versie 1 als protobuf-TakMessage. Beide dragen dezelfde events.
  • Het transport. UDP-multicast op de mesh, een persistente TLS-stream naar TAK Server of een federatielink tussen servers — elk framet de payload anders.

De protocolbeschrijving die met de TAK-producten meeleevert, stelt twee grondregels: een client die versie V verstuurt, kan versie V ook decoderen, en elke client moet nog steeds XML versie 0 kunnen decoderen. Daarom blijven gemengde vlooten werken — alles valt netjes terug op XML.

Diagram van de TAK-protocoltransporten: ATAK-, WinTAK- en iTAK-apparaten delen serverloze UDP-multicast op 239.2.3.1:6969; apparaten of een CoT-gateway streamen naar TAK Server over mutual TLS op poort 8089; de server federeert met een tweede TAK Server op poort 9000 en 9001; sensor- en C2-feeds worden door de gatewayservice tot CoT geconverteerd.
TAK-protocoltransporten: serverloze mesh-multicast, mutual-TLS-streaming naar TAK Server (8089) en server-naar-serverfederatie (9000/9001), met een CoT-gateway die de server voedt.

TAK-protocol versie 0: gewone CoT XML

Versie 0 droeg het ecosysteem een decennium lang en is overal nog de fallback. Per transport gedraagt het zich anders:

  • Mesh SA (multicast). Situational-awareness-aankondigingen zijn UDP-datagrammen naar de welbekende multicastgroep 239.2.3.1:6969 — één CoT XML-event per datagram, zonder server. Elk apparaat in de groep ontvangt elk event, en er is geen hertransmissie: een verloren datagram is een verloren positiemelding. Dit is de modus achter serverloze blue force tracking op een sectie-Wi-Fi- of MANET-segment. (ATAK multicast GeoChat op een aparte groep, 224.10.10.1:17012, die TAK Server als input kan opnemen.)
  • Gerichte berichten. Berichten naar één ontvanger gebruiken een kortstondige TCP-verbinding: verbind, verstuur één event, verbreek. Een ATAK-apparaat dat naar directe peers luistert, accepteert ze op TCP-poort 4242 — handig om één toestel zonder server van een event te voorzien.
  • Stream naar TAK Server. Een persistente verbinding (meestal TLS) draagt een doorlopende stroom XML-events, elk voorafgegaan door een XML-declaratie en gevolgd door een newline. De ontvanger krijgt geen lengteprefix en geen scheidingsteken: hij knipt de stroom door op het letterlijke token </event> en snijdt direct daarna — de volgende declaratie begint op de allereerstvolgende byte.

In de praktijk ziet de streamingvorm er zo uit (verkort):

<?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>

Die token-scannende splitter is protocolgedrag, geen implementatie-eigenaardigheid — TAK Servers eigen streaming-codec documenteert het ontbreken van scheidingstekens en zoekt op de sluittag. Elke gateway moet events emitteren die zuiver knippen: complete events, declaratie voorop, niets ertussen. Geannoteerde volledige events staan in onze voorbeelden van CoT-berichten.

TAK-protocol versie 1: de protobuf-TakMessage

Versie 1 vervangt de XML-tekst door één proto3-bericht — atakmap.commoncommo.protobuf.v1.TakMessage — waarvan de definitie met de TAK-distributies meekomt en weerspiegeld is in bibliotheken zoals het Python-pakket takproto. De structuur is compact maar strikt gespecificeerd:

  • TakMessage bevat twee optionele delen: een TakControl (protocolboekhouding — de min/max-versies die de zender decodeert, plus een contact-UID) en het CotEvent zelf.
  • CotEvent draagt de envelop: type, uid, how, optionele access/qos/opex, de drie tijdstempels als milliseconden sinds de Unix-epoch (sendTime, startTime, staleTime) en de puntvelden lat, lon, hae, ce, le als doubles. Onbekende hoogte of foutwaarden gebruiken de sentinel 999999, net als in de XML-conventie.
  • Detail wordt hier interessant. Zes bekende detail-elementen werden getypeerde subberichten: contact (endpoint, callsign), group (uit __group: name, role), precisionLocation (geopointsrc, altsrc), status (battery), takv (device, platform, os, version), track (speed, course). Alles andere — remarks, chat-inhouden, plugin-elementen — wordt in één xmlDetail-string gestopt met de ruwe XML van de overige children.

Twee specificatieregels redden teams van subtiele corruptie. Ten eerste, alleen hele elementen: een detail-element wordt volledig naar zijn getypeerde bericht geconverteerd of blijft volledig in xmlDetail — nooit gesplitst, en als het niet netjes mapt, blijft het in xmlDetail. Ten tweede voegen ontvangers de getypeerde berichten weer samen tot XML, en bij conflict wint xmlDetail. Nieuwe velden mogen alleen achteraan aan bestaande berichten worden toegevoegd; alles semantische vraagt een versieverhoging. In de praktijk krimpt de protobuf-winst naarmate ongetypeerde detail groeit — precies wat je ziet bij chat- of plugin-zwaar verkeer.

Mesh- en stream-framing: de feitelijke bytes

Beide versies rijden op beide transporten; framing verschilt per transport, niet per payload:

  • Mesh-datagram: 0xbf, een varint protocolversie, 0xbf, dan de payload. De magic byte 0xbf (191 decimaal) laat een ontvanger één datagram besnuffelen en weten of het protobuf is of legacy-XML, die begint met < — TAK Servers UDP-inputs doen precies die controle op elk datagram.
  • Streaming-frame: 0xbf, een varint payloadlengte in bytes, dan de payload. Geen versiebyte — de versie is één keer per verbinding onderhandeld (volgende sectie), dus herhaling per frame zou verspilling zijn.

De varints zijn standaard unsigned protobuf-varints — 7 bits per keer, minst significatief eerst, de hoogste bit markeert voortzetting, maximaal 64 bits (10 bytes). Een payload van 258 bytes codeert als 82 02; 127 is 7f, 128 is 80 01.

Byte-layoutdiagram van TAK-protocol-framing: een mesh-UDP-datagram als 0xbf, versie-varint, 0xbf, daarna de protobuf-TakMessage-payload; een streamingframe over TCP of TLS als 0xbf gevolgd door een lengte-varint en de payload; en versie-0 XML-events die op het sluitende event-token worden geknipt.
TAK-protocol v1-framing: de mesh-header herhaalt magic byte, versie, magic byte; de stream-header is magic byte plus een lengte-varint; versie 0 vervoert ruwe XML, geknipt op het sluitende event-token.

Omdat elk frame zijn eigen lengte draagt, is een streamparser een kleine toestandsmachine: verwacht 0xbf, verzamel de varint, buffer precies zoveel bytes, decodeer, herhaal — met partiële frames over leesacties heen. Versie 0 geeft je daar niets van; je scant tekst op </event> en hoopt dat er niets midden in een event afbreekt.

Streaming-onderhandeling: t-x-takp-v, t-x-takp-q, t-x-takp-r

Een client kan niet weten of een server protobuf spreekt, dus de omschakeling wordt binnen de verbinding onderhandeld met drie CoT-besturingsevents — zelf als XML verstuurd:

  1. Het aanbod (t-x-takp-v). Een server met TAK-protocolondersteuning mag één event van dit type sturen met <detail><TakControl><TakProtocolSupport version="1"/> — één element per ondersteunde versie, hoogstens één keer per verbinding, na authenticatie als de input die vereist.
  2. Het verzoek (t-x-takp-q). De client kiest een versie uit het aanbod en antwoordt met <TakRequest version="1"/>, en moet daarna stoppen met XML sturen (inkomende XML blijft verwerken) en wachten — minstens een minuut voordat hij opgeeft en opnieuw verbindt.
  3. Het antwoord (t-x-takp-r). De server antwoordt <TakResponse status="true"/> of "false". Bij true schakelen beide zijden de hele verbinding om naar lengte-geframde versie-1-payloads — dezelfde versie in beide richtingen — en er vloeit geen XML meer. Bij false blijft de verbinding op XML en kan de client het later opnieuw proberen.

Alle drie de events delen één transactie-UID (de protouid uit de specificatie), en de dans is streng: vóór het true-antwoord verstuurde protobuf breekt op de referentieserver. Op de mesh is er geen handshake: elk apparaat broadcast minstens elke 60 seconden een TakControl-bericht met de minimale en maximale versies die het decodeert; contacts die twee minuten zwijgen vallen terug op de versie van hun laatste decodeerbare bericht; en iedereen zendt op de hoogste versie die alle bekende contacts kunnen decoderen, met terugval op XML zodra een legacy-apparaat aanwezig is. Belast de onderhandeling met tests voordat je aanneemt dat de vloot is omgeschakeld — de tuningknoppen staan in onze gids voor TAK Server-prestaties.

TAK Server-poorten: de standaardkaart

Standaardwaarden uit de configuratiegids van TAK Server 5.7 en het bijgevoegde voorbeeld-CoreConfig.xml; elk is configureerbaar, dus beschouw dit als wat een voorraadimplementatie opent, niet als een contract. De eigen firewallraad van de gids is minimaal: open 8089 en 8443.

PoortProtocolRol
8089TCP/TLSCoT-streaming-input — waar ATAK, WinTAK en gateways met clientcertificaten op verbinden
8090UDP (QUIC)Optionele QUIC-streaming-input, aanwezig in de huidige voorbeeldconfiguratie
8087TCP of UDPOngelimiteerde CoT-input (voorbeeldinputs; alleen labgebruik)
8088TCPStreaming-TCP zonder TLS (stcp) — alleen testen
8443TCP/HTTPSBeheerinterface, REST API en WebTAK (clientcertificaat-authenticatie)
8444TCP/HTTPSFederatie-gerichte HTTPS (federatie-truststore; ophalen van mission packages)
8446TCP/HTTPSCertificaatinschrijving (CSR, HTTP Basic auth) en OAuth2-tokenendpoint
9000TCP/TLSFederation v1-listener
9001TCP/TLSFederation v2-listener (gRPC over HTTP/2)
9002TCP/TLSFederatie-tokenauthenticatie (indien ingeschakeld)
239.2.3.1:6969UDP-multicastMesh SA-groep (clientstandaard; als serverinput te bruggen)

Twee voetnoten. FreeTAKServer, de Python-server van het open-source-ecosysteem (zie onze gids voor het open-source TAK-ecosysteem), houdt 8089 voor CoT over TLS maar gebruikt 8087 voor kale TCP-CoT. En federatie verdient eigen lectuur: de v1-link wisselt protobuf-FederatedEvent-berichten uit achter een vierbytes-lengteprefix, terwijl v2 een gRPC-dienst draait met streaming-RPC's en health checks — behandeld in onze gids voor federatie-setup en het architectuuroverzicht van de Federation Hub.

Berichtgrootte en bandbreedte: XML versus protobuf

We codeerden twee representatieve events op beide manieren — een ATAK-achtige eigen positiemelding (getypeerde detail plus een ongetypeerd uid-element) en een kleine drone-track van een MAVLink-brug, de protobuf-kant met de referentie-Python-encoder:

EventCoT XMLXML in een stream (declaratie mee)Protobuf-payloadOp de lijn (geframed)
ATAK-eigen positiemelding578 B634 B258 B261 B
Track van de dronebrug363 B419 B171 B174 B

Een reductie van 52–59% voor deze vormen — consistent met de 55–65% die we aanhaalden in ons artikel over drone-telemetrie-integratie en met Isodes veldmetingen uit 2025 voor TAK over HF-radio: ruwweg 530-byte XML-events tegenover 376–380-byte gefedereerde protobuf-berichten, vóór compressie. Protobuf helpt het meest waar XML pure envelop is — declaraties, attribuutnamen, sluittags — terwijl detail die in xmlDetail geparkeerd is zijn XML-grootte houdt.

Waarom dat op radio telt: veertig gebruikers die zich elke tien seconden melden kosten circa 20 kbps aan gestreamde XML (634 B per stuk) tegenover circa 8 kbps aan protobuf, vóór de TLS-record-overhead per bericht. Op smalband is het effect genadeloos — bij 75 bps mat Isode 29–33 seconden end-to-end-latency voor één event. Nog één groottegedrag: de streaming-uitgang van TAK Server weigert een protobuf-TakMessage groter dan 65.536 bytes te sturen; een te groot event wordt vervangen door een kleine bestandsoverdracht-verwijzing die de client het volledige XML over HTTPS laat ophalen. Chatverkeer wordt geanalyseerd in ons artikel over de datastrategie voor tactische chat.

CoT versturen vanuit Python: TLS, certificaten, protobuf

Al het bovenstaande comprimeert tot een klein programma — de standaardbibliotheek alleen kan al een TLS-verbinding met de 8089-input openen met een clientcertificaat en versie-0-XML-events streamen, zonder dependencies:

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())

Drie details dragen hier alles. Asyncio-sockets zetten Nagles algoritme standaard uit, dus elk event vertrekt direct — met ruwe sockets zet je TCP_NODELAY zelf. De drain-taak is geen decoratie: een server die schrijft naar een client die nooit leest, blijft uiteindelijk steken op TCP-flowcontrol. Certificaten moeten PEM zijn: TAK Server geeft een PKCS#12-.p12 uit (wat ATAK consumeert), dat OpenSSL in drie regels omzet:

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

Voor protobuf converteert het pakket takproto (PyPI) CoT XML naar en vanuit versie-1-payloads en voegt de framing toe; de bibliotheek PyTAK pakt de hele client in — COT_URL accepteert tls://host:8089 of udp+wo://239.2.3.1:6969, TAK_PROTO=1 kiest protobuf, en certificaten importeren rechtstreeks uit een TAK-datapakket .zip. De afweging "zelf bouwen of een bibliotheek nemen" werkt ons artikel over TAK C2-integratiepatronen uit.

Dit is waar een weekendprototype operationele werkelijkheid ontmoet: certificaatinschrijving op vlootschaal, protobuf-onderhandeling over gemengde clientversies, multicast die daadwerkelijk moet routen. Wij bouwen CoT/TAK-protocolgateways, migreren feeds van XML naar protobuf, en integreren en harden TAK Server. Vertel ons wat je moet koppelen →

Afleversemantiek, beveiliging en de valkuilen die bijten

Geen acknowledgements — het stale-tijdstip doet het werk

CoT is fire-and-forget op elke laag: geen acknowledgements per bericht, geen volgnummers, geen sessies. Versheid wordt beheerd door het stale-tijdstempel — consumers laten events daarvoor verouderen of vallen ze af — en door de cadans: verstuur ruim binnen je stale-venster of accepteer spookbeelden op de kaart. TAK Server verzacht reconnects met zijn latest SA-buffer (nieuwe clients krijgen direct de laatst bekende posities van bereikbare gebruikers), en ATAK houdt verbindingen levend met een ping (t-x-c-t) die de server met een pong (t-x-c-t-r) beantwoordt. Stuur je huidige beeld na elke reconnect opnieuw in plaats van aan te nemen dat de server het onthield.

Certificaten, groepen, kanalen

Operationeel TAK-verkeer is mutual TLS: de client verifieert de server tegen de CA van de implementatie, de server verifieert een clientcertificaat van diezelfde CA, en de CN van het certificaat wordt de gebruikersnaam voor groepstoewijzing. Groepslidmaatschap — per input, per certificaat of via LDAP-/bestandsbackends — is het hele toegangsmodel voor wie wiens tracks ziet; niet-matchende verbindingen belanden in __ANON__. Federatie gebruikt bewust een aparte truststore, zodat een partner-CA nooit stilletjes clientverbindingen autoriseert, en inschrijving draait op poort 8446 achter HTTP Basic auth. Waar een implementatie HTTP-API's nodig heeft in plaats van ruwe sockets, beschrijft onze gids voor CloudTAK API-integratie dat vlak.

De terugkerende faalmodi

  • Multicast die niet aankomt: multicast wordt alleen doorgestuurd zolang de TTL het toestaat (standaard TTL 1 houdt datagrammen op het lokale segment; de voorbeeldconfiguratie van TAK Server verhoogt die naar 5), verkeerd geconfigureerde IGMP-snooping laat groepen stilletjes vallen, en multicast gaat nooit door NAT. Mesh SA is same-subnet-technologie.
  • Klokafwijking: met stale-based veroudering laat een verkeerde klok óf ieders tracks verdampen óf eeuwig blijven. Synchroniseer de tijd (GNSS of NTP) voordat je iets anders debugt.
  • Certificaatformatwrijving: de server spreekt JKS, de clients PKCS#12, jouw dienst PEM — en certificaten zonder het extended key usage client-auth worden al in de handshake geweigerd. Converteer bewust en test de exacte keten.
  • Nagles algoritme: een batchingvertraging van 200 ms is onzichtbaar op een datacenterlink, dodelijk op een tactische. Zet het uit of batch expliciet.
  • Reconnect-stormen: honderd gateways die na een radiostoring tegelijk herverbinden lijken op een DDoS. Gebruik gejitterde exponentiële backoff, herauthenticeer, speel de huidige staat in.
  • Aannames over gemengde versies: één legacy-client op de mesh gooit iedereen terug op XML, en een server die nooit t-x-takp-v aanbiedt krijgt nooit protobuf. Instrumenteer op welke codering je links zijn beland — bytes per minuut op de lijn vertelt de waarheid.

Referentiearchitectuur: een CoT-gatewayservice

Het duurzame patroon om een TAK-netwerk uit niet-TAK-systemen te voeden is een kleine, toegewijde gatewayservice, geen code die in elke bron is ingebed:

  • Inkomende adapters — MAVLink, radar, AIS, GPS-trackers, REST/WebSocket-feeds — elk genormaliseerd naar een intern trackmodel.
  • Een CoT-builder — één plek die het UID-beleid bezit (stabiel, namespaced, collision-bestendig), typemapping, how-codes en stale-vensters per bron, en XML of protobuf emitteert volgens dezelfde detailregels.
  • Een uitgangs-superisor — een pool van geauthenticeerde TLS-verbindingen met onderhandeling (protobuf waar aangeboden, anders XML), gejitterde reconnects, rate-shaping per link voor smalbandpaden en replay van de huidige staat.
  • Operationeel vlak — linkgezondheid, actieve codering, bytes per minuut en monitoring van certificaatverloop; op tactische netwerken is het protocol de eerste verdachte en het laatste geïnstrumenteerde.

Die vorm — een protocoll-getrouw rand tussen andersmans data en een TAK Server — is een component die wij bouwen voor defensieprogramma's, naast de TAKpilot-copiloot op dezelfde infrastructuur. Als jouw programma dit diagram nu tekent, haal er een team bij dat het eerder heeft geleverd.

Dit nodig op jouw netwerk?

Wij bouwen CoT/TAK-protocolgateways, migreren feeds van XML naar protobuf, en integreren en harden TAK Server — inclusief certificaten, groepen en federatie.

Bouw je CoT-gateway → Bekijk TAKpilot →

Opgesteld door het engineeringteam van Corvus Intelligence, dat CoT/TAK-gateways, ATAK-plugins en TAK Server-integraties bouwt voor defensieprogramma's (ISO 9001/27001-gecertificeerd, Brave1-lid). Over Corvus Intelligence →