This repository provides two high-performance streaming daemons for the redBorder platform:
x2kafka(Ingress): Collects data events from UNIX domain sockets, named pipes (FIFOs), Syslog (UDP/TCP/UNIX), Direct SNMP Traps, and HTTP(S) endpoints into Apache Kafka topics.kafka2x(Egress): Consumes events from Kafka topics and reliably forwards them in batches to remote HTTP(S) REST bulk endpoints with compression, framing, and automatic topic-qualified routing (replaces legacyk2http/rbforwarder).
-
Multi-Protocol Syslog Listener (
proto: "syslog","syslog_udp","syslog_tcp","syslog_unix"): Parses RFC 3164 (BSD syslog) and RFC 5424 (IETF syslog) messages matching rsyslog schema fields. Specifying"proto": "syslog"automatically binds both UDP and TCP on the designated port. -
HTTP / HTTPS &
http2kCollector:-
Transparent HTTP Decompression: Automatically decompresses incoming GZIP, ZLIB, and raw DEFLATE payloads (supporting
kafka2x/k2httpcompressed batches). -
Multi-Format Bulk Support: Handles single JSON records, line-delimited records (NDJSON), JSON arrays (
[...]), and concatenated JSON objects ({...}{...}). -
REST Path Routing & Sensor Extraction: Parses REST URIs like
POST /rbdata/<sensor_uuid>/<topic>(e.g.,POST /rbdata/bd2fe2c3-d0ff-4c27-aef9-122b698239b9/rb_flow), extractingsensor_uuid,proxy_uuid, and the target Kafka topic dynamically.
-
Transparent HTTP Decompression: Automatically decompresses incoming GZIP, ZLIB, and raw DEFLATE payloads (supporting
-
UNIX Domain Sockets: Supports both
unix(Stream, SOCK_STREAM) andunixgram(Datagram, SOCK_DGRAM) sockets. - FIFO (Named Pipes): Continuously reads from Linux FIFOs with auto-reconnect handling for external writer processes.
-
Direct SNMP Trap Receiver: Supports direct SNMP v1/v2c/v3 trap reception on UDP 162 (
snmptrap_udp) with automatic numeric OID to MIB name translation using dynamic MIB directories (mib_dirs). -
Standards-Compliant Flow Ingestion (
proto: "flow","netflow","ipfix","sflow"):-
Multi-Version Auto-Detection: Specifying
"proto": "netflow"(or"flow") on UDP 2055 automatically detects whether each incoming packet is NetFlow v5, v9, or IPFIX by inspecting the wire header. Devices sending different versions can share the same port. -
NetFlow v5 (RFC 1883): Fixed-format 5-tuple flow records (
type: "netflowv5"). -
NetFlow v9 (RFC 3954): 100% dynamic template and options decoding (
type: "netflowv9"). -
IPFIX / NetFlow v10 (RFC 7011 / 7012): Dynamic template decoding with variable-length elements and enterprise Information Elements (
type: "netflowv10"). -
sFlow v5 (sFlow.org): Ingests Flow Samples (Format 1) and Expanded Flow Samples (Format 3) on UDP 6343 (
type: "sflow"). -
100% Flat JSON Compatibility: Drop-in replacement for
f2kandredborder-flow-agent. Emits flat JSON records (no nested objects) for Druid/ClickHouse ingestion, with Cisco NBAR binary applications decoded into stringengine:appidentifiers (e.g."3:123"). -
RedBorder Directional Model A (
home_nets): Evaluates traffic orientation against configuredhome_netsCIDR blocks (defaults to RFC 1918/6598/4193). For downstream flows (WAN$\to$ LAN),lan_ipis automatically oriented to the internal host, withdirectionset to"upstream","downstream", or"internal". -
L7 & Network Layer Metadata: Decodes HTTP User-Agent (
http_user_agent), URL (http_url), Host (http_host), Referer (http_referer), human-readable TCP flags (tcp_flags, e.g."SYN|ACK"), and TTL (src_ttl,dst_ttl) from Cisco AVC/NBAR2, IPFIX, and sFlow. -
Output Schema &
sensor_ip: Emits normalized flow JSON withsensor_ipautomatically populated with the exporter's IP address, alongsidelan_ip,wan_ip,lan_l4_port,wan_l4_port,l4_proto,bytes,pkts, and timestamps. -
Sampling Renormalization (
renormalize_sampling): Automatically scales byte and packet volumes by the flow sampling rate so downstream metrics reflect true wire volume. -
SPAN Port Mode (
span_port): Configurable per-listener boolean. When enabled ("span_port": true), ingress MAC addresses are prioritized over post-routed gateway MACs (postDestinationMacAddress), matching mirrored SPAN port tap behavior. -
Observation ID Enrichment (
observation_domain_id/observations_id): Extracts NetFlow v9 Source ID and IPFIX Observation Domain ID intoobservation_domain_id. Supports hierarchical enrichment lookup matching both flat<ip>:<observation_id>keys and nested Chefobservations_idmaps. -
Field Exclusion (
exclude_fields): Allows dropping specified flow fields from the emitted JSON records before Kafka serialization.
-
Multi-Version Auto-Detection: Specifying
-
IP Security & Subnet Filtering: Granular IP allowlisting (
allowed_ips) and blacklisting (blacklist_ips) supporting single IPs and CIDR subnet blocks globally or per listener. -
Message Splitting & Field Extraction: Extract structured data from raw log strings using Key-Value parsing (
kv_extract), CEF security headers (cef_extract), or custom named Regex patterns (regex_patterns). -
Schema Standardization: Map vendor-specific log keys (e.g.,
src,srcip,source_ip) to unified redBorder schema keys (src_ip,dst_ip,src_port,dst_port,transport,username) automatically viaschema_standardization. -
Dynamic & Static JSON Enrichment: Flexible per-sensor lookup maps (
enrichment_map) and conditional rules engine (contains,match_key) for tagging JSON payloads.
- Consumer Group Engine: Subscribes to multiple Kafka topics (e.g.
rb_flow,rb_monitor,rb_syslog,rb_trap) with automatic partition rebalancing and fault tolerance. - Topic-Qualified URL Dispatch: Automatically appends the source Kafka topic to the destination REST path (e.g., posting to
/rbdata/<sensor_uuid>automatically dispatches batches to/rbdata/<sensor_uuid>/rb_flow,/rbdata/<sensor_uuid>/rb_monitor, etc.). - RFC-Compliant Compression: Clean stream compression supporting
"gzip","zlib","deflate", or"none"(guarantees valid Adler-32 / CRC32 checksum footers). - Framing Modes:
"newline": Standard newline-delimited JSON (NDJSON /\n)."concatenated": RedBorder streaming concatenated JSON ({...}{...})."json_array": Standard JSON array bulk ([ {...}, {...} ]).
- At-Least-Once Delivery: Kafka consumer offsets are only committed after a successful HTTP 2xx response from the remote endpoint. If the destination is temporarily unavailable, workers retry with configurable backoff.
- HTTP Connection Pooling: Tuned
http.Transportwith persistent connection reuse and TLS verification settings.
x2kafka supports granular IP address and CIDR subnet filtering to restrict data ingestion to authorized senders:
{
"brokers": ["127.0.0.1:9092"],
"topic": "rb_trap",
"allowed_ips": ["10.1.33.0/24", "192.168.10.1"],
"blacklist_ips": ["10.1.33.100"],
"listeners": [
{
"name": "snmptrap-listener",
"proto": "snmptrap_udp",
"port": 162,
"allowed_ips": ["192.168.10.0/24"]
}
]
}{
"debug": false,
"brokers": ["kafka.service:9092"],
"topic": "x2kafka_default",
"num_workers": 16,
"channel_buffer_size": 50000,
"socket_buffer_bytes": 8388608,
"stats_port": 7979,
"stats_socket": "/run/x2kafka/x2kafka.sock",
"listeners": [
{
"name": "syslog-collector",
"proto": "syslog",
"bind": "0.0.0.0",
"port": 514,
"mode": "syslog",
"topic": "rb_syslog",
"kv_extract": true,
"cef_extract": true,
"schema_standardization": true
},
{
"name": "http2k-listener",
"proto": "http",
"bind": "0.0.0.0",
"port": 7980,
"mode": "json",
"enrichment_key": "sensor_uuid",
"enrichment_map": {
"bd2fe2c3-d0ff-4c27-aef9-122b698239b9": {
"index_partitions": 5,
"index_replicas": 1,
"proxy_uuid": "bd2fe2c3-d0ff-4c27-aef9-122b698239b9",
"sensor_uuid": "bd2fe2c3-d0ff-4c27-aef9-122b698239b9"
}
}
},
{
"name": "snmptrap-listener",
"proto": "snmptrap",
"bind": "0.0.0.0",
"port": 162,
"topic": "rb_trap"
},
{
"name": "netflow-listener",
"proto": "netflow",
"bind": "0.0.0.0",
"port": 2055,
"topic": "rb_flow",
"home_nets": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"],
"renormalize_sampling": true,
"span_port": false,
"exclude_fields": ["tcp_flags", "duration"],
"allowed_ips": ["10.0.0.0/8", "192.168.1.0/24"],
"enrichment_key": "sensor_ip",
"enrichment_map": {
"10.10.10.1": {
"observations_id": {
"100": { "sensor_uuid": "bd2fe2c3-d0ff-4c27-aef9-122b698239b9", "sensor_name": "router-subdomain-100" },
"default": { "sensor_uuid": "bd2fe2c3-d0ff-4c27-aef9-122b698239b9", "sensor_name": "router-default" }
}
}
}
},
{
"name": "sflow-listener",
"proto": "sflow",
"bind": "0.0.0.0",
"port": 6343,
"topic": "rb_flow",
"home_nets": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"],
"renormalize_sampling": true,
"allowed_ips": ["10.0.0.0/8"],
"enrichment_key": "sensor_ip",
"enrichment_map": {
"10.20.20.1": {
"sensor_uuid": "e55fe2c3-d0ff-4c27-aef9-122b698239e5",
"sensor_name": "switch-core-01"
}
}
}
]
}100% flat JSON compatible with f2k and Druid/ClickHouse schemas:
{
"type": "netflowv10",
"sensor_ip": "10.1.50.20",
"flow_sequence": "57534",
"ip_protocol_version": 4,
"l4_proto": 17,
"direction": "upstream",
"application_id_name": "3:123",
"engine_id_name": "3",
"biflow_direction": "initiator",
"flow_end_reason": "idle timeout",
"lan_ip": "10.1.32.17",
"wan_ip": "162.159.200.123",
"lan_l4_port": 50024,
"wan_l4_port": 123,
"lan_interface": 13,
"lan_interface_name": "13",
"wan_interface": 1,
"wan_interface_name": "1",
"client_mac": "2c:f0:5d:0b:33:f0",
"observation_domain_id": 100,
"tcp_flags": "SYN|ACK",
"src_ttl": 64,
"dst_ttl": 58,
"http_user_agent": "Mozilla/5.0 (X11; Linux x86_64) ...",
"http_url": "https://example.com/api/v1",
"http_host": "example.com",
"bytes": 76,
"pkts": 1,
"timestamp": 1792523691
}Note: "type" is automatically set to "netflowv5", "netflowv9", "netflowv10" (IPFIX), or "sflow" based on the incoming datagram. Model A automatically ensures "lan_ip" is the internal home_nets IP and sets "direction" to "upstream" or "downstream". HTTP metadata (http_user_agent, http_url, http_host) is decoded from Cisco AVC/NBAR2 or sFlow payloads when present.
When enrichment_map is configured on a flow listener:
<exporter_ip>:<observation_id>(e.g."10.1.50.20:100")<exporter_ip>(or key defined byenrichment_key, e.g."10.1.50.20")- Nested Chef-style
observations_idwithin the matched IP ("10.1.50.20": { "observations_id": { "100": { ... }, "default": { ... } } }) "default"entry inenrichment_map
If an exporter IP is defined directly without observations_id (e.g. "10.1.50.20": { "sensor_uuid": "...", "sensor_name": "..." }), it applies cleanly to all flows from that sensor IP without any special configuration needed.
Supports both JSON and legacy YAML format:
{
"debug": false,
"kafka": {
"brokers": ["kafka.service:9092"],
"group_id": "kafka2x-http-forwarder",
"topics": [
"rb_flow",
"rb_monitor",
"rb_syslog",
"rb_trap"
]
},
"pipeline": {
"workers": 2,
"batch_size": 1000,
"timeout_ms": 100,
"retries": 3,
"backoff_sec": 2
},
"http": {
"url": "https://http2k.redborder.cluster/rbdata/938c7905-807e-4b8f-b488-70d525ac933b",
"method": "POST",
"framing": "newline",
"compression": "gzip",
"insecure": false,
"timeout": "15s"
},
"stats_port": 7989,
"stats_socket": "/run/kafka2x/kafka2x.sock"
}Both daemons offer CLI commands to query stats and run diagnostics:
# Query live stats via UNIX socket or HTTP:
x2kafka -stats -c /etc/x2kafka/config.json
# Query stats directly with curl or netcat:
curl --unix-socket /run/x2kafka/x2kafka.sock http://localhost/stats
curl http://127.0.0.1:7979/stats
echo "stats" | nc -U /run/x2kafka/x2kafka.sock
# Run in debug mode:
x2kafka -d -c /etc/x2kafka/config.json# Query live stats via UNIX socket or HTTP:
kafka2x -stats -c /etc/kafka2x/config.json
# Query stats directly:
curl --unix-socket /run/kafka2x/kafka2x.sock http://localhost/stats
curl http://127.0.0.1:7989/stats
echo "stats" | nc -U /run/kafka2x/kafka2x.sock
# Run in debug mode:
kafka2x -d -c /etc/kafka2x/config.jsonBuild both binaries into bin/:
make buildRun test suite across all packages:
make testCode linting and vetting:
make lintBuilding the RPM produces two distinct packages:
x2kafka-<version>-<release>.x86_64.rpm(Daemon binary/usr/bin/x2kafka,/etc/x2kafka/config.json,x2kafka.service)kafka2x-<version>-<release>.x86_64.rpm(Daemon binary/usr/bin/kafka2x,/etc/kafka2x/config.json,kafka2x.service)
Build packages using mock:
make rpmEach daemon has its own isolated systemd service:
sudo systemctl enable --now x2kafka
sudo systemctl status x2kafkasudo systemctl enable --now kafka2x
sudo systemctl status kafka2xWhile x2kafka can run all listeners inside a single process, the recommended production architecture is to run dedicated systemd services for each protocol (syslog, http2k, snmptrap).
- Isolated Fault Domains: A spike in Syslog traffic or a slow network client won't affect HTTP2K or SNMP Trap ingestion.
- Independent Restarts & Upgrades: Restarting or reloading one collector (e.g.
systemctl restart x2kafka-syslog) does not interrupt connections to other endpoints. - Dedicated Tuning & Resource Limits: Allows assigning custom CPU quotas, worker thread counts, memory limits (
MemoryMax=), or scheduling priorities per service in systemd. - Independent Monitoring: Each service runs with its own telemetry port and IPC socket, allowing independent throughput and error tracking.
Example systemd units and configs are provided in the repository:
- Syslog Service (UDP/TCP 514):
- Unit:
resources/systemd/examples/x2kafka-syslog.service - Config:
configs_example/x2kafka_syslog.json(stats_port: 7979,stats_socket: /run/x2kafka/syslog.sock)
- Unit:
- HTTP2K Service (HTTP 7980):
- Unit:
resources/systemd/examples/x2kafka-http2k.service - Config:
configs_example/x2kafka_http2k.json(stats_port: 7980,stats_socket: /run/x2kafka/http2k.sock)
- Unit:
- Direct SNMP Trap Receiver (UDP 162):
- Unit:
resources/systemd/examples/x2kafka-snmptrap.service - Config:
configs_example/x2kafka_snmptrap.json(stats_port: 7981,stats_socket: /run/x2kafka/snmptrap.sock)
- Unit:
# 1. Copy the configuration files to /etc/x2kafka/
sudo cp configs_example/x2kafka_syslog.json /etc/x2kafka/syslog.json
sudo cp configs_example/x2kafka_http2k.json /etc/x2kafka/http2k.json
sudo cp configs_example/x2kafka_snmptrap.json /etc/x2kafka/snmptrap.json
# 2. Copy the example systemd unit files to /etc/systemd/system/
sudo cp resources/systemd/examples/x2kafka-syslog.service /etc/systemd/system/
sudo cp resources/systemd/examples/x2kafka-http2k.service /etc/systemd/system/
sudo cp resources/systemd/examples/x2kafka-snmptrap.service /etc/systemd/system/
# 3. Reload systemd and enable the services you require
sudo systemctl daemon-reload
sudo systemctl enable --now x2kafka-syslog
sudo systemctl enable --now x2kafka-http2k
sudo systemctl enable --now x2kafka-snmptrapImportant
When running multiple x2kafka instances concurrently on the same host, ensure that each configuration specifies a unique stats_port and stats_socket (as pre-configured in the example files) to prevent IPC socket or TCP port collisions.