# How to Debug Keylog Issues in iroh Connections

> Debug keylog issues in iroh connections using SSLKEYLOGFILE and rustls. Enable key logging in iroh for secure debugging.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: how-to-guide
- Published: 2026-07-14

---

**Enable TLS key logging in iroh by setting the `SSLKEYLOGFILE` environment variable and calling `.keylog(true)` on the `EndpointBuilder`, which writes pre-master secrets to the specified file via rustls.**

The iroh networking library uses **rustls** for TLS encryption, providing a built-in mechanism to log cryptographic keys for debugging QUIC connections. When you need to inspect encrypted traffic with tools like Wireshark, enabling the keylog feature is essential. This guide explains how to debug keylog issues in iroh connections by examining the source code in the `n0-computer/iroh` repository.

## How Key Logging Works in iroh

Iroh implements key logging through a coordinated chain between the endpoint builder and the TLS configuration layer. Understanding this flow helps diagnose why keys might not appear in your log file.

### Endpoint Configuration

The keylog behavior is controlled by the `EndpointBuilder` in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs). At lines 730–734, the builder maintains a `keylog: bool` field that defaults to `false`. You must explicitly enable it using the `.keylog(true)` method before constructing the endpoint.

```rust
let endpoint = Endpoint::builder()
    .keylog(true)  // Enables TLS key logging
    .bind(([0, 0, 0, 0], 0))?;

```

When the endpoint builds the QUIC client or server configuration, it passes this boolean flag to the TLS configuration helpers.

### TLS Configuration

The actual key logging implementation resides in [`iroh/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/tls.rs) at lines 74–107. The functions `make_server_config` and `make_client_config` accept the `keylog` argument. When set to `true`, they configure rustls to emit key material:

```rust
if keylog {
    cfg.key_log = Arc::new(rustls::KeyLogFile::new());
}

```

This delegates to rustls's `KeyLogFile`, which checks the `SSLKEYLOGFILE` environment variable and writes the TLS pre-master secret in the standard NSS key log format.

## Common Symptoms and Root Causes

When debugging keylog issues in iroh connections, identify your specific symptom to isolate the root cause:

- **No keylog file created**: The `SSLKEYLOGFILE` environment variable is unset or points to a non-writable directory. Verify with `echo $SSLKEYLOGFILE` and check filesystem permissions.
- **Empty keylog file**: The `keylog` flag was not passed to the endpoint builder. Search your code for `.keylog(true)` and ensure it appears before `.bind()`.
- **Stale or missing entries**: The connection reused a cached session ticket before keylog was enabled. Clear the client's session cache or restart the endpoint to force a full handshake.
- **Application crashes**: The `rustls` crate was compiled without the `dangerous_configuration` feature, which is required for key logging. Check your [`Cargo.toml`](https://github.com/n0-computer/iroh/blob/main/Cargo.toml) for `features = ["dangerous_configuration"]`.

## Step-by-Step Debugging Procedure

Follow these steps to verify and fix key logging functionality:

1. **Set the environment variable**
   
   Ensure `SSLKEYLOGFILE` is exported before your process starts:
   
   ```bash
   export SSLKEYLOGFILE=$HOME/iroh_keylog.txt
   touch $SSLKEYLOGFILE
   ```

2. **Enable keylog in your code**
   
   Confirm the builder calls `.keylog(true)` as shown in [`iroh/examples/0rtt.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/examples/0rtt.rs) at line 68:
   
   ```rust
   let endpoint = Endpoint::builder()
       .keylog(true)
       .bind(([0, 0, 0, 0], 0))?;
   ```

3. **Verify the TLS configuration**
   
   Inspect [`iroh/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/tls.rs) to confirm `make_server_config` or `make_client_config` contains the key logging logic:
   
   ```rust
   if keylog {
       cfg.key_log = Arc::new(rustls::KeyLogFile::new());
   }
   ```

4. **Validate the rustls version**
   
   Check your `Cargo.lock` to ensure you are using a rustls version that supports `KeyLogFile`. If necessary, update your [`Cargo.toml`](https://github.com/n0-computer/iroh/blob/main/Cargo.toml):
   
   ```toml
   [dependencies]
   rustls = { version = "0.22", features = ["dangerous_configuration"] }
   ```

5. **Inspect the output**
   
   After running a connection, verify the file contains entries starting with `CLIENT_RANDOM` or `SERVER_HANDSHAKE`:
   
   ```bash
   head -n 5 $SSLKEYLOGFILE
   ```

## Working Code Example

Below is a complete example combining environment setup and endpoint configuration:

```rust
use iroh::endpoint::Endpoint;

fn main() -> anyhow::Result<()> {
    // Set before any connections are established
    std::env::set_var("SSLKEYLOGFILE", "/tmp/iroh_keys.log");
    
    let endpoint = Endpoint::builder()
        .keylog(true)  // Critical: enables key logging
        .bind(([0, 0, 0, 0], 0))?;
    
    // Proceed with connection logic...
    Ok(())
}

```

## Key Source Files Reference

When debugging keylog issues in iroh connections, examine these specific files in the repository:

- **[`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs)**: Contains the `keylog` field and builder method (lines 730–734).
- **[`iroh/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/tls.rs)**: Implements `make_server_config` and `make_client_config`; enables rustls key logging when the flag is true (lines 74–107).
- **[`iroh/examples/0rtt.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/examples/0rtt.rs)**: Reference implementation showing `.keylog(true)` usage (line 68).
- **[`Cargo.toml`](https://github.com/n0-computer/iroh/blob/main/Cargo.toml)**: Declares the `rustls` dependency; must include the `dangerous_configuration` feature.

## Summary

- **Set** the `SSLKEYLOGFILE` environment variable to a writable path before starting your application.
- **Enable** the `.keylog(true)` method on the `EndpointBuilder` to pass the flag through to the TLS layer.
- **Verify** the `rustls` dependency includes the `dangerous_configuration` feature in your [`Cargo.toml`](https://github.com/n0-computer/iroh/blob/main/Cargo.toml).
- **Check** [`iroh/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/tls.rs) to confirm `KeyLogFile` is instantiated when the flag is enabled.
- **Clear** session caches if keys appear stale, as resumed connections may predate the keylog setting.

## Frequently Asked Questions

### Why is my keylog file empty even though SSLKEYLOGFILE is set?

The file remains empty when the `.keylog(true)` method is omitted from the `EndpointBuilder` or when the connection reuses a cached session ticket without performing a full handshake. Verify that your code explicitly calls `.keylog(true)` and restart the endpoint to ensure a fresh handshake occurs.

### Does enabling key logging require special rustls features?

Yes, key logging requires the `dangerous_configuration` feature to be enabled in your [`Cargo.toml`](https://github.com/n0-computer/iroh/blob/main/Cargo.toml) for the `rustls` crate. Without this feature flag, the `KeyLogFile` API is unavailable and the application may fail to compile or panic at runtime when key logging is attempted.

### Is it safe to enable keylog in production applications?

No, enabling key logging exposes the pre-master secrets and compromises the confidentiality of all encrypted connections. According to the iroh source code, this feature is intended for debugging only, as demonstrated in example files like [`iroh/examples/0rtt.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/examples/0rtt.rs). Never enable `.keylog(true)` in production environments.

### How can I verify the keylog is capturing the correct connection?

Inspect the keylog file for entries beginning with `CLIENT_RANDOM` or `SERVER_HANDSHAKE`. Each line corresponds to a specific TLS handshake. If you see entries but cannot decrypt traffic in Wireshark, ensure you are capturing the entire QUIC handshake from the initial Client Hello packet, as keys are only logged during the handshake phase.