IBM QRadar
Synopsis
The IBM QRadar target forwards events, formatted as LEEF, to an IBM QRadar Event Collector over syslog. It handles transport framing (UDP, TCP, or TLS) — the event payload is expected to already be in LEEF format when it reaches the target.
Schema
- name: <string>
description: <string>
type: qradar
pipelines: <pipeline[]>
status: <boolean>
properties:
address: <string>
port: <numeric>
protocol: <string>
hostname: <string>
priority: <numeric>
template: <string>
max_message_size: <numeric>
application_name: <string>
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>
field_format: <string>
debug:
status: <boolean>
dont_send_logs: <boolean>
Configuration
The following fields are used to define the target:
| Field | Required | Default | Description |
|---|---|---|---|
name | Y | Target name | |
description | N | - | Optional description |
type | Y | Must be qradar | |
pipelines | N | - | Optional post-processor pipelines |
status | N | true | Enable/disable the target |
Connection
| Field | Required | Default | Description |
|---|---|---|---|
address | Y | - | QRadar Event Collector IP or hostname. Resolved at dial time |
port | N | 514 | Remote receiver port. 514 for tcp/udp, often 6514 for tls. Valid range 1–65535 |
protocol | N | tcp | Transport protocol: tcp, udp, or tls |
In the GUI, the Port field is prefilled with 514 and switches to 6514 — the IANA syslog-tls port — as soon as protocol is set to tls or TLS Encryption is enabled. It switches back if TLS is turned off. A port you type yourself is never changed, and leaving it blank keeps the server-side default. This runs in the create wizard only: a saved target keeps its stored port when its transport changes. The prefill is a console convenience — the configuration default remains 514 regardless of transport.
Framing
| Field | Required | Default | Description |
|---|---|---|---|
hostname | N | this host's name | Hostname written into the syslog header |
priority | N | 13 | Syslog PRI value (facility×8 + severity). Valid range 0–191; 13 = user.notice |
template | N | `<{{.Priority}}>{{.BSDTimestamp}} {{.Hostname}} {{.Message}}` | BSD (RFC 3164) syslog header template. Set to `{{.Message}}` to send the raw payload with no header |
max_message_size | N | 0 | Maximum framed line length in bytes. 0 sends the full event |
application_name | N | product name | Syslog tag / app-name. Only rendered when template references `{{.AppName}}` — the default template does not use it |
TLS
| Field | Required | Default | Description |
|---|---|---|---|
tls.status | N | false | Enable TLS. Must be true for any other tls.* field to take effect, including when protocol is tls |
tls.verify | N | true | Verify the server certificate |
tls.server_name | N | - | SNI / expected server hostname |
tls.ca_name | N | - | Custom CA to trust. Empty uses the OS trust store |
tls.cert_name | N* | - | Client certificate for mutual TLS |
tls.key_name | N* | - | Client key for mutual TLS |
tls.passphrase | N | - | Passphrase for an encrypted client key |
tls.min_tls_version | N | tls1.2 | Minimum negotiated TLS version |
tls.max_tls_version | N | tls1.3 | Maximum negotiated TLS version |
* = Conditionally optional. tls.cert_name and tls.key_name must be supplied together to enable mutual TLS; supplying only one fails configuration validation.
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.pemare 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=...}.
Processing
| Field | Required | Default | Description |
|---|---|---|---|
field_format | N | - | Optional target-side normalization format applied before delivery. Typically left empty, since the payload already arrives in LEEF from upstream processing. See applicable Normalization section |
Scheduling
See Scheduling and Pool Behavior for interval and cron fields shared by all targets.
Debug Options
| Field | Required | Default | Description |
|---|---|---|---|
debug.status | N | false | Enable debug logging |
debug.dont_send_logs | N | false | Process logs but don't send to target (testing) |
Details
This target is transport-only: it does not render LEEF itself. It expects each event to already be a complete LEEF record when it reaches the target, and applies syslog framing and delivery on top of that payload. There is no batching — each event is a single, complete delivery to the QRadar Event Collector.
It is deliberately close to the generic syslog target but corrects two behaviors that matter for QRadar: there is no RFC-driven truncation (a generic syslog target forces a hard 2048-byte cut, and several LEEF events exceed that; here max_message_size, default 0, is the only cap and defaults to unlimited), and stream framing guarantees exactly one trailing newline per event so QRadar can separate consecutive events on a TCP or TLS connection.
Template Variables
The following variables are available in template:
| Variable | Description |
|---|---|
{{.Year}} | Current year (4-digit) |
{{.Month}} | Current month (2-digit) |
{{.Day}} | Current day (2-digit) |
{{.Priority}} | Syslog PRI value |
{{.Timestamp}} | Current time, RFC3339 |
{{.BSDTimestamp}} | Current time, RFC3164 (Jan _2 15:04:05) |
{{.Hostname}} | Syslog-header hostname |
{{.AppName}} | Application name (application_name) |
{{.PID}} | Process ID |
{{.Message}} | The LEEF payload |
If template fails to render, the target falls back to sending the raw, sanitized payload with no header.
Framing and Transport
Embedded carriage returns and line feeds in the payload are neutralized before framing, so one event cannot forge a second line on the wire. On a TCP or TLS stream, exactly one trailing newline delimits each event (RFC 6587 non-transparent framing); this is harmless on UDP. No size limit applies by default (max_message_size: 0); set a cap when the transport is UDP and the receiver enforces a lower datagram limit.
TLS
Set tls.status: true to use TLS. This field is the switch for the whole tls.* block. When it is not true, every other field in the block is ignored, including tls.verify, tls.ca_name, tls.server_name, and the client certificate. Setting protocol: tls on its own does not apply them, so always set both. Remember to set port as well, since it defaults to 514 for every protocol.
A client certificate is optional. Supplying tls.cert_name without tls.key_name, or the other way round, fails configuration validation. tls.verify defaults to true.
The target does not perform LEEF rendering or field mapping — it only frames and delivers the payload it receives. Format the event as LEEF before it reaches this target.
Examples
Basic Configuration
Sending LEEF events to a QRadar Event Collector over TCP... | |
Secure TLS
Delivering over an encrypted TLS connection with server verification... | |
Raw LEEF Payload
Sending the LEEF payload with no syslog header, for a receiver that keys the log source another way... | |
Troubleshooting
This section covers the errors you are most likely to see with the qradar target, what causes each one, and how to fix it. The target only frames the event and writes it to the Event Collector, so almost every failure is a transport problem: the wrong port, the wrong protocol, or a certificate the Director host does not trust.
Where to look:
- Director logs. Target errors are tagged with the target name and carry
"Section":"SenderPool". The part afterReason:or after the last colon is the actual cause. - The target's connection status in the web interface. It shows the same reason as the log line, prefixed with
connection failed for <target name>:.
See Target Delivery Errors for how Director logs and retries target failures.
No failure of this target is treated as permanent. Every error is retried until it clears, so data waits in the queue instead of being dropped. The one case where that works against you is an oversized event on UDP, described below.
What the log source needs
Most delivery problems come down to one of these. Match the error you see against the last column first.
| Prerequisite | When it applies | Error when it is missing |
|---|---|---|
A QRadar log source listening on the same protocol as protocol and the same port as port | Always | connect: connection refused, i/o timeout, or tls: first record does not look like a TLS handshake. With protocol: udp there is no error at all |
Outbound TCP or UDP from the Director host to address on port | Always | dial tcp ...: i/o timeout |
Name resolution for address on the Director host | address is a hostname | no such host |
tls.status: true | Whenever any tls.* field should apply | No error of its own. The rest of the block is ignored, which surfaces as one of the certificate errors below |
The collector's certificate chain trusted, through the host trust store or tls.ca_name | TLS with tls.verify: true, the default | x509: certificate signed by unknown authority |
A certificate that matches address, or tls.server_name set to a name on it | TLS with verification | x509: certificate is valid for ..., not ... |
A client certificate the log source trusts, in tls.cert_name and tls.key_name | Only when the log source requires client authentication | remote error: tls: bad certificate |
port defaults to 514 for every protocol, TLS included. A QRadar TLS Syslog log source typically listens on 6514, so set port yourself when you enable TLS.
"dial tcp ...: connect: connection refused"
[Error] [director] [target-<target id>] [qradar] Failed to reinitialize target "qradar" (attempt 12). Reason: dial tcp qradar.example.com:514: connect: connection refused
Cause: nothing is accepting connections on that address and port. Most often the log source is configured for a different protocol or port than the target. The target defaults to tcp on 514, while the log source may be a UDP Syslog source, or a TLS Syslog source on another port, typically 6514. An Event Collector that is down produces the same text. On Windows the wording typically mentions actively refused it instead.
Fix:
- Open the log source in QRadar and read the protocol and the listen port it is configured for.
- Set
protocolto the matching value in lowercase. Onlytcp,udp, andtlsare accepted, and the comparison is case-sensitive, soTCPis rejected withunknown connection typebefore the target starts. - Set
portto the log source's port. It is not derived fromprotocol. - From the Director host, confirm that the port accepts a connection.
Nothing is sent while this lasts. Incoming data waits in the Director queue and is delivered once the connection succeeds. No records are dropped, and no restart is needed after you correct the configuration.
"x509: certificate signed by unknown authority"
[Error] [director] [target-<target id>] [qradar-tls] Failed to reinitialize target "qradar-tls" (attempt 1). Reason: tls: failed to verify certificate: x509: certificate signed by unknown authority
Cause: the certificate the Event Collector presents is not trusted by the Director host. A private or internal certificate authority is the usual reason: its certificate is not in the host trust store, and tls.ca_name is either not set or not in effect. Check tls.status first. If it is not true, tls.ca_name and tls.verify are ignored, so this error appears even when you have configured the right authority. See the next entry.
Fix:
- Set
tls.status: true. - Export the issuing authority as PEM and point
tls.ca_nameat it. The file must be readable by the Director service account and must resolve to a path under the service root. Inline PEM and the other value forms listed under TLS above work as well. - To skip verification instead, set
tls.verify: false. It only applies whentls.statusistrue.
Related errors from the same block, all reported the same way:
| Error text | Cause | Fix |
|---|---|---|
x509: certificate is valid for ..., not ... | address is an IP address, or a name that is not on the certificate | Set tls.server_name to a name the certificate carries, or use that name as address |
x509: certificate has expired or is not yet valid: ... | The collector's certificate is out of date | Renew it on the QRadar side |
remote error: tls: bad certificate | The log source requires client authentication, and no certificate it trusts was sent | Set tls.cert_name and tls.key_name to a certificate QRadar trusts. Both are required together |
ca_name: ... could not be resolved, ca_name ... contains no valid PEM certificate(s) | The file is missing, unreadable, outside the service root, or not PEM | Place the PEM under the service root, and export it as PEM rather than DER |
client certificate: tls: private key does not match public key, decrypt PKCS#8 private key (wrong passphrase?) | tls.cert_name and tls.key_name are swapped or unrelated, or tls.passphrase is wrong | Pair the matching certificate and key, and correct tls.passphrase |
Nothing is sent while any of these persist. The data stays queued and is delivered after the next successful handshake.
TLS settings have no effect unless tls.status is true
Symptom: you set protocol: tls and configured tls.verify, tls.ca_name, tls.server_name, or a client certificate, and none of them changes anything. The connection is made without TLS, or it fails in a way that looks like a protocol mismatch, most often tls: first record does not look like a TLS handshake, or x509: certificate signed by unknown authority against an authority you have already configured.
[Error] [director] [target-<target id>] [qradar-tls] Failed to reinitialize target "qradar-tls" (attempt 1). Reason: tls: failed to verify certificate: x509: certificate signed by unknown authority
Cause: tls.status is the switch for the whole tls.* block. When it is not true, verification, the named authority, the server name, and the client certificate are all skipped silently. Setting protocol: tls on its own does not turn them on.
Fix: set tls.status: true alongside protocol: tls and the TLS port.
protocol: tls
port: 6514
tls:
status: true
verify: true
ca_name: "qradar-ca.pem"
Confirm tls.status before you trust a green connection status. A target that connects while the block is ignored is not using the certificate settings you configured.
"tls: first record does not look like a TLS handshake"
[Error] [director] [target-<target id>] [qradar-tls] Failed to reinitialize target "qradar-tls" (attempt 1). Reason: tls: first record does not look like a TLS handshake
Cause: the target is speaking TLS to a port that expects plain syslog. Either port was left at the default 514 while the TLS log source listens elsewhere, or the log source on that port is a plain Syslog source rather than a TLS Syslog source.
Fix: set port to the port of the TLS Syslog log source, typically 6514, or drop TLS and use protocol: tcp against the plaintext port. In QRadar a TLS Syslog log source is a separate log source from a plain one, so enabling TLS on the target does not change what the collector expects.
Nothing is sent while this lasts. The data stays queued and is delivered once the handshake succeeds.
"write: connection reset by peer" or "broken pipe"
[Error] [director] [target-<target id>] [qradar] Sender worker 3 execute() failed for <payload>: target broken: write tcp <local address>-><collector address>: write: connection reset by peer
[Information] [director] [target-<target id>] [qradar] Target "qradar" reinitialized successfully (generation 2).
Cause: the Event Collector closed a connection the target was still writing to. QRadar restarted, the log source was disabled, or a firewall cut an idle session. write: broken pipe has the same causes, and on Windows the wording typically mentions forcibly closed by the remote host. A write that ends in i/o timeout means the collector stopped reading for 30 seconds, which is typically an overloaded collector or license back-pressure.
Fix: nothing on the Director side if this happens occasionally. The target reconnects by itself, and the reinitialized successfully line that follows confirms it. If it repeats, check the Event Collector's health and its events-per-second limit.
The payload is not resent from the start. Records written before the failure are checkpointed and skipped when the payload is redelivered, so they are not sent twice, and delivery resumes from the record that failed. Records written just before the close can still be lost with no error at all, because syslog has no application-level acknowledgment and a successful write only means the host accepted the bytes for sending.
UDP hides most delivery failures
[Error] [director] [target-<target id>] [qradar] Sender worker 1 execute() failed for <payload>: target broken: write udp <local address>-><collector address>: sendto: connection refused
Cause: with protocol: udp there is no connection to fail. The target reports the connection as ready even when nothing is listening on the far side, and every write succeeds locally. The error above is the only one that ever appears, and only when the remote host answers with an ICMP port-unreachable message. It arrives after the fact, so the first datagrams are already counted as sent.
Fix: prefer tcp or tls when the log source supports it, so that a wrong port or a stopped collector is visible immediately. If UDP is required, enable the UDP log source on the configured port, and confirm arrival in QRadar rather than trusting the target's counters.
Events lost this way are counted as delivered and leave no trace in Director. Nothing is queued and nothing is retried, because no error was ever reported.
"sendto: message too long"
[Error] [director] [target-<target id>] [qradar] Sender worker 1 execute() failed for <payload>: target broken: write udp <local address>-><collector address>: sendto: message too long
Cause: one framed event is larger than a single datagram, roughly 64 KB, or larger than the path allows when fragmentation is blocked. The target applies no size cap of its own, since max_message_size defaults to 0. QRadar log sources also have their own per-event maximum, typically lower, and events above it are typically truncated or discarded on the QRadar side without any feedback to the sender.
Fix: set max_message_size, for example 8192, or switch to protocol: tcp, which has no datagram limit. Keep the cap at 4096 or above. Truncation is a hard cut with no marker, and a LEEF line cut in the middle of an attribute is parsed as a partial event.
This record is never dropped. It fails in exactly the same way on every redelivery, and every attempt reinitializes the target, so nothing else reaches this target until you set a cap or move to TCP.
The target is healthy but nothing arrives in QRadar
Check these in order.
-
debug.dont_send_logsis enabled. Events are processed and nothing is written. The records are counted as accepted and checkpointed, so they are not redelivered later. The explanatory line is only logged whendebug.status: trueis set as well. Remove the flag. -
The route does not produce LEEF. This target is transport-only. If no pipeline renders LEEF, the collector receives the payload as it arrives, and QRadar typically stores it as unparsed events instead of matching it to a parser. Attach the
siem_qradarpack, or another LEEF encoder, to the route. -
The content pack filtered the records out. The pack drops record types whose
keep_*flags are off, along with anything the pipeline did not mark as processed. These show in the pipeline's dropped counters, not the target's, so the target still looks healthy. Enable the relevantkeep_*flags in the route. -
templatedoes not render. A template that fails to parse or execute is not reported. The sanitized payload is sent with no syslog header, and QRadar then identifies the log source by the sending IP address rather than byhostname. A variable that does not exist renders the literal text<no value>into the header. Use the variables listed under Template Variables above, and test against the default template. -
max_message_sizeis too small. The framed line is cut at the cap with no marker, and the delivered counters still report the original event length, so the truncation is invisible from Director. -
hostnameis empty and the host name cannot be determined. The syslog header then carries an empty hostname, and QRadar's log source identification can pick the wrong source. Sethostnameexplicitly. -
The transport is UDP. See the UDP entry above. It is the most common reason for a healthy-looking target with no events in QRadar.