Skip to content

Feature: Native DNS query parsing in TracingPolicy, capture queried domain names from udp_sendmsg/udp_recvmsg payloads #4948

Description

@rams3sh

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem?

Note:

This request stems from this discussion on the Cilium Slack (Tetragon channel). I'm raising it here because filing it on GitHub gives everyone interested a public place to subscribe to and watch progress, rather than having the discussion get lost in Slack history. It also gives maintainers something concrete to reference from PRs or related efforts. I'm personally interested in seeing this feature land, which is the other reason I'm filing it.

Tetragon TracingPolicies can observe DNS-related socket activity today (e.g. by hooking udp_sendmsg and filtering on DPort: 53), but there is no supported way to extract the actual DNS payload i.e. the domain name being queried from a hooked function.

The use case originated on the Cilium Slack, where a user running Tetragon v1.6.0 was attempting to monitor per-pod DNS lookups for observability purposes, specifically, to log which domains are being queried by which pods, with the longer-term goal of detecting things like typosquatting attempts. They were able to capture socket metadata (src/dst IP, port 53) reliably by hooking udp_sendmsg with a sock arg, but extracting the DNS payload itself proved unworkable with the current argument types:

  • type: sock on arg 0 of udp_sendmsg — returns IP/port only, no payload.
  • type: skb on ip_output — returns header metadata only.
  • type: char_buf / char_iovec on arg 1 (msghdr) of udp_sendmsg — either errors with CharBufErrorBufTooLarge or reads the struct memory rather than the underlying message data.

@kevsecurity responded in the same thread, confirming that this isn't currently supported in open-source Tetragon, and indicating that DNS-specific support is something the team could probably attempt — likely via a hook type that can reliably access skb packet data (e.g. CGroupSKB) and read it via skb_load_bytes(), paired with some form of payload-matching logic.

Describe the feature you would like

A first-class way, inside a TracingPolicy, to observe DNS queries and responses on the workload's network path and emit them as structured fields in the resulting Tetragon event.
Concretely:

  • Per-pod and per-process visibility into the domain names being queried, with the standard Tetragon process and Kubernetes context attached.
  • Structured output in the gRPC and JSON event schema (queried name, qtype, qclass, transaction ID, rcode), rather than a raw byte buffer the user has to decode.
  • Filtering on the queried name and qtype in selectors, so policies can scope events (for example, only *.example.com, or only A and AAAA lookups).
  • A TracingPolicy example and accompanying documentation showing per-pod DNS observability end-to-end.

DoT and DoH (encrypted DNS) are out of scope.

Describe your proposed solution

No concrete proposal from my side. The Slack thread already surfaced a likely direction (an skb-data-capable hook such as CGroupSKB combined with a small payload-matching mechanism, with DNS as the first concrete consumer), and the design
is best left to the maintainers.

One possible shape worth mentioning, purely as a discussion starter and not as the expected outcome:

A pluggable parser concept attached to an argument or return value in a TracingPolicy. A parser would handle the protocol-specific decoding on the code side and expose structured fields that existing selectors (matchArgs, matchReturnArgs) can reference. New parsers could be added incrementally as use cases come up, without growing the policy schema for each one.

For DNS, a parser would take the relevant payload (for example, arg 1 of udp_sendmsg or udp_recvmsg, reached via msghdr and iovec, or the data portion of an skb) and expose fields like domain, qtype, and qclass to the selector layer.

....

selectors:
  - matchArgs:
      - index: 1
        parser: udp_sendmsg_dns     # parser used to interpret the argument
        parsedField: domain         # field exposed by the parser's output object
        operator: "Equal"
        values:
          - "example.com."
      - index: 1
        parser: udp_sendmsg_dns
        parsedField: qtype
        operator: "Equal"
        values:
          - "A"
          

The same concept could later extend to uprobes on TLS libraries (for example, SSL_read and SSL_write in OpenSSL), where a parser would decode the decrypted payload and expose application-layer fields such as HTTP method, path, headers or host. This is out of scope for this request and listed only to show that the parser idea generalizes beyond DNS.

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions