wireguard

package
v0.366.0 Latest Latest
Warning

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

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

Documentation

Overview

Package wireguard decodes WireGuard UDP packets per the official protocol specification at https://www.wireguard.com/protocol/.

Wrap-vs-native judgement

Native. The WireGuard wire format is a tight fixed-
layout binary header with a documented set of four
message types. There are no variable-length integers,
no version negotiation, no extensions, and no
compression at this layer. Operators paste UDP payload
bytes from a Wireshark wg dissector, an `iptables -j
LOG` capture, or any `tcpdump -X udp port 51820` line
and inspect every documented field. Pure offline parser.
The cryptographic primitives (Curve25519, Blake2s,
ChaCha20Poly1305, XChaCha20Poly1305) are NOT decoded —
encrypted material is surfaced as hex for traceability,
and decryption belongs in a separate Spec.

What this package covers

  • Auto-detect by leading message-type byte: 0x01 Handshake Initiation, 0x02 Handshake Response, 0x03 Cookie Reply, 0x04 Transport Data. The 3 reserved bytes after the type are required to be zero per spec — non-zero values are surfaced as a note (some middleboxes / forks abuse them).

  • **Handshake Initiation** (148 bytes fixed): sender index (u32 LE) + unencrypted ephemeral Curve25519 public key (32 bytes) + encrypted static key (32+16 AEAD) + encrypted timestamp (12+16 AEAD) + MAC1 (16 bytes Blake2s(MAC1_key || msg)) + MAC2 (16 bytes, zero when no cookie).

  • **Handshake Response** (92 bytes fixed): sender index

  • receiver index + unencrypted ephemeral key (32 bytes)

  • encrypted nothing (0+16 AEAD — proves the static keypair was used) + MAC1 + MAC2.

  • **Cookie Reply** (64 bytes fixed): receiver index + nonce (24 bytes XChaCha20Poly1305) + encrypted cookie (16+16 AEAD).

  • **Transport Data** (variable, ≥ 32 bytes): receiver index + counter (u64 LE — increments per direction; replay-protection nonce) + encrypted encapsulated packet (≥0 bytes plaintext IP packet + 16-byte Poly1305 tag). Surfaces the payload length as the inner-IP-packet length minus the 16-byte tag.

  • MAC2 detection: the all-zero pattern is recognised and flagged as "no cookie applied" — clients only populate MAC2 after they receive a Cookie Reply.

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

  • Decryption — operators need the static + ephemeral key material plus the noise-IK handshake state. A separate Spec would handle the symmetric layer.

  • Noise IK handshake state machine — we surface what's on the wire; reconstructing the chain of derived keys is a session-tracker's job.

  • UDP / IP framing — feed the UDP payload bytes after the IP+UDP headers (or after a Wireshark Follow UDP Stream extraction).

  • MAC1 / MAC2 verification — would require the responder's static public key. The values are surfaced so an operator with the key can re-derive and verify.

  • Cookie reply re-derivation (Blake2s of source IP + port + responder mac1_key) — same reason.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cookie struct {
	ReceiverIndex    uint32 `json:"receiver_index"`
	ReceiverIndexHex string `json:"receiver_index_hex"`
	NonceHex         string `json:"nonce_hex"`
	EncryptedCookie  string `json:"encrypted_cookie_hex"`
}

Cookie is the body of message type 3.

type Initiation

type Initiation struct {
	SenderIndex           uint32 `json:"sender_index"`
	SenderIndexHex        string `json:"sender_index_hex"`
	EphemeralPubKeyHex    string `json:"unencrypted_ephemeral_pubkey_hex"`
	EncryptedStaticHex    string `json:"encrypted_static_hex"`
	EncryptedTimestampHex string `json:"encrypted_timestamp_hex"`
	MAC1Hex               string `json:"mac1_hex"`
	MAC2Hex               string `json:"mac2_hex"`
	MAC2Zero              bool   `json:"mac2_zero"`
}

Initiation is the body of message type 1.

type Response

type Response struct {
	SenderIndex         uint32 `json:"sender_index"`
	SenderIndexHex      string `json:"sender_index_hex"`
	ReceiverIndex       uint32 `json:"receiver_index"`
	ReceiverIndexHex    string `json:"receiver_index_hex"`
	EphemeralPubKeyHex  string `json:"unencrypted_ephemeral_pubkey_hex"`
	EncryptedNothingHex string `json:"encrypted_nothing_hex"`
	MAC1Hex             string `json:"mac1_hex"`
	MAC2Hex             string `json:"mac2_hex"`
	MAC2Zero            bool   `json:"mac2_zero"`
}

Response is the body of message type 2.

type Result

type Result struct {
	MessageType     int    `json:"message_type"`
	MessageTypeName string `json:"message_type_name"`
	TotalBytes      int    `json:"total_bytes"`
	ReservedZero    bool   `json:"reserved_zero"`
	ReservedHex     string `json:"reserved_hex,omitempty"`

	Initiation *Initiation `json:"initiation,omitempty"`
	Response   *Response   `json:"response,omitempty"`
	Cookie     *Cookie     `json:"cookie_reply,omitempty"`
	Transport  *Transport  `json:"transport,omitempty"`

	Notes []string `json:"notes,omitempty"`
}

Result is the top-level decoded view.

func Decode

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

Decode parses a WireGuard datagram from hex.

type Transport

type Transport struct {
	ReceiverIndex       uint32 `json:"receiver_index"`
	ReceiverIndexHex    string `json:"receiver_index_hex"`
	Counter             uint64 `json:"counter"`
	EncryptedPayloadHex string `json:"encrypted_payload_hex,omitempty"`
	EncryptedPayloadLen int    `json:"encrypted_payload_length"`
	InnerPlaintextLen   int    `json:"inner_plaintext_length_inferred"`
	KeepAlive           bool   `json:"keep_alive,omitempty"`
}

Transport is the body of message type 4.

Jump to

Keyboard shortcuts

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