ntp

package
v0.331.0 Latest Latest
Warning

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

Go to latest
Published: May 21, 2026 License: AGPL-3.0 Imports: 7 Imported by: 0

Documentation

Overview

Package ntp decodes NTP / SNTP packets per RFC 5905 (v4), RFC 1305 (v3), and RFC 4330 (SNTPv4). NTP is the time- synchronisation protocol every networked device speaks against pool.ntp.org / its vendor pool / a local stratum-2 server. Capturing NTP traffic is the workhorse primitive for time-sync forensics, NTP amplification DDoS detection (mode 7 / monlist abuse), log-timestamp correlation, and certificate-validity-window debugging.

Wrap-vs-native judgement

Native. The NTP wire format is a fixed 48-byte header per RFC 5905 §7.3 with optional extension fields + authenticator at the end. Every field is a fixed-position integer or fixed-point seconds value. NTP timestamps are 64-bit (32-bit integer seconds since 1900-01-01 + 32-bit fractional seconds at 2^-32 resolution). Pasting a hex blob from Wireshark / tshark / tcpdump-of-123 capture is enough — no time server, no key material, no live network attach.

What this package covers

  • Byte 0 broken out: LI (Leap Indicator: 0 no warning / 1 +61sec / 2 -61sec / 3 alarm-unsynchronised), VN (Version Number — 1, 2, 3, 4), Mode (1 symmetric active / 2 symmetric passive / 3 client / 4 server / 5 broadcast / 6 NTP control message / 7 private use).
  • Stratum (1=primary reference / 2-15=secondary / 16=unsynchronised / 17-255=reserved) with name lookup.
  • Poll (signed log2 seconds — the maximum poll interval between successive messages, rendered as both raw log2 and as seconds).
  • Precision (signed log2 seconds — the precision of the local clock, similarly rendered).
  • Root Delay + Root Dispersion as 32-bit NTPv3 short- format fixed-point seconds (16-bit integer + 16-bit fractional, surfaced as float64 seconds).
  • Reference ID with stratum-dependent interpretation:
  • Stratum 0: Kiss-o'-Death (KoD) 4-character code (ACST/AUTH/AUTO/BCST/CRYP/DENY/DROP/RSTR/INIT/ MCST/NKEY/NTSN/RATE/RMOT/STEP) per RFC 5905 §7.4.
  • Stratum 1: 4-character ASCII source identifier (GPS/PPS/NIST/ACTS/WWV/WWVB/WWVH/DCF/MSF/DTOC/PTB/ USNO/LORC) per RFC 5905 §7.3.
  • Stratum 2-15: IPv4 of the upstream server (or the MD5 hash of the upstream IPv6 if IPv6 is being used, but we report the 4 bytes as IPv4 for the common case).
  • 4 NTP timestamps: Reference (last time the local clock was set), Origin / T1 (when client sent the request), Receive / T2 (when server received the request), Transmit / T3 (when server sent the response). Each is surfaced as both the raw 64-bit NTP value and an RFC 3339 string in UTC.
  • Optional NTPv4 extension fields (RFC 5906) — count + raw hex for each.
  • Optional authenticator (key ID + MAC) — detected by remaining bytes after the header + extensions; the key ID and the MAC hex are surfaced (MAC length 16 bytes = MD5, 20 bytes = SHA-1).

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

  • NTP control message (mode 6) deep decode — the RFC 1305 §3.5 control message format is its own ~150 LoC parser (op-code + sequence + status + assoc ID + offset + count + data); the envelope is recognised and labeled but the body is surfaced as raw hex.
  • NTP mode 7 (private use, vendor-specific) — historically abused for monlist DDoS amplification; we label it but don't dissect the vendor body.
  • Autokey (RFC 5906) authentication — extension fields are counted but the certificate / cookie / signature contents are not validated.
  • NTS (Network Time Security, RFC 8915) — newer authenticated-NTP variant; the cookie/AEAD extension fields are recognised by tag but the contents are surfaced as raw hex (decryption requires session keys).
  • SNTP simple-client behaviour — the wire format is identical to NTP so the same decoder applies.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Authenticator

type Authenticator struct {
	KeyID  uint32 `json:"key_id"`
	MACHex string `json:"mac_hex"`
	MACAlg string `json:"mac_algorithm"`
}

Authenticator carries the optional Key Identifier + MAC at the tail of an authenticated NTP packet (RFC 5905 §7.5 + RFC 1305 §3.2).

type NTPTimestamp

type NTPTimestamp struct {
	Seconds     uint32  `json:"seconds_since_1900"`
	Fraction    uint32  `json:"fraction"`
	UnixSeconds int64   `json:"unix_seconds,omitempty"`
	FractionSec float64 `json:"fraction_sec"`
	RFC3339     string  `json:"rfc3339,omitempty"`
	IsZero      bool    `json:"is_zero,omitempty"`
}

NTPTimestamp is one decoded 64-bit NTP timestamp.

The NTP epoch starts at 1900-01-01 00:00:00 UTC; Unix epoch is 1970-01-01 00:00:00 UTC. The offset between the two is 2,208,988,800 seconds.

type Packet

type Packet struct {
	HexInput          string         `json:"hex_input"`
	LeapIndicator     int            `json:"leap_indicator"`
	LeapIndicatorName string         `json:"leap_indicator_name"`
	VersionNumber     int            `json:"version_number"`
	Mode              int            `json:"mode"`
	ModeName          string         `json:"mode_name"`
	Stratum           int            `json:"stratum"`
	StratumName       string         `json:"stratum_name"`
	PollIntervalLog2  int            `json:"poll_interval_log2"`
	PollIntervalSec   float64        `json:"poll_interval_sec"`
	PrecisionLog2     int            `json:"precision_log2"`
	PrecisionSec      float64        `json:"precision_sec"`
	RootDelaySec      float64        `json:"root_delay_sec"`
	RootDispersionSec float64        `json:"root_dispersion_sec"`
	ReferenceID       *ReferenceID   `json:"reference_id"`
	ReferenceTime     *NTPTimestamp  `json:"reference_time,omitempty"`
	OriginTime        *NTPTimestamp  `json:"origin_time,omitempty"`
	ReceiveTime       *NTPTimestamp  `json:"receive_time,omitempty"`
	TransmitTime      *NTPTimestamp  `json:"transmit_time,omitempty"`
	ExtensionCount    int            `json:"extension_count,omitempty"`
	ExtensionsHex     []string       `json:"extensions_hex,omitempty"`
	Authenticator     *Authenticator `json:"authenticator,omitempty"`
}

Packet is the decoded NTP message view.

func Decode

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

Decode parses a hex-encoded NTP packet.

func DecodeBytes

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

DecodeBytes parses a raw NTP packet.

type ReferenceID

type ReferenceID struct {
	RawHex         string `json:"raw_hex"`
	Interpretation string `json:"interpretation"`
	ASCIICode      string `json:"ascii_code,omitempty"`
	ASCIIName      string `json:"ascii_name,omitempty"`
	KoDCode        string `json:"kod_code,omitempty"`
	KoDName        string `json:"kod_name,omitempty"`
	IPv4           string `json:"ipv4,omitempty"`
}

ReferenceID is the 4-byte Reference Identifier field interpreted per the current stratum.

Jump to

Keyboard shortcuts

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