NetLogo and Node-RED

The Goal: Reverse-Engineering NetLogo’s HubNet Protocol for Bidirectional Communication

NetLogo is a powerful tool for agent-based modeling and simulation, widely used in education and research. However, its native capabilities for external communication are surprisingly limited. While it supports one-way HTTP requests, creating a bidirectional bridge between a NetLogo simulation and external systems (like IoT devices or web services) often requires workarounds.

This post details a reverse-engineering approach to the HubNet protocol, NetLogo’s internal TCP-based mechanism for connecting multiple instances. By implementing a Man-in-the-Middle (MitM) proxy using Node-RED, we can intercept, inspect, and manipulate the binary traffic between a client and server. This allows us to build a custom interface that sends commands back into the simulation, effectively turning NetLogo into a reactive system.

Background & Disclaimer

This post describes the Node-RED flow that implements a MitM proxy for the HubNet protocol defined by NetLogo.

This is an by an AI rewrite of Human generated content. The content is accurate and suitable for AI and Human consumption.

The Problem: Limited External Connectivity

The primary motivation for this project was the need to communicate bidirectionally with an external world from within a NetLogo simulation.

Native Limitations

The HubNet Alternative

HubNet was originally designed for classroom scenarios where a teacher’s server broadcasts simulation states to multiple student clients. It is a connection-based protocol using TCP with binary payloads. Crucially, it supports:

  1. Handshakes: Initial client identification.
  2. Bidirectional Messaging: Clients send inputs (button presses, slider changes) to the server; the server broadcasts state updates to all connected clients.
  3. Broadcasting: The server can push data to all connected clients simultaneously.

Since HubNet is built-in and unencrypted, it presents a viable target for reverse engineering, provided we can decode its binary structure.

The Solution: A Man-in-the-Middle Proxy

Attempting to re-implement Java object serialization in another language (like Node.js) is non-trivial and error-prone. Instead of parsing the protocol specification (which doesn’t exist publicly), we adopted a pragmatic approach: traffic interception.

Architecture Overview

We set up a proxy server using Node-RED to sit between the NetLogo client and the actual NetLogo HubNet server.

  1. The Client: Connects to the Node-RED proxy on port 9174 (instead of the default 9173).
  2. The Proxy (Node-RED):
    • Accepts the connection from the client.
    • Transparently forwards traffic to the real NetLogo server on port 9173.
    • Inspects and modifies packets in transit.
  3. The Server: The actual NetLogo simulation running on port 9173, unaware that it is communicating with a proxy.

This setup allows us to observe the raw binary blobs exchanged during handshakes, identification, and message passing without needing to understand the underlying Java serialization format immediately.

Port Configuration

The client believes it is talking directly to the simulation, while the proxy handles the logic of translating external events into HubNet-compatible packets.

Reverse-Engineering the Protocol Flow

By monitoring the traffic through the Node-RED proxy, we identified the following message structure:

  1. Preamble & Version: Initial protocol identification.
  2. Handshake: Establishing the connection and version compatibility.
  3. Identification: The client sends its name; the server registers it in an internal table based on the TCP connection.
  4. Message Exchange:
    • Client -> Server: Button presses, slider adjustments.
    • Server -> Client: Broadcast updates (e.g., “Turtle moved to X,Y”).

Simulating Client Actions

To control the simulation externally, we discovered that button press events are the most reliable mechanism for sending commands.

Implementation: Processing Broadcast Messages

In our warehouse simulation scenario, the NetLogo server broadcasts a message when a robot prepares to move (e.g., “Bot 123 wants to move to B”). The Node-RED proxy must intercept this, process it, and send an acknowledgment back.

The Data Flow

  1. Inbound: NetLogo sends a broadcast containing multiple grouped messages in a single binary chunk.
  2. Chunkification: The Node-RED flow splits this single chunk into individual logical messages.
  3. Parsing: Extract the Bot ID and target position from the message payload.
  4. Response Generation: Construct a “button press” packet that simulates an approval or state update (e.g., “Bot 123 has arrived at B”).
  5. Outbound: Send the response back to the NetLogo server over the TCP connection.

Node-RED Logic Pattern

While the specific binary encoding is opaque, the logical flow in Node-RED follows this pattern:

// Pseudo-code representation of the Node-RED logic flow
function processHubNetMessage(msg) {
    // 1. Chunkify: Split the incoming binary blob into individual messages
    const messages = splitBinaryBlob(msg.payload);
    
    let responses = [];
    
    messages.forEach(packet => {
        // 2. Parse: Extract command type, Bot ID, and Position
        const { commandType, botId, targetPos } = parsePacket(packet);
        
        if (commandType === 'BOT_MOVE_REQUEST') {
            // 3. Generate Response: Create a button press packet
            // We encode the approval logic into the button name string
            const responsePayload = generateButtonPress({
                buttonName: `APPROVE_MOVE_${botId}_${targetPos}`,
                // Reuse the structure of the initial handshake/button press packet
            });
            
            responses.push(responsePayload);
        }
    });
    
    // 4. Send: Transmit individual responses back to the server
    // Note: We send individually rather than grouping for simplicity in this prototype
    return responses;
}

Note: In a production environment, you would likely group these responses into a single packet to reduce network overhead, but individual transmission is sufficient for proof-of-concept validation.

Conclusion

By leveraging the unencrypted nature of the HubNet protocol and employing a Man-in-the-Middle proxy, we successfully bridged the gap between NetLogo’s internal simulation world and external systems. This approach bypasses the need for complex Java serialization implementations or unmaintained extensions.

Key Takeaways

This “hack” solution provides a functional pathway for integrating NetLogo simulations with real-world data streams, IoT devices, or web APIs, opening new possibilities for dynamic, reactive modeling.

Last updated: 2026-03-17T16:48:55.470Z

Comments powered by giscus

The author is available for Node-RED development and consultancy.