# Forward logs to your SIEM

URL: /integrate/siem

Stream the audit log and the delivery ledger to your SIEM over syslog with TLS, send findings over Splunk HEC or another forward-logs destination, and verify the audit hash chain from the messages your SIEM receives.



Your SIEM already watches the rest of the enclave. Forwarding puts Foxborne's audit log, delivery ledger and findings beside everything else it collects. Your security team can then correlate them with its own tools.

The **Forward logs** group on the **Destinations** tab of **Integrations** holds these destinations. The console describes it as "Findings, the audit log and normalized events for your SIEM or data platform."

## What each destination carries [#what-each-destination-carries]

In the example dataset, two forward-logs destinations have egress on:

| Destination     | What it carries                                                                      | Class in the example   |
| --------------- | ------------------------------------------------------------------------------------ | ---------------------- |
| Syslog over TLS | The audit log and the delivery ledger. Every audit entry becomes one syslog message. | L1, authorized for CUI |
| Splunk HEC      | Findings, one batch per run when it closes out, such as `4 findings, R-0934`         | L1, authorized for CUI |

The **Hosting** page lists the syslog stream under **Outbound connections** as **Your SIEM**: "Audit log and delivery ledger, syslog over TLS to logs.soc.hfr.internal:6514. Data class L1." In the example dataset, it was configured and its egress turned on when the deployment was set up.

## The audit stream [#the-audit-stream]

Each audit entry travels as one RFC 5424 message in an octet-counted frame. The ledger lists each one as, for example, **Audit entry 18,226, Quarantined file**. Its request reads "TLS 1.3 to logs.soc.hfr.internal:6514, one octet-counted frame of 383 bytes", and its response **Written over TLS 1.3**.

```text title="Payload, as sent" caption="Example dataset: audit entry 18,226, one line"
<134>1 2026-09-25T12:02:18.048Z foxborne.hfr.internal foxborne - audit - {"marking":"CUI","n":18226,"at":"2026-09-25T12:02:18.000Z","by":"System","action":"Quarantined file","object":"R-0933","detail":"Truncated inside a data message","hash":"32b8ef7ac5a0a2f1ee23abcef01eea03868d092cd2bbc5f8ea968fba575b934a","prev":"8296e75d91d0640337591fcb80aec6fb5640d2a3ce860189d853fc925ffc0132"}
```

The priority `<134>` is facility 16 (`local0`) times 8, plus severity 6 (informational). The header carries the time, the host, the app name `foxborne` and the message ID `audit`.

The JSON repeats the audit entry: marking, number, time, person, action, object and detail. It ends with the entry's own `hash` and the `prev` hash before it.

## Findings over Splunk HEC [#findings-over-splunk-hec]

Foxborne posts one event per finding to `/services/collector/event`, in index `foxborne` with source type `foxborne:finding`. With indexer acknowledgment on, the request carries a channel GUID and Splunk answers with an `ackId`.

```json title="Payload, as sent" caption="Example dataset: 1 finding, R-0929, L1"
{"time":1790180422.534,"host":"foxborne.hfr.internal","source":"foxborne","sourcetype":"foxborne:finding","index":"foxborne","event":{"marking":"CUI","rule":"memory_pressure","version":"1.1","run":"R-0929","vehicle":"UAS-06","time":"2026-09-23T16:20:22.534Z","title":"perception_node memory above 6,144 MiB for 3 samples","case":null}}
```

Each event names the detection rule and its version, so a search in Splunk can tell which threshold produced it.

## Choose a protocol [#choose-a-protocol]

Each destination's settings offer these **Protocol** choices, and the target field takes the label shown.

| Destination                 | Protocol choices                                                                                                                         | Target field                        | Air-gapped                                                 |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | ---------------------------------------------------------- |
| Syslog over TLS             | RFC 5424 over TLS (RFC 5425), TCP 6514, octet counting                                                                                   | **Streams**                         | Yes                                                        |
| Splunk HEC                  | HEC /services/collector/event, indexer acknowledgment on; HEC /services/collector/event, acknowledgment off; HEC /services/collector/raw | **Index and source type**           | Yes (Enterprise)                                           |
| Elasticsearch or OpenSearch | \_bulk API, NDJSON                                                                                                                       | **Index or data stream**            | Yes (self-managed)                                         |
| Microsoft Sentinel          | Logs Ingestion API, api-version 2023-01-01                                                                                               | **Data collection rule and stream** | No                                                         |
| Kafka                       | Kafka producer, mTLS; Kafka producer, SASL SCRAM-SHA-512; Kafka producer, SASL OAUTHBEARER                                               | **Topic**                           | Yes (self-managed)                                         |
| OTLP export                 | OTLP/HTTP, protobuf; OTLP/HTTP, JSON                                                                                                     | **Collector endpoint**              | Yes                                                        |
| AWS SQS or EventBridge      | SQS SendMessage; EventBridge PutEvents                                                                                                   | **Queue or event bus**              | No                                                         |
| S3 with Object Lock         | PutObject, s3-fips.us-gov-west-1, compliance mode                                                                                        | **Bucket and retention**            | Only with an on-prem S3-compatible store (vendor-specific) |

Microsoft Sentinel needs a network path out of the enclave. AWS SQS or EventBridge needs a VPC endpoint, because egress is denied at the VPC.

**Syslog over TLS.** RFC 5425 carries RFC 5424 messages over TLS on TCP port 6514, with octet-counting framing, and both sides present certificates. RFC 9662 keeps TLS 1.2 mandatory, says implementations should support TLS 1.3 and requires `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`.

**Splunk HEC.** The HEC port is 8088 by default. Indexer acknowledgment is off by default and set per token, so turn it on for the token Foxborne uses.

**Elasticsearch or OpenSearch.** The `_bulk` API takes an NDJSON body that ends in a newline. In GovCloud, keep export-controlled data out of index names, document IDs, aliases and snapshot names.

**Microsoft Sentinel.** The Logs Ingestion API takes a JSON array of at most 1 MB per call, with a client-credentials token whose audience is `https://monitor.azure.us`. The app needs the Monitoring Metrics Publisher role on the data collection rule.

The older HTTP Data Collector API reached end of support on 14 September 2026, so new work belongs on the Logs Ingestion API.

**Kafka and OTLP export.** Kafka 4.0 removed ZooKeeper, so clusters run in KRaft mode only; authorize the producer with ACLs. OTLP export posts to your OpenTelemetry Collector inside the enclave, as protobuf or JSON, on port 4318 by default.

**AWS SQS, EventBridge and S3.** In GovCloud, EventBridge has no API destinations, no Pipes and no API Gateway target, so webhook fan-out has to come from Foxborne. S3 with Object Lock in compliance mode gives write-once retention and legal hold, through FIPS endpoints such as `s3-fips.us-gov-west-1`.

## Before you start [#before-you-start]

* An admin is available to turn on egress. Admins confirm with a hardware security key.
* The deployment can reach the SIEM's host and port.
* The credential sits in your secret store: a client certificate, a HEC token, an API key or client credentials. Foxborne takes the reference, never the secret.
* For L1, your program has authorized the SIEM for CUI.
* To verify the audit chain, you need a role that reads the audit log: **Admin** or **Auditor**.

## Connect your SIEM over syslog [#connect-your-siem-over-syslog]

<Steps>
  <Step title="Open the destination">
    Go to **Integrations**. On the **Destinations** tab, select **Syslog over TLS** in the **Forward logs** panel, then **Set up** in its drawer.
  </Step>

  <Step title="Fill in the settings">
    The example dataset's stream uses these values:

    <Fields>
      <Field name="Host allowlist">
        logs.soc.hfr.internal:6514
      </Field>

      <Field name="Protocol">
        RFC 5424 over TLS (RFC 5425), TCP 6514, octet counting
      </Field>

      <Field name="Streams">
        Audit log and delivery ledger, to the security operations collector
      </Field>

      <Field name="Credential reference">
        secretsmanager:foxborne/int/syslog-client-cert
      </Field>

      <Field name="Data class">
        L1, authorized for CUI
      </Field>
    </Fields>

    For L1, tick **The program has authorized this destination for CUI**.
  </Step>

  <Step title="Send a test">
    Select **Send test**. Foxborne writes one octet-counted frame with no data to the first host, and the dialog reports **Delivered at** a UTC time. The test goes into the ledger and the audit log records **Sent test delivery**.
  </Step>

  <Step title="Save and turn on egress">
    Select **Save**, then the switch in the **Egress** column and **Turn on egress**. From then on, every audit entry is forwarded as it is written.
  </Step>
</Steps>

Splunk HEC and the other destinations follow the same steps with their own fields. The example dataset's Splunk HEC destination sends to `splunk-hec.hfr.internal:8088` with **HEC /services/collector/event, indexer acknowledgment on**.

## Verify the audit hash chain downstream [#verify-the-audit-hash-chain-downstream]

Each audit entry carries the hash of the one before it, and every forwarded message carries both `hash` and `prev`. Your SIEM therefore holds the whole chain. [Audit log](/security/audit-log) explains it in full.

<Steps>
  <Step title="Walk the links in your SIEM">
    Sort the forwarded entries by `n`. Each entry's `prev` must equal the `hash` of the entry before it, and a missing `n` is a gap in forwarding or in the log.
  </Step>

  <Step title="Compare with an export">
    On the **Audit log** page, select **Export**, choose **JSON Lines** or **CSV** and a **Range**, and select **Export**. Match the exported entries against what your SIEM holds for the same range.
  </Step>

  <Step title="Recompute in the console">
    Walking the links catches missing and inserted entries. Catching an edited entry takes each hash recomputed from its entry, which **Verify chain** on the **Audit log** page does. It reports &#x2A;*Chain intact. Every entry matches.**
  </Step>
</Steps>

## Check the result [#check-the-result]

On the **Delivery ledger** tab, filter to **Audit stream**. Each entry reads **Audit entry** with its number and action, with class L1 and the answer **Written over TLS 1.3**. In the **All destinations** list, pick **Splunk HEC** to see the findings batches.

## Troubleshoot [#troubleshoot]

**Turning off syslog egress warns about the SIEM.** The dialog reads "Your SIEM stops receiving the audit log and the delivery ledger." Leave it on unless you mean to stop the stream.

**The syslog connection drops during the handshake.** Both sides must trust each other's certificates. Both must also support `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`.

**Splunk never acknowledges events.** Indexer acknowledgment is off by default and set per token. Turn it on for the Foxborne token in Splunk Enterprise, or choose **HEC /services/collector/event, acknowledgment off**.

**A Splunk batch shows Retrying or Dead letter.** In the example dataset, the findings for R-0931 got `503 Service Unavailable` while Splunk was busy and were delivered on attempt 2. After 5 failed attempts, fix Splunk and select **Replay**.

**Sentinel refuses the token.** In Azure Government the audience must be `https://monitor.azure.us`, and the app needs the Monitoring Metrics Publisher role on the data collection rule.

**An index or topic name carries a program name.** Rename it. The GovCloud guidance keeps export-controlled data out of resource names, tags and subjects.

## Next [#next]

* [Egress, data classes and the delivery ledger](/integrate/egress-controls) explains the classes and what the ledger records.
* [Audit log](/security/audit-log) covers the hash chain and the audit export.
* [Automations](/integrate/automations) shows A4 forwarding an audit event when a case is approved.
