dnsdecode

package
v0.807.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: AGPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

Package dnsdecode parses DNS messages on the wire — the most-traffic-bearing UDP protocol on the internet and a staple of every blue-team / red-team / network-debugging workflow.

Wrap-vs-native judgement

Native. DNS is defined by RFC 1035 + a long tail of supporting RFCs (1996 NOTIFY, 2136 UPDATE, 2671/6891 EDNS, 4034/4035 DNSSEC, 6844 CAA, 6698 TLSA, 9460 SVCB/HTTPS, etc.). The wire format is a 12-byte header + four length-prefixed section lists, with RR data dispatched on a 16-bit type. Name compression uses 14-bit pointers (top 2 bits set on the length byte). Pasting a hex blob from Wireshark / tshark / a dig +short capture is enough — no key material, no cryptography, no live network attach.

What this package covers

  • DNS header (RFC 1035 §4.1.1): transaction ID, flag fields broken out as QR (query/response), Opcode (QUERY/IQUERY/STATUS/NOTIFY/UPDATE), AA (authoritative answer), TC (truncation), RD (recursion desired), RA (recursion available), AD (authentic data, DNSSEC), CD (checking disabled, DNSSEC), and RCODE (NOERROR / FORMERR / SERVFAIL / NXDOMAIN / NOTIMP / REFUSED / YXDOMAIN / YXRRSET / NXRRSET / NOTAUTH / NOTZONE / plus EDNS extended RCODEs).
  • Section counts: QDCOUNT, ANCOUNT, NSCOUNT, ARCOUNT.
  • Question section (RFC 1035 §4.1.2): QNAME with compression pointer resolution, QTYPE, QCLASS.
  • RR sections with type-specific decode for the common types operators care about:
  • A (1) — 4-byte IPv4.
  • NS (2) — owner-domain name.
  • CNAME (5) — canonical name.
  • SOA (6) — primary NS, RNAME, serial, refresh, retry, expire, minimum.
  • PTR (12) — domain name (reverse-DNS).
  • MX (15) — preference + exchange.
  • TXT (16) — list of <character-string>s.
  • AAAA (28) — 16-byte IPv6 in canonical colon form.
  • SRV (33) — priority + weight + port + target.
  • OPT (41, EDNS) — UDP-size from class field, extended RCODE + version + DO flag from TTL field, and per-option [code, length, raw data].
  • DNSKEY (48) — flags + protocol + algorithm + key data hex; key-tag (RFC 4034 Appx B) when computable.
  • DS (43) — key tag + algorithm + digest type + digest hex.
  • CAA (257, RFC 6844) — flags + tag + value (plus the well-known tags issue / issuewild / iodef / contactemail / contactphone).
  • Name decompression with pointer-chain max-depth guard to defeat the classic pointer-loop denial-of-service.
  • RCODE / Opcode / RR type / RR class lookup tables.

What this package does NOT cover (deliberately out of scope)

  • DNSSEC signature validation (RRSIG / NSEC / NSEC3 walk) — RRSIG records are surfaced with type-covered and key-tag fields but the signature blob is exposed as base64; cryptographic validation is a separate iteration that needs a trust-anchor store.
  • TLSA (52) and SVCB/HTTPS (64/65) — well-defined but usage is still niche; future Spec when real captures surface.
  • LOC (29), NAPTR (35), URI (256), and the long-tail experimental types — the type code is named but the RDATA is surfaced as raw hex.
  • DNS-over-HTTPS / DNS-over-TLS / DNS-over-QUIC framing — those wrap the same DNS message on the wire, so callers feed the inner message here.
  • Multi-message reassembly for TCP (the 2-byte length prefix used by TCP DNS) — operators are expected to strip the prefix before passing the message body.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CAAData

type CAAData struct {
	Flags      int    `json:"flags"`
	IsCritical bool   `json:"is_critical"`
	Tag        string `json:"tag"`
	Value      string `json:"value"`
}

CAAData is the type-257 RDATA per RFC 6844.

type DNSKEYData

type DNSKEYData struct {
	Flags         int    `json:"flags"`
	IsKSK         bool   `json:"is_ksk"`
	IsZSK         bool   `json:"is_zsk"`
	Protocol      int    `json:"protocol"`
	Algorithm     int    `json:"algorithm"`
	AlgorithmName string `json:"algorithm_name"`
	KeyTag        int    `json:"key_tag"`
	PublicKeyHex  string `json:"public_key_hex"`
}

DNSKEYData is the type-48 RDATA.

type DSData

type DSData struct {
	KeyTag         int    `json:"key_tag"`
	Algorithm      int    `json:"algorithm"`
	AlgorithmName  string `json:"algorithm_name"`
	DigestType     int    `json:"digest_type"`
	DigestTypeName string `json:"digest_type_name"`
	DigestHex      string `json:"digest_hex"`
}

DSData is the type-43 RDATA.

type Flags

type Flags struct {
	QR               int    `json:"qr"`
	QRName           string `json:"qr_name"`
	Opcode           int    `json:"opcode"`
	OpcodeName       string `json:"opcode_name"`
	AuthAnswer       bool   `json:"authoritative_answer"`
	Truncation       bool   `json:"truncation"`
	RecursionDesired bool   `json:"recursion_desired"`
	RecursionAvail   bool   `json:"recursion_available"`
	AuthenticData    bool   `json:"authentic_data"`
	CheckingDisabled bool   `json:"checking_disabled"`
	RCode            int    `json:"rcode"`
	RCodeName        string `json:"rcode_name"`
}

Flags is the broken-out DNS header flag bits.

type MXData

type MXData struct {
	Preference int    `json:"preference"`
	Exchange   string `json:"exchange"`
}

MXData is the type-15 RDATA: preference + exchange.

type Message

type Message struct {
	HexInput      string      `json:"hex_input"`
	TransactionID int         `json:"transaction_id"`
	Flags         *Flags      `json:"flags"`
	QDCount       int         `json:"qdcount"`
	ANCount       int         `json:"ancount"`
	NSCount       int         `json:"nscount"`
	ARCount       int         `json:"arcount"`
	Questions     []*Question `json:"questions,omitempty"`
	Answers       []*Record   `json:"answers,omitempty"`
	Authority     []*Record   `json:"authority,omitempty"`
	Additional    []*Record   `json:"additional,omitempty"`
}

Message is the decoded view of a DNS packet.

func Decode

func Decode(hexBlob string) (*Message, error)

Decode parses a hex-encoded DNS message.

func DecodeBytes

func DecodeBytes(b []byte) (*Message, error)

DecodeBytes parses a raw DNS message.

type OPTData

type OPTData struct {
	UDPSize       int         `json:"udp_size"`
	ExtendedRCode int         `json:"extended_rcode"`
	Version       int         `json:"version"`
	DOFlag        bool        `json:"do_flag"`
	Options       []OPTOption `json:"options,omitempty"`
}

OPTData is the type-41 RDATA: EDNS pseudo-RR. UDP size + extended RCODE/version/DO are pulled out of the class + TTL fields per RFC 6891.

type OPTOption

type OPTOption struct {
	Code    int    `json:"code"`
	Name    string `json:"name"`
	Length  int    `json:"length"`
	DataHex string `json:"data_hex,omitempty"`
}

OPTOption is one EDNS option [code, length, raw hex].

type Question

type Question struct {
	Name      string `json:"name"`
	Type      int    `json:"type"`
	TypeName  string `json:"type_name"`
	Class     int    `json:"class"`
	ClassName string `json:"class_name"`
}

Question is one entry in the question section.

type Record

type Record struct {
	Name        string `json:"name"`
	Type        int    `json:"type"`
	TypeName    string `json:"type_name"`
	Class       int    `json:"class"`
	ClassName   string `json:"class_name"`
	TTL         uint32 `json:"ttl,omitempty"`
	RDataLength int    `json:"rdata_length"`
	RDataHex    string `json:"rdata_hex,omitempty"`

	// Type-specific decoded fields. Only one of these is
	// populated per record; the others are empty.
	IPv4        string      `json:"ipv4,omitempty"`
	IPv6        string      `json:"ipv6,omitempty"`
	Target      string      `json:"target,omitempty"`
	TextRecords []string    `json:"text_records,omitempty"`
	MX          *MXData     `json:"mx,omitempty"`
	SOA         *SOAData    `json:"soa,omitempty"`
	SRV         *SRVData    `json:"srv,omitempty"`
	OPT         *OPTData    `json:"opt,omitempty"`
	DNSKEY      *DNSKEYData `json:"dnskey,omitempty"`
	DS          *DSData     `json:"ds,omitempty"`
	CAA         *CAAData    `json:"caa,omitempty"`
}

Record is one resource record. Only the field that matches the type is populated; everything else is RDataHex.

type SOAData

type SOAData struct {
	PrimaryNS       string `json:"primary_ns"`
	ResponsibleName string `json:"responsible_name"`
	Serial          uint32 `json:"serial"`
	RefreshSec      uint32 `json:"refresh_sec"`
	RetrySec        uint32 `json:"retry_sec"`
	ExpireSec       uint32 `json:"expire_sec"`
	MinimumSec      uint32 `json:"minimum_sec"`
}

SOAData is the type-6 RDATA: zone authority.

type SRVData

type SRVData struct {
	Priority int    `json:"priority"`
	Weight   int    `json:"weight"`
	Port     int    `json:"port"`
	Target   string `json:"target"`
}

SRVData is the type-33 RDATA: service location.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL