Repository navigation
Security release, from the 2026-10-21 audit. Upgrade both boxes together,
and copy the new key file to both (see Upgrading below): a 1.5.0 output
box refuses unsigned messages from a 1.4.x input box.
Security
- Messages through the diode are signed. Every Modbus update, log batch,
screen frame and folder manifest now carries an HMAC-SHA256 made with a
shared key,dyode.key, besideconfig.yamlon both boxes, plus a random
sender id and counter so a recorded message cannot be replayed. A host on
the IT network can no longer feed false values to the Modbus mirror, write
into the OT logs, or announce files for the output box to accept. Files are
matched to a signed manifest by SHA-256, so they are covered too. DYODE
stops at start-up if the key is missing;auth.required: falseruns
unauthenticated, with a warning. Wire format:DYA1inside the DYO1
framing. - Diode-port firewall (D-02).
install.shnow installs nftables rules on
receiving boxes: a datagram for a diode port is dropped unless it arrives on
the diode NIC from the input box (and never over IPv6). Nothing else on the
box is touched.--no-firewallskips it (works unattended too);
--firewall-onlyreapplies it. It also setsrp_filter=1on the diode NIC.
The Modbus, log and screen listeners additionally bind to the diode NIC. - Received files are never placed through a symlink (D-01). A link inside
out/(from a read-write share, for example) could take a file, written as
root, anywhere on the box. Every folder is now opened without following
links. A refusal logsfile_rejectedwithreason: unsafe_destination. - The input box sends exactly the file it checked (D-04). A drop-folder
user could swap a file for a link after the scan and have any file the
input box can read sent across. Files are now opened once, without
following links, and hashed and sent from that open file. - Reassembly is bounded (D-05). Oversized pieces, messages announcing
more pieces than a module ever sends, partial messages older than 10 s and
anything over 32 MB held per listener are dropped, so a flood cannot
exhaust memory. - The Modbus mirror is read-only (D-03). Client writes get exception 01
(Illegal Function) and are logged. Reads outside the configured ranges get
exception 02 (Illegal Data Address);unmapped: zerokeeps the old answer
of 0. - Every bundled package is checksummed again. The bundle workflow merged
each build job's stale copies of the other targets into the bundle, so
packaging/debs/*/*/carried old package versions and aSHA256SUMSthat
listed only some of the.debfiles (22 of 82 for Ubuntu 24.04 amd64 in
1.4.3).install.shchecked only the listed ones. Each job now uploads only
its own target, andinstall.shrefuses a bundle with any unlisted
package. - Smaller items (D-10 to D-12). NFS exports of a folder inside a larger
filesystem usesubtree_check. The screen viewer listens on the IT-side
address by default instead of every address, and allows at most
max_streams(8) viewers. The wizard asks for syslogallow_fromand warns
when it is empty.
Changed
- pymodbus is pinned to 3.12 (
>=3.12,<3.13): the read-only mirror uses its
exception-returning datastore API. Moving to 3.13 is planned separately. - New config keys:
auth.key_file,auth.required, modbusunmapped,
screenmax_streams.http_bindnow defaults to the IT-side address.
Upgrading
- On one box:
python3 dyode_setup.py --new-key(in the DYODE folder). - Copy
DYODE_v1_full/dyode.keyto the other box, same folder,chmod 600. - Run
sudo ./install.shon both boxes and restart both services. - On the output box:
sudo nft list table inet dyodeshows the rules.
A SCADA client that wrote to the mirror (a heartbeat register, say) now
gets exceptions; those writes never reached the PLC.