Metadata-Version: 2.5
Name: dhcpig
Version: 2.7.3
Summary: DHCP exhaustion / network-hardening validation tool (whitehat)
Author: Kevin Amorin
License: GPL-2.0-or-later
License-File: LICENSE
Keywords: dhcp,exhaustion,ipv4,ipv6,pentest,scapy,security
Requires-Python: >=3.11
Requires-Dist: scapy>=2.5
Provides-Extra: dev
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Provides-Extra: web
Description-Content-Type: text/markdown

<h1>
  <img src="packaging/dhcpig.svg" alt="" width="110" height="110" align="left" />
  DHCPig
</h1>

Whitehat DHCP hardening validation: exhaust a pool, hijack neighbours' leases, evict hosts off
their addresses with forged ARP, and report whether the network stopped you. Needs root and
Python 3.11+.

Run the web UI
--------------

**Debian / Kali:** grab the latest `.deb` from
[Releases](https://github.com/kamorin/DHCPig/releases/latest) and install it —
puts `dhcpig` and `dhcpig-web` on `PATH`, no venv needed:

    curl -LO https://github.com/kamorin/DHCPig/releases/download/v2.7.2/dhcpig_2.7.2-1_all.deb
    sudo apt install ./dhcpig_2.7.2-1_all.deb
    sudo dhcpig-web --open

**Global install** (any Linux, Python 3.11+, no venv):

    git clone https://github.com/kamorin/DHCPig && cd DHCPig
    sudo pip install --break-system-packages .
    sudo dhcpig-web --open

Installs straight into the system Python as root, so `sudo dhcpig-web` finds the command with
no `.venv/bin/` path juggling. `--break-system-packages` overrides Debian/Kali's PEP 668 guard
against pip touching system packages — that guard exists to protect `apt`-managed packages, not
because this install is unusual; the `.deb` or a venv avoid needing it at all.

**From source** (any Linux, Python 3.11+):

    git clone https://github.com/kamorin/DHCPig && cd DHCPig
    python3 -m venv .venv && .venv/bin/pip install -e .
    sudo .venv/bin/dhcpig-web --open

Open the printed `http://127.0.0.1:8787/?token=...` URL. Three gotchas:

* **Root is required either way** (raw sockets). From source (venv), use the full `.venv/bin/`
  path — `sudo` resets `PATH`.
* **The `?token=` is mandatory.** Without it you get 401s and a blank page.
* **Headless?** It binds loopback on purpose. Forward it, don't re-bind:
  `ssh -L 8787:127.0.0.1:8787 user@<vm-ip>`. Drop `--open`.

On Debian/Kali, `sudo apt install -y python3-venv` first if the venv step fails.

CLI
---

    sudo .venv/bin/dhcpig exhaust eth0 --report run.json
    sudo .venv/bin/dhcpig release eth0 --scope 192.168.4.0/22     # DESTRUCTIVE
    sudo .venv/bin/dhcpig active-scan eth0 --scope 192.168.4.0/22 # read-only
    sudo .venv/bin/dhcpig release-previous eth0                   # undo a previous run
    dhcpig ifaces

| Flag | |
|---|---|
| `--dry-run` | recon only: ARP sweep + control transactions run for real, nothing mutating is sent |
| `--scope CIDR` | bound the targets (repeatable); defaults to the interface's own network |
| `--rate N` | pps, default 7 — not on `exhaust`, which self-paces |
| `--no-evict` | skip the ARP-conflict phase |
| `--report FILE` | write a session report to `FILE` when the run ends; format follows `FILE`'s extension (`.json`/`.csv`/`.html`, default JSON) |
| `--client-mac MAC` | `exhaust` only; use this MAC instead of a random one (repeatable — rotates through the list) |
| `--request-option SPEC` | `exhaust`/`active-scan`; DHCP option-55 (parameter-request-list) content to send, e.g. `12,14-19,23` (default: the built-in macOS-order profile) |
| `--no-spoof-eth-src` | `exhaust` only; use the real NIC MAC as the Ethernet source for every frame (Wi-Fi; APs drop frames whose source MAC isn't the associated station) |

`-v0` prints results only; `-v3` adds packet-level debug. Full flag reference: `man dhcpig`
(or `packaging/dhcpig.1` before install).

What each mode does
-------------------

**DHCP Exhaustion** (`exhaust`) — destructive
* ARP-inventories the segment, then proves DHCP works from this machine and for an unknown MAC
* DHCPRELEASEs every neighbour's lease — the protocol requires no proof of ownership
* Floods DISCOVER/REQUEST from fabricated MACs until the server stops answering
* Re-requests the released addresses by name (option 50) once the pool is drained
* Forges RFC 5227 ARP conflicts against what it took, to see if hosts surrender the address
* **Verdict:** could a brand-new client still get an address afterwards?

**DHCP Release Active Clients** (`release`) — destructive
* Same chain minus the flood: inventory → release → re-request by name → ARP conflict
* Hits devices connected right now; the pool is left intact so most can re-acquire
* **Verdict:** did any host lose its address and fail to get a new one?

**Post Exhaustion / Reset** (`release-previous`) — recovery
* Replays the on-disk lease journal and hands back every address this tool took
* Filtered to this interface, network and DHCP server; `--max-age` drops stale entries
* Records whether the pool was already exhausted, but releases journalled leases either way
* **Verdict:** is the pool usable again?

**Find Neighbors** (`active-scan`) — read-only
* ARP-sweeps the scope, sends one DHCPINFORM to fingerprint the DHCP servers
* Takes no addresses, disturbs no leases

**Passive scan** (`scan`) — read-only, CLI only
* Watches DHCP and ARP; fingerprints hosts by option-55 order, falling back to MAC vendor
* Sends nothing. Runs until stopped

Reading a run
-------------

Everything lands in the event log, worst first: findings, then one line per host, then an
`OUTCOME` roll-up. `Verbosity 0` (web) or `-v0` (CLI) hides the packet traffic. The JSON export
is the complete record — the log is a summary.

Undoing a run
-------------

Leases are **kept** after a run so the exhausted state can be verified. Release them:

    sudo .venv/bin/dhcpig restore eth0             # same process still running
    sudo .venv/bin/dhcpig release-previous eth0    # any time later, from the lease journal

The journal (`$XDG_STATE_HOME/dhcpig/leases-<iface>.jsonl`) records MAC, IP, server and
timestamp per lease taken — engagement data. Delete it when you're done.

Disclaimer
----------

Only run this against networks you own or are explicitly authorized to test. `release` and
`exhaust` disrupt live clients by design; `--scope` is optional and defaults to the whole
segment. The authors are not responsible for misuse.

Design notes and internals: `docs/DESIGN.md`. Contributing: `CONTRIBUTING.md`.
Licence: GPL v2 or later.
