ssdp

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: 5 Imported by: 0

Documentation

Overview

Package ssdp decodes SSDP (Simple Service Discovery Protocol) messages per the UPnP Device Architecture 1.1 (UPnP Forum, 2008). SSDP is the foundational discovery layer for UPnP + DLNA + a broad swath of consumer IoT devices — smart TVs, streaming receivers, media servers, NAS units, network printers, routers (UPnP-IGD), smart-home hubs, and any device that wants to advertise its presence on a LAN without prior configuration.

SSDP runs over **multicast UDP** to 239.255.255.250:1900 (IPv4) or `[FF02::C]:1900` (IPv6 link-local). The protocol is HTTP-over-UDP — every SSDP packet is a complete HTTP/1.1 request or response line followed by `Key: Value` headers and a blank line. There is no body.

Operationally, an attacker tapping into a consumer / SMB network sees SSDP first because:

  • **It's chatty by design.** Every UPnP device sends NOTIFY announcements at ~30-minute intervals (per the CACHE-CONTROL max-age semantics) plus on every reboot.
  • **It leaks every device's identity.** The USN header carries a UUID; LOCATION points at a vendor-specific `rootDesc.xml`; SERVER carries OS + UPnP version + product name; ST/NT carries the device type (e.g. `urn:schemas-upnp-org:device:MediaServer:1`).
  • **UPnP-IGD reachability** — routers that respond to `M-SEARCH ST: urn:schemas-upnp-org:device:InternetGateway Device:1` expose their WAN-port-forwarding control URL, which has historically been the entry point for unauthenticated NAT-traversal attacks (CVE-2020-12695 CallStranger, the BlackHat 2008 "Hacking the UPnP" talk, the Conficker self-propagation primitive).
  • **Smart-TV / Chromecast / Sonos enumeration** — every consumer media device sends NOTIFY announcements with enough metadata to identify model + firmware version, a starting point for downstream CVE lookup.

Wrap-vs-native judgement

Native. SSDP is a tiny text-based protocol — three message
kinds (M-SEARCH request, NOTIFY announcement, HTTP/1.1
response), CRLF-terminated lines, and a flat header set.
The UPnP Device Architecture 1.1 spec is publicly available;
canonical header names are documented in §1.3 (Discovery)
and §2.3 (Description). No crypto at the parse layer.

What this package covers

  • **Three message kinds** discriminated by the first whitespace-delimited token of the first line:

  • **`M-SEARCH * HTTP/1.1`** — search request sent by a client looking for devices. Carries `ST` (Search Target), `MAN` (= `"ssdp:discover"`), `MX` (Maximum response delay seconds — receivers spread responses over this many seconds to avoid storm), and `HOST` (always `239.255.255.250:1900`).

  • **`NOTIFY * HTTP/1.1`** — periodic advertisement sent by a device. Carries `NT` (Notification Type — device type URN), `NTS` (Notification Subtype: `ssdp:alive` for advertisement, `ssdp:byebye` for planned shutdown, `ssdp:update` for boot-id change), `USN` (Unique Service Name — `uuid:<deviceUUID>::<nt>`), `LOCATION` (URL of the XML description document), `SERVER` (UA-style OS

  • UPnP version + product string), `CACHE-CONTROL` (`max-age=<seconds>` — refresh interval).

  • **`HTTP/1.1 200 OK`** — unicast search response a device sends in reply to an M-SEARCH. Carries `ST` (echoes the request's Search Target), `USN`, `LOCATION`, `SERVER`, `CACHE-CONTROL`.

  • **Header parser** — case-insensitive key matching (per RFC 7230, all HTTP-style protocols are case- insensitive on header field names). Surfaces:

  • `Host`, `Cache-Control`, `Location`, `Server`, `ST` (Search Target), `USN` (Unique Service Name), `NT` (Notification Type), `NTS` (Notification Subtype), `MAN`, `MX`, `BOOTID.UPNP.ORG`, `CONFIGID.UPNP.ORG`, `SEARCHPORT.UPNP.ORG` — each as a dedicated typed field.

  • All other headers — surfaced as a generic `other_headers` map for caller-side inspection (vendor-specific headers like `01-NLS:` for AXIS IP cameras or `X-RINCON-HOUSEHOLD:` for Sonos groups are common).

  • **`max-age` extraction** — when `Cache-Control` starts with `max-age=`, the integer seconds value is surfaced as `cache_max_age_seconds`.

  • **`USN` deconstruction** — when the USN starts with `uuid:<UUID>`, the UUID portion is surfaced as `usn_uuid` and the trailing `::<NT>` (if present) as `usn_nt`.

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

  • **Network framing** — feed SSDP bytes after the UDP- datagram header strip (UDP port 1900 multicast + occasional UDP/1900 unicast for search responses).
  • **UPnP Description XML fetch** — the `LOCATION` header points at a per-device `rootDesc.xml` that enumerates services + control URLs; fetching + parsing that XML is a follow-on step (the `mcpfed:upnp_describe` style Spec).
  • **UPnP Control / Eventing SOAP** — the `controlURL` + `eventSubURL` from the description XML are SOAP endpoints with their own per-action shapes; out of scope.
  • **SSDP-over-IPv6** — the same wire format runs to `[FF02::C]:1900` (link-local), `[FF05::C]:1900` (site- local), and `[FF08::C]:1900` (organisation-local); this decoder treats the bytes identically regardless of transport.
  • **DLNA / OCF (Open Connectivity Foundation) extensions** — DLNA + OCF layer additional headers on top of base SSDP; surfaced via the generic `other_headers` map.
  • **mDNS / DNS-SD discovery** — a parallel discovery protocol on UDP/5353 with a different (DNS-style) wire format. Separate decoder.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type MessageKind

type MessageKind string

MessageKind enumerates the three SSDP message kinds.

const (
	KindSearch       MessageKind = "M-SEARCH"
	KindNotify       MessageKind = "NOTIFY"
	KindResponse     MessageKind = "RESPONSE"
	KindUncatalogued MessageKind = "uncatalogued"
)

type Result

type Result struct {
	TotalBytes int         `json:"total_bytes"`
	Kind       MessageKind `json:"kind"`
	StartLine  string      `json:"start_line"`

	// HTTP/1.1 response only.
	StatusCode   int    `json:"status_code,omitempty"`
	StatusPhrase string `json:"status_phrase,omitempty"`

	// Headers documented in UPnP Device Architecture 1.1.
	Host            string `json:"host,omitempty"`
	CacheControl    string `json:"cache_control,omitempty"`
	CacheMaxAgeSecs int    `json:"cache_max_age_seconds,omitempty"`
	Location        string `json:"location,omitempty"`
	Server          string `json:"server,omitempty"`
	ST              string `json:"st_search_target,omitempty"`
	USN             string `json:"usn,omitempty"`
	USNUUID         string `json:"usn_uuid,omitempty"`
	USNNT           string `json:"usn_nt,omitempty"`
	NT              string `json:"nt_notification_type,omitempty"`
	NTS             string `json:"nts_notification_subtype,omitempty"`
	MAN             string `json:"man,omitempty"`
	MX              int    `json:"mx_max_seconds,omitempty"`
	BootID          string `json:"bootid_upnp_org,omitempty"`
	ConfigID        string `json:"configid_upnp_org,omitempty"`
	SearchPort      string `json:"searchport_upnp_org,omitempty"`

	// Vendor / non-standard headers.
	OtherHeaders map[string]string `json:"other_headers,omitempty"`
}

Result is the structured decode of an SSDP message.

func Decode

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

Decode parses an SSDP message from a hex string. Separators (':' '-' '_' whitespace) tolerated; '0x' prefix tolerated.

Jump to

Keyboard shortcuts

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