dtls

package
v0.689.0 Latest Latest
Warning

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

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

Documentation

Overview

Package dtls decodes Datagram Transport Layer Security records and handshake messages per RFC 6347 (DTLS 1.2) and RFC 9147 (DTLS 1.3 — unified header form is not supported here; we decode the legacy DTLS 1.3 record layer that uses the same 13-byte header as 1.2).

Wrap-vs-native judgement

Native. Both DTLS RFCs are fully public; the wire format
is a tight fixed-layout binary record header plus a
well-documented handshake-message catalogue. No crypto
is performed at this layer — handshake bodies of
post-Finished records and ApplicationData payloads are
encrypted (when the cipher state has advanced past the
null cipher) and are surfaced as hex. Operators paste
UDP payload bytes from a Wireshark Follow-UDP-Stream
view, a `tcpdump -X udp port 443` line, or any DTLS-
emitting tool and inspect every documented field.

What this package covers

  • **Record layer** (13 bytes fixed, RFC 6347 §4.1): ContentType (1 byte) + Version (2 bytes) + Epoch (2 bytes BE — incremented on each cipher state change) + Sequence Number (6 bytes BE — replay-protection nonce)

  • Length (2 bytes BE) + Fragment (Length bytes). The walker iterates concatenated records until the buffer is consumed.

  • **Content types** (RFC 5246 §6.2.1):

  • 20 ChangeCipherSpec

  • 21 Alert

  • 22 Handshake

  • 23 ApplicationData

  • 24 Heartbeat (RFC 6520 — yes, that one)

  • **Version values**:

  • 0xFEFF DTLS 1.0

  • 0xFEFD DTLS 1.2

  • 0xFEFC DTLS 1.3 (legacy-form records)

  • **Alert body** (2 bytes): Level (1 warning / 2 fatal) + Description with a **23-entry name table** covering close_notify, unexpected_message, bad_record_mac, decryption_failed, record_overflow, decompression_ failure, handshake_failure, no_certificate (TLS 1.0), bad_certificate, unsupported_certificate, certificate_ revoked, certificate_expired, certificate_unknown, illegal_parameter, unknown_ca, access_denied, decode_ error, decrypt_error, export_restriction, protocol_ version, insufficient_security, internal_error, user_canceled, no_renegotiation, unsupported_extension.

  • **ChangeCipherSpec body** (1 byte, always 0x01).

  • **Handshake message header** (12 bytes fixed, RFC 6347 §4.2.2): MsgType (1 byte) + Length (3 bytes BE — total reassembled message length) + MessageSeq (2 bytes BE — for fragment reassembly) + FragmentOffset (3 bytes BE) + FragmentLength (3 bytes BE) + FragmentBody.

  • **Handshake message types** (RFC 5246 + RFC 6347):

  • 0 HelloRequest

  • 1 ClientHello

  • 2 ServerHello

  • 3 HelloVerifyRequest (DTLS-specific cookie exchange)

  • 4 NewSessionTicket

  • 8 EncryptedExtensions (TLS 1.3)

  • 11 Certificate

  • 12 ServerKeyExchange

  • 13 CertificateRequest

  • 14 ServerHelloDone

  • 15 CertificateVerify

  • 16 ClientKeyExchange

  • 20 Finished

  • **ClientHello body** parsed: legacy_version + random (32 bytes) + session_id (length-prefixed) + cookie (length-prefixed, DTLS-specific) + cipher_suites (length-prefixed list of uint16 BE; rendered as count

  • raw hex blob) + compression_methods (length-prefixed list of uint8) + extensions (length-prefixed list of uint16 type + uint16 length + body bytes, rendered as count + raw hex blob).

  • **ServerHello body** parsed: legacy_version + random

  • session_id + selected cipher_suite (uint16 BE) + selected compression_method (uint8) + extensions.

  • **HelloVerifyRequest body** parsed: server_version + cookie (length-prefixed). The hallmark of DTLS's stateless cookie exchange (mitigates UDP amplification DoS).

  • **Heartbeat body** (RFC 6520): MessageType (1 byte: 1 Request / 2 Response) + PayloadLength (uint16 BE) + Payload + Padding. NB: a mismatched PayloadLength vs declared was the basis for Heartbleed (CVE-2014- 0160) — we surface the declared value AND the actual remaining bytes so operators can spot the gap.

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

  • Decryption of encrypted records — operators need session keys exported from the TLS handshake; the ciphertext is surfaced as hex.

  • DTLS 1.3 unified header records (RFC 9147 §4) — the ultra-compact variant with 8-bit-tag header is a future Spec.

  • Full TLS extension dissection (SNI / ALPN / supported_ groups / signature_algorithms / key_share / etc.) — extension bodies are surfaced as hex. The TLS extension catalogue is handled by `tls_handshake_decode` for cleartext TCP records; the same table would apply once cleartext bytes have been extracted from DTLS.

  • UDP / IP framing — feed the UDP payload bytes.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Alert

type Alert struct {
	Level           int    `json:"level"`
	LevelName       string `json:"level_name"`
	Description     int    `json:"description"`
	DescriptionName string `json:"description_name"`
}

Alert is the body of content type 21.

type ApplicationData

type ApplicationData struct {
	CipherTextLen int    `json:"cipher_text_length"`
	CipherTextHex string `json:"cipher_text_hex,omitempty"`
}

ApplicationData surfaces the ciphertext blob with length.

type CertEntry added in v0.474.0

type CertEntry struct {
	Length      int                     `json:"length"`
	Certificate *x509decode.Certificate `json:"x509,omitempty"`
	DERHex      string                  `json:"der_hex,omitempty"`
	DecodeError string                  `json:"decode_error,omitempty"`
}

CertEntry is one certificate from the chain, decoded via internal/x509decode.

type Certificate added in v0.474.0

type Certificate struct {
	CertificateCount int          `json:"certificate_count"`
	Certificates     []*CertEntry `json:"certificates,omitempty"`
	Notes            []string     `json:"notes,omitempty"`
}

Certificate is a decoded DTLS Certificate handshake message. Its body uses the same layout as TLS 1.2 (a 3-byte certificate_list length followed by 3-byte-length-prefixed DER certificates); each DER certificate is decoded via internal/x509decode. Only attempted on an unfragmented handshake message (the dispatch above returns early when IsFragmented).

type ClientHello

type ClientHello struct {
	LegacyVersion      string `json:"legacy_version"`
	LegacyVersionHex   string `json:"legacy_version_hex"`
	RandomHex          string `json:"random_hex"`
	SessionIDHex       string `json:"session_id_hex,omitempty"`
	SessionIDLength    int    `json:"session_id_length"`
	CookieHex          string `json:"cookie_hex,omitempty"`
	CookieLength       int    `json:"cookie_length"`
	CipherSuiteCount   int    `json:"cipher_suite_count"`
	CipherSuitesHex    string `json:"cipher_suites_hex,omitempty"`
	CompressionCount   int    `json:"compression_count"`
	CompressionMethods string `json:"compression_methods_hex,omitempty"`
	ExtensionsLength   int    `json:"extensions_length,omitempty"`
	ExtensionsHex      string `json:"extensions_hex,omitempty"`
}

ClientHello body fields.

type Handshake

type Handshake struct {
	MsgType        int    `json:"msg_type"`
	MsgTypeName    string `json:"msg_type_name"`
	Length         int    `json:"total_message_length"`
	MessageSeq     uint16 `json:"message_seq"`
	FragmentOffset int    `json:"fragment_offset"`
	FragmentLength int    `json:"fragment_length"`
	IsFragmented   bool   `json:"is_fragmented"`

	ClientHello        *ClientHello        `json:"client_hello,omitempty"`
	ServerHello        *ServerHello        `json:"server_hello,omitempty"`
	HelloVerifyRequest *HelloVerifyRequest `json:"hello_verify_request,omitempty"`
	Certificate        *Certificate        `json:"certificate,omitempty"`
}

Handshake is the dissected DTLS handshake header + per-type body. When the fragment is encrypted (post-ChangeCipherSpec), only the FragmentHex on the parent Record is meaningful and this struct is nil.

type Heartbeat

type Heartbeat struct {
	MessageType     int    `json:"message_type"`
	MessageTypeName string `json:"message_type_name"`
	PayloadLength   int    `json:"payload_length_declared"`
	ActualRemaining int    `json:"actual_remaining_bytes"`
	PayloadHex      string `json:"payload_hex,omitempty"`
	HeartbleedHint  string `json:"heartbleed_hint,omitempty"`
}

Heartbeat is the body of content type 24 (RFC 6520).

type HelloVerifyRequest

type HelloVerifyRequest struct {
	ServerVersion    string `json:"server_version"`
	ServerVersionHex string `json:"server_version_hex"`
	CookieHex        string `json:"cookie_hex"`
	CookieLength     int    `json:"cookie_length"`
}

HelloVerifyRequest body fields.

type Record

type Record struct {
	ContentType     int    `json:"content_type"`
	ContentTypeName string `json:"content_type_name"`
	Version         string `json:"version"`
	VersionHex      string `json:"version_hex"`
	Epoch           uint16 `json:"epoch"`
	SequenceNumber  uint64 `json:"sequence_number"`
	Length          int    `json:"length"`
	FragmentHex     string `json:"fragment_hex,omitempty"`

	Handshake        *Handshake       `json:"handshake,omitempty"`
	Alert            *Alert           `json:"alert,omitempty"`
	ChangeCipherSpec *uint8           `json:"change_cipher_spec,omitempty"`
	Heartbeat        *Heartbeat       `json:"heartbeat,omitempty"`
	ApplicationData  *ApplicationData `json:"application_data,omitempty"`
}

Record is one DTLS record-layer frame.

type Result

type Result struct {
	Records     []Record `json:"records"`
	RecordCount int      `json:"record_count"`
	TotalBytes  int      `json:"total_bytes"`
	Summary     string   `json:"summary"`
}

Result is the top-level decoded view.

func Decode

func Decode(hexStr string) (*Result, error)

Decode parses one or more concatenated DTLS records from hex.

type ServerHello

type ServerHello struct {
	LegacyVersion     string `json:"legacy_version"`
	LegacyVersionHex  string `json:"legacy_version_hex"`
	RandomHex         string `json:"random_hex"`
	SessionIDHex      string `json:"session_id_hex,omitempty"`
	SessionIDLength   int    `json:"session_id_length"`
	CipherSuiteHex    string `json:"cipher_suite_hex"`
	CompressionMethod int    `json:"compression_method"`
	ExtensionsLength  int    `json:"extensions_length,omitempty"`
	ExtensionsHex     string `json:"extensions_hex,omitempty"`
}

ServerHello body fields.

Jump to

Keyboard shortcuts

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