Skip to content

DHCP Stream

The DHCP Stream page shows a real-time feed of DHCP packets as they are processed, with filtering, protocol badges, and expandable event details.

The stream connects to the server via WebSocket (wss://<host>/api/ws/dhcp-events) and displays each DHCP event as a row in a live-updating table. It is the primary tool for real-time packet inspection and troubleshooting.


The stream opens a WebSocket connection automatically when you navigate to the page.

Authentication uses your current session token, passed as a query parameter on the WebSocket URL. The connection is subject to the server’s maximum WebSocket connection limit (configured in config.yaml under api.websocket.max_connections).

If the connection drops, the stream pauses and shows a reconnection indicator. The page attempts automatic reconnection at a fixed 5-second interval; there is no exponential backoff.


The toolbar at the top of the stream provides play/pause, clear, and filter controls.

Click the play/pause button to temporarily stop new events from appearing. Events continue to arrive over the WebSocket but are buffered. When you resume, buffered events appear in order. Use pause when you need to examine a specific event without the table scrolling.

Click clear to remove all events from the current display. This does not affect the WebSocket connection or ClickHouse storage — it only clears the in-browser buffer.

The toolbar shows the running event count and how many events have been dropped from the local buffer (Events: <n> / Dropped: <n>). There is no per-second rate indicator; high sustained event volumes (above ~500/s) may cause the browser to use more memory.

Note: Devices with an active Deny action do not appear in the stream. Denied devices have their event generation suppressed entirely — no WebSocket events are broadcast and no ClickHouse records are written. If you expect to see a device but it is missing, check whether it has been denied on the Firewall Decisions or Actions Log page.


Each row in the stream table represents a single DHCP packet with the following columns.

ColumnDescriptionExample
TimeWhen the packet was processed (server time)2026-03-07T14:23:01Z
TypeDHCP message typeDISCOVER, OFFER, REQUEST, ACK, SOLICIT, ADVERTISE
ProtoDHCPv4 or DHCPv6 badgev4 or v6
XIDTransaction ID0xa1b2c3d4
Client MACClient hardware addressaa:bb:cc:dd:ee:ff
Source IPIP address the packet came from192.168.1.100
HostnameClient-provided hostname (Option 12)laptop-jsmith
VendorClient vendor class (Option 60)MSFT 5.0
Requested IPThe IP the client asked for (DHCPv4 Option 50 / DHCPv6 IA address)192.168.1.100
Server IPServer identifier (siaddr / Option 54)192.168.1.1
LeaseLease time / valid lifetime3600s
MarkNFTables mark assigned to this packet0x0a1b2c3d
RuleDescription of the rule that matched (defaults to unknown when no rule matched)Default printer pool
OptsCompact summary of additional DHCP optionst82, t82.1

These columns are fixed; the GUI does not currently provide a column-visibility toggle.


Each event displays a protocol badge indicating whether it is a DHCPv4 or DHCPv6 packet.

  • v4 (blue badge): Standard DHCPv4 packet using the DORA (Discover-Offer-Request-Ack) flow
  • v6 (purple badge): DHCPv6 packet using Solicit-Advertise-Request-Reply or other v6 message types

DHCPv6 events include additional fields visible in the expanded detail view: Client DUID, Server DUID, DUID Type, IA Type, IA Addresses, Delegated Prefix, and Preferred/Valid Lifetimes.


Filters control which events appear in the stream. They are evaluated SERVER-side — the GUI sends an update_filters message to the WebSocket, the server validates the filter set, and only matching events are pushed to your stream.

Filters use a rule-based system with AND/OR logic. Each rule specifies a field, an operator, and a value:

{
"logic": "AND",
"rules": [
{ "field": "message_type", "operator": "eq", "value": "DISCOVER" },
{ "field": "vendor_class", "operator": "contains", "value": "MSFT" }
]
}
FieldTypeDescription
client_macstringClient hardware address
source_macstringSource MAC from Ethernet frame
source_ipstringSource IP address
dest_ipstringDestination IP address
dest_macstringDestination MAC address
message_typestringDHCP message type name
hostnamestringClient hostname (Option 12)
vendor_classstringVendor class identifier (Option 60)
client_identifierstringClient identifier (Option 61)
xidstringTransaction ID
server_ipstringDHCP server IP
relay_ipstringRelay agent IP (giaddr)
gateway_ipstringGateway IP
client_ipstringClient IP (ciaddr)
your_ipstringYour IP (yiaddr — assigned IP)
requested_ipstringRequested IP (Option 50)
matched_rulestringName of the matched config rule
lease_timenumericLease time in seconds
renewal_timenumericRenewal time (T1) in seconds
rebinding_timenumericRebinding time (T2) in seconds
marknumericNFTables mark value
processing_time_msnumericProcessing time in milliseconds
option_countnumericNumber of DHCP options present
op_codestringDHCP opcode (BOOTREQUEST/BOOTREPLY)
hw_typestringHardware type
source_portnumericUDP source port
dest_portnumericUDP destination port
dhcp_options.<CODE>stringAny DHCP option by code number (e.g., dhcp_options.82)
OperatorCodeWorks WithExample
EqualseqAll typesmessage_type eq DISCOVER
Not equalsneAll typesvendor_class ne ""
ContainscontainsStringshostname contains laptop
Starts withstartswithStringsclient_mac startswith aa:bb
Ends withendswithStringsclient_mac endswith ee:ff
RegexregexStringshostname regex ^srv-\d+
Greater thangtNumericslease_time gt 3600
Greater or equalgteNumericsmark gte 256
Less thanltNumericsprocessing_time_ms lt 1.0
Less or equallteNumericsoption_count lte 10
IninAll typesmessage_type in [DISCOVER, REQUEST]
Not innot_inAll typesmessage_type not_in [OFFER, ACK]

Use AND logic to require all rules to match. Use OR logic to match any rule. You can nest groups for complex conditions:

AND:
- message_type eq DISCOVER
- OR:
- vendor_class contains MSFT
- vendor_class contains dhcpcd

Filters are saved per-user in the dhcp_stream_filters table. You can name and save your current filter set, then load it later from the filter dropdown. Saved filters persist across sessions.

To manage saved filters, use the filter menu in the toolbar. You can create, rename, and delete saved filters from there.


Click any row to expand it and see the full packet details.

The expanded view shows all DHCP fields including options that are not displayed in the table columns. Key sections in the detail view:

  • Packet Header: OpCode, hardware type, hop count, transaction ID, seconds elapsed, flags
  • Addresses: Client IP, Your IP, Server IP, Gateway IP, Client MAC
  • DHCP Options: Full list of options with code number, name, and decoded value
  • Network Layer: Source/destination IP, source/destination port, source/destination MAC
  • Processing: Mark assigned, matched rule, processing time
  • DHCPv6 Fields (v6 only): Client DUID, Server DUID, DUID type, IA type, IAID, IA addresses, prefixes, lifetimes, T1/T2 timers, FQDN flags

The stream is designed for real-time monitoring but browser performance degrades at very high event rates.

At sustained rates above 1000 events/second, consider these practices:

  • Apply filters to reduce the number of displayed events. Filter to a specific MAC, message type, or relay IP
  • Pause the stream when investigating a specific event to prevent the table from scrolling
  • Clear periodically to release browser memory if running the stream for extended periods
  • Use the events API (GET /api/events) for historical analysis instead of streaming large time windows

The WebSocket connection applies server-side rate limiting (configured as events_per_second with a burst multiplier in config.yaml). Events exceeding the rate limit are dropped from the stream but are still stored in ClickHouse.

Stream shows no events? Verify the processor is running, NFQueue is active (sudo nft list table inet dhcp_inspection | grep queue), and there is DHCP traffic on the network. Check the WebSocket connection status indicator in the toolbar.