Wazuh SIEM Integration#
InfraGuard ships a built-in plugin that forwards events to Wazuh’s indexer (OpenSearch-compatible) in bulk. Events are batched in memory and flushed periodically, keeping network overhead low while still delivering near-real-time visibility into your redirector traffic.
Architecture#
The Wazuh plugin extends BatchForwardingPlugin, which handles the buffering and flush logic. The plugin itself handles Wazuh-specific authentication and payload formatting.
Filter Pipeline --> Event Dispatcher --> Wazuh Plugin
|
buffer (deque)
|
flush at batch_size or interval
|
POST /_bulk (NDJSON)
|
Wazuh-Indexer (OpenSearch)Configuration#
plugins:
wazuh:
enabled: true
wazuh_api_url: "https://wazuh-manager:55000"
indexer_url: "https://wazuh-indexer:9200"
username: "wazuh-wui"
password: "${WAZUH_PASSWORD}"
index_name: "infraguard-events"
batch_size: 50 # flush after 50 events (default)
flush_interval_seconds: 10 # or flush every 10 seconds (default)
verify_ssl: trueAuthentication#
The plugin authenticates against the Wazuh API using JWT:
- POSTs credentials to
/security/user/authenticate - Receives a JWT token
- Caches the token and refreshes it every 800 seconds (tokens expire at ~900s)
The JWT is used for the Wazuh manager API. The indexer uses basic auth with the same credentials.
Event Format#
Events are sent as NDJSON (newline-delimited JSON) to the /_bulk endpoint:
{"index": {"_index": "infraguard-events"}}
{"timestamp": "2025-03-15T14:30:00Z", "domain": "cdn.example.com", "client_ip": "203.0.113.42", "method": "GET", "uri": "/api/updates", "filter_result": "block", "filter_reason": "ja3_blocked", "user_agent": "python-requests/2.28.0", "protocol": "https"}Each flush sends one HTTP request with all buffered events in a single _bulk payload.
Batch Buffering#
The BatchForwardingPlugin base class provides:
- In-memory deque: Events are appended to a deque as they arrive
- Size-triggered flush: When the deque reaches
batch_size, a flush fires immediately - Time-triggered flush: A background asyncio task flushes every
flush_interval_secondsregardless of buffer size - Backpressure: If the indexer is unreachable, events stay in the buffer. The deque is unbounded, so a prolonged outage will eventually consume memory. Monitor the circuit breaker state and indexer health.
Querying Events#
Once events land in Wazuh-Indexer, they’re searchable through the Wazuh dashboard (Kibana fork) or the OpenSearch API:
# Find all blocked requests from a specific IP
curl -k -u admin:admin "https://wazuh-indexer:9200/infraguard-events/_search" \
-H "Content-Type: application/json" \
-d '{"query": {"bool": {"must": [{"match": {"client_ip": "203.0.113.42"}}, {"match": {"filter_result": "block"}}]}}}'