Skip to main content

Splunk S2S

Splunk Observability

Synopsis

Creates a target that sends events to a Splunk indexer over Splunk's native Splunk-to-Splunk (S2S) protocol on port 9997 — the wire protocol a Splunk universal forwarder speaks, as opposed to the HTTP Event Collector used by the splunk and splunksecurity targets. Supports weighted load balancing across an indexer tier, protocol v3/v4 framing, delivery acknowledgement, and compression.

Schema

- name: <string>
description: <string>
type: splunks2s
pipelines: <pipeline[]>
status: <boolean>
properties:
address: <string>
port: <numeric>
servers: <string[]>
destinations:
- address: <string>
port: <numeric>
weight: <numeric>
load_balance_seconds: <numeric>
load_balance_bytes: <numeric>
load_balance_stats_seconds: <numeric>
dns_resolve_seconds: <numeric>
destination_down_seconds: <numeric>
protocol: <string>
index: <string>
source: <string>
source_type: <string>
host: <string>
extract_metadata: <boolean>
ack: <boolean>
ack_timeout: <numeric>
compression: <boolean>
server_name: <string>
mgmt_port: <string>
batch_size: <numeric>
timeout: <numeric>
max_retries: <numeric>
retry_delay: <numeric>
max_event_bytes: <numeric>
nested_field_serialization: <string>
throttle_bytes_per_second: <numeric>
field_format: <string>
debug:
status: <boolean>
dont_send_logs: <boolean>
tls:
status: <boolean>
verify: <boolean>
server_name: <string>
ca_name: <string>
cert_name: <string>
key_name: <string>
passphrase: <string>
min_tls_version: <string>
max_tls_version: <string>

Configuration

The following are the fields used to define the target:

FieldRequiredDefaultDescription
nameYTarget name
descriptionN-Optional description
typeYMust be splunks2s
pipelinesN-Optional post-processor pipelines
statusNtrueEnable/disable the target

Destinations

FieldRequiredDefaultDescription
addressY*-Single indexer address (hostname or IP), paired with port
portN9997Port for address, and the default port for any destinations entry that omits one
serversN-Array of "host:port" strings, one indexer per entry
destinationsN-Weighted destination list. Each entry: address, port (default 9997), weight (default 1)

* = address, servers, and destinations are combinable and additive; at least one is required.

Load Balancing

FieldRequiredDefaultDescription
load_balance_secondsN30Seconds a worker holds one connection before reconsidering the destination. 0 pins the connection
load_balance_bytesN0Bytes written on one connection before it is rotated. 0 rotates on time only
load_balance_stats_secondsN300Window over which per-destination volume is remembered when apportioning load; half of it carries forward each rollover
dns_resolve_secondsN600How often a configured hostname is re-resolved
destination_down_secondsN30How long a destination that refused a connection is passed over before being retried

Protocol

FieldRequiredDefaultDescription
protocolN"v3"Wire framing: v3 (legacy cooked, default), v4 (compact framing), auto (negotiate v4, fall back to v3)
ackNfalseWait for indexer acknowledgement before reporting a batch delivered. Requires protocol: v4 or auto
ack_timeoutN60Seconds to wait for acknowledgement before a batch counts as undelivered. Only meaningful with ack: true
compressionNfalsezlib-compress the connection
server_nameNproduct nameIdentity presented to the indexer during the handshake
mgmt_portN"8089"Management port advertised during the handshake

Event Metadata

FieldRequiredDefaultDescription
indexN-Default Splunk index stamped on every event
sourceN-Default source
source_typeN-Default sourcetype
hostN-Default host
extract_metadataNtrueLift _raw/host/source/sourcetype/index/time out of a Splunk-shaped JSON envelope. Explicitly configured metadata above still wins
nested_field_serializationN"none"How an object/array-valued envelope field is handled: none (drop it) or json (forward its JSON text)

Batching and Delivery

FieldRequiredDefaultDescription
batch_sizeN1000Events buffered before a flush
timeoutN30Connection and write timeout in seconds
max_retriesN3Maximum delivery attempts per batch
retry_delayN1Seconds between retry attempts
max_event_bytesN66060288 (~63 MB)Ceiling on one event's payload; events past this are truncated rather than sent
throttle_bytes_per_secondN0Ceiling on outbound bytes per second per sender worker, measured post-compression. 0 disables it

TLS

FieldRequiredDefaultDescription
tls.statusNfalseEnable TLS
tls.verifyNtrueVerify the server certificate
tls.server_nameN-SNI / expected server hostname
tls.ca_nameN-Custom CA to trust. Empty uses the OS trust store
tls.cert_nameN*-Client certificate for mutual TLS
tls.key_nameN*-Client key for mutual TLS
tls.passphraseN-Passphrase for an encrypted client key
tls.min_tls_versionNtls1.2Minimum negotiated TLS version
tls.max_tls_versionNtls1.3Maximum negotiated TLS version

* = Conditionally required. tls.cert_name and tls.key_name must be supplied together; supplying only one fails configuration validation.

note

TLS material fields (cert_name, key_name, ca_name, client_ca_name) accept any of the following:

  • File name — resolved relative to the service root directory. Nested paths such as certs/prod/server.pem are supported.
  • Absolute path — honored only if it resolves inside the service root. Any path that escapes the root is refused.
  • Inline PEM content — used verbatim when the value contains -----BEGIN.
  • Environment variable${ENV_VAR}.
  • Vault reference$secret{id=...} or $secret{store=...,ref=...}.

Normalization

FieldRequiredDefaultDescription
field_formatN-Data normalization format. See applicable Normalization section

Scheduling

See Scheduling and Pool Behavior for interval and cron fields shared by all targets.

Debug Options

FieldRequiredDefaultDescription
debug.statusNfalseEnable debug logging
debug.dont_send_logsNfalseProcess logs but don't send to target (testing)

Details

The Splunk S2S target speaks the same wire protocol a Splunk universal forwarder uses on port 9997, so an indexer accepts the data as cooked, pre-attributed events with no HEC token and no ingest-time parsing. It is a single-type target — splunks2s is its only registered type, unlike splunk/splunksecurity/crowdstrike, which share one HEC implementation.

Indexer Load Balancing

address/port configure a single destination, servers a plain list, and destinations a weighted list — the three forms are combinable and additive, so a weight can be added to one member of an existing servers list without rewriting the rest. A weight is a share of traffic, not an absolute value: keep weights within the same order of magnitude (1/5/4 works; 10/120/9 does not). Weight 0 parks a destination — configured and reachable as a last resort, but never chosen while any weighted destination is up.

A configured hostname is resolved to every address it has, and each resolved address becomes its own destination — so a single name fronting an indexer tier spreads traffic across the whole tier instead of pinning one member. TLS is still verified against the configured hostname, not the resolved address.

Two settings trigger rotation to a new destination:

  • load_balance_seconds is how long a worker holds one connection before reconsidering, mirroring Splunk's own autoLBFrequency default of 30. Without it, the first indexer a worker reaches keeps every batch that worker ever sends — an indexer added to the tier never receives anything, and one that was briefly down never gets its share back. 0 pins the connection.
  • load_balance_bytes is the volume trigger, and the one that matters for bursty input: a batch that arrives all at once fits inside any sensible time interval, so a time-only rule sends the whole burst to whichever destination the first batch picked. Measured against two indexers with time-only rotation, a 500-event burst went 500/0. Splunk carries the same pair of levers as autoLBFrequency and autoLBVolume. 0 rotates on time only.

load_balance_stats_seconds is the window over which per-destination volume is remembered when apportioning load; half of it carries forward on each rollover, so short-term imbalance decays instead of either persisting indefinitely or being forgotten between windows. dns_resolve_seconds controls how often a configured hostname is re-resolved — a resolution that fails keeps the last known address set rather than emptying it. destination_down_seconds is how long a destination that refused a connection is passed over; the cooldown is shared across every worker of the target, so one worker's discovery is not re-learned by the rest.

Protocol Versions

protocol: v3 (the default) sends legacy cooked messages, where each message carries its own _done terminator — the indexer takes the event exactly as sent, so the original timestamp is preserved and a multi-line event stays one event. v4 (or auto, which negotiates v4 and falls back to v3 if the receiver refuses it) sends the compact framing a Universal Forwarder uses, which hands event-boundary detection and timestamp extraction back to the indexer. ack: true requires protocol: v4 or auto — acknowledgement rides on v4 message IDs, so it cannot be combined with an explicitly configured v3.

Event Metadata

index, source, source_type, and host set the attribution stamped on every event; leaving them empty lets the source's own attribution through. When extract_metadata is enabled (the default), the target lifts _raw/host/source/sourcetype/index/time out of a Splunk-shaped JSON envelope, so data received from another Splunk source keeps its original attribution instead of arriving as an opaque JSON blob — any of the fields above that are explicitly set still take priority. Every other envelope member is forwarded on as an indexed field; nested_field_serialization decides what happens when one of those fields is an object or array, which has no representation in Splunk's flat, text-only indexed fields: none (the default) drops it, json forwards its JSON text.

If an event has no host attribution after metadata resolution, the target falls back to the originating device's name rather than letting Splunk misattribute it to the receiving indexer. Setting schema, source, or log_type in a pipeline overrides source_type for that event, the same last-write-wins mechanism the splunk target uses for its sourcetype override.

Compression

compression: true zlib-compresses the connection, as a forwarder's compressed = true setting does. It is worth enabling on a slow or metered link — a 211 KB batch of repetitive log text went out in 3.7 KB in testing — at the cost of CPU on both ends.

Payload Limits

max_event_bytes bounds a single event's payload before it is framed. Splunk's receiver enforces a hard ceiling near 64 MB and does not report it as an error — it resets the TCP connection instead. An event that exceeds max_event_bytes is truncated and counted rather than sent; without a ceiling, an oversized event that keeps getting retried resets the connection every time and wedges the destination in a reconnect loop that looks like a network fault.

Delivery and Retry

max_retries and retry_delay only absorb a brief blip in reaching a destination. Once retries are exhausted, the target returns the send error and the sender pool NAKs the source records for redelivery — which is what actually prevents loss, and which requires persistent_storage to be enabled on the Director.

Throttling

throttle_bytes_per_second caps outbound bytes per second on each sender worker, measured on what is actually written to the wire — so on a compressed connection the ceiling applies to the post-compression byte count. 0 disables it.

Examples

Basic

Sending events to a single indexer over the S2S protocol...

targets:
- name: splunks2s_basic
type: splunks2s
properties:
address: "idx1.example.com"
port: 9997

Indexer Tier with Failover

Spreading events across an indexer tier with automatic failover...

targets:
- name: splunks2s_tier
type: splunks2s
properties:
servers:
- "idx1.example.com:9997"
- "idx2.example.com:9997"
- "idx3.example.com:9997"

Weighted Destinations

Favoring a larger indexer over two smaller ones with weighted destinations...

targets:
- name: splunks2s_weighted
type: splunks2s
properties:
destinations:
- address: "idx1.example.com"
port: 9997
weight: 5
- address: "idx2.example.com"
port: 9997
weight: 1
- address: "idx3.example.com"
port: 9997
weight: 1

Acknowledged Delivery

Waiting for indexer acknowledgement on the compact v4 framing...

targets:
- name: splunks2s_acked
type: splunks2s
properties:
address: "idx1.example.com"
port: 9997
protocol: auto
ack: true
ack_timeout: 60

Secure (TLS)

Connecting to an indexer tier over TLS, verified by hostname...

targets:
- name: splunks2s_tls
type: splunks2s
properties:
address: "indexers.example.com"
port: 9997
tls:
status: true
verify: true
server_name: "indexers.example.com"
ca_name: "splunk-ca.pem"
min_tls_version: "tls1.2"

High-Volume with Compression

Compressing the connection and capping outbound bandwidth for a bursty, high-volume source...

targets:
- name: splunks2s_highvolume
type: splunks2s
properties:
address: "idx1.example.com"
port: 9997
batch_size: 5000
compression: true
load_balance_bytes: 10485760
throttle_bytes_per_second: 5242880