Skip to main content

Overview

The Firewall ACL Agent is the enforcement endpoint of ML Defender’s pipeline, translating ML detections into kernel-level blocking rules using IPSet and IPTables. Validated with 36,000 events across 4 stress tests, it achieves 364 events/sec throughput with 0 crypto errors.

Stress Test Results

  • 36K events processed (Day 52)
  • 364 events/sec peak rate
  • 0 crypto errors (ChaCha20-Poly1305)
  • 0 decompression errors (LZ4)

Performance

  • <10ms blocking latency (detection → block)
  • 54% CPU max under extreme load
  • 127MB RAM at peak
  • Graceful degradation at capacity

Architecture

The Firewall Agent implements a config-driven architecture with no hardcoded values, ensuring production reliability:

IPSet vs IPTables

Role: Hash table data structure for storing IP lists
  • O(1) lookup complexity
  • Kernel-space storage
  • Automatic expiration (configurable TTL)
  • Atomic updates (thread-safe)
# Create IPSet
ipset create ml_defender_blacklist_test hash:ip \
  hashsize 1024 \
  maxelem 1000 \
  timeout 3600 \
  comment "ML Defender blocked IPs"

# Add IP with timeout
ipset add ml_defender_blacklist_test 192.168.1.100 timeout 3600

# List entries
ipset list ml_defender_blacklist_test

ChaCha20-Poly1305 Decryption Pipeline

The Firewall Agent is the pipeline endpoint and only decrypts + decompresses incoming data (no downstream encryption).
// 1. Receive encrypted + compressed message from ML Detector
zmq::message_t encrypted_msg;
subscriber.recv(&encrypted_msg);

// 2. Decrypt with ChaCha20-Poly1305 (AEAD)
std::vector<uint8_t> compressed_data;
if (!crypto_transport::decrypt(
    encrypted_msg.data(), 
    encrypted_msg.size(), 
    crypto_key_,  // From etcd
    compressed_data
)) {
    metrics_.crypto_errors++;
    return false;
}

// 3. Decompress with LZ4
std::vector<uint8_t> raw_data;
if (!crypto_transport::decompress_lz4(
    compressed_data, 
    raw_data
)) {
    metrics_.decompression_errors++;
    return false;
}

// 4. Parse Protobuf
PacketEvent event;
if (!event.ParseFromArray(raw_data.data(), raw_data.size())) {
    metrics_.protobuf_parse_errors++;
    return false;
}

// 5. Process event (IPSet add)
process_detection(event);

Configuration

Single Source of Truth (Day 52 Cleanup)

All configuration is loaded from config/firewall.json with no hardcoded values:
{
  "ipsets": {
    "blacklist": {
      "set_name": "ml_defender_blacklist_test",
      "set_type": "hash:ip",
      "hash_size": 1024,
      "max_elements": 1000,
      "timeout": 3600,
      "comment": "ML Defender TEST blocked IPs",
      "family": "inet",
      "create_if_missing": true,
      "flush_on_startup": false
    },
    "whitelist": {
      "set_name": "ml_defender_whitelist",
      "set_type": "hash:ip",
      "hash_size": 512,
      "max_elements": 500,
      "timeout": 0,
      "comment": "ML Defender whitelisted IPs",
      "family": "inet",
      "create_if_missing": true,
      "flush_on_startup": false
    }
  }
}

Validation Rules

{
  "validation": {
    "validate_ip_addresses": true,
    "validate_confidence_scores": true,
    "min_confidence_score": 0.5,
    "max_confidence_score": 1.0,
    "allowed_ip_ranges": [
      "192.168.0.0/16",
      "10.0.0.0/8",
      "172.16.0.0/12"
    ],
    "block_localhost": false,
    "block_gateway": false
  }
}

Stress Test Results (Day 52)

Test Progression

Configuration:
./synthetic_ml_output_injector 1000 50
Results:
  • Events: 1,000
  • Rate: 42.6 events/sec
  • CPU: N/A (too fast to measure)
  • Status: ✅ PASS
  • IPSet Successes: 118
  • IPSet Failures: 882 (capacity limit)

Cumulative Metrics (36K Events Total)

╔═══════════════════════════════════════════════════════════════╗
║  CRYPTO PIPELINE: PRODUCTION-READY                            ║
╚═══════════════════════════════════════════════════════════════╝

crypto_errors:              0  ← Perfect ChaCha20-Poly1305
decompression_errors:       0  ← Perfect LZ4 pipeline
protobuf_parse_errors:      0  ← Perfect message parsing
ipset_successes:          118  ← First ~1000 IPs blocked
ipset_failures:        16,681  ← Capacity limit (max_elements=1000)
max_queue_depth:       16,690  ← Backpressure handled gracefully
peak_throughput:    364.9/sec  ← +629% over target (50/sec)
cpu_efficiency:           54%  ← Excellent under extreme load
memory_footprint:        127MB ← Efficient

Status: ✅ PRODUCTION-READY (0 crypto errors)

Capacity Planning

IPSet Capacity Limits

Discovery: IPSet max_elements=1000 was exceeded during stress tests, causing graceful failures (not crashes).
Realistic Capacity Planning:
DeploymentMax IPsConfiguration
Testing1,000max_elements: 1000, hash_size: 1024
SMB10,000max_elements: 10000, hash_size: 8192
Enterprise100,000max_elements: 100000, hash_size: 65536
ISP500,000max_elements: 500000, hash_size: 262144
Hash Size Calculation:
# Rule of thumb: hash_size = max_elements / 8 * 64 (load factor 12.5%)
max_elements=10000
hash_size=$((max_elements * 8))
echo "hash_size: $hash_size"  # Output: 80000

Multi-Tier Storage (Roadmap)

Priority 1.1 (planned):
┌───────────────────────────────────┐
│  IPSet (Hot: 1K IPs)                │
│  O(1) kernel lookup, &lt;1μs latency   │
└───────────────────────────────────┘
           │ Eviction (LRU)

┌───────────────────────────────────┐
│  SQLite (Warm: 100K IPs)            │
│  Indexed, ~1ms query time           │
└───────────────────────────────────┘
           │ Archival

┌───────────────────────────────────┐
│  Parquet (Cold: Unlimited)          │
│  Columnar storage, forensics        │
└───────────────────────────────────┘

Deployment

Prerequisites

sudo apt-get install -y \
    build-essential cmake \
    libzmq3-dev libprotobuf-dev protobuf-compiler \
    libjsoncpp-dev libssl-dev liblz4-dev \
    ipset iptables

Build

1

Navigate

cd /vagrant/firewall-acl-agent
mkdir -p build && cd build
2

Configure

cmake .. -DCMAKE_BUILD_TYPE=Release
3

Compile

make -j$(nproc)

Run

sudo ./firewall-acl-agent -c ../config/firewall.json
Real-time Output:
[FIREWALL] 🚀 Starting Firewall ACL Agent v1.2.1
[FIREWALL] 🔐 Loaded crypto key from etcd: /crypto/firewall/tokens
[FIREWALL] 📦 IPSet verified: ml_defender_blacklist_test (0 entries)
[FIREWALL] 🔗 IPTables chain created: ML_DEFENDER_TEST
[FIREWALL] 🔌 Connected to ZMQ SUB tcp://127.0.0.1:5572
[FIREWALL] ✅ Ready for detections

[BLOCK] 192.168.1.100 (DDoS, confidence=0.97) → IPSet added
[BLOCK] 10.0.0.50 (Ransomware, confidence=0.92) → IPSet added
[METRICS] Processed: 1847 | Blocked: 112 | Crypto Errors: 0

Verify Blocking

sudo ipset list ml_defender_blacklist_test

Testing

Synthetic Data Injection

cd /vagrant/tools/build
./synthetic_ml_output_injector 1000 50

# Arguments:
#   1000 = number of events
#   50   = events per second

Monitor Blocking

watch -n 1 'sudo ipset list ml_defender_blacklist_test | head -20'

Troubleshooting

# Check if IPSet is already loaded
lsmod | grep ip_set

# Load kernel module
sudo modprobe ip_set
sudo modprobe ip_set_hash_ip

# Verify installation
ipset --version
# Verify etcd connection
etcdctl get /crypto/firewall/tokens

# Check key matches ML Detector
# Both must use same ChaCha20-Poly1305 key

# Enable verbose crypto logging
sudo ./firewall-acl-agent \
  -c ../config/firewall.json \
  --log-crypto-events
Symptom: ipset_failures increasing in metricsSolution: Increase max_elements in config:
{
  "ipsets": {
    "blacklist": {
      "max_elements": 10000,  // From 1000
      "hash_size": 8192       // From 1024
    }
  }
}
Recreate IPSet:
sudo ipset destroy ml_defender_blacklist_test
sudo systemctl restart firewall-acl-agent
# Verify ML Detector is running and publishing
netstat -tulpn | grep 5572

# Check firewall rules
sudo iptables -L -n | grep 5572

# Test ZMQ connectivity
zmq_proxy -v tcp://127.0.0.1:5572 tcp://127.0.0.1:5573

Roadmap

Priority 1: Production Scale (2 weeks)

1

P1.1: Multi-tier Storage

Goal: Handle 500K+ IPs without performance degradation
  • IPSet (hot: 1K IPs, <1μs lookup)
  • SQLite (warm: 100K IPs, ~1ms query)
  • Parquet (cold: unlimited, forensics)
2

P1.2: Async Queue + Worker Pool

Goal: 1K+ events/sec sustained throughput
  • Lock-free ring buffer
  • 4-8 worker threads
  • Batch IPSet updates (100 IPs/operation)
3

P1.3: Capacity Monitoring + Auto-eviction

Goal: Zero operator intervention for capacity management
  • LRU eviction policy
  • Automatic tier migration
  • Prometheus metrics export

Priority 2: Observability (1 week)

  • Prometheus metrics exporter
  • Grafana dashboards
  • Health check endpoints (Kubernetes readiness/liveness)
  • Runtime config updates via etcd

Next Steps

RAG System

Query blocked IPs using natural language

etcd Server

Manage distributed configuration and crypto keys

Monitoring

Set up Prometheus + Grafana dashboards

Performance Tuning

Optimize for 10Gbps+ environments

Build docs developers (and LLMs) love