Deployment Modes
DHCP DPI supports two deployment modes: inline (full enforcement) and mirrored (passive monitoring). Inline is the default and is the mode you should plan for unless you have a specific reason not to.
Your deployment mode determines whether the system can block, throttle, and rate-limit traffic, or only observe and analyze it. Choose based on your network requirements and risk tolerance.
Default installation = inline, single host. When you install DHCP DPI from the shipped deb packages with
install.sh, the script provisions an inline deployment with every component — the packet processor, nftables ruleset, ClickHouse, the API/GUI, and the support backchannel — on the same host (typically a dedicated VM or LXC container). This is the simplest setup to operate and the one the rest of the manual assumes unless a chapter says otherwise. Distributed setups (separate ClickHouse host, dedicated API server, remote LLM, etc.) are supported but require manual configuration.
Inline Deployment
Section titled “Inline Deployment”The system sits directly in the DHCP packet path and can enforce actions on live traffic. This is the recommended and default mode.
ASCII fallback
DHCP Clients | v [Switch / Network] | v +------------------+ | DHCP DPI Host | <-- nftables + NFQueue + Application | (inline) | +------------------+ | v DHCP ServerIn inline mode, DHCP packets physically pass through the host running DHCP DPI. The system intercepts them via nftables prerouting hooks, inspects them in userspace, and returns verdicts that accept, drop, or rate-limit the traffic.
Capabilities
Section titled “Capabilities”- Full packet inspection and marking
- Rate limiting per MAC and per rule
- Blocking and throttling enforcement
- LLM-recommended actions take immediate effect
- Automation rules can block or throttle directly
Requirements
Section titled “Requirements”- The DHCP DPI host must be in the Layer 2 path between clients and the DHCP server, or Layer 3 if only Relay based requests are planned
- Alternatively, the DHCP server and DHCP DPI can run on the same host
- nftables rules must be deployed (see nftables Deployment)
- The
bypassflag in NFQueue ensures fail-open: if the application stops, packets pass through
Collocated Deployment
Section titled “Collocated Deployment”Running DHCP DPI on the same host as the DHCP server is the possible inline setup — but watch for raw sockets.
When both run on the same machine, all DHCP traffic naturally passes through the host’s network stack. The prerouting hook captures inbound client messages, and the output hook captures server responses. No network topology changes are required.
Caveat: DHCP servers that use raw sockets bypass nftables. Many DHCP server implementations (ISC
dhcpd, the default Kea v4 socket typeraw, and others) openAF_PACKET/SOCK_RAWlisteners so they can answer DHCPDISCOVER from clients that do not yet have an IP. Raw-socket reads sit below the netfilter hooks the DPI inspector relies on, which causes two problems on a collocated host:
- Inbound packets are not filtered. The DHCP server receives every DISCOVER / REQUEST directly off the wire while DPI sees a parallel copy via the prerouting hook. Block / throttle / deny actions in nftables do not stop the server from responding — both the DPI and the server “catch” each request independently.
- Outbound responses may bypass the output hook. Servers that craft replies with a raw socket can emit them through
AF_PACKETas well, in which case thedhcp_inspect_outputchain never sees the OFFER / ACK / NAK and you lose the v4 server-side fields from your events.Two ways out:
- Switch the DHCP server to UDP sockets if it supports the option. For Kea v4, set
dhcp-socket-type: udpin the interfaces config; for ISCdhcpd, the server has no UDP-only mode, so this option is not available there.- Separate DHCP DPI and the DHCP server, at minimum at the physical (or virtual) interface level, so packets must transit the DPI host’s nftables stack before reaching the server. A dedicated DPI VM or LXC with the server reachable only via that DPI’s outbound interface is the cleanest setup and the one the project’s reference topology uses. In case of LXC the DHCP server should not use the same physical interface as the DHCP DPI.
Two-Hook Capture: Prerouting + Output
Section titled “Two-Hook Capture: Prerouting + Output”Each traffic direction is inspected by its own nftables hook — prerouting for arriving packets, output for locally generated replies.
In inline mode the ruleset uses two complementary entry chains:
dhcp_inspecton the prerouting hook (priority -100) — captures client-to-server messages arriving at the host: DISCOVER, REQUEST, DECLINE, RELEASE, INFORM (DHCPv4) and SOLICIT, REQUEST, RENEW, REBIND, RELEASE, DECLINE, INFORMATION-REQUEST (DHCPv6).dhcp_inspect_outputon the output hook (priority -100) — captures server-to-client replies generated by the local DHCP server: OFFER, ACK, NAK (DHCPv4) and ADVERTISE, REPLY, RECONFIGURE (DHCPv6).
The output hook is used instead of postrouting deliberately: output fires earlier in the egress path, runs before any conntrack rewriting, and never sees packets that are merely forwarded through the host (those go through prerouting + forward + postrouting). That keeps the outbound chain scoped strictly to replies the local DHCP server emits, which is exactly what we want.
Both hooks queue into the same NFQueue range and feed the same inspector, so events from both directions land in the same pipeline (ClickHouse, WebSocket, automation, alarms).
Mirrored Deployment
Section titled “Mirrored Deployment”The system receives copies of DHCP traffic via port mirroring or TZSP tunneling and can only observe.
ASCII fallback
DHCP Clients | v [Switch]-----mirror/TZSP----->+------------------+ | | DHCP DPI Host | v | (mirrored) | DHCP Server +------------------+In mirrored mode, the DHCP DPI host receives copies of DHCP packets on dedicated ports (1067 for DHCPv4, 1547 for DHCPv6). The original traffic flows directly between clients and the DHCP server without passing through the DPI host.
Capabilities
Section titled “Capabilities”- Full packet inspection, parsing, and analysis
- ClickHouse event storage and historical queries
- LLM analysis and anomaly detection
- WebSocket streaming and GUI monitoring
- Automation rule detection (identify anomalies)
Limitations
Section titled “Limitations”- No enforcement: Block, throttle, and deny actions have no effect on the original traffic
- No rate limiting: nftables rate limiting only affects the mirrored copies
- Actions are informational: LLM recommendations are logged but cannot be enforced
How Mirrored Traffic Is Handled
Section titled “How Mirrored Traffic Is Handled”Mirrored packets are analyzed by NFQueue, then immediately dropped by the drop_mirrored chain.
The drop_mirrored chain (priority -99) runs immediately after the dhcp_inspect chain (priority -100). It drops all packets on ports 1067 and 1547 after they have been queued and processed by the Go application. This prevents mirrored copies from reaching the DHCP server or triggering enforcement chains.
ASCII fallback
Mirrored packet (port 1067/1547) | vdhcp_inspect (-100) --> NFQueue --> Go app (parse, log, analyze) | vdrop_mirrored (-99) --> DROP (never reaches throttle/block chains)Choosing a Deployment Mode
Section titled “Choosing a Deployment Mode”Use inline when you need enforcement. Use mirrored when you need visibility without risk.
| Factor | Inline | Mirrored |
|---|---|---|
| Enforcement | Full (block, throttle, allow) | None (observe only) |
| Network changes | Required (host in packet path) | Minimal (mirror port or TZSP) |
| Risk | Application failure affects DHCP (mitigated by bypass flag) | Zero risk to DHCP service |
| Latency impact | Microseconds per packet | None |
| Use case | Production enforcement | Monitoring, evaluation, remote sites |
Recommended Approach
Section titled “Recommended Approach”Start with mirrored mode to evaluate the system, tune rules, and build confidence in LLM recommendations. Once you trust the detection quality, switch to inline mode for active enforcement.
Mixed Deployment
Section titled “Mixed Deployment”You can run inline on your primary site and mirrored on remote sites simultaneously.
A single DHCP DPI instance can receive both direct traffic (ports 67/68, 546/547) and mirrored traffic (ports 1067/1547) at the same time. The system distinguishes them by port number. Direct traffic goes through full enforcement; mirrored traffic is analyzed and dropped after inspection.
This allows centralized monitoring of multiple sites while only enforcing on the local network.
Common Topologies
Section titled “Common Topologies”Three deployment topologies cover the vast majority of installations.
Flat Network (Collocated)
Section titled “Flat Network (Collocated)”All clients and the DHCP server share a single broadcast domain; DHCP DPI runs on the DHCP server host.
ASCII fallback
+--------+ +--------+ +--------+ | Client | | Client | | Client | +---+----+ +---+----+ +---+----+ | | | +-----+-----+-----+-----+ | | [L2 Switch] | | | +---------+---------+ | | DHCP Server + DPI |-+ +-------------------+This is the simplest topology and matches the install.sh default. DHCP broadcasts reach the server directly. The DPI host (collocated) sees all traffic. No relay agents required.
Routed Network with DHCP Relay
Section titled “Routed Network with DHCP Relay”Clients live in different VLANs / subnets and relay agents forward DHCP to a central server.
ASCII fallback
VLAN 10 VLAN 20 VLAN 30 +--------+ +--------+ +--------+ | Client | | Client | | Client | +---+----+ +---+----+ +---+----+ | | | [Access SW] [Access SW] [Access SW] | | | +--------+---------+---------+--------+ | | [Core Router] [Core Router] (DHCP Relay) (DHCP Relay) | | +---+--------+------+ | +------+-------+ | DHCP Server | | + DHCP DPI | +--------------+Relay agents convert broadcasts to unicast and add Option 82 (relay agent information). The DPI host sees relayed traffic as unicast UDP on port 67. Option 82 is parsed and stored, so you get per-relay (and therefore per-subnet) visibility for every client. Because the client MAC is gone from the Ethernet header after relaying, classification relies on Option 61 / Option 82 / DUID — exactly what the userspace inspector is designed for (see chapter 01, Why Not Pure nftables Matching?).
TZSP Mirrored from Remote Sites
Section titled “TZSP Mirrored from Remote Sites”Use TZSP packet tunneling to send DHCP traffic from remote sites to a central DPI host for observation only.
What is TZSP? TZSP (TaZmen Sniffer Protocol) is a lightweight UDP encapsulation that wraps a copy of a raw Ethernet frame and ships it to a remote collector. It is unidirectional and lossy by design — the originating side never expects a reply and the collector never enforces anything back. MikroTik RouterOS supports TZSP natively as a packet-sniffer destination, which is why MikroTik environments can stream mirrored traffic directly without any extra software on the remote side.
MikroTik gotcha: one router cannot mirror its own DHCP-server replies. MikroTik’s TZSP sniffer hooks the same low-level path the DHCP server uses to emit OFFER / ACK responses, and those locally-originated outbound packets simply do not show up in the mirror stream — the same raw-socket blind spot described earlier for collocated DHCP servers, just expressed at the router level. Inbound DISCOVER / REQUEST from clients are captured normally, so you get a one-sided view of every transaction. There is no software workaround on the router side. If you want full bidirectional visibility into a MikroTik-served subnet, you need two physical machines: one MikroTik (or other device) hosting the DHCP server, and a second MikroTik (or any host running
dhcp-agent) doing the TZSP mirroring on the link between clients and the server.
Two project-supplied components handle the TZSP path:
dhcp-agentruns at each remote site. It captures local DHCP traffic via libpcap on one or more interfaces, filters down to DHCP-only frames, wraps each one in TZSP, and forwards it over UDP to the central collector. Lightweight, single-binary, runs on anything from an x86 VM to an ARM SoC.dhcp-collectorruns at the central site (typically on the DPI host itself). It listens for TZSP datagrams from any number ofdhcp-agentinstances and also accepts direct DHCP relay traffic from OLT / router relay agents. Received packets are re-injected to local DHCP ports so they flow through NFQueue and the full DPI pipeline as if they had arrived on the wire locally.
ASCII fallback
Remote Site A Remote Site B +-----------------+ +-----------------+ | Switch + clients| | Switch + clients| +--------+--------+ +--------+--------+ | | +-------+--------+ +--------+--------+ | dhcp-agent | or natively | MikroTik Router | | (libpcap → | | (built-in TZSP | | TZSP) | | mirror) | +-------+--------+ +--------+--------+ | | +---------------[WAN / VPN]---------+ | TZSP/UDP v +-----------------+ | dhcp-collector | re-injects to | (TZSP listener) | ports 1067/1547 +--------+--------+ | v +-----------------+ | DHCP DPI | inspects via NFQueue, | (central host) | stores events, +-----------------+ analyses (no enforcement)Mirrored traffic is analysed only — enforcement is impossible on copies, regardless of whether they arrived via dhcp-agent or a native MikroTik mirror. Pair this with an inline DPI deployment at HQ to get the best of both: local enforcement plus centralised visibility across remote sites.
DHCPv4 vs DHCPv6 Ports
Section titled “DHCPv4 vs DHCPv6 Ports”Both protocols are handled by the same ruleset; only the port numbers differ.
| Protocol | Client Port | Server Port | Mirrored Port |
|---|---|---|---|
| DHCPv4 | 68 | 67 | 1067 |
| DHCPv6 | 546 | 547 | 1547 |
The shipped nft-v2.sh matches all six ports and queues them to the same NFQueue workers; the application auto-detects the protocol version from the packet content. DHCPv6 relay messages (RELAY-FORW, RELAY-REPL) are encapsulated on port 547 — the inspector walks the relay encapsulation and extracts the inner client message.
Beyond the Three Topologies
Section titled “Beyond the Three Topologies”The three topologies above cover the common cases. Real networks always have more variety. The mental model below is what lets DHCP DPI adapt to almost any of them.
Real deployments do not stop at “flat”, “relayed”, or “TZSP-mirrored”. Operators may run the appliance inside LXC containers, KVM and Proxmox VMs, OpenStack instances, bare-metal hosts. All along multi-NIC routers, bonded uplinks, VRFs, bridged segments behind hypervisors, exotic switch fabrics, OLT chassis with their own DHCP-relay quirks, vendor-customised firmware that handles options non-standardly, and the occasional cable plugged into the wrong port. The list is endless.
The simplest way to reason about whether DHCP DPI will work in a given setup is this:
Think of the appliance as an ordinary Linux host running a standard nftables firewall, placed where DHCP traffic can pass through it (or where mirrored copies can be delivered to it). Everything else — the GUI, the ClickHouse store, the LLM, the support backchannel, the MCP server, Vector fan-out, alarms, automation — is a nice hat on top. Those hats can stay local, run on a separate host, or be turned off entirely without breaking the core packet-inspection-and-enforcement function.
That is the whole flexibility story. If the chosen topology lets DHCP packets reach a Linux box where you can attach an nftables ruleset, DPI works. The rest is implementation detail you can fit to your environment.