Le protocole TAK est le contrat de liaison qu'ATAK, WinTAK, iTAK et TAK Server utilisent pour échanger des événements Cursor on Target (CoT). La version 0 envoie l'événement en XML brut ; la version 1 en message protobuf précédé d'une longueur, environ deux fois plus petit. La même charge utile emprunte trois transports : multicast UDP sans serveur sur le mesh local, flux TCP/TLS persistants vers TAK Server (port 8089 par défaut) et fédération serveur à serveur (9000/9001).

Si vous intégrez un capteur, un drone ou un système C2 à l'écosystème TAK, cette distinction compte immédiatement : CoT est le modèle de données — <event>, <point>, <detail> — tandis que le protocole TAK définit comment ces octets sont tramés, versionnés et négociés sur chaque transport. Le schéma XML lui-même est couvert par notre guide du format Cursor on Target et notre plongée dans le schéma CoT ; cet article est l'autre moitié : la liaison.

CoT contre protocole TAK : modèle de données contre contrat de liaison

Gardez trois couches séparées — la documentation de l'écosystème les confond régulièrement :

  • Le modèle d'événement CoT. Un document XML par événement : code de type, UID, time/start/stale, un point WGS-84, un <detail> extensible. Le contenu sémantique, identique sur tous les transports.
  • L'encodage (version du protocole TAK). La version 0 encode l'événement en texte XML ; la version 1 en TakMessage protobuf. Les deux transportent les mêmes événements.
  • Le transport. Multicast UDP sur le mesh, flux TLS persistant vers TAK Server ou lien de fédération entre serveurs — chacun trame la charge utile différemment.

La description du protocole distribuée avec les produits TAK pose deux règles de base : un client qui émet la version V sait aussi décoder la version V, et chaque client doit toujours décoder le XML de la version 0. C'est pourquoi les parcs mixtes continuent de fonctionner — tout retombe en douceur sur le XML.

Diagramme des transports du protocole TAK : appareils ATAK, WinTAK et iTAK partageant un multicast UDP sans serveur sur 239.2.3.1:6969 ; appareils ou passerelle CoT en flux vers TAK Server en TLS mutuel sur le port 8089 ; le serveur se fédérant avec un second TAK Server sur les ports 9000 et 9001 ; flux capteurs et C2 convertis en CoT par le service passerelle.
Transports du protocole TAK : multicast mesh sans serveur, flux TLS mutuel vers TAK Server (8089) et fédération serveur à serveur (9000/9001), avec une passerelle CoT alimentant le serveur.

Protocole TAK version 0 : le CoT XML brut

La version 0 a porté l'écosystème pendant sa première décennie et reste partout la solution de repli. Elle se comporte différemment sur chaque transport :

  • Mesh SA (multicast). Les annonces de situation sont des datagrammes UDP envoyés au groupe multicast bien connu 239.2.3.1:6969 — un événement CoT XML par datagramme, sans aucun serveur. Chaque appareil joint au groupe reçoit chaque événement, et il n'y a pas de retransmission : un datagramme perdu est un rapport de position perdu. C'est le mode derrière le blue force tracking sans serveur sur un segment Wi-Fi de groupe ou MANET. (ATAK émet le GeoChat en multicast sur un groupe séparé, 224.10.10.1:17012, que TAK Server peut capter comme entrée.)
  • Messages adressés. Les messages à un destinataire unique passent par une connexion TCP éphémère : se connecter, envoyer un événement, se déconnecter. Un appareil ATAK à l'écoute de pairs directs les accepte sur le port TCP 4242 — pratique pour injecter un événement dans un seul terminal sans serveur.
  • Flux vers TAK Server. Une connexion persistante (généralement TLS) transporte un flux continu d'événements XML, chacun précédé d'une déclaration XML et suivi d'un saut de ligne. Le récepteur ne reçoit ni préfixe de longueur ni délimiteur : il découpe le flux en cherchant le jeton littéral </event> et en coupant juste après — la déclaration suivante commence à l'octet immédiatement suivant.

En pratique, la forme en flux ressemble à ceci (abrégé) :

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

Ce découpeur par balayage de jeton est un comportement du protocole, pas une bizarrerie d'implémentation — le propre codec de flux de TAK Server documente l'absence de délimiteurs et recherche la balise fermante. Toute passerelle doit émettre des événements qui se découpent proprement : événements complets, déclaration en tête, rien entre eux. Pour des événements complets annotés, voir nos exemples de messages CoT.

Protocole TAK version 1 : la TakMessage protobuf

La version 1 remplace le texte XML par un unique message proto3 — atakmap.commoncommo.protobuf.v1.TakMessage — dont la définition est livrée avec les distributions TAK et reflétée dans des bibliothèques comme le paquet Python takproto. La structure est compacte mais strictement spécifiée :

  • TakMessage contient deux parties optionnelles : un TakControl (la comptabilité du protocole — versions min/max décodées par l'émetteur, plus un UID de contact) et le CotEvent lui-même.
  • CotEvent porte l'enveloppe : type, uid, how, access/qos/opex optionnels, les trois horodatages en millisecondes depuis l'époque Unix (sendTime, startTime, staleTime) et les champs du point lat, lon, hae, ce, le en double. Hauteur ou erreur inconnue : la sentinelle 999999, comme dans la convention XML.
  • Detail est là que ça devient intéressant. Six éléments de détail bien connus sont devenus des sous-messages typés : contact (endpoint, callsign), group (de __group : name, role), precisionLocation (geopointsrc, altsrc), status (battery), takv (device, platform, os, version), track (speed, course). Tout le reste — remarks, corps de chat, éléments de plugins — est entassé dans une unique chaîne xmlDetail contenant le XML brut des enfants restants.

Deux règles de la spécification préservent les équipes d'une corruption insidieuse. Premièrement, des éléments entiers uniquement : un élément de détail est intégralement converti en son message typé ou reste intégralement dans xmlDetail — jamais coupé en deux, et s'il ne se mappe pas proprement, il reste dans xmlDetail. Deuxièmement, les récepteurs refusionnent les messages typés en XML et, en cas de conflit, xmlDetail gagne. Les nouveaux champs ne peuvent s'ajouter qu'à la fin des messages existants ; toute sémantique nouvelle exige un incrément de version. En pratique, le gain protobuf fond à mesure que le détail non typé croît — exactement ce qu'on observe sur un trafic riche en chat ou en plugins.

Tramage du mesh et du flux : les octets réels

Les deux versions empruntent les deux transports ; le tramage diffère par transport, pas par charge utile :

  • Datagramme mesh : 0xbf, un varint de version du protocole, 0xbf, puis la charge utile. L'octet magique 0xbf (191 en décimal) permet à un récepteur de renifler un datagramme et de savoir s'il s'agit de protobuf ou de XML hérité, qui commence par < — les entrées UDP de TAK Server font exactement cette vérification sur chaque datagramme.
  • Trame de flux : 0xbf, un varint de longueur de charge en octets, puis la charge utile. Pas d'octet de version — la version a été négociée une fois par connexion (section suivante), la répéter par trame serait du gaspillage.

Les varints sont des varints protobuf non signés standard — 7 bits à la fois, poids faible d'abord, bit de poids fort marquant la continuation, 64 bits maximum (10 octets). Une charge de 258 octets s'encode 82 02 ; 127 est 7f, 128 est 80 01.

Diagramme d'agencement des octets du tramage TAK : un datagramme UDP mesh comme 0xbf, varint de version, 0xbf, puis la charge protobuf TakMessage ; une trame de flux TCP ou TLS comme 0xbf suivi d'un varint de longueur puis la charge ; et les événements XML version 0 découpés sur le jeton event fermant.
Tramage TAK v1 : l'en-tête mesh répète octet magique, version, octet magique ; l'en-tête de flux est octet magique plus varint de longueur ; la version 0 transporte du XML brut découpé sur le jeton event fermant.

Comme chaque trame porte sa propre longueur, un analyseur de flux est une petite machine à états : attendre 0xbf, accumuler le varint, tamponner exactement ce nombre d'octets, décoder, répéter — en portant les trames partielles d'une lecture à l'autre. La version 0 ne vous offre rien de tout cela ; vous balayez le texte à la recherche de </event> en espérant que rien ne se coupe en plein événement.

Négociation du flux : t-x-takp-v, t-x-takp-q, t-x-takp-r

Un client ne peut pas savoir si un serveur parle protobuf : le basculement se négocie donc à l'intérieur de la connexion par trois événements de contrôle CoT — eux-mêmes envoyés en XML :

  1. L'offre (t-x-takp-v). Un serveur qui prend en charge le protocole TAK peut envoyer un événement de ce type portant <detail><TakControl><TakProtocolSupport version="1"/> — un élément par version prise en charge, au plus une fois par connexion, après authentification quand l'entrée l'exige.
  2. La demande (t-x-takp-q). Le client choisit une version dans l'offre et répond <TakRequest version="1"/>, puis doit cesser d'émettre du XML (tout en traitant le XML entrant) et attendre — au moins une minute avant d'abandonner et de se reconnecter.
  3. La réponse (t-x-takp-r). Le serveur répond <TakResponse status="true"/> ou "false". Sur true, les deux côtés basculent toute la connexion sur des charges version 1 tramées par longueur — la même version dans les deux sens — et plus aucun XML ne circule. Sur false, la connexion reste en XML et le client peut réessayer plus tard.

Les trois événements partagent un UID de transaction (le protouid de la spécification) et le pas de danse est strict : du protobuf émis avant la réponse true casse contre le serveur de référence. Sur le mesh, pas de poignée de main : chaque appareil diffuse un message TakControl au moins toutes les 60 secondes déclarant les versions min et max qu'il décode ; les contacts silencieux depuis deux minutes retombent à la version de leur dernier message décodable ; et tout le monde émet à la version la plus haute que tous les contacts connus savent décoder, avec repli sur le XML dès qu'apparaît un appareil hérité. Testez la négociation en charge avant de supposer que le parc a basculé — les leviers de réglage sont dans notre guide de performance TAK Server.

Ports TAK Server : la carte par défaut

Valeurs par défaut tirées du guide de configuration TAK Server 5.7 et de son CoreConfig.xml d'exemple ; chacun est configurable, considérez donc ceci comme ce qu'ouvre un déploiement standard, pas comme un contrat. Le conseil pare-feu du guide lui-même est minimal : ouvrir 8089 et 8443.

PortProtocoleRôle
8089TCP/TLSEntrée de flux CoT — celle où ATAK, WinTAK et les passerelles se connectent avec des certificats clients
8090UDP (QUIC)Entrée de flux QUIC optionnelle, présente dans la configuration d'exemple actuelle
8087TCP ou UDPEntrée CoT non chiffrée (entrées d'exemple ; laboratoire uniquement)
8088TCPFlux TCP sans TLS (stcp) — tests uniquement
8443TCP/HTTPSInterface d'administration, API REST et WebTAK (authentifiés par certificat client)
8444TCP/HTTPSHTTPS côté fédération (magasin de confiance fédération ; récupération de mission packages)
8446TCP/HTTPSInscription de certificats (CSR, HTTP Basic auth) et point de terminaison de jetons OAuth2
9000TCP/TLSÉcouteur fédération v1
9001TCP/TLSÉcouteur fédération v2 (gRPC sur HTTP/2)
9002TCP/TLSAuthentification par jetons de fédération (si activée)
239.2.3.1:6969UDP multicastGroupe mesh SA (valeur client ; relayable comme entrée serveur)

Deux notes. FreeTAKServer, le serveur Python de l'écosystème open source (voir notre guide de l'écosystème TAK open source), garde 8089 pour le CoT sur TLS mais utilise 8087 pour le CoT TCP en clair. Et la fédération mérite une lecture propre : le lien v1 échange des messages protobuf FederatedEvent derrière un préfixe de longueur de quatre octets, tandis que v2 fait tourner un service gRPC avec des RPC en flux et des contrôles de santé — couverts dans notre guide d'installation de la fédération et notre aperçu de l'architecture Federation Hub.

Taille des messages et bande passante : XML contre protobuf

Nous avons encodé deux événements représentatifs des deux façons — un rapport de position propre style ATAK (détail typé plus un élément uid non typé) et une petite piste de drone d'un pont MAVLink, côté protobuf avec l'encodeur Python de référence :

ÉvénementCoT XMLXML en flux (déclaration incluse)Charge protobufSur la liaison (tramée)
Rapport de position ATAK578 o634 o258 o261 o
Piste du pont de drone363 o419 o171 o174 o

Une réduction de 52–59 % pour ces formes — cohérente avec les 55–65 % que nous citions dans notre article d'intégration de la télémétrie de drones et avec les mesures de terrain d'Isode en 2025 pour TAK sur radio HF : environ 530 octets par événement XML contre 376–380 octets par message protobuf fédéré, avant compression. Protobuf aide surtout là où le XML est pure enveloppe — déclarations, noms d'attributs, balises fermantes — tandis que le détail parqué dans xmlDetail garde sa taille XML.

Pourquoi cela compte à la radio : quarante utilisateurs s'auto-rapportant toutes les dix secondes coûtent environ 20 kbps en XML en flux (634 o chacun) contre environ 8 kbps en protobuf, avant l'overhead d'enregistrement TLS par message. Sur bande étroite l'effet est brutal — à 75 bps, Isode a mesuré 29–33 secondes de latence de bout en bout pour un seul événement. Un autre comportement de taille : la sortie de flux de TAK Server refuse d'envoyer une TakMessage protobuf de plus de 65 536 octets ; un événement trop grand est remplacé par un petit pointeur de transfert de fichier invitant le client à récupérer le XML complet en HTTPS. Le trafic de chat est examiné dans notre article sur la stratégie de données du chat tactique.

Envoyer du CoT depuis Python : TLS, certificats, protobuf

Tout ce qui précède se résume en un petit programme — la bibliothèque standard seule peut ouvrir une connexion TLS vers l'entrée 8089 avec un certificat client et streamer des événements XML version 0, sans dépendance :

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

Trois détails portent tout ici. Les sockets asyncio désactivent l'algorithme de Nagle par défaut, donc chaque événement part immédiatement — avec des sockets bruts, réglez TCP_NODELAY vous-même. La tâche drain n'est pas décorative : un serveur qui écrit vers un client qui ne lit jamais finit par se bloquer sur le contrôle de flux TCP. Les certificats doivent être en PEM : TAK Server délivre un PKCS#12 .p12 (ce que consomme ATAK), qu'OpenSSL convertit en trois lignes :

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

Côté protobuf, le paquet takproto (PyPI) convertit le CoT XML vers et depuis les charges version 1 et ajoute le tramage ; la bibliothèque PyTAK encapsule tout le client — COT_URL accepte tls://host:8089 ou udp+wo://239.2.3.1:6969, TAK_PROTO=1 sélectionne protobuf, et les certificats s'importent directement d'un data package TAK .zip. Le calcul « construire soi-même ou adopter une bibliothèque » est développé dans notre article sur les patterns d'intégration C2 avec TAK.

C'est ici qu'un prototype de week-end rencontre la réalité opérationnelle : inscription de certificats à l'échelle du parc, négociation protobuf entre versions clients mixtes, multicast qui doit réellement router. Nous construisons des passerelles CoT/protocole TAK, migrons des flux du XML vers protobuf, intégrons et durcissons TAK Server. Dites-nous ce que vous devez connecter →

Sémantique de livraison, sécurité et pièges qui mordent

Pas d'accusés de réception — le stale fait le travail

CoT est du fire-and-forget à chaque couche : pas d'accusé par message, pas de numéros de séquence, pas de sessions. La fraîcheur est gérée par l'horodatage stale — les consommateurs vieillissent ou abandonnent les événements au-delà — et par la cadence : émettez bien dans votre fenêtre de stale ou acceptez des fantômes sur la carte. TAK Server adoucit les reconnexions avec son tampon latest SA (les nouveaux clients reçoivent immédiatement les dernières positions connues des utilisateurs joignables), et ATAK garde les connexions vivantes par un ping (t-x-c-t) auquel le serveur répond par un pong (t-x-c-t-r). Renvoyez votre image actuelle après chaque reconnexion au lieu de supposer que le serveur s'en souvenait.

Certificats, groupes, canaux

Le trafic TAK opérationnel est du TLS mutuel : le client vérifie le serveur contre l'AC du déploiement, le serveur vérifie un certificat client de cette même AC, et le CN du certificat devient le nom d'utilisateur pour l'affectation aux groupes. L'appartenance aux groupes — par entrée, par certificat ou via des backends LDAP/fichiers — est tout le modèle de contrôle d'accès déterminant qui voit les pistes de qui ; les connexions sans correspondance atterrissent dans __ANON__. La fédération utilise délibérément un magasin de confiance séparé, pour que l'AC d'un partenaire n'autorise jamais silencieusement des connexions clientes, et l'inscription tourne sur le port 8446 derrière HTTP Basic auth. Quand un déploiement préfère des API HTTP aux sockets bruts, cette surface est décrite dans notre guide d'intégration de l'API CloudTAK.

Les modes de défaillance récurrents

  • Multicast qui n'arrive pas : le multicast ne progresse que tant que le TTL le permet (TTL 1 par défaut confine les datagrammes au segment local ; la configuration d'exemple de TAK Server le monte à 5), un IGMP snooping mal réglé silencieusement perd les groupes, et le multicast ne traverse jamais NAT. Le mesh SA est une technologie de même sous-réseau.
  • Dérive d'horloge : avec un vieillissement par stale, une horloge fausse fait soit évaporer les pistes de tout le monde, soit les laisser pour toujours. Synchronisez le temps (GNSS ou NTP) avant de déboguer quoi que ce soit d'autre.
  • Frictions de format de certificats : le serveur parle JKS, les clients PKCS#12, votre service PEM — et les certificats sans l'usage étendu de clé client-auth sont rejetés dès la poignée de main. Convertissez délibérément et testez la chaîne exacte.
  • Algorithme de Nagle : un délai de groupage de 200 ms est invisible sur une liaison de datacenter, mortel sur une liaison tactique. Désactivez-le ou groupez explicitement.
  • Tempêtes de reconnexion : des centaines de passerelles se reconnectant d'un coup après une coupure radio ressemblent à un DDoS. Utilisez un backoff exponentiel avec gigue, réauthentifiez-vous, rejouez l'état courant.
  • Hypothèses de versions mixtes : un seul client hérité sur le mesh fait retomber tout le monde en XML, et un serveur qui n'émet jamais t-x-takp-v n'aura jamais le protobuf. Instrumentez l'encodage sur lequel vos liens se sont installés — les octets par minute sur la liaison disent la vérité.

Architecture de référence : un service passerelle CoT

Le modèle durable pour alimenter un réseau TAK depuis des systèmes non-TAK est un petit service passerelle dédié, pas du code embarqué dans chaque source :

  • Adaptateurs en entrée — MAVLink, radar, AIS, traceurs GPS, flux REST/WebSocket — chacun normalisé vers un modèle de piste interne.
  • Un constructeur CoT — un seul endroit qui possède la politique d'UID (stables, namespacés, résistants aux collisions), le mapping des types, les codes how et les fenêtres de stale par source, émettant du XML ou du protobuf selon les mêmes règles de détail.
  • Un superviseur de sortie — un pool de connexions TLS authentifiées avec négociation (protobuf si offert, XML sinon), reconnexion avec gigue, mise en forme du débit par lien pour les chemins à bande étroite et rejeu de l'état courant.
  • Surface opérationnelle — santé des liens, encodage en cours, octets par minute et surveillance d'expiration des certificats ; sur les réseaux tactiques, le protocole est le premier accusé et le dernier instrumenté.

Cette forme — un bord fidèle au protocole entre les données de d'autres et un TAK Server — est un composant que nous construisons pour des programmes de défense, aux côtés du copilote TAKpilot sur la même infrastructure. Si votre programme dessine ce diagramme en ce moment, faites venir une équipe qui l'a déjà livré.

Besoin de cela sur votre réseau ?

Nous construisons des passerelles CoT/protocole TAK, migrons des flux du XML vers protobuf, intégrons et durcissons TAK Server — certificats, groupes et fédération compris.

Construisez votre passerelle CoT → Voir TAKpilot →

Préparé par l'équipe d'ingénierie de Corvus Intelligence, qui construit des passerelles CoT/TAK, des plugins ATAK et des intégrations TAK Server pour des programmes de défense (certifié ISO 9001/27001, membre Brave1). À propos de Corvus Intelligence →