Skip to content

Architecture

bmwl edited this page Nov 22, 2025 · 5 revisions

Architecture Notes

This page provides some technical info on the Soft Data Diode architecture. For basic setup and usage, see the main README.

Core Components

The system consists of two main components: the sender and the receiver(s). Each component is designed with unidirectional communication as a core principle.

Sender Architecture

The sender operates in four modes: web capture, RTSP stream capture, VNC display capture, or file synchronization. In all modes, the sender never binds to listening ports, maintaining the unidirectional security model.

Capture Modes

Web Capture Mode

  • Uses Selenium with headless Chrome to load and render web pages
  • Supports authentication via URL embedding
  • Renders pages to JPEG images at configurable quality

RTSP Stream Mode

  • Uses OpenCV to connect to RTSP video streams
  • Supports authentication via URL embedding
  • Captures individual frames at configurable intervals
  • Resizes frames to target resolution

VNC Display Mode

  • Uses vncsnapshot utility to capture VNC displays
  • Supports password authentication via encrypted VNC password files
  • Renders screens to JPEG images at configurable quality

File Synchronization Mode

  • Scans directories or single files for changes
  • Maintains file metadata (size, modification time, checksums)
  • Uses sliding window approach for best-effort delivery
  • Supports path preservation and dotfile inclusion options

Encryption and Fragmentation

All data is encrypted using AES-256-GCM via the Fernet implementation from the cryptography library. The encryption happens after fragmentation to allow for efficient UDP transmission.

The fragmentation process divides data (JPEG image or file content) into fragments, each getting a 16-byte header (8-byte sequence number, 4-byte fragment index, 4-byte total fragments). The header plus fragment data is encrypted and sent via UDP with fire-and-forget semantics.

Packet Structure:

---
title: "Data Diode UDP Packet Structure"
---
packet
0-15: "Sequence Number 8 bytes"
16-23: "Fragment Index 4 bytes"
24-31: "Total Fragments 4 bytes"
32-47: "Packet Type Optional, variable"
48-63: "Fragment Data up to 1400 bytes..."

Loading

The packet structure includes a sequence number, fragment index, total fragments, optional packet type, and fragment data up to 1400 bytes. Fernet (AES-128-CBC with HMAC-SHA256) encrypts each packet independently with no session state maintained between packets. Pre-shared keys are required with no key exchange.

Network Behavior

The sender creates a UDP socket but never calls any listening function. It only ever calls sendto() with a destination address. This is the fundamental application-level unidirectionality guarantee.

Receiver Architecture

The receiver maintains a separate thread per stream, each listening on its configured UDP port. Received fragments are stored in a reassembly buffer until all fragments for a sequence number arrive.

Fragment Reassembly

Buffer Management:

  • Fragments are stored in a defaultdict(dict) keyed by sequence number
  • Metadata is tracked separately for each sequence number
  • A background thread cleans up incomplete frames after 10 seconds
  • The circular buffer holds completed frames (size configurable)

Reassembly Process:

  1. Decrypt incoming packet
  2. Extract header to get sequence number, fragment index, and total fragments
  3. Store fragment data in reassembly buffer
  4. Check if all fragments received
  5. If complete, reassemble and add to frame buffer
  6. If incomplete, wait for more fragments or timeout

Frame Buffer and Streaming

The receiver maintains a circular buffer of completed frames. The HTTP server streams these frames to clients using multipart/x-mixed-replace MIME type for Motion JPEG streaming.

Webserver

The webserver is just a plain HTTP server and was meant to be behind a reverse-proxy. There's no encryption or authentication whatsoever. The server uses threading to handle multiple simultaneous clients. Each stream can be viewed by multiple clients concurrently.

Endpoints:

  • / - Landing page with all streams and freshness indicators
  • /{stream_name} - Individual stream viewer page
  • /{stream_name}/stream - Motion JPEG stream
  • /{stream_name}/freshness - JSON freshness status
  • /{stream_name}/stats - Stream statistics (debugging)

Freshness monitoring tracks time since last received frame with three states: Live (<30s), Stalled (30s-5min), and Stale (>5min). Visual indicators appear on the web interface with a programmatic JSON endpoint for integration.

There is some intelligence built into the web page served to clients that pauses fetching and rendering of frames when the browser window is tabbed out or minimized. No point in putting load on the server for images no one will see.

Clone this wiki locally