takproto

Crates.iotakproto
lib.rstakproto
version0.4.2
created_at2025-11-10 03:43:46.893783+00
updated_at2025-11-11 21:54:42.706809+00
descriptionRust library for TAK (Team Awareness Kit) Protocol - send CoT messages to TAK servers with mTLS support
homepage
repositoryhttps://github.com/rabarar/takproto
max_upload_size
id1924690
size345,650
Rob Baruch (rabarar)

documentation

https://docs.rs/takproto

README

takproto

Crates.io Documentation License: MIT OR Apache-2.0

A Rust library for sending TAK (Team Awareness Kit) Protocol messages to TAK servers with full mTLS support.

Features

  • TAK Protocol Version 1 - Protocol Buffer-based messaging
  • mTLS Support - Client certificate authentication
  • Protocol Negotiation - Automatic handshake with TAK servers
  • XML Mode - Legacy Protocol Version 0 support
  • Async/Await - Built on Tokio for efficient I/O
  • Type-Safe - Generated protobuf types with prost
  • Builder Pattern - Ergonomic CotEventBuilder for easy event creation
  • Detail Helpers - Contact, track, group, status, and more
  • Helper Functions - Easy marker and URL creation

Quick Start

Add to your Cargo.toml:

[dependencies]
takproto = "0.4"
tokio = { version = "1", features = ["full"] }

Feature Flags

  • openssl-p12: Enable full PKCS#12 support using OpenSSL (recommended for legacy TAK P12 files)
[dependencies]
takproto = { version = "0.4", features = ["openssl-p12"] }

Certificate Validation Options

For development, testing, or working with self-signed certificates, use TlsConfigBuilder to customize validation:

use takproto::TlsConfigBuilder;

// Accept self-signed server certificates (with client auth)
let tls_config = TlsConfigBuilder::new()
    .with_p12("user.p12", "password")?
    .danger_accept_invalid_certs(true)
    .build()?;

// Disable hostname verification (useful for IP-based connections)
let tls_config = TlsConfigBuilder::new()
    .with_p12("user.p12", "password")?
    .danger_disable_hostname_verification(true)
    .build()?;

// Both options together (very insecure - testing only!)
let tls_config = TlsConfigBuilder::new()
    .with_p12("user.p12", "password")?
    .danger_accept_invalid_certs(true)
    .danger_disable_hostname_verification(true)
    .build()?;

// Also works with PEM certificates
let tls_config = TlsConfigBuilder::new()
    .with_client_cert("ca.pem", "client.pem", "client-key.pem")?
    .danger_accept_invalid_certs(true)
    .build()?;

⚠️ WARNING: These options reduce security and should only be used in trusted networks or during development.

Note: Client authentication (mTLS) is fully supported with all validation options.

Example: Send a Position Report with Builder

Using PKCS#12 Certificate (Recommended for TAK)

Important: Legacy TAK Server P12 files use RC2-40-CBC encryption which is disabled in OpenSSL 3.x. You must convert them to a modern format first:

# Convert legacy TAK Server P12 to modern format
openssl pkcs12 -in legacy.p12 -out temp.pem -nodes -password pass:atakatak -legacy
openssl pkcs12 -export -in temp.pem -out modern.p12 -password pass:atakatak \
    -certpbe AES-256-CBC -keypbe AES-256-CBC -macalg SHA256
rm temp.pem

Or use the provided conversion script:

./convert_p12.sh legacy.p12 modern.p12 atakatak
use takproto::{TakClient, TlsConfig, CotEventBuilder};
use takproto::helpers::{contact, track, status};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // For legacy P12 files, first extract to PEM using openssl:
    // openssl pkcs12 -legacy -in user.p12 -nokeys -out client.pem -passin pass:atakatak
    // openssl pkcs12 -legacy -in user.p12 -nocerts -nodes -out client-key.pem -passin pass:atakatak
    // openssl pkcs12 -legacy -in user.p12 -cacerts -nokeys -out ca.pem -passin pass:atakatak

    // Configure mTLS with P12 file (or use extracted PEM files with new_with_client_cert)
    let tls_config = TlsConfig::new_with_p12("user.p12", "atakatak")?;

    // Connect to TAK server
    let mut client = TakClient::connect_tls(
        "takserver.example.com:8089",
        "takserver.example.com",
        tls_config
    ).await?;

    // Negotiate protocol (optional - for protobuf mode)
    client.negotiate_protocol(1, 60).await?;

    // Create a position report with builder
    let event = CotEventBuilder::new()
        .uid("RUST-TAK-1")
        .cot_type("a-f-G-U-C")  // Friendly ground unit
        .lat_lon(37.7749, -122.4194)
        .hae(10.0)
        .ce_le(9.9, 9.9)
        .how("m-g")
        .stale_minutes(5)
        .with_contact(contact("ALPHA-1", Some("192.168.1.100:4242")))
        .with_track(track(15.0, 270.0))  // 15 m/s heading west
        .with_status(status(85))  // 85% battery
        .build()?;

    // Send the event
    client.send_cot_event(event).await?;

    Ok(())
}

Using Separate PEM Files

use takproto::{TakClient, TlsConfig, CotEventBuilder};
use takproto::helpers::{contact, track, status};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Configure mTLS with separate PEM files
    let tls_config = TlsConfig::new_with_client_cert(
        "ca.pem",
        "client.pem",
        "client-key.pem"
    )?;

    // Connect to TAK server
    let mut client = TakClient::connect_tls(
        "takserver.example.com:8089",
        "takserver.example.com",
        tls_config
    ).await?;

    // Negotiate protocol (optional - for protobuf mode)
    client.negotiate_protocol(1, 60).await?;

    // Create a position report with builder
    let event = CotEventBuilder::new()
        .uid("RUST-TAK-1")
        .cot_type("a-f-G-U-C")  // Friendly ground unit
        .lat_lon(37.7749, -122.4194)
        .hae(10.0)
        .ce_le(9.9, 9.9)
        .how("m-g")
        .stale_minutes(5)
        .with_contact(contact("ALPHA-1", Some("192.168.1.100:4242")))
        .with_track(track(15.0, 270.0))  // 15 m/s heading west
        .with_status(status(85))  // 85% battery
        .build()?;

    // Send the event
    client.send_cot_event(event).await?;

    Ok(())
}

Example: Create Markers with URLs (iTAK Compatible)

use takproto::helpers::{url_to_uid, remarks, color, colors};
use takproto::proto::{CotEvent, Detail};

// Put URL in marker name for visibility
let event = CotEvent {
    r#type: "b-m-p-s-m".to_string(),
    uid: url_to_uid("https://status.example.com"),  // Shows as "status.example.com"
    // ... time and position fields ...

    detail: Some(Detail {
        xml_detail: format!(
            "{}\n{}",
            remarks("📊 System Status Dashboard"),
            color(colors::GREEN)
        ),
        ..Default::default()
    }),
    ..Default::default()
};

// Send as XML for maximum compatibility
client.send_cot_event_xml(event).await?;

CoT Event Types

Common CoT types for markers:

Type Description Icon
a-f-G-U-C Friendly ground unit Soldier
a-f-A-M-F Friendly aircraft Aircraft
a-h-G-U-C Hostile ground unit Enemy
b-m-p-s-m Map marker Pin

Protocol Modes

Protobuf Mode (Recommended for high-frequency updates)

// Negotiate protocol
client.negotiate_protocol(1, 60).await?;

// Send as protobuf
client.send_cot_event(event).await?;

XML Mode (Recommended for markers with details)

// No negotiation needed - stays in XML mode

// Send as XML
client.send_cot_event_xml(event).await?;

Helper Functions

The library includes helpers for common tasks:

Detail Helpers (Protobuf messages)

use takproto::helpers::*;

// Contact information
let c = contact("ALPHA-1", Some("192.168.1.100:4242"));

// Movement tracking
let t = track(15.0, 270.0);  // 15 m/s heading west (270°)

// Group affiliation
let g = group("Team Alpha", "Team Leader");

// Device status
let s = status(85);  // 85% battery

// TAK version info
let tv = takv("iPhone 14", "iOS", "17.0", "iTAK 2.12.3");

// GPS precision
let p = precision_location("GPS", "GPS");

XML Helpers

use takproto::helpers::*;

// Convert URL to clean UID
let uid = url_to_uid("https://www.example.com");  // "example.com"

// Create colored marker
let xml = format!("{}\n{}",
    remarks("Important location"),
    color(colors::RED)
);

// Create remarks with URLs
let xml = remarks_with_urls(
    "Resources",
    &[("Report", "https://example.com/report")]
);

Platform Support

Platform Client Certificate Protocol Negotiation XML Mode Protobuf Mode
iTAK 2.12.3
ATAK
WinTAK

Documentation

Examples

The repository includes comprehensive examples:

  • send_position_tls.rs - Basic mTLS connection and position report
  • best_practice_itak.rs - iTAK-compatible markers with URLs
  • listen_tls.rs - Receive messages from TAK server
  • And many more in the examples/ directory

Run an example:

cargo run --example send_position_tls -- \
  takserver.example.com:8089 \
  takserver.example.com \
  ca.pem client.pem client-key.pem

Security

This library supports:

  • mTLS - Mutual TLS authentication with client certificates
  • TLS 1.2/1.3 - Modern TLS protocols via rustls
  • Certificate validation - Proper CA certificate chain validation

Requirements

  • Rust 1.70 or later
  • TAK server (FreeTAKServer, TAK Server, etc.)
  • Client certificates for mTLS (if required by server)

License

Licensed under either of:

at your option.

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

Related Projects

Acknowledgments

Based on the TAK Protocol specification. Protocol Buffer definitions from the official TAK protocol documentation.

Commit count: 0

cargo fmt