ExfilGuardian
Architecture

Data Flow

How packets travel through the ExfilGuardian pipeline

End-to-End Pipeline

Stage 1: Kernel Packet Interception

The WDM kernel driver registers WFP (Windows Filtering Platform) callouts on four layers — FWPM_LAYER_DATAGRAM_DATA_V4 / _V6 (UDP, ICMP) and FWPM_LAYER_STREAM_V4 / _V6 (TCP). A matching packet triggers the callout, which copies the 5-tuple, direction, owning PID and up to 4 KiB of payload (plus the real wire_size) into an ExfilPacket struct delivered to the agent.

The driver uses an inverted IRP model: the agent pre-posts IRP_MJ_DEVICE_CONTROL requests, and the driver completes them when packets are available. This avoids polling and provides event-driven delivery with minimal latency.

ExfilPacket {
    protocol: u8,        // IANA protocol number
    direction: u8,       // 0 unknown, 1 outbound, 2 inbound
    ip_version: u8,      // 4 or 6
    padding: u8,
    pid: u32,            // owning process PID (from WFP metadata)
    local_ip: [u8; 16],  // source IP (IPv4 in the first 4 bytes, or full IPv6)
    remote_ip: [u8; 16], // destination IP
    local_port: u16,
    remote_port: u16,
    payload_len: u32,    // captured payload length (<= 4096)
    wire_size: u32,      // real datagram/chunk byte count (NOT capped at 4096)
    payload: [u8; 4096], // raw payload bytes (truncated to 4 KiB)
}
// There is no kernel timestamp field: the timestamp is stamped agent-side at
// processing time. The capture covers IPv4 + IPv6, UDP/ICMP (datagram layer)
// and TCP (stream layer).

Stage 2: Agent Forwarding

The agent runs as a Windows service and reads packets from the driver via DeviceIoControl with the IOCTL_EXFIL_GET_PACKET control code. The agent is a deliberately thin collector — all analysis is done by the server. Before forwarding it applies only a minimal noise drop: loopback (127.0.0.0/8, ::1) and multicast/broadcast, to spare bandwidth. Every other filtering decision (whitelist, protocol allowlist, signatures, behavioural) is the server's responsibility.

The agent forwards the raw kernel PID — process attribution (PID → name) is resolved server-side from the ProcessEvent stream — and the real byte volume (wire_size), independent of the 4 KiB payload-capture cap.

Packets are serialized into Protobuf NetworkPacket messages and written to a SQLite database in WAL mode, which is the single FIFO writer. This is a durable queue across agent restarts and server outages: packets accumulate on disk and drain in order when connectivity returns. Delivery is best-effort (at-most-once at the precise instant of a link break): a row is deleted once handed to the gRPC stream, without a per-message server acknowledgement.

Stage 3: gRPC Streaming

The agent opens a StreamPackets bidirectional gRPC stream to the server on port 50051. The connection is authenticated with mTLS: both agent and server present X.509 certificates signed by the ExfilGuardian CA.

service ExfilService {
  rpc StreamPackets(stream NetworkPacket) returns (StreamResponse);
}

message NetworkPacket {
  uint32 protocol = 1;
  uint32 local_ip = 2;
  uint32 remote_ip = 3;
  uint32 local_port = 4;
  uint32 remote_port = 5;
  uint64 timestamp = 6;
  bytes payload = 7;
  string auth_token = 8;
}

The agent continuously reads from the SQLite queue and pushes NetworkPacket messages into the stream. Backpressure is handled by gRPC flow control: if the server is slow, the agent blocks on send and packets accumulate in SQLite.

Stage 4: Server Analysis Pipeline

The gRPC receiver on the server deserializes incoming packets and dispatches them to three detection modules in parallel:

ModuleInputOutput
DPIRaw packet payloadProtocol-specific detections (DNS tunneling, TLS anomalies, ICMP covert channels)
SignaturesPacket fields + payloadRule-match detections from YAML signature files
BehavioralFlow statisticsStatistical anomaly detections (Z-score, CUSUM, beaconing)

Each module produces zero or more Detection events that flow into the Correlation engine.

Stage 5: Correlation and Alerting

The correlation engine aggregates detections within a temporal window and computes a final threat confidence score using Bayesian combination:

  • Multiple independent detections on the same flow increase confidence
  • A diversity bonus rewards detections from different modules (DPI + Behavioral is stronger than two DPI detections alone)
  • Temporal decay reduces confidence of stale detections

When the combined score exceeds the configured threshold, an Alert is emitted with severity (Low / Medium / High / Critical) and published to the REST API.

Stage 6: REST API to Desktop

The Axum HTTP server on port 8080 exposes alert data via REST endpoints. The Electron + Next.js desktop dashboard polls or subscribes for real-time updates and presents alerts, flow details, and detection metadata to the SOC operator.

On this page