Please generate explore and sessions fxt files for @chrome-doh-example-with-secrets.pcapng
Ran analyze_capture. Detected 5 protocols: DNS, TLS, HTTP/2, TCP, IPv6. The capture is Chrome resolving names via Cloudflare's DoH endpoint (chrome.cloudflare-dns.com) over IPv6, with TLS secrets embedded in the pcapng DSB block so tshark auto-decrypts the HTTP/2 + inner DNS payload.
Best matching template: http2/explore.fxt.xml (60% coverage). Used the bundled HTTP/2 samples as a starting point and customized for IPv6 (added tcpv6-message / udpv6-message duplicates of every tcp-message / udp-message template) plus inner-DNS-over-TCP templates so the decrypted DoH payload renders.
| File | Templates (incl. v6) | Session types | Outcome |
|---|---|---|---|
explore.fxt.xml | ~50 | 0 | 25 / 41 frames matched |
sessions.fxt.xml | ~60 | 2 (http2-session, dns-session) | 1 dns success::resolved, 1 http2 success::closed, 4 http2 incomplete::no-close |
The explore mode does not show DNS messages. I see them in dns-session.
Diagnosed: explore uses first-match-wins. Inner-DNS templates were placed after the HTTP/2 DATA template, so HTTP/2 DATA absorbed the frame before DNS got a chance. Sessions mode uses multi-match (per-session-type), so DNS still appeared there.
Fix: Moved all inner-DNS templates (dns.qry.type, dns.a, dns.aaaa, dns.flags.response) above the HTTP/2 DATA & control frames in explore.fxt.xml. Same matched-frame count (25/41), but now DoH inner DNS Query/Response render inline with the HTTP/2 flow.
Please generate the hosts.txt file
Ran extract_endpoints. Two IPv6 endpoints:
2603:3005:1402:a740:c985:8b1c:f4ed:fc26 Chrome Client
2606:4700::6812:dad chrome.cloudflare-dns.com
Saved as hosts.txt (tab-separated IPv6<TAB>Name). Re-ran both explore and extract_sessions with hosts_file=hosts.txt so friendly names appear in the diagrams.
Please add lightbulb remarks to explain the DoH messages in both fxt files.
Added <remark> elements (rendered as 💡 callouts) focused on why DoH behaves the way it does, not just what each message is.
explore.fxt.xml remarks added on:
?dns=... (cacheable)application/dns-message; HTTP cache-control overrides DNS TTL for shared cachessessions.fxt.xml remarks added on:
/dns-query (each request = a new HTTP/2 stream = a new http2-session)http2.time = key DoH performance metric vs plain UDP/53)dns-session::0x0000 explainedIn dns session with key: dns-session::0x0000, please explain why cloudflare-dns is also sending DNS Queries to the browser.
Two distinct quirks:
Why dns.id = 0x0000 — RFC 8484 §4.1 recommends DoH clients set the DNS transaction ID to 0:
In order to maximize HTTP cache friendliness, DoH clients … SHOULD use a DNS ID of 0 in every DNS request.
Correlation is no longer needed at the DNS layer — the HTTP/2 stream pairs request/response. Zeroing the ID lets shared HTTP caches deduplicate identical ?dns=… GETs across clients. Chrome follows this, so every DoH query+response collapses into a single dns-session bucket keyed by 0x0000.
Why the resolver appears to send queries back — it isn't. A DNS response echoes the original Question section verbatim before the Answer. Tshark dissects that echoed Question with the same dns.qry.type / dns.qry.name fields it uses for actual queries. In multi-match mode the response packet matches both the session-start template (Question echo → 🔍 DNS Query) and the session-stop template (dns.a → 📋 DNS Response), and since the server is the source the query-shaped render points server→client.
This is fine. Let us update the lightbulb remark to clarify this.
Updated the dns-session start remarks for A and AAAA queries in sessions.fxt.xml to call out:
dns.id=0x0000 per RFC 8484 §4.1 (collapses all queries into one bucket)Should we display the DNS interactions in the http2-session as well?
Added duplicates of the inner-DNS templates tagged session-type="http2-session" (no session-start/session-stop, so they decorate existing sessions instead of creating new ones).
I don't see the DNS messages in http://127.0.0.1:56043/.../http2-session/success/00002_viewer.html?
The session router needs the session key field present on the matched message to bucket it. The new inner-DNS http2-session templates didn't include http2.streamid as a <param>. Added http2.streamid to all four (Query A, Query AAAA, Response A, Response AAAA — both tcp-message and tcpv6-message variants).
Still not enough — see next turn.
multi-match at rootWe have to specify the session key.
Investigated fxt.rs and FXT_SYNTAX_REFERENCE.md. Per-template session keys are not supported ("no inline session-key"). The real missing piece was the root attribute multi-match="true" — without it, each packet matches only the first template, so a response packet was routed only to dns-session and never to http2-session.
Added <FXT multi-match="true"> to sessions.fxt.xml. Outcome counts changed dramatically:
| Before | After | |
|---|---|---|
dns-session success::resolved | 1 | 3 |
http2-session success::2xx | 0 | 4 |
http2-session success::closed | 1 | 1 |
http2-session incomplete::no-close | 4 | 0 |
Inner DNS Query/Response now renders inline within each http2-session timeline alongside the POST/200 OK pair, and the four DoH requests now correctly close as success::2xx instead of being orphaned as incomplete.
How much is the response time for DoH requests?
Extracted http2.time (Wireshark's request→response delta on the same stream) via tshark filtered to http2.headers.status==200:
| Stream | Response time |
|---|---|
| 1 | 23.2 ms |
| 5 | 33.2 ms |
| 3 | 33.4 ms |
| 7 | 38.4 ms |
Mean ≈ 32 ms, range 23–38 ms. These measure only the round-trip + server processing; the TCP/TLS handshake is amortized once across all four queries thanks to HTTP/2 multiplexing.
| File | Purpose |
|---|---|
chrome-doh-example-with-secrets.pcapng | Source capture (DoH over IPv6, TLS keys in DSB block) |
explore.fxt.xml | Combined-flow templates (HTTP/2 + inner DNS + TLS + TCP, IPv4 + IPv6) |
sessions.fxt.xml | Session tracking (http2-session keyed by http2.streamid, dns-session keyed by dns.id); multi-match="true" |
hosts.txt | IPv6 → friendly name (Chrome Client, chrome.cloudflare-dns.com) |
out/chrome-doh-example-with-secrets/ | Generated viewers (explore HTML + per-session HTML) |
/dns-query (application/dns-message) → wrapped DNS query/response.sessions.fxt.xml whenever one packet must contribute to multiple session types (here: the DoH response is both an http2-session stop and a dns-session stop).