Modbus is a simple request and reply protocol that lets a client, such as an HMI, SCADA server or engineering laptop, read and write data in a server device, such as a PLC, drive, meter or remote I/O block. It runs over serial lines (Modbus RTU and Modbus ASCII) and over TCP on port 502, and in its classic form it has no authentication, no encryption and no integrity protection beyond an error check. The Modbus Organization's TLS based variant, Modbus/TCP Security, runs on port 802 and adds mutual certificate authentication and role based authorisation.
This post covers the framing, function codes and data model, the serial and TCP transports, what the Modbus/TCP Security specification requires, the weakness classes that follow from the design, how to find who talks Modbus on networks you own, and when DNP3 or OPC UA fits better.
Key takeaways
- Modbus is an application layer protocol. The Modbus Application Protocol Specification V1.1b3 (26 April 2012) defines one PDU of a function code plus data, carried in different ADUs on serial lines and TCP.
- IANA registers port 502 as
mbap(Modbus Application Protocol) and port 802 asmbap-s(Modbus Application Protocol Secure), both for TCP and UDP. The Modbus/TCP guide says servers must listen on 502 by default. - The data model has four tables: discrete inputs and coils (single bits), input registers and holding registers (16 bit words). Each table can address 65,536 items, and the PDU is capped at 253 bytes.
- Serial Modbus is single master. Devices take addresses 1 to 247, address 0 is broadcast, and RTU mode with a 16 bit CRC is mandatory; ASCII mode with an LRC is optional.
- Classic Modbus has no concept of identity. A server checks that a function code, address range and value are valid, not who sent the request. The CRC and the TCP checksum detect corruption, not tampering.
- The current Modbus/TCP Security specification (MB-TCP-Security-v36, 30 July 2021) requires TLS 1.2 or newer, mutual X.509v3 authentication, and, where authorisation is enforced, a role carried in a certificate extension and checked by a vendor defined rules database.
- Most of the defence is architecture, per NIST SP 800-82 Rev. 3 and CISA: keep Modbus off the internet, segment it, control remote access and restrict who may write.
What Modbus is for, the layer and the standard
Modbus moves process values and commands between control system components. A SCADA server polls a PLC for tank levels held in input registers, writes a new setpoint into a holding register, or switches a pump by writing a coil. An energy meter exposes voltages and totals as registers. A variable speed drive takes its speed reference the same way. The protocol is small, openly documented and easy to implement on an 8 bit microcontroller, which is why almost every industrial device vendor supports it and why integrators still reach for it first.
Why it is still everywhere in OT
The Application Protocol specification calls Modbus "the industry's serial de facto standard since 1979". Equipment in water, power, oil and gas, building automation and manufacturing has a service life measured in decades, and Modbus is the lowest common denominator that lets a new HMI talk to a twenty year old drive. Gateways translate between serial Modbus and Modbus/TCP, so the protocol also survives every network upgrade: the field wiring stays RS-485 and the plant network sees port 502. NIST SP 800-82 Rev. 3 lists Modbus among the "standard industrial communication protocols designed by industry groups" used on control and fieldbus networks.
Where it sits in the stack
The specification places Modbus "at level 7 of the OSI model" as a client and server messaging protocol. It defines the request and reply exchange, and leaves transport to separate documents:
| Variant | Transport | Defining document |
|---|---|---|
| Modbus RTU | Asynchronous serial: TIA/EIA-485 (two wire most common), TIA/EIA-232, fibre, radio | Modbus over Serial Line Specification and Implementation Guide V1.02 |
| Modbus ASCII | Same serial media, hexadecimal characters | Same serial line guide |
| Modbus/TCP | TCP over IP, port 502 | Modbus Messaging on TCP/IP Implementation Guide V1.0b |
| Modbus/TCP Security | TLS over TCP, port 802 | Modbus/TCP Security Protocol Specification |
| Modbus Plus | A high speed token passing network | Listed in the Application Protocol specification for context; not covered here |
Because the PDU is the same everywhere, a gateway can unwrap a Modbus/TCP request, put the same function code and data into an RTU frame and send it down a serial bus. That is convenient for integrators and important for security: anything that can reach the gateway on 502 can reach every serial device behind it.
The defining documents
All four core documents are published free by the Modbus Organization:
- Modbus Application Protocol Specification V1.1b3, dated 26 April 2012. It defines the PDU, data model, addressing, public function codes and exception responses.
- Modbus over Serial Line Specification and Implementation Guide V1.02, dated 20 December 2006. Its revision table shows 1.01 (30 August 2006) and 1.02 as "minor clarifications and correction of typos".
- Modbus Messaging on TCP/IP Implementation Guide V1.0b, dated 24 October 2006. It defines the MBAP header, connection management and the TCP port rules.
- Modbus/TCP Security Protocol Specification, the version fetched for this post identified as MB-TCP-Security-v36 and dated 30 July 2021. It defines how the unchanged Modbus/TCP ADU is carried inside TLS.
None of these obsolete the classic protocol. The security specification says plainly that "there MUST be no change to the mbap protocol as a consequence of it being encapsulated by the secure transport" (requirement R-05). Secure Modbus is classic Modbus inside a TLS tunnel with an authorisation hook.
How Modbus works on the wire
The PDU and the ADU
Every Modbus message has a protocol data unit that is independent of the transport:
| Field | Size | Meaning |
|---|---|---|
| Function code | 1 byte | What the server should do. Valid codes are 1 to 255; 128 to 255 are reserved for exception responses and 0 is not valid |
| Data | 0 to 252 bytes | Function dependent: starting address, quantity, byte count, values, sub-function codes |
The transport wraps the PDU in an application data unit that adds addressing and, on serial lines, an error check. The size limit comes from the first serial implementations, where the maximum RS-485 ADU was 256 bytes:
| Transport | ADU layout | Maximum size |
|---|---|---|
| Serial (RTU or ASCII) | Server address (1 byte) + PDU + CRC or LRC | 256 bytes in RTU: 1 + 253 + 2 |
| TCP | MBAP header (7 bytes) + PDU | 260 bytes: 7 + 253 |
Multi byte numbers are big endian: a 16 bit register holding 0x1234 is sent as 0x12 then 0x34. Note that this applies to single registers. How a device packs a 32 bit float or integer across two registers is vendor specific, which is a long running source of integration bugs.
The transaction
Modbus is strictly request and reply. The specification's server side state machine is short: wait for a request, validate the function code, validate the data address, validate the data value, execute, then reply.
Client (HMI / SCADA) Server (PLC / device)
| |
| Request PDU: function code + request data |
|---------------------------------------------->|
| | 1. function code valid? else exception 01
| | 2. address range valid? else exception 02
| | 3. data value valid? else exception 03
| | 4. execute else exception 04, 05, 06
| Normal reply: same function code + data |
|<----------------------------------------------|
| |
| or Exception: function code + 0x80, |
| one byte exception code |
|<----------------------------------------------|
A normal response echoes the request's function code. An exception response sets the most significant bit, so a failed Read Holding Registers (0x03) comes back as 0x83 followed by an exception code. The specification recommends that clients manage a timeout so they do not wait forever for a reply that will never arrive.
The server validates function, address range and format, nothing more. The exception code table is explicit that ILLEGAL DATA VALUE "specifically does NOT mean" a value outside what the application expects, "since the MODBUS protocol is unaware of the significance of any particular value of any particular register". Range checks on setpoints, if they exist, live in the PLC program, not the protocol.
The data model: coils, discrete inputs and registers
| Table | Object type | Access | Typical use |
|---|---|---|---|
| Discrete inputs | Single bit | Read only | Limit switches, alarm contacts, status bits from I/O |
| Coils | Single bit | Read and write | Digital outputs, run and stop commands, internal flags |
| Input registers | 16 bit word | Read only | Analogue measurements, counters |
| Holding registers | 16 bit word | Read and write | Setpoints, configuration, values written by a program |
The specification notes it is "perfectly acceptable, and very common" for the four tables to overlay the same memory, so a register write might also change bits read as coils. The mapping from the Modbus tables to the device's real memory is "totally vendor device specific", which is why every device ships a register map document.
Addressing trips up newcomers. In the PDU, each table is addressed from 0 to 65535. In the data model, elements are numbered from 1. The specification's rule is that "a MODBUS data numbered X is addressed in the MODBUS PDU X-1", so coils numbered 1 to 16 travel as addresses 0 to 15. The familiar five and six digit references in vendor manuals (40001 for the first holding register, for example) are a documentation convention rather than part of the protocol; check each device's map instead of assuming an offset.
Function codes
The specification defines three categories: public function codes (documented, unique, validated by the Modbus community), user defined codes in the ranges 65 to 72 and 100 to 110 (no guarantee of uniqueness), and reserved codes used by some companies for legacy products. The public codes most often seen on a plant network:
| Code (hex) | Name | Access | Limits from the specification |
|---|---|---|---|
| 01 (0x01) | Read Coils | Read | 1 to 2000 coils |
| 02 (0x02) | Read Discrete Inputs | Read | 1 to 2000 inputs |
| 03 (0x03) | Read Holding Registers | Read | 1 to 125 registers |
| 04 (0x04) | Read Input Registers | Read | 1 to 125 registers |
| 05 (0x05) | Write Single Coil | Write | Value 0xFF00 for ON or 0x0000 for OFF; anything else is illegal |
| 06 (0x06) | Write Single Register | Write | One 16 bit value |
| 08 (0x08) | Diagnostics | Diagnostic | Serial line only; two byte sub-function codes |
| 15 (0x0F) | Write Multiple Coils | Write | 1 to 1968 (0x07B0) coils |
| 16 (0x10) | Write Multiple Registers | Write | 1 to 123 registers |
| 21 (0x15) | Write File Record | Write | File record access |
| 22 (0x16) | Mask Write Register | Write | AND mask and OR mask applied to one register |
| 23 (0x17) | Read/Write Multiple Registers | Read and write | One transaction does both |
| 43 (0x2B) | Encapsulated Interface Transport | Other | MEI type 13 (CANopen General Reference) and MEI type 14 (Read Device Identification) |
The rest of the public list is serial line diagnostics (07 Read Exception Status, 11 Get Comm Event Counter, 12 Get Comm Event Log, 17 Report Server ID), 20 Read File Record and 24 Read FIFO Queue.
Function code 08 deserves a security note even though it is a serial line feature. Its sub-functions reset counters and restart communications, and sub-function 04, Force Listen Only Mode, puts the addressed device into a state where it monitors traffic "but no actions will be taken and no responses will be sent". The only request it will then process is Restart Communications Option (sub-function 01). The specification describes this as a way to remove a malfunctioning device from the bus. It is also a reminder that Modbus includes management functions with availability consequences, and that the protocol has no way to restrict who sends them.
Function code 43 with MEI type 14, Read Device Identification, returns objects in three categories. The Basic category is mandatory and holds VendorName, ProductCode and MajorMinorRevision; Regular and Extended categories add optional data such as VendorUrl, ProductName and ModelName. It is useful for asset inventory, and it tells anyone who can reach the device exactly which firmware revision to look up.
Exception codes
| Code | Name | Meaning in short |
|---|---|---|
| 01 | ILLEGAL FUNCTION | The function is not supported, or not allowed in the server's current state |
| 02 | ILLEGAL DATA ADDRESS | The start address plus quantity runs outside the server's tables |
| 03 | ILLEGAL DATA VALUE | The request is malformed, for example an implied length is wrong |
| 04 | SERVER DEVICE FAILURE | An unrecoverable error while executing |
| 05 | ACKNOWLEDGE | Accepted, but a long operation is in progress; poll later |
| 06 | SERVER DEVICE BUSY | Busy with a long running command; retry later |
| 08 | MEMORY PARITY ERROR | Used with file record functions when the extended file area fails a consistency check |
| 0A | GATEWAY PATH UNAVAILABLE | A gateway could not allocate a path to the target |
| 0B | GATEWAY TARGET DEVICE FAILED TO RESPOND | A gateway got no reply from the target device |
Modbus over serial line: RTU and ASCII
The serial line guide describes a master and slaves protocol: "Only one master (at the same time) is connected to the bus". The master sends either a unicast request to one address or a broadcast. Addressing:
| Address | Use |
|---|---|
| 0 | Broadcast. All devices must accept broadcast writes and none replies |
| 1 to 247 | Individual device addresses, unique on the bus |
| 248 to 255 | Reserved |
Broadcast requests are "necessarily writing commands", so a single broadcast frame changes state in every device on the segment without any acknowledgement.
RTU mode is mandatory for every device and must be the default. Each byte travels as 11 bits: a start bit, eight data bits sent least significant bit first, a parity bit and a stop bit; the guide notes that no parity requires two stop bits. Even parity is required and is the default. Frames are delimited by silence: a gap of at least 3.5 character times (t3.5) separates frames, and a gap of more than 1.5 character times (t1.5) inside a frame marks it incomplete. At baud rates above 19200 the guide recommends fixed timers of 750 microseconds for t1.5 and 1.750 milliseconds for t3.5. The frame ends with a 16 bit CRC, low order byte first. The guide requires 9600 and 19200 bit/s support, with 19200 as the default.
RTU frame
| silence >= 3.5 char | Address (8 bits) | Function (8 bits) | Data (N x 8 bits) | CRC (16 bits) | silence >= 3.5 char |
ASCII mode is optional. Each byte of the message is sent as two hexadecimal ASCII characters, each character as 10 bits. A frame starts with a colon (0x3A) and ends with carriage return and line feed (0x0D 0x0A), and carries a one byte LRC (longitudinal redundancy check) encoded as two characters before the CRLF. The guide allows intervals of up to one second between characters within an ASCII message, which suited slow radio and modem links.
ASCII frame
| ":" | Address (2 chars) | Function (2 chars) | Data (0 to 2 x 252 chars) | LRC (2 chars) | CR LF |
The CRC and LRC detect line noise. Neither is a cryptographic check: anyone who can write a frame can compute a valid CRC.
Modbus/TCP: the MBAP header and port 502
Modbus/TCP drops the serial address and checksum and puts a 7 byte Modbus Application Protocol (MBAP) header in front of the PDU. The TCP guide's field table:
| Field | Length | Set by client | Set by server | Meaning |
|---|---|---|---|---|
| Transaction Identifier | 2 bytes | Initialises | Copies from request | Pairs a response with its request when several are outstanding |
| Protocol Identifier | 2 bytes | Initialises to 0 | Copies from request | 0 means Modbus |
| Length | 2 bytes | Initialises | Initialises for its response | Count of the bytes that follow, including Unit Identifier and PDU |
| Unit Identifier | 1 byte | Initialises | Copies from request | Routes the request through a gateway to a serial or Modbus Plus device |
Modbus/TCP ADU (max 260 bytes)
| Transaction ID (2) | Protocol ID (2) = 0 | Length (2) | Unit ID (1) | Function code (1) | Data (0 to 252) |
|<-------------------------- MBAP header, 7 bytes ------------------>|<----------- PDU ------------------>|
All fields are big endian. The explicit Length field lets a receiver find message boundaries when TCP splits a message across segments. When a client talks directly to a TCP device rather than through a gateway, the guide says the Unit Identifier is "useless" and recommends the value 0xFF; a gateway uses it to pick the serial device to forward to.
Connection handling, from the guide:
- The messaging service "must provide a listening socket on Port 502". Vendors may add a configurable port, but 502 "must still be available in addition to any application specific ports". The guide reserves port 502 as the default and recommends that users be able to set a different one.
- A client connects from a local port above 1024 to the server's 502, and the guide recommends keeping that connection open rather than opening one per transaction. Several transactions may be in flight on one connection, matched by Transaction Identifier.
- Servers keep two connection pools. A priority pool serves "marked" client IP addresses that are configured in advance; a non priority pool serves everyone else, and when it is full the server closes the oldest connection to accept a new one.
- An optional access control module "can be activated to check if the IP address of the remote client is authorized. If not the new connection is refused." The guide frames this as needed only "in certain critical contexts".
That last point is the whole of classic Modbus/TCP security: an optional source IP allowlist on some devices. The guide also relies on TCP keepalive to detect a broken connection. Everything in our TCP state machine post about connection lifecycle applies to port 502, and TCP vs UDP: what an eavesdropper can see and change describes exactly what anyone on the path sees in a plaintext Modbus session: everything.
IANA registrations
| Service name | Port | Transport | Description in the registry |
|---|---|---|---|
mbap | 502 | TCP and UDP | Modbus Application Protocol |
mbap-s | 802 | TCP and UDP | Modbus Application Protocol Secure |
The security specification says Modbus/TCP was registered with IANA in 1996 and that the registration process gave it the name mbap, which persists in the registry. Both entries name modbus.org as the registrant. UDP is registered for both ports, but the Modbus Organization documents describe TCP; UDP use is a vendor extension.
Versions and history
| Year | Milestone | What changed |
|---|---|---|
| 1979 | Modbus appears as a serial protocol | Master and slave polling over serial links; the specification calls it the de facto serial standard since then |
| 1996 | Port 502 registered with IANA | Modbus/TCP gets a system port, per the security specification's history |
| 2006 | Serial Line guide V1.02 (20 December) and TCP/IP Implementation Guide V1.0b (24 October) | Current editions of the transport documents |
| 2012 | Application Protocol V1.1b3 (26 April) | Current edition of the core protocol: function codes, data model, exceptions, "client" and "server" wording |
| 2021 | Modbus/TCP Security, MB-TCP-Security-v36 (30 July) | The revision available from modbus.org today; TLS 1.2 or newer, mutual certificates, role based authorisation, port 802 |
The older documents use "master" and "slave" for the serial roles; V1.1b3 uses "client" and "server". Modbus Plus and the legacy serial guide are still listed on modbus.org for installed base support. What is deployed in practice is overwhelmingly RTU on RS-485 at the field level and plaintext Modbus/TCP on 502 above it. Support for port 802 depends on the device and its firmware, and most installed equipment predates the security specification, so plants should expect to run both for years.
Security properties and known weakness classes
What classic Modbus does and does not guarantee
| Property | Classic Modbus (RTU, ASCII, TCP on 502) | Modbus/TCP Security on 802 |
|---|---|---|
| Confidentiality | None. Every value and command is readable on the wire | TLS encryption when a cipher suite with encryption is chosen; NULL encryption suites are allowed where only integrity is required |
| Integrity | Error detection only: CRC or LRC on serial, TCP checksum and Ethernet CRC on TCP | TLS record MAC; HMAC-MD5 and HMAC-SHA-1 are prohibited, HMAC-SHA-256 is required |
| Client authentication | None. A server cannot tell one client from another | Mandatory mutual TLS with X.509v3 certificates |
| Server authentication | None | Server certificate, chain sent to the root CA |
| Authorisation | None in the protocol; optional source IP allowlist on some TCP devices | Optional but recommended: role from a certificate extension checked against a vendor defined rules database |
| Replay protection | None | TLS sequence numbers within a session |
| Availability | Timeouts; connection pool rules | Same, plus TLS handshake cost |
NIST SP 800-82 Rev. 3 states the general case in its table of OT network vulnerabilities: "Many OT protocols have no authentication at any level", and "Integrity checks are not built into most OT protocols, so adversaries could manipulate communications undetected." It notes that devices and protocols at Purdue Level 0 often "cannot be authenticated", which creates "the potential to replay, modify, or spoof data". Modbus is the textbook example. It was designed for a closed serial bus where physical access was the only access, and the transports that followed carried that trust model onto routable networks.
Weakness classes, explained as concepts
These are the recurring ways Modbus deployments go wrong, described so you can recognise them in your own systems. None of them needs a software bug; they follow from the design.
Unauthenticated writes
Because the server validates only function, address and format, any host that can deliver a well formed write request to a device gets the same result as the legitimate SCADA server. Write Single Coil, Write Single Register, Write Multiple Coils, Write Multiple Registers, Mask Write Register, Read/Write Multiple Registers and Write File Record all change state. On serial buses a broadcast write reaches every device at once with no reply. The protocol has no session, token or identity to check, so the only controls are which hosts can reach the device at all and what the PLC program does with the value it receives.
Spoofing, injection and replay
The Transaction Identifier is a pairing number, not a nonce, and neither the CRC nor the TCP checksum authenticates anything. A host with a path to the network can, in principle, inject requests, alter values in transit or replay earlier commands, and the server and client have no protocol level way to notice. The same applies to responses: an HMI shows whatever values arrive, which is why NIST talks about spoofed data as well as spoofed commands.
Reconnaissance through function codes
Modbus is self describing enough to map. Exception responses tell a client which function codes a device supports (01) and which address ranges exist (02). Read Device Identification returns vendor, product code and firmware revision, and Report Server ID returns device specific identification on serial lines. That is helpful for inventory and equally helpful to anyone building a list of vulnerable firmware. Treat any unexpected source of these requests as a finding.
Diagnostics and management functions
Function code 08 can reset counters, restart communications or force a device into listen only mode, and user defined or reserved function codes may carry vendor programming and configuration commands that do far more than read and write data. A CISA advisory (AA22-103A, first published 13 April 2022) described tooling aimed at programmable logic controllers that included modules able to "send custom Modbus commands". The lesson for defenders is that "only reads and writes" understates what a Modbus port exposes.
Gateways and the Unit Identifier
A Modbus/TCP to serial gateway turns every device on its RS-485 segment into a TCP reachable target selected by Unit Identifier. Serial devices that were safe behind physical access inherit the exposure of the gateway's IP address. The same applies to protocol converters inside HMIs and edge computers.
Exposure through flat networks and remote access
Most real incidents with Modbus in them start with reachability: a PLC on a flat network shared with office machines, a port forward for a contractor, a cellular modem with a public address, a vendor remote access tool left running. CISA's May 2025 fact sheet on OT mitigations says OT devices on the internet "are quickly found by searching for open ports on public IP ranges" and puts "Remove OT connections to the public internet" first in its list. Once something is reachable, Modbus itself offers no second line.
Connection exhaustion
When a device's non priority connection pool is full, the TCP guide has it close the oldest connection, so a misbehaving client can push legitimate ones off. A priority pool for configured SCADA addresses resists this.
Parser flaws in implementations
Modbus stacks parse length fields, byte counts and quantities that are supposed to agree with each other. Mismatches, such as a Length field that disagrees with the bytes received, are a classic source of crashes in embedded stacks, gateways and the open source libraries that SCADA software, historians and IIoT collectors use. That part of the risk is a software supply chain question, covered below.
What Modbus/TCP Security adds
The Modbus/TCP Security specification leaves the Modbus ADU untouched and wraps it in TLS on port 802. It says TLS was chosen after analysing representative industrial data flows "in the context of" IEC 62443-3-3 and 62443-4-2. Its key normative requirements, by number:
| Area | Requirements |
|---|---|
| TLS version | TLS 1.2 (RFC 5246) "or newer" (R-01, R-32); never negotiate down to TLS 1.1, 1.0 or SSL 3.0, or use SSL 2.0 or 1.0 (R-34, R-35) |
| Mutual authentication | Mandatory. The server sends CertificateRequest, the client must answer with a certificate, and the server must send a fatal alert and close if it does not (R-02, R-06 to R-10, R-44); no resumption after a fatal alert (R-11) |
| Certificates | X.509v3 per RFC 5280 (R-03, R-47), signed by a CA (R-45, should), full chain to the root sent (R-46) |
| Cipher suites | From the IANA registry only (R-12, R-38); at least TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 with RSA keys (R-14); with ECC, at least P-256 and TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (R-61, R-62); never TLS_NULL_WITH_NULL_NULL (R-37) |
| Encryption optional | Where encryption is not required, a NULL bulk encryption suite such as TLS_RSA_WITH_NULL_SHA256 may be used (R-49, R-67); clients should rank NULL suites last (R-66) |
| MAC and PRF | No HMAC-MD5, HMAC-SHA-1 or NULL MAC; HMAC-SHA-256 required, including in the PRF (R-50 to R-55) |
| Small devices | Maximum Fragment Length extension with 512 byte fragments (R-57, R-58); compression NULL (R-59); secure renegotiation per RFC 5746 (R-60) |
| Role based authorisation | Should be provided (R-16). The role travels in the client certificate under the Modbus.org OID 1.3.6.1.4.1.50316.802.1 as a UTF8String, one per certificate (R-21, R-22, R-65); no role means a NULL role (R-23); the algorithm and rules database are vendor defined, user configured, with no unchangeable default roles (R-24 to R-28); a rejected request gets exception 01 (R-31) |
The design is sound, and it has limits worth knowing. Authorisation is optional and vendor specific, so two compliant devices may express "operator may read, engineer may write setpoints" in entirely different ways. NULL encryption suites are permitted, so "uses port 802" does not mean "encrypted". A certificate is only as good as the private key storage on the device and the process that issues and revokes it. And Modbus/TCP Security protects the TCP leg only; the RTU segment behind a gateway is still unauthenticated serial.
Secure configuration and exposure checks, with defender side commands
Classic Modbus has almost nothing to configure in the protocol itself, so securing it is mostly about where it can be reached, from where, and with what. Commands below come from the ss(8) man page, the tcpdump and pcap-filter man pages, the tshark and wireshark-filter man pages with Wireshark's Modbus display filter reference, the OpenSSL s_client manual and Microsoft Learn's Get-NetTCPConnection page, all listed in Sources. Only run them against systems and networks you own or are authorised to test. Capturing on a control network is generally safe because it is passive, but agree it with operations first; never send Modbus requests to production devices as a "test".
1. Find every listener and every client on hosts you run
Start with the Linux and Windows hosts on the control network: SCADA servers, historians, HMIs, gateways and engineering workstations. A listener on 502 on a server you did not expect, such as a simulator left from commissioning, is a common finding.
# Linux: which processes listen on Modbus/TCP or Modbus/TCP Security
ss -tlnp 'sport = :502'
ss -tlnp 'sport = :802'
# Linux: which processes on this host hold client connections to Modbus devices
ss -tnp 'dport = :502'
-t limits output to TCP, -l to listening sockets, -n keeps ports numeric and -p shows the owning process; the filter syntax is from the ss(8) man page.
# Windows: listeners and outbound Modbus connections
Get-NetTCPConnection -LocalPort 502 -State Listen
Get-NetTCPConnection -RemotePort 502
2. List who talks Modbus on the network
Embedded PLCs cannot run ss, so you learn about them from the network. On a mirror or SPAN port you control, capture port 502 traffic for a representative period:
# Capture Modbus/TCP on a monitoring interface you own (no name resolution)
tcpdump -n -i eth1 -w modbus-502.pcap 'tcp port 502'
Then summarise conversations and function codes with tshark:
# Every TCP conversation in the capture: which hosts talk to which devices
tshark -r modbus-502.pcap -q -z conv,tcp
# Client, device, unit ID and function code for each Modbus/TCP message
tshark -r modbus-502.pcap -Y 'mbtcp' -T fields \
-e ip.src -e ip.dst -e mbtcp.unit_id -e modbus.func_code | sort | uniq -c | sort -rn
# Only state changing requests: write coils, registers, file records, mask write
tshark -r modbus-502.pcap -Y 'modbus.func_code in {5,6,15,16,21,22,23}' -T fields \
-e frame.time -e ip.src -e ip.dst -e mbtcp.unit_id -e modbus.func_code
# Exception responses, which often reveal misconfigured or probing clients
tshark -r modbus-502.pcap -Y 'modbus.exception_code' -T fields \
-e ip.src -e ip.dst -e modbus.func_code -e modbus.exception_code
mbtcp.unit_id, mbtcp.trans_id, modbus.func_code and modbus.exception_code are field names in Wireshark's display filter reference; the in set syntax is from the wireshark-filter man page. The output becomes your baseline: the short list of SCADA and HMI addresses that should read, the even shorter list that should write, and the function codes each one uses. Anything else, such as a laptop issuing function 43 or a historian sending writes, is a question for the owner.
3. Check exposure from outside
Ask the people who run your perimeter and your cloud accounts the simplest question: is TCP 502 or 802 reachable from the internet, a partner network or a remote access segment? Check firewall and security group rules for 502 and 802, port forwards on site routers, and cellular modems that carry a public address. CISA's fact sheet recommends that organisations "identify their public-facing assets and remove unintentional exposure". If you need an external view, use an exposure service your organisation already licenses, scoped to your own address ranges.
4. Segment with zones and conduits
The IEC 62443 series, published in the US as ANSI/ISA-62443, organises IACS security around grouping assets into security zones with common requirements and controlling the communication paths, or conduits, between them. ISA's overview lists Part 3-2, "Security risk assessment for system design" (ANSI/ISA-62443-3-2-2020), and Part 3-3, "System security requirements and security levels", as the system level parts. NIST SP 800-82 Rev. 3 applies the same idea: group components into "levels, tiers, or zones", restrict connections between adjacent ones, and use encryption for "connections or conduits" that must cross non OT segments such as the corporate network or the internet.
Applied to Modbus:
- Put field devices that speak Modbus in a cell or area zone with the PLCs and HMIs that need them, and nothing else.
- Make the conduit into that zone explicit: only the SCADA and historian addresses from your baseline may open TCP 502 to the devices, and the rule is written per device or per subnet, not "any to any on 502".
- Keep the enterprise network out entirely. NIST and CISA both describe a demilitarised zone between IT and OT; historians or data diodes in that DMZ publish values outward so office users never touch 502.
- Where a firewall or gateway can inspect Modbus, NIST notes that "industrial OT protocols may be restricted using inbound and outbound traffic rules" between OT and IT, and that for serial links devices "may be configured to limit commands to and from specific tags". A read only conduit, with writes allowed only from the engineering station, removes most of the unauthenticated write risk.
- Turn on the device's own IP access control list or priority connection pool where it exists, as a second layer behind the network rule.
5. Control remote access
CISA's guidance is direct: if remote access is essential, move OT assets off the public internet onto a private connection and use a VPN with "phishing-resistant multifactor authentication", configured with least privilege for the specific asset and role, and disable dormant accounts. Vendor support connections should land in a controlled jump host in the DMZ, never directly on the Modbus network, and should be enabled only for the duration of the job.
6. Prefer port 802 where devices support it, and verify it
When both ends support Modbus/TCP Security, configure them for it and close 502 on those devices if the vendor allows. Verify the server's TLS behaviour from a host you own with the client certificate issued for that host:
# Confirm TLS 1.2 or newer, the negotiated suite and the server's certificate chain
openssl s_client -connect plc-07.ot.example:802 -tls1_2 -brief \
-cert client.crt -key client.key -CAfile ot-root-ca.pem
# Repeat without a client certificate: a compliant server must refuse the handshake
openssl s_client -connect plc-07.ot.example:802 -tls1_2 -brief -CAfile ot-root-ca.pem
Check that the negotiated suite has real encryption (not a NULL suite) unless you made a deliberate integrity only choice, that the chain verifies against your OT CA, and that the second command fails. Then confirm the device's roles to rights rules: which role may write, which may only read, and what a certificate with no role gets. Run your own OT certificate authority, issue one certificate per client host, and plan for renewal and revocation before you deploy.
7. Log and monitor
Record the baseline from step 2, alert on new Modbus talkers, new function codes and writes from unexpected sources, and keep firewall logs for the conduit rules. NIST notes that OT specific firewalls often include parsers for protocols such as DNP3, CIP and Modbus, which is what makes per function code rules possible. Keep the PLC program's own range checks on setpoints, because the protocol will deliver any well formed value.
8. Keep the software that speaks Modbus patched
Modbus runs inside software you own: HMI and SCADA servers, historians, gateways running embedded Linux, IIoT collectors built on open source Modbus libraries, and container images at the edge. Inventory those components and their versions like any other dependency. Our post on the Civil Infrastructure Platform and industrial Linux security covers the long lived Linux base many gateways and HMIs ship on, and our analysis of vulnerabilities in SCADA and industrial control software covers the patterns that recur in that software. For utilities, energy sector software security and NERC CIP covers the compliance side.
Where NIST SP 800-82 fits
NIST SP 800-82 Rev. 3, "Guide to Operational Technology (OT) Security", was published in September 2023 and supersedes Rev. 2 (3 June 2015). It covers OT topologies, threats, countermeasures and an OT overlay of the SP 800-53 Rev. 5 controls (Appendix F). NIST's page notes an initial public draft of Revision 4, with comments due 30 November 2026.
When to use Modbus versus DNP3 and OPC UA
| Protocol | Model | Best fit | Security model | Operational cost |
|---|---|---|---|---|
| Modbus RTU / ASCII | Single master polling on serial | Simple field devices, meters, drives on RS-485 | None; physical access only | Very low; every device supports it |
| Modbus/TCP | Client and server, stateless polling, port 502 | Plant floor I/O and PLC data on Ethernet | None in protocol; optional IP allowlist; relies entirely on segmentation | Low; easy to integrate, hard to secure |
| Modbus/TCP Security | Same, inside mutual TLS on port 802 | New installations where both ends support it | Mutual X.509 authentication, TLS, optional role authorisation | Needs an OT PKI and device support; limited installed base |
| DNP3 (IEEE 1815) | Master and outstation with event reporting, time stamps and unsolicited responses | Utility SCADA over WAN, radio and serial: electricity, water, oil and gas | Secure Authentication defined in IEEE 1815 | Moderate; richer semantics, more configuration |
| OPC UA (IEC 62541) | Client and server with an information model, plus PubSub | Plant to enterprise integration, MES, modelled data with types | Secure channel with application certificates, Sign or SignAndEncrypt modes, user authentication | Higher; certificate management and larger stacks |
Choose Modbus when the device only speaks Modbus, the data is a handful of registers, and the network around it can be locked down. Choose Modbus/TCP Security for new Modbus links where both sides support it and you can run certificates properly. Choose DNP3 for utility telemetry over wide area links where event buffering, time stamps and report by exception matter. Choose OPC UA when data needs to leave the cell with structure and security attached, for example to an MES or cloud platform. Many plants run all three: Modbus at the field level, OPC UA or DNP3 above it, translated at a gateway that becomes the security boundary. For the OPC UA security sections specifically, see what the MQTT and OPC UA specs say about security, and for publish and subscribe telemetry see our MQTT 5 deep dive.
Common mistakes
- Treating the CRC as security. It catches line noise. Anyone who can send a frame can compute a valid CRC.
- Assuming read only because the HMI only reads. The protocol lets any client write. Unless the network or device blocks writes, every host that can reach 502 can change coils and registers.
- Forgetting the gateway. A Modbus/TCP gateway exposes every serial device behind it by Unit Identifier.
- Port forwarding 502 for a contractor, or leaving a cellular modem with a public address on the control network.
- Writing firewall rules as "any to PLC subnet on 502" instead of named sources per device and separate rules for writes.
- Equating port 802 with encryption. The security specification permits NULL encryption suites; check what is negotiated.
- Auto enrolling or sharing client certificates, so every HMI holds the same identity and role, which defeats role based authorisation.
- No range checks in the PLC program. The protocol accepts any well formed value; the application must reject unsafe setpoints.
FAQ
What port does Modbus use?
Modbus/TCP uses TCP port 502, registered with IANA as mbap. Modbus/TCP Security, the TLS version, uses port 802, registered as mbap-s. Serial Modbus RTU and ASCII do not use ports; they run on RS-485 or RS-232 lines with device addresses 1 to 247.
Is Modbus encrypted?
Classic Modbus is not. RTU, ASCII and Modbus/TCP on 502 send every value and command in the clear. Modbus/TCP Security on port 802 wraps the same messages in TLS 1.2 or newer, but it permits NULL encryption cipher suites for integrity only use, so check the negotiated suite.
Does Modbus have authentication?
Not in the classic protocol. A server cannot distinguish one client from another; some TCP devices offer an optional source IP allowlist. Modbus/TCP Security adds mandatory mutual certificate authentication and optional role based authorisation.
What is the difference between Modbus RTU and Modbus TCP?
Both carry the same PDU. RTU runs on serial lines with a one byte device address, binary data and a 16 bit CRC, framed by silent intervals. Modbus/TCP runs over TCP port 502 with a 7 byte MBAP header (transaction ID, protocol ID, length, unit ID) and no CRC, relying on TCP and Ethernet checks.
What are coils and registers in Modbus?
Coils are single bits a client can read and write, usually digital outputs. Discrete inputs are read only bits. Holding registers are read and write 16 bit words such as setpoints, and input registers are read only 16 bit words such as measurements.
Is Modbus safe to expose to the internet?
No. Classic Modbus has no authentication, so exposure means anyone who finds the port can read and write device data. CISA lists removing OT connections from the public internet as the first mitigation. Use private links and a VPN with phishing resistant MFA for remote access.
Modbus vs DNP3 vs OPC UA: which should I use?
Modbus for simple device data on a well segmented network, DNP3 for utility SCADA over wide area links with event reporting and Secure Authentication, and OPC UA for structured, certificate secured data moving between the plant and enterprise systems.
What is the Modbus Unit ID?
A one byte field in the Modbus/TCP header that a gateway uses to route a request to a serial device. When a client talks directly to a TCP device, the TCP guide recommends 0xFF.
Fix it without waiting for upstream
Modbus problems that are not architecture usually live in software you build or deploy: the Modbus/TCP library inside an IIoT collector or historian connector, the gateway or edge container image that bridges serial devices to 502, or the TLS library that a Modbus/TCP Security client links against. Safeguard's software composition analysis, generally available, inventories those components with their full transitive dependencies, alongside SBOM generation in SPDX and CycloneDX and container image scanning; findings are enriched with EPSS and CISA KEV data and ranked with reachability analysis, all generally available. Safeguard does not inspect, filter or block Modbus traffic and does not patch PLC firmware. What it does is tell you which Modbus and TLS library versions you ship in your own code and images, and help you replace the vulnerable ones quickly.
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
These demos show dependency, SBOM and remediation workflows, not Modbus traffic monitoring or PLC changes. You can download Safeguard and follow the CLI docs to try them on your own projects.
This demo sets up the Safeguard runner on your own machine, approves it with its device code and then scans from the terminal. Pointed at the container image for an edge gateway or a data collector that polls Modbus devices, the same scan lists the Modbus and TLS libraries inside with their versions and any known vulnerabilities, without the image leaving your machine.
Click through it at your own pace, or open it full screen.
This demo is a real CLI session: install, open the interactive terminal, ask it to fix the lodash CVE in a repository, and watch it read the finding and advisory, ask before each command, move lodash to 4.17.21, run npm install and npm test with approval, and print a summary without pushing anything. The same approve each step flow applies when the package to bump is a Modbus client library pinned in a historian connector or an IIoT service.
Click through it at your own pace, or open it full screen.
This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. Once connected, you can ask in plain language which of your projects or images include a particular Modbus library version, and get the answer from your own scan data rather than from memory.
Click through it at your own pace, or open it full screen.
Quick check
A Modbus/TCP device answers every request with a valid CRC and a matching transaction ID. Does that prove the request came from your SCADA server?
No. Modbus/TCP has no CRC at all, and the serial CRC and the TCP checksum only detect accidental corruption. The transaction ID just pairs replies with requests. Classic Modbus has no client identity, so only network controls, or mutual TLS with Modbus/TCP Security on port 802, can tell you who sent a request.
Your new PLCs support Modbus/TCP Security on port 802. Are their sessions necessarily encrypted?
Not necessarily. The specification requires TLS 1.2 or newer and mutual certificate authentication, but it permits authentication only cipher suites with NULL bulk encryption, such as TLS_RSA_WITH_NULL_SHA256, where encryption is not required. Check the negotiated suite, and check what the roles to rights rules allow, since authorisation is optional and vendor defined.
Sources
- Modbus Organization: Modbus specifications page
- Modbus Organization: Modbus Application Protocol Specification V1.1b3, 26 April 2012 (PDF)
- Modbus Organization: Modbus Messaging on TCP/IP Implementation Guide V1.0b, 24 October 2006 (PDF)
- Modbus Organization: Modbus over Serial Line Specification and Implementation Guide V1.02, 20 December 2006 (PDF)
- Modbus Organization: Modbus/TCP Security Protocol Specification, MB-TCP-Security-v36, 30 July 2021 (PDF)
- IANA: Service Name and Transport Protocol Port Number Registry
- NIST SP 800-82 Rev. 3: Guide to Operational Technology (OT) Security, September 2023
- NIST SP 800-82 Rev. 3 full text (PDF)
- CISA: Primary Mitigations to Reduce Cyber Threats to Operational Technology, 6 May 2025
- CISA: Advisory AA22-103A, APT Cyber Tools Targeting ICS/SCADA Devices
- ISA: ISA/IEC 62443 Series of Standards
- man7.org: ss(8)
- tcpdump: tcpdump(1) man page
- tcpdump: pcap-filter(7) man page
- Wireshark: tshark man page
- Wireshark: wireshark-filter man page
- Wireshark: Display Filter Reference, Modbus/TCP (mbtcp)
- Wireshark: Display Filter Reference, Modbus (modbus)
- OpenSSL: openssl-s_client manual
- Microsoft Learn: Get-NetTCPConnection
Last reviewed: 23 October 2026. Device support for Modbus/TCP Security and vendor authorisation rules vary by product and firmware; check your vendor's documentation, and check NIST's page for the status of SP 800-82 Rev. 4.