skip to content

Wireshark 4.6 has your key log configured, yet some HTTPS sessions in the capture still show only Application Data; how do you find out why?

level: seniorimportance: should knowfreq 12%

answer

  1. ask the dissector, not guess
  2. a debug file per session
  3. is the ClientHello there?
  4. same process, same run?
  5. UDP may carry it instead

basics

~20 s

Turn on the TLS debug file and read why each session failed. The usual causes: the ClientHello is not in the capture, the key log came from another process or run, the client never read SSLKEYLOGFILE, or the browser used QUIC.

solid answer

~40 s

Ask the dissector: set the TLS preference *TLS debug file* (`tls.debug_file`, or `-` for stderr) and reload. "missing Client Random" or "Cipher suite (Server Hello) is missing!" means the handshake is not in the capture, a capture-side gap no preference fixes. "Cannot find CLIENT_HANDSHAKE_TRAFFIC_SECRET, decryption impossible" (TLS 1.3) or "Cannot find master secret" (TLS 1.2) with the handshake present means the log has no line for that client random: it came from another process, host or run, or the client never read `SSLKEYLOGFILE`. A TLS 1.2 session flagged `tls.resumed` needs its client-random line or the earlier full handshake. A browser may also have used HTTP/3 over QUIC, decrypted by the QUIC dissector from the same log. If the log grew after opening, use *View > Redissect Packets*, new in 4.6.

go deeper

for a junior

Recall that the key log only helps when the capture holds each session's handshake and the log holds that session's lines.

for a middle

Explain how lines are matched by client random, and use the TLS debug file to see which secret Wireshark looked for and did not find.

for a senior

Separate capture-side gaps from key-log gaps before changing anything, and check resumption, QUIC and timing before blaming the client.

for a principal

Design test captures so decryption is reliable: capture before the client starts, one log per run, and a written check that every expected session decrypted.

## Start from the dissector's own account Guessing is slow because several unrelated faults look identical in the packet list: the session stays at *Encrypted Application Data*. Wireshark's TLS dissector can explain itself: 1. In **Preferences > Protocols > TLS**, set **TLS debug file** (`tls.debug_file`) to a path, or to `-` to send the trace to standard error. The file is overwritten each time it is opened, so use a scratch path. 2. Reload the capture or re-dissect it, then search the trace for the frames of the failing session. 3. Clear the preference afterwards; the trace is large and contains secrets. With tshark the same works for one run: `-o tls.debug_file:-` together with `-o tls.keylog_file:<path>`. ## Reading the messages | Message in the TLS debug file | What it means | Side of the problem | |---|---|---| | `missing Client Random` | A TLS 1.3 session was seen without its `ClientHello` | Capture | | `Cipher suite (Server Hello) is missing!` | The `ServerHello` was not captured | Capture | | `No Session resumption, missing packets?` | The conversation starts mid-handshake | Capture | | `Cannot find CLIENT_HANDSHAKE_TRAFFIC_SECRET, decryption impossible` | TLS 1.3 handshake present, no matching log line | Key log | | `Cannot find master secret` | TLS 1.2 handshake present, no matching log line, session ID or ticket | Key log | | `session uses Diffie-Hellman key exchange ... cannot be decrypted using a RSA private key file` | An RSA key was offered for an ephemeral session | Key material | The split matters. **Capture-side gaps** (the capture started late, the handshake was dropped or truncated, the conversation was captured on only one path) are fixed by capturing again, never by a preference. **Key-log gaps** are fixed by finding the right log. ## The causes behind a key-log gap Every line is keyed by the session's 32-byte client random, so ask why that random is absent: - **Another process wrote the log.** Only processes started with `SSLKEYLOGFILE` set write lines. A browser that was already running, a helper process launched from elsewhere, or a command run in a different shell leaves no lines. - **Another run wrote the log.** Each handshake has a fresh client random and fresh secrets, so yesterday's log matches none of today's sessions, even for the same request to the same server. - **Another host wrote the log.** A capture on a gateway includes clients other than your test client; their sessions were never logged. - **The client does not support key logging**, or was built without it, so the file stays empty for its sessions. To confirm, copy the session's random from `tls.handshake.random` in the `ClientHello` and search the key log for it. ## Resumed and moved sessions - A TLS 1.2 session that **resumed** an earlier one carries the expert note `tls.resumed` ("This session reuses previously negotiated keys"). It decrypts from its own client-random line if the client logged it, or from the master secret Wireshark derived for the earlier full handshake, if that handshake is in the same capture. - A browser may have sent the request over **HTTP/3**, which runs on QUIC over UDP. Those sessions never appear as TLS-over-TCP records; the QUIC dissector decrypts them from the same key log's TLS 1.3 secrets, so look under `quic` before concluding the log failed. - Traffic on a port Wireshark does not associate with TLS may not be dissected as TLS at all; mapping a port to a dissector is a separate skill. - Records the capture holds only in part, because packets were lost at the capture point or cut short by a small snapshot length, cannot be decrypted however good the key log is. TLS records split across several TCP segments also need TCP reassembly enabled, which is a stream-analysis setting rather than a decryption one. ## Timing: when the log changes after you open the file Wireshark keeps reading lines appended to the key log, but packets already dissected are not revisited automatically. Wireshark 4.6 added **View > Redissect Packets** for cases like this one, when decryption secrets change after the file was loaded. ## A short routine 1. Confirm the failing session's handshake is in the capture. 2. Enable the TLS debug file and read the message for that session. 3. Match the client random against the key log. 4. Check for resumption, QUIC and port mapping. 5. Re-dissect after any change to the log.

  • How do you tell quickly whether a failing session's handshake is in the capture at all?
    Filter on that connection and look for its `ClientHello` and `ServerHello` (`tls.handshake.type == 1` and `== 2`). If they are absent, the capture started late or lost them, and no key log can help; capture again with the client started after the capture. If they are present, take `tls.handshake.random` from the `ClientHello` and search the key log for it.
  • Why might a browser's request be missing from the TLS sessions in the capture entirely?
    The browser may have used HTTP/3, which runs over QUIC on UDP rather than TLS over TCP. The QUIC dissector decrypts those packets from the TLS 1.3 secrets in the same key log, so filter on `quic` and check there. A capture filter that kept only TCP would have discarded them before Wireshark ever saw them.

saying these in an interview costs you the question

  • Once the key log is set, every TLS session in the capture will decrypt.
  • A key log from yesterday's run decrypts today's capture of the same request.
  • A missing ClientHello can be worked around with a Wireshark preference.
  • A session that stays encrypted always means the key log file is wrong.
  • A browser's HTTPS request always appears as TLS over TCP.