It isn't a single protocol, rather a category of communication protocols designed to safely, reliably, and efficiently transmit real-time data. This data often include performance metrics, sensor readings, logs, and security events. Therefore, these data can be very sensitive, which needs to be secured in their transmission.
To convert an insecure protocol into a secure telemetry that must ensure the Three Pillars.
- Encryption: If an attacker intercepts the network, they only see scrambled text.
- Authentication: Prevents rogue devices from injecting fake metrics.
- Integrity: Assures that the data is not altered or tampered with.
In this article, I'm going to walk you through how I built SCTP (Secure Context Telemetry Protocol) from scratch using the Rust language and how I created a visualizer for it.
- The Cryptographic Engine (crypto.rs)
This is where the core pillars of our secure telemetry protocol are implemented. Rather than reinventing, the implementation uses the ring cryptographic library.
- Authentication (ECDSA): To prevent spoofing, we need to establish identity. By using the Elliptic Curve Digital Signature Algorithm (ECDSA over p-256 curve), the client and server can sign cryptographic handshakes and verify public keys. This will guarantee both sides are exactly who they should be before transmission happens.
- Key Exchange and Derivation: We use Ephemeral Elliptic Curve Diffie-Hellman (ECDHE) to securely agree on a shared secret over an untrusted network. This secret is then fed into HKDF (HMAC-based Extract and Expand Key Derivation Function) to generate a unique and symmetric session key. Since these keys are ephemeral, the system achieves Perfect Forward Secrecy(PFS).
- Authenticated Encryption: We employ AES-256 in Galois/Counter Mode(GCM) for the payload. The choice of AEAD (Authenticated Encryption with Associated Data) is intentional, as GCM simultaneously provides Confidentiality and Integrity.
2. The Communication Language (protocol.rs)
How do we structure data over the wire so it doesn't dissolve into an ambiguous blob of binary noise? In protocol.rs, we define a strict message schema using serde for seamless serialization. Rather than treating telemetry as a single monolithic packet, the protocol is broken into lifecycle-specific data structures:
- Handshake Protocol: Before data flows, the client and server must establish trust. This bundles the sender's long-term identity (
ecdsa_public_key) alongside their ephemeral key session (ecdhe_public_key). This includes an ECDSA signature over the ephemeral key, which prevents Man-in-the-Middle from swapping out the key exchange parameters. - The Telemetry Payload: Our protocol isn't just sending basic CPU metrics; it's designed to transport rich software context such as Abstract Syntax Trees (ast_data), semantic code models (
call_graph), and exposed application endpoints (api_routes). To protect this sensitive data, we wrap it in aSecurePayloadalongside a Unix timestamp. This will act as a defense against Replay Attacks. - The Wire Format: Once our crypto engine encrypts the payload, it is packed into an
EncryptedPacketcontaining only rawciphertextand a unique initialization vector (nonce). This structure ensures that internal code metadata remains completely opaque to onlookers.
3. The Orchestration
To prove our secure telemetry protocol, we need a complete simulation environment representing the client, the server, and a hostile actor. So let's create them
- The DAST Orchestrator
server.rs: Operating as the centralized system, the server listens for telemetry streams on port 18080. It handles the heavy cryptographic lifting, such as mutually authenticating incoming workers, deriving AES session keys, and enforcing replay protection. Other than that, it integrates an asynchronous Tokio broadcast channel to stream state changes directly to the React frontend visualization via WebSockets. - The Rust Parsing Engine
client.rs: Acting as the secure worker agent, the component mimics a real-world static or dynamic analysis pipeline. This processes highly sensitive software context. Therefore, we seal them using AES-256-GCM encryption and ships it down the wire. - The MITM Proxy
mitm.rs: The intentional "chaos monkey" of our structure. To test our design against real-world sniffing and tampering, the client intentionally routes its traffic through this TCP proxy listening on port18081.
4. The Security Payoff in Action
The beauty of three-actor architecture lies in how it visually demonstrates security mechanisms during execution:
- Confidentiality Proven: When
client.rstransmits data, from the console output of themitm.rswe can see that it cannot read the sensitive data. The strings "AST" or "login" never leak; instead, it logs raw, unreadable, encrypted data. - Integrity Proven: If a developer goes into
mitm.rsand uncomments the bit-flipping line (buf[n-1] ^= 0xFF;) to simulate data corruption, theserver.rsengine instantly catches it. Theringdecryption engine fails on the modified ciphertext tag, triggering an immediate termination of the socket connection before processing bad data.
5. The React Visualizer
So we have built our secure telemetry protocol. But if we are going to watch the terminal output, then it is very stressful. Therefore, we are going to build a Frontend with React, Framer Motion, and WebSockets.
The UI is essentially a "dumb" terminal that reacts to whatever the Rust backend tells it. I spun up a lightweight WebSocket server alongside the Rust Orchestrator. Whenever the Rust server intercepts a handshake, derives a key, or decrypts a payload, it broadcasts a JSON event to the WebSocket channel.
Source code
Check out the full implementation.