pydhcp
A pure-Python DHCPv4 library with a server, a client, a relay agent and a capture tool, each in a blocking and an asyncio form over typed messages and options. It targets Python 3.9 and newer: packet parsing and the structured formats are portable, while actually serving DHCP still depends on OS socket permissions and platform-specific UDP behavior.
- Packet parsing and construction: every DHCPv4 message, a
DHCPOptionCodemember and a typed codec for each IANA option, and a JSON form of every message (YAML, TOML and INI with thepktcapextra). Liberal on receive, strict on send. - Server base: lease and option policy hooks, an in-memory and a file lease backend, and
a threaded and an asyncio driver (
DHCPServer,AsyncDHCPServer) over one core, so a fix to the rules reaches both. - Relay agent:
DHCPRelayforwards client traffic to upstream servers per RFC 1542 / RFC 2131 ยง4.1, with hop-limit loop protection and optional RFC 3046 option-82 tagging. - Packet client and capture:
DHCPClientbuilds and sends the client messages and runs a DORA exchange;sniff_dhcpand thepydhcp capturecommand (pktcap's, with thepktcapextra) record, filter, replay and hand each packet to a hook.
Installation
pip install pydhcp
The library (packets, options, server, client, relay) needs nothing else. What else you ask of it is an extra, one for each capability:
| Extra | Adds | Needed for |
|---|---|---|
cli |
duho |
the pydhcp command (python -m pydhcp) |
pktcap |
pktcap |
captures (pydhcp capture, pydhcp replay, sniff_dhcp) and a message or a lease as YAML, TOML or INI text (which also needs pktcap[yaml] or pktcap[toml]) |
For example pip install "pydhcp[cli,pktcap]". JSON needs no extra.
30-second tour
from pydhcp.server import DHCPServer
with DHCPServer(listen="*") as server: # binds; does not serve yet
server.serve_forever() # until shutdown(); Ctrl-C raises KeyboardInterrupt
start() receives on a daemon thread instead and returns. shutdown() ends
either and never blocks, so a handler may call it; wait_closed() blocks until
receiving has stopped; close() (which leaving the with block calls) does both
and then releases the sockets. Closed is final, and the library installs no
signal handler.
from pydhcp.client import DHCPClient
client = DHCPClient(listen=("127.0.0.1", 6768))
discover = client.build_discover(b"\x00\x11\x22\x33\x44\x55")
client.send(discover, dst="127.0.0.1", port=6767)
DHCPClient is intentionally packet-level tooling; it does not configure the operating
system network stack.
pydhcp capture --listen 127.0.0.1:6767 --filter msg_type=DHCPDISCOVER --output -
pydhcp --config server.toml server
Learn more
- API reference: the message, the options, the roles and the capture tools, from their docstrings.
- Examples: a custom lease backend, a custom server policy, a config file, the packet client and a full DORA exchange.
- Common DHCP options: typed examples for the options most sites set.
- Conformance: what is compared with dnsmasq and ISC dhclient, what each role covers and the differences.
- Deployment and Troubleshooting.
- FAQ and the changelog.