Which Industrial Protocols Can a W5500 and ESP32-S3 Detect on an OT Network?
Five: Modbus TCP, S7, PROFINET DCP, OPC UA and EtherNet/IP. This ESP32-S3 firmware runs the W5500 in promiscuous mode to read Layer 2 frames.

WIZnet - W5500
SPI Ethernet controller on the Waveshare ESP32-S3-ETH target. platformio.ini sets -DETH_PHY_TYPE=5500 with SCLK 13, MOSI 11, MISO 12, CS 14, INT 10, RST 9 on SPI2_HOST at 20 MHz; sdkconfig.esp32s3eth.
An ESP32 Firmware That Watches Five Industrial Protocols
Francesco Adriani works in Perugia, Italy, and describes himself on GitHub as an OT cybersecurity and automation engineer covering PLC, SCADA and MES systems, industrial protocols, and teaching. His account, opened in October 2022 under the handle il-prof-f-a, holds seventeen public repositories, many of them small Python and Java teaching pieces, two local-only MQTT bridges for Tuya and Kasa devices, and an ESP32 bell manager for schools and workplaces. ESP32-OT-Security-Assessment is a much larger piece of work: roughly 90,000 lines of C and C++ across 176 source files, created on 15 August 2026 and last pushed on 23 August 2026, checked here on 27 August 2026.
The tested W5500 target. Board photo: Waveshare ESP32-S3-ETH product page.
The firmware turns a development board into a passive observer of a plant network. It watches five operational-technology protocols, keeps a rule-based intrusion detection engine, runs authorised vulnerability checks and rate-limited fuzzing jobs, and serves all of it from a web interface on the device. One of the three tested hardware profiles is the Waveshare ESP32-S3-ETH, and the README states its make-up in one line: "This target combines ESP32-S3 Wi-Fi with a W5500 SPI Ethernet controller."
Two Networks on One Board
Operational technology has an awkward requirement for any monitoring device. The tool has to sit on the plant segment to see the traffic, while the person configuring the tool must not have to reach that segment to do so. The W5500 profile answers this with two separate interfaces: Wi-Fi carries the management web interface, and the wired port faces the network under assessment.
Generated technical diagram of the two lanes, drawn from platformio.ini and the network sources.
The capture path is short. EthL2Adapter installs itself as the driver input path with esp_eth_update_input_path(), reads the fourteen-byte Ethernet header off each frame, and hands the source MAC, destination MAC, EtherType and payload to NetworkEngine, which parks them in a ring buffer in external RAM. Every frame is then passed on with esp_netif_receive(), so the device keeps its own IP address and normal networking while the analyser works on the copy.
Why the W5500 Runs in Promiscuous Mode
An Ethernet controller normally throws away frames that are not addressed to it. That default makes a sniffer useless, so the esp32-s3-eth build sets CONFIG_ETH_ENABLE_PROMISCUOUS=y in its sdkconfig defaults and the adapter calls esp_eth_ioctl(eth_, ETH_CMD_S_PROMISCUOUS, &enable) once the input path is hooked. The code comment credits the LILYGO eth2ap example as the source of that call.
Generated technical diagram of the bring-up sequence in src/network/ethernet_manager.cpp.
The chip evidence sits in the build files rather than in prose. platformio.ini gives the esp32-s3-eth environment -DETH_PHY_TYPE=5500 with SCLK on GPIO 13, MOSI on GPIO 11, MISO on GPIO 12, chip select on GPIO 14, interrupt on GPIO 10, reset on GPIO 9, SPI2_HOST and a 20 MHz clock. sdkconfig.esp32s3eth.defaults sets CONFIG_ETH_SPI_ETHERNET_W5500=y, and ethernet_manager.cpp builds the interface with esp_eth_mac_new_w5500() and esp_eth_phy_new_w5500().
The README passage that names the controller and the pins. Screenshot: github.com.
One detail is worth borrowing regardless of the application. Before creating the driver the firmware pulses reset low for 10 ms and high for 50 ms, then sends the four raw bytes 00 39 80 00 over SPI, a read of the W5500 version register at address 0x0039. A W5500 answers 0x04. Anything else makes the firmware log "W5500 probe failed", free the SPI bus and stop, which turns a vague ESP_ERR_INVALID_VERSION into a pin or chip-select fault the installer can act on. The Waveshare board carries a Pulse H1102NL magnetics package next to its RJ45 jack, visible in the vendor product photograph.
Which Protocols the Firmware Watches, and How
The classifier in NetworkEngine reads the EtherType first and the transport port second. PROFINET DCP frames carry EtherType 0x8892 and LLDP frames carry 0x88CC, and both are routed to the PROFINET plugin because PROFINET builds its topology view from neighbour announcements. Everything else is matched on port: TCP 102 for S7, TCP 502 for Modbus TCP, TCP 4840 for OPC UA, and TCP 44818 with UDP 2222 for EtherNet/IP.
Generated technical diagram of the classifier, drawn from infer_proto() and the protocol plugins.
The Layer 2 path is the part that needs the W5500 in promiscuous mode. The project user guide is explicit about what that buys: PROFINET DCP discovery "uses Layer 2 discovery and therefore does not require an IP subnet". A PROFINET device answers DCP Identify before anyone has assigned it an address, so an IP-only scanner cannot see it at all.
Detection rules differ per protocol and are configurable from the IDS page. PROFINET rules cover DCP spoofing, DCP Set commands, topology changes, Hello floods and XID replay. S7 rules cover plaintext sessions, STOP CPU commands, SZL reconnaissance, write storms and brute-force patterns, with thresholds expressed as writes per 60 seconds and reads per 30 seconds.
Three Tested Targets, and What Each One Gives Up
The README publishes a hardware table that is unusually candid about limits. The W5500 board is not the best performer in the repository, and the author says so.
| Board | Ethernet front end | Management transport | Stated limitation |
|---|---|---|---|
| LILYGO T-POE Pro | LAN8720 RMII PHY, PoE | HTTP only | HTTPS causes instability, so management traffic is unencrypted |
| Waveshare ESP32-S3-ETH | W5500 over SPI | HTTPS, per-device self-signed certificate | "Network compatibility is limited"; no 24 V input, no screw-terminal GPIO |
| Waveshare ESP32-P4-ETH | IP101GRI RMII PHY | HTTPS, per-device self-signed certificate | No Wi-Fi, so management shares the OT subnet |
Read as a whole, the hardware table describes a trade rather than a ranking. The ESP32-P4 target gives the "best current functional result" but has no radio, which collapses the management and OT networks onto one wire. The W5500 target is rated "Functional on a limited set of tested networks", yet it is the only one of the three that keeps the operator on Wi-Fi while the wired port stays on the plant segment.
What the Operator Sees
First boot is deliberately awkward, which is the right instinct for a tool that reads industrial traffic. A release image contains no administrator password. The device raises a WPA2 setup access point named from its own MAC, prints a one-time setup token and the HTTPS certificate fingerprint on the serial console, requires an administrator password of at least 16 bytes, and stores only a PBKDF2-HMAC-SHA-256 hash. Five wrong tokens in a minute lock setup for 60 seconds, and the session expires after 15 minutes.
Beyond provisioning, the interface covers discovery, IDS policy and allowlists, a CVE byte-signature editor, scanner jobs with cron scheduling, fuzzing jobs, diagnostics, a serial monitor and reporting. Findings leave the device through six reporters: file, serial, MQTT, webhook, email and GPIO. Eighteen markdown pages of illustrated user guide, index included, document those screens against the running v0.1.0 interface.
What Keeps the Tool Off the Process
Generated technical diagram of the guard rails, drawn from the README, sandbox_defaults.h and the fuzzing guide.
Every fuzzing job carries a Safe Mode flag that blocks write-oriented actions, and the profiles that can stop a PLC refuse to run until it is switched off. Underneath, each protocol plugin runs against its own sandbox policy: 180 packets and 128 KB per minute, a 3000 ms timeout per operation, priority 6, an 8 KB task stack, and exactly one permitted TCP port. PROFINET gets no TCP at all, only raw Ethernet transmit for DCP Identify.
Where This Fits, and What It Is Not
The repository is honest about its stage. The README warns above the hardware table, "This project is still under test", v0.1.0 is a prerelease published on 18 August 2026, and the fourteen open issues were all filed by the author himself on 17 August as a hardening backlog covering watchdog registration, crash diagnostics, HTTPS lifecycle and packet-pipeline load. External validation is absent: one star, no forks, no watchers, and one download each for the three flash bundles.
Licensing matters here more than usual. LICENSE.md is the PolyForm Noncommercial License 1.0.0 with the notice "Copyright 2026 Francesco Adriani", and the README states plainly that this is "source-available research software under the PolyForm Noncommercial License 1.0.0, not OSI-approved open-source software". Anyone planning a commercial deployment needs a separate arrangement with the author.
For a WIZnet reader the value is the pattern rather than the product. A W5500 is normally chosen for its hardwired TCP/IP sockets, and here it is doing the opposite job: the sockets are bypassed, the MAC filter is switched off, and the chip becomes a Layer 2 capture front end for an ESP32-S3 that still needs its Wi-Fi for something else. Continuous integration builds all three targets on every push, and each release ships a factory image, an app image, a flash bundle and a manifest per board with a sorted SHA256SUMS.txt, so the pattern is reproducible by anyone with the same board.
Related WIZnet Maker Projects
ESP32-S3-ETH OPC UA Gateway runs on exactly the same Waveshare board, which makes it the closest comparison on this site. That project writes Rust and serves OPC UA as a device on the network; this one reads OPC UA as an observer of the network, so the two occupy opposite ends of the same port.
Setting Up W5500 Ethernet on ESP32-S3 Using ESP-IDF is the plain version of the same ESP-IDF bring-up, without the promiscuous mode or the version-register probe. Readers who want to reproduce the capture path should start there, then add the promiscuous ioctl and the input-path hook.
Arduino Packet Sniffer using w5100 ethernet shield shows the same instinct on older hardware, capturing frames with a W5100 shield. The difference is scope: that sketch dumps packets, while this firmware classifies them by industrial protocol and applies rules to what it finds.
POSEIDON, Cardputer Pentesting Firmware with W5500 is the other security-tooling project on this site built around a W5500. POSEIDON targets general IT and radio assessment from a handheld, whereas this firmware stays wired and stays inside five industrial protocols.
FAQ
Q. Does the W5500 need special hardware support for promiscuous mode? No. The ESP-IDF W5500 driver exposes it through esp_eth_ioctl(handle, ETH_CMD_S_PROMISCUOUS, &enable), and all three build environments define CONFIG_ETH_ENABLE_PROMISCUOUS at compile time.
Q. Can the device still use its own IP address while sniffing? Yes. The input-path hook forwards every captured frame to the network interface with esp_netif_receive(), so DHCP, the HTTPS server and normal traffic keep working alongside capture.
Q. Why does PROFINET need Layer 2 capture when the other four do not? PROFINET DCP rides directly on Ethernet with EtherType 0x8892 and is used before a device has an IP address. The user guide states that DCP discovery "does not require an IP subnet", so an IP-only scan misses it.
Q. Is this firmware safe to point at a production plant? The project says no. The README limits it to laboratories or systems you own or are explicitly authorised to assess, and warns against connecting active assessment functions to a production OT network without a reviewed test plan.
Q. Can I use this commercially? Not under the published terms. LICENSE.md is PolyForm Noncommercial 1.0.0, and the README describes the project as source-available research software rather than OSI-approved open source, so commercial use requires a separate agreement with the author.
-
ESP32 OT Security Assessment repository
Firmware source, hardware table and the sentence naming the W5500 SPI Ethernet controller. Created 2026-08-15, last pushed 2026-08-23.
-
Web interface user guide
Eighteen illustrated pages covering login, dashboard, discovery, IDS policy, CVE signatures, scanner, fuzzing, reporting and diagnostics on the v0.1.0 interface.
-
platformio.ini build environments
The esp32-s3-eth environment with ETH_PHY_TYPE=5500, the SPI pin map, the 20 MHz clock and CONFIG_ETH_ENABLE_PROMISCUOUS=1.
-
ethernet_manager.cpp W5500 bring-up
Reset pulse, VERSIONR probe expecting 0x04, esp_eth_mac_new_w5500() and esp_eth_phy_new_w5500(), and the ETH_CMD_S_PROMISCUOUS ioctl.
-
eth_l2_adapter.cpp Layer 2 capture path
Hooks esp_eth_update_input_path(), parses the Ethernet header and forwards each frame with esp_netif_receive() so the IP stack keeps working.
-
v0.1.0 prerelease
Published 2026-08-18 as a prerelease. Factory, app, flash-bundle and manifest assets for all three targets, plus a sorted SHA256SUMS.txt generated by the release workflow.
-
PolyForm Noncommercial License 1.0.0
Source-available, noncommercial only. Required notice reads Copyright 2026 Francesco Adriani.
-
Waveshare ESP32-S3-ETH wiki
Official hardware documentation for the tested W5500 board, and the source of the board photograph used in this post.
-
WIZnet W5500
Datasheet and register map for the controller, including the VERSIONR register at 0x0039 used by the boot probe.
