Safeguard
Supply Chain Security•

Modbus Explained: RTU, Modbus/TCP and the Modbus Security Protocol

Modbus is a request and reply protocol for PLC data over serial lines or TCP port 502. How RTU and TCP work, why it lacks auth, and how to secure it.

Safeguard Security Team
44 min read

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 as mbap-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:

VariantTransportDefining document
Modbus RTUAsynchronous serial: TIA/EIA-485 (two wire most common), TIA/EIA-232, fibre, radioModbus over Serial Line Specification and Implementation Guide V1.02
Modbus ASCIISame serial media, hexadecimal charactersSame serial line guide
Modbus/TCPTCP over IP, port 502Modbus Messaging on TCP/IP Implementation Guide V1.0b
Modbus/TCP SecurityTLS over TCP, port 802Modbus/TCP Security Protocol Specification
Modbus PlusA high speed token passing networkListed 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:

FieldSizeMeaning
Function code1 byteWhat the server should do. Valid codes are 1 to 255; 128 to 255 are reserved for exception responses and 0 is not valid
Data0 to 252 bytesFunction 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:

TransportADU layoutMaximum size
Serial (RTU or ASCII)Server address (1 byte) + PDU + CRC or LRC256 bytes in RTU: 1 + 253 + 2
TCPMBAP header (7 bytes) + PDU260 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

TableObject typeAccessTypical use
Discrete inputsSingle bitRead onlyLimit switches, alarm contacts, status bits from I/O
CoilsSingle bitRead and writeDigital outputs, run and stop commands, internal flags
Input registers16 bit wordRead onlyAnalogue measurements, counters
Holding registers16 bit wordRead and writeSetpoints, 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)NameAccessLimits from the specification
01 (0x01)Read CoilsRead1 to 2000 coils
02 (0x02)Read Discrete InputsRead1 to 2000 inputs
03 (0x03)Read Holding RegistersRead1 to 125 registers
04 (0x04)Read Input RegistersRead1 to 125 registers
05 (0x05)Write Single CoilWriteValue 0xFF00 for ON or 0x0000 for OFF; anything else is illegal
06 (0x06)Write Single RegisterWriteOne 16 bit value
08 (0x08)DiagnosticsDiagnosticSerial line only; two byte sub-function codes
15 (0x0F)Write Multiple CoilsWrite1 to 1968 (0x07B0) coils
16 (0x10)Write Multiple RegistersWrite1 to 123 registers
21 (0x15)Write File RecordWriteFile record access
22 (0x16)Mask Write RegisterWriteAND mask and OR mask applied to one register
23 (0x17)Read/Write Multiple RegistersRead and writeOne transaction does both
43 (0x2B)Encapsulated Interface TransportOtherMEI 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

CodeNameMeaning in short
01ILLEGAL FUNCTIONThe function is not supported, or not allowed in the server's current state
02ILLEGAL DATA ADDRESSThe start address plus quantity runs outside the server's tables
03ILLEGAL DATA VALUEThe request is malformed, for example an implied length is wrong
04SERVER DEVICE FAILUREAn unrecoverable error while executing
05ACKNOWLEDGEAccepted, but a long operation is in progress; poll later
06SERVER DEVICE BUSYBusy with a long running command; retry later
08MEMORY PARITY ERRORUsed with file record functions when the extended file area fails a consistency check
0AGATEWAY PATH UNAVAILABLEA gateway could not allocate a path to the target
0BGATEWAY TARGET DEVICE FAILED TO RESPONDA 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:

AddressUse
0Broadcast. All devices must accept broadcast writes and none replies
1 to 247Individual device addresses, unique on the bus
248 to 255Reserved

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:

FieldLengthSet by clientSet by serverMeaning
Transaction Identifier2 bytesInitialisesCopies from requestPairs a response with its request when several are outstanding
Protocol Identifier2 bytesInitialises to 0Copies from request0 means Modbus
Length2 bytesInitialisesInitialises for its responseCount of the bytes that follow, including Unit Identifier and PDU
Unit Identifier1 byteInitialisesCopies from requestRoutes 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 namePortTransportDescription in the registry
mbap502TCP and UDPModbus Application Protocol
mbap-s802TCP and UDPModbus 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

YearMilestoneWhat changed
1979Modbus appears as a serial protocolMaster and slave polling over serial links; the specification calls it the de facto serial standard since then
1996Port 502 registered with IANAModbus/TCP gets a system port, per the security specification's history
2006Serial Line guide V1.02 (20 December) and TCP/IP Implementation Guide V1.0b (24 October)Current editions of the transport documents
2012Application Protocol V1.1b3 (26 April)Current edition of the core protocol: function codes, data model, exceptions, "client" and "server" wording
2021Modbus/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

PropertyClassic Modbus (RTU, ASCII, TCP on 502)Modbus/TCP Security on 802
ConfidentialityNone. Every value and command is readable on the wireTLS encryption when a cipher suite with encryption is chosen; NULL encryption suites are allowed where only integrity is required
IntegrityError detection only: CRC or LRC on serial, TCP checksum and Ethernet CRC on TCPTLS record MAC; HMAC-MD5 and HMAC-SHA-1 are prohibited, HMAC-SHA-256 is required
Client authenticationNone. A server cannot tell one client from anotherMandatory mutual TLS with X.509v3 certificates
Server authenticationNoneServer certificate, chain sent to the root CA
AuthorisationNone in the protocol; optional source IP allowlist on some TCP devicesOptional but recommended: role from a certificate extension checked against a vendor defined rules database
Replay protectionNoneTLS sequence numbers within a session
AvailabilityTimeouts; connection pool rulesSame, 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:

AreaRequirements
TLS versionTLS 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 authenticationMandatory. 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)
CertificatesX.509v3 per RFC 5280 (R-03, R-47), signed by a CA (R-45, should), full chain to the root sent (R-46)
Cipher suitesFrom 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 optionalWhere 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 PRFNo HMAC-MD5, HMAC-SHA-1 or NULL MAC; HMAC-SHA-256 required, including in the PRF (R-50 to R-55)
Small devicesMaximum Fragment Length extension with 512 byte fragments (R-57, R-58); compression NULL (R-59); secure renegotiation per RFC 5746 (R-60)
Role based authorisationShould 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

ProtocolModelBest fitSecurity modelOperational cost
Modbus RTU / ASCIISingle master polling on serialSimple field devices, meters, drives on RS-485None; physical access onlyVery low; every device supports it
Modbus/TCPClient and server, stateless polling, port 502Plant floor I/O and PLC data on EthernetNone in protocol; optional IP allowlist; relies entirely on segmentationLow; easy to integrate, hard to secure
Modbus/TCP SecuritySame, inside mutual TLS on port 802New installations where both ends support itMutual X.509 authentication, TLS, optional role authorisationNeeds an OT PKI and device support; limited installed base
DNP3 (IEEE 1815)Master and outstation with event reporting, time stamps and unsolicited responsesUtility SCADA over WAN, radio and serial: electricity, water, oil and gasSecure Authentication defined in IEEE 1815Moderate; richer semantics, more configuration
OPC UA (IEC 62541)Client and server with an information model, plus PubSubPlant to enterprise integration, MES, modelled data with typesSecure channel with application certificates, Sign or SignAndEncrypt modes, user authenticationHigher; 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 situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull 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

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.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.