Wiki / Protocols

DNP3

The SCADA protocol of electric and water utilities (IEEE 1815). Master and outstation, points and objects, and on TCP port 20000 the base protocol has no authentication at all.

DNP3 stack and roles
Master (control center)
Application layer
Objects / variations, function codes
Transport + Data link
16-bit link addresses, CRC
Outstation (RTU/IED)
Binary/analog in/out, counters
A DNP3 master polls one or more outstations (RTUs and IEDs in the field). The application layer names data as points grouped into objects with variations, the data link layer carries 16-bit source and destination addresses with per-block CRCs, and outstations may also push unsolicited responses when a point changes.

DNP3 (Distributed Network Protocol 3, standardized as IEEE 1815) is the SCADA protocol that runs electric power distribution and much of water and wastewater in North America and beyond. Where Modbus is flat and dumb, DNP3 is richer: it models time-stamped events, report-by-exception, and unsolicited pushes from the field. What it shares with Modbus is the original sin: the base protocol has no authentication and no encryption.

What it is

DNP3 is a master/outstation protocol. A master in the control center polls outstations (RTUs and IEDs) sitting on substations, pumping stations, and reclosers. It runs over serial and over TCP, where it registers on port 20000. Unlike most protocols it uses a three-layer stack of its own:

Layer Job
Application function codes and data objects (points)
Transport (pseudo) segments long application messages
Data link 16-bit source/dest addresses, per-block 16-bit CRC

Data is named as points grouped by type: binary inputs and outputs, analog inputs and outputs, and counters. Each is addressed by an object group, a variation (encoding: with or without flags, with or without a timestamp), and an index. Common function codes: READ (1), WRITE (2), SELECT (3) and OPERATE (4) which together form select-before-operate, DIRECT_OPERATE (5), plus COLD_RESTART, WARM_RESTART, and ENABLE/DISABLE_UNSOLICITED. The headline control is the CROB (Control Relay Output Block, group 12), the object that trips or closes a breaker.

Why it matters

DNP3 controls the grid. An outstation index that reads as an analog input is a bus voltage; a binary output driven by a CROB is a breaker or a recloser. Because the base protocol trusts any peer that can frame a packet, an attacker with a route to port 20000 can enumerate points, read the live state of a substation, and issue a CROB to operate a breaker. The 16-bit link addresses are not a credential; they are just routing, and they are trivially spoofable, which also opens unsolicited-response spoofing (feeding a master fake events) and denial via COLD_RESTART.

How to work it

  1. Find DNP3 endpoints and read their link addresses:
nmap -p 20000 --script dnp3-info --open <subnet>
  1. Enumerate points with a DNP3 stack (opendnp3, or the python dnp3-python/pydnp3 bindings). An integrity poll (a class 0/1/2/3 READ) returns the outstation's full current state.
  2. Read the analog and binary inputs to map the process, correlating indices against the utility's point list.
  3. Operate an output. A DIRECT_OPERATE or a SELECT then OPERATE carrying a CROB toggles a control point:
# conceptually: SELECT g12v1 index N (LATCH_ON), then OPERATE
  1. Capture a live session in Wireshark (the dnp3 dissector) and study or replay function codes and unsolicited responses.

Pitfalls

  • This operates real grid equipment. A CROB on a live outstation trips a breaker; keep every write on a lab or a system you own.
  • Select-before-operate is stateful: a bare OPERATE without a matching SELECT (same sequence, within the timeout) is rejected. Direct-operate skips the two-step.
  • DNP3 Secure Authentication (SAv5, IEC 62351-5) adds an HMAC challenge-response, and DNP3 can run over TLS, but both are rarely deployed. Confirm which you face before assuming an open target.
  • Do not confuse the object model with Modbus registers: a DNP3 point is (group, variation, index), not a single 16-bit address.

Further reading