How spolinovskiy/industrial-protocols-labs works
Purpose and Entry Points
This repository is a unified Docker-based industrial-control-system (ICS) protocol testbed. It runs one selected protocol lab at a time, exposes a consistent FUXA HMI, and supports bounded packet capture/diagnostics. The primary operator interface is labctl (start, switch, stop); Docker Compose can also start a profile directly through platform/docker-compose.platform.yml. The supported architecture is platform/ plus protocols/; legacy/ preserves superseded per-protocol stacks.
Platform Orchestration
The central Compose definition provisions shared platform services and conditionally enables protocol profiles: platform/docker-compose.platform.yml. A selected profile starts its protocol server alongside the common gateway, HMI, diagnostics, and reset services. labctl is the control-plane boundary for selecting/stopping the active protocol; the optional switcher API/UI invokes that same command path through scripts/lab_switcher_server.py and platform/lab_switcher/index.html.
Protocol Simulation Layer
Each protocol is independently containerized and follows a server/client pattern around a common canonical tag model (digital/analog I/O, timer, counter). Representative implementations are:
• Modbus: protocols/modbus/server/modbus_server.py, protocols/modbus/client/modbus_client.py
• OPC UA: protocols/opcua/server/opcua_server.py, protocols/opcua/client/opcua_client.py
• BACnet: protocols/bacnet/server/bacnet_server.py, protocols/bacnet/client/bacnet_client.py
• MQTT: protocols/mqtt/broker/mosquitto.conf, protocols/mqtt/device-bridge/device_bridge.py
• S7: protocols/s7/plc-sim/s7_server.py, protocols/s7/client/s7_client.py
CIP, DNP3, and IEC-104 additionally include gateway adapters where needed: protocols/cip/gateway/app.py, protocols/dnp3/gateway/app.py, protocols/iec104/gateway/app.py. Protocol services are Python-based Docker workloads; MQTT uses a Mosquitto broker.
HMI, Access, and Routing Boundary
FUXA provides the common HMI, with protocol-specific project blueprints in platform/fuxa/seeds/modbus.project.json, platform/fuxa/seeds/opcua.project.json, and related seed files. Nginx is the external boundary separating guest view-only and admin/diagnostic access, including basic-auth credentials: platform/nginx/nginx.conf, platform/nginx/auth/guest.htpasswd, platform/nginx/auth/admin.htpasswd. The gateway routes HMI and diagnostics while protocol services remain on the internal Docker network.
Diagnostics and Lifecycle Management
The diagnostics container supplies a constrained terminal menu and protocol-aware packet capture scripts: platform/diagnostics/entrypoint.sh, platform/diagnostics/menu.sh, platform/diagnostics/capture/common.sh. Per-protocol captures bind to standard protocol ports and are retention-limited. The reset controller enforces TTL/idle reset policy, stops the active server, cleans captures, and attempts FUXA seed import: platform/reset/reset.sh, platform/reset/policy.yaml, platform/reset/Dockerfile.
Optional Web Frontend
frontend/ is a separate TypeScript/React application rather than the core lab runtime. Its browser entry is frontend/client/src/main.tsx, composed by frontend/client/src/App.tsx; the Labs and protocol-testing screens are frontend/client/src/pages/labs.tsx and frontend/client/src/pages/protocol-test.tsx. Its Node server can proxy or call the switcher backend via frontend/server/index.ts, frontend/server/routes.ts, and frontend/server/lib/lab-client.ts. Authentication integration is Replit-specific: frontend/server/replit_integrations/auth/replitAuth.ts.
External Dependencies and Operational Boundaries
Material runtimes are Docker/Compose, Python protocol simulators, Nginx, FUXA, Mosquitto, and the optional Node/Vite React frontend. The platform has no indicated cloud control plane; external exposure should terminate TLS at Nginx or an upstream reverse proxy. Protocol state, FUXA state, captures, and reset behavior are operationally isolated from the optional frontend and from archived legacy/ deployments.
Main entry points: docker-compose.platform.yml Platform Compose · modbus_server.py Protocol servers · reset.sh Reset controller · entrypoint.sh Diagnostics
Components 18
Control Plane
- Operator
- labctl · Selects, switches, and stops the active lab.
- Switcher API/UI
scripts/lab_switcher_server.py
Shared Platform
- Platform Compose · Starts shared services and the selected protocol profile.
platform/docker-compose.platform.yml - Nginx gateway · Separates guest and admin/diagnostic access from internal services.
platform/nginx/nginx.conf - FUXA HMI
- HMI project seeds · Protocol-specific HMI projects are imported on reset.
platform/fuxa/seeds/modbus.project.json - Diagnostics · Provides bounded, protocol-aware packet capture.
platform/diagnostics/entrypoint.sh - Reset controller · Enforces TTL and idle reset policy.
platform/reset/reset.sh - Internal protocol network · Keeps protocol services behind the gateway.
Protocol Labs
- Canonical tag model · Digital and analog I/O, timer, and counter semantics.
- Protocol servers · Profile-selected Modbus, OPC UA, BACnet, S7, and related servers.
protocols/modbus/server/modbus_server.py - Protocol clients · Exercise representative server implementations.
protocols/modbus/client/modbus_client.py - MQTT lab
protocols/mqtt/broker/mosquitto.conf - Protocol gateway adapters · Used by CIP, DNP3, and IEC-104 where required.
protocols/cip/gateway/app.py
Optional Frontend
- React browser app · Separate from the core lab runtime.
frontend/client/src/main.tsx - Node frontend server · Can proxy or call the lab switcher.
frontend/server/index.ts - Replit auth
frontend/server/replit_integrations/auth/replitAuth.ts
Connections 27
- Operator → labctl: start / switch / stop
- Operator → Switcher API/UI: optional web control
- Switcher API/UI → labctl: invokes command path
- labctl → Platform Compose: selects profile
- Platform Compose → Nginx gateway: starts
- Platform Compose → FUXA HMI: starts
- Platform Compose → Diagnostics: starts
- Platform Compose → Reset controller: starts
- Platform Compose → Protocol servers: starts selected profile
- Platform Compose → MQTT lab: starts MQTT profile
- Nginx gateway → FUXA HMI: routes HMI access
- Nginx gateway → Diagnostics: routes admin access
- FUXA HMI → Internal protocol network: reads/writes tags
- Internal protocol network → Protocol servers: internal connectivity
- Internal protocol network → MQTT lab: internal connectivity
- Protocol servers → Canonical tag model: implements
- Protocol clients → Protocol servers: tests protocol exchange
- MQTT lab → Canonical tag model: bridges device tags
- Protocol gateway adapters → Protocol servers: adapts selected protocols
- Diagnostics → Internal protocol network: captures traffic
- Reset controller → Protocol servers: stops active server
- Reset controller → Diagnostics: cleans captures
- Reset controller → HMI project seeds: imports project
- HMI project seeds → FUXA HMI: seed configuration
- React browser app → Node frontend server: browser requests
- Node frontend server → Switcher API/UI: proxies control calls
- Node frontend server → Replit auth: authenticates users