Skip to main content

Overview

The etcd Server is ML Defender’s distributed coordination hub, providing centralized configuration management, automatic crypto seed exchange, and service discovery for all components. Implemented in C++ with the etcd v3 API, it ensures consistent state across the entire pipeline.

Core Functions

  • Distributed Configuration: Single source of truth
  • Crypto Key Exchange: ChaCha20-Poly1305 seed distribution
  • Service Registration: Component discovery
  • Health Monitoring: Heartbeat tracking

Performance

  • <50ms service registration latency
  • <100ms crypto seed exchange
  • 30-second heartbeat intervals
  • 60-second lease TTL

Architecture

The etcd Server acts as the coordination layer between all ML Defender components:

Key-Value Store Structure

Path: /crypto/<component>/tokens
/crypto/
  ├── sniffer/tokens       → ChaCha20-Poly1305 key (256-bit)
  ├── ml-detector/tokens   → ChaCha20-Poly1305 key (256-bit)
  └── firewall/tokens      → ChaCha20-Poly1305 key (256-bit)
Purpose: Automatic encryption key distribution without manual key exchange.

Crypto Seed Exchange

The etcd Server automates ChaCha20-Poly1305 key distribution across the pipeline:

Key Exchange Flow

1

Component Registration

Sniffer registers with etcd Server on startup:
// Sniffer registration request
POST http://localhost:2379/register
{
  "component": "sniffer",
  "version": "3.3.3",
  "node_id": "cpp_sniffer_v33_day12",
  "capabilities": ["ebpf", "xdp", "encryption"]
}
2

etcd Generates Key

etcd Server generates a 256-bit ChaCha20-Poly1305 key:
// etcd_server.cpp
std::string ComponentRegistry::get_encryption_key() {
    if (encryption_key_.empty()) {
        // Generate 256-bit key (32 bytes)
        encryption_key_ = generate_random_hex(32);
    }
    return encryption_key_;
}
3

Key Stored in etcd

Key persisted in etcd key-value store:
etcdctl put /crypto/sniffer/tokens "a1b2c3d4e5f6..."
4

Downstream Components Retrieve

ML Detector and Firewall Agent retrieve the key:
// ML Detector retrieves key
std::string key = etcd_client.get("/crypto/sniffer/tokens");
crypto_transport::set_decryption_key(key);
Security: Keys are generated once at component registration and rotated every 24 hours automatically.

Service Registration & Heartbeats

Registration Protocol

POST /register
{
  "component": "ml-detector",
  "version": "1.0.0",
  "node_id": "ml-detector-default",
  "endpoints": {
    "zmq_pull": "tcp://127.0.0.1:5571",
    "zmq_pub": "tcp://127.0.0.1:5572"
  },
  "partner_component": "sniffer",
  "capabilities": [
    "tricapa_classification",
    "onnx_inference",
    "encryption",
    "compression"
  ]
}

Health Monitoring

// Check if component is healthy (heartbeat within TTL)
bool ComponentRegistry::is_component_healthy(
    const std::string& component_name
) {
    auto it = components_.find(component_name);
    if (it == components_.end()) return false;
    
    auto now = std::chrono::system_clock::now();
    auto last_heartbeat = it->second.last_heartbeat;
    auto diff = std::chrono::duration_cast<std::chrono::seconds>(
        now - last_heartbeat
    );
    
    // Unhealthy if no heartbeat in 90 seconds (1.5x TTL)
    return diff.count() < 90;
}

C++ Implementation

The etcd Server is implemented in modern C++ using the httplib library for HTTP endpoints:
// etcd_server/src/etcd_server.cpp
#include "etcd_server/etcd_server.hpp"
#include "httplib.h"
#include <nlohmann/json.hpp>

using json = nlohmann::json;

void EtcdServer::run_server() {
    httplib::Server server;
    
    // Registration endpoint
    server.Post("/register", [this](const httplib::Request& req, 
                                     httplib::Response& res) {
        try {
            auto json_body = json::parse(req.body);
            std::string component_name = json_body["component"];
            
            if (component_registry_->register_component(
                component_name, req.body
            )) {
                json response = {
                    {"status", "success"},
                    {"component", component_name},
                    {"encryption_key", 
                     component_registry_->get_encryption_key()}
                };
                res.set_content(response.dump(), "application/json");
            } else {
                res.status = 400;
                res.set_content(
                    R"({"status": "error"})", 
                    "application/json"
                );
            }
        } catch (const std::exception& e) {
            res.status = 400;
            json error = {
                {"status", "error"},
                {"message", "JSON invalid"},
                {"details", e.what()}
            };
            res.set_content(error.dump(), "application/json");
        }
    });
    
    // Listen on port 2379
    server.listen("0.0.0.0", port_);
}

Configuration

etcd Server Configuration

{
  "server": {
    "port": 2379,
    "bind_address": "0.0.0.0",
    "enable_tls": false,
    "max_connections": 100
  },
  
  "storage": {
    "backend": "in_memory",
    "persist_to_disk": false,
    "data_dir": "/var/lib/ml-defender/etcd"
  },
  
  "crypto": {
    "key_generation": "automatic",
    "key_rotation_hours": 24,
    "key_length_bits": 256
  },
  
  "lease": {
    "default_ttl_seconds": 60,
    "min_ttl_seconds": 10,
    "max_ttl_seconds": 3600
  },
  
  "logging": {
    "level": "info",
    "file": "/vagrant/logs/lab/etcd-server.log"
  }
}

Client Configuration (per component)

{
  "etcd": {
    "enabled": true,
    "endpoints": ["localhost:2379"],
    "connection_timeout_ms": 5000,
    "retry_attempts": 3,
    "retry_interval_ms": 1000,
    "crypto_token_path": "/crypto/sniffer/tokens",
    "config_sync_path": "/config/sniffer",
    "required_for_encryption": true,
    "heartbeat_interval_seconds": 30,
    "lease_ttl_seconds": 60
  }
}

Deployment

Prerequisites

sudo apt-get install -y \
    build-essential cmake \
    nlohmann-json3-dev \
    libssl-dev

Build

1

Navigate

cd /vagrant/etcd-server
mkdir -p build && cd build
2

Configure

cmake .. -DCMAKE_BUILD_TYPE=Release
3

Compile

make -j$(nproc)

Run

./etcd_server
Real-time Output:
[ETCD-SERVER] 🔧 Initializing server on port 2379
[ETCD-SERVER] 🚀 Server started
[ETCD-SERVER] 📝 POST /register received
[ETCD-SERVER] ✅ Component registered: sniffer
[ETCD-SERVER] 🔐 Generated encryption key: a1b2c3d4...
[ETCD-SERVER] 📝 POST /register received
[ETCD-SERVER] ✅ Component registered: ml-detector
[ETCD-SERVER] ❤️ Heartbeat received: sniffer (healthy)

API Reference

REST Endpoints

Request:
{
  "component": "sniffer",
  "version": "3.3.3",
  "node_id": "cpp_sniffer_v33_day12",
  "capabilities": ["ebpf", "xdp"]
}
Response (200 OK):
{
  "status": "success",
  "message": "Component registered successfully",
  "component": "sniffer",
  "encryption_key": "a1b2c3d4e5f6789..."
}
Request:
{
  "component": "ml-detector",
  "node_id": "ml-detector-default",
  "timestamp": 1638360000,
  "status": "healthy"
}
Response (200 OK):
{
  "status": "success",
  "lease_renewed": true,
  "ttl_remaining": 60
}
Request:
curl http://localhost:2379/config/sniffer
Response (200 OK):
{
  "interface": "eth1",
  "profile": "lab",
  "thresholds": {
    "ddos": 0.85,
    "ransomware": 0.90
  }
}
Request:
PUT /config/sniffer/thresholds.ddos
{
  "value": 0.90
}
Response (200 OK):
{
  "status": "success",
  "updated": "thresholds.ddos",
  "old_value": 0.85,
  "new_value": 0.90
}
Request:
curl http://localhost:2379/validate
Response (200 OK):
{
  "sniffer": {
    "warnings": [],
    "errors": []
  },
  "ml-detector": {
    "warnings": [],
    "errors": []
  },
  "firewall": {
    "warnings": [
      "IPSet capacity approaching limit (900/1000)"
    ],
    "errors": []
  }
}

Troubleshooting

# Check etcd Server is running
netstat -tulpn | grep 2379

# Test HTTP endpoint
curl http://localhost:2379/health

# Check firewall rules
sudo iptables -L -n | grep 2379
# Enable verbose logging
./etcd_server --log-level debug

# Check component JSON is valid
echo '{"component": "test"}' | jq .

# Verify HTTP POST
curl -X POST http://localhost:2379/register \
  -H 'Content-Type: application/json' \
  -d '{"component": "test"}'
Symptom: Components marked as unhealthy after 90 secondsSolution: Increase heartbeat frequency or TTL:
{
  "etcd": {
    "heartbeat_interval_seconds": 20,  // From 30
    "lease_ttl_seconds": 90            // From 60
  }
}

Next Steps

Sniffer

Configure network packet capture

ML Detector

Set up ML inference pipeline

Firewall Agent

Deploy autonomous blocking

Distributed Deployment

Multi-node etcd cluster setup

Build docs developers (and LLMs) love