Skip to content

Federation

Germán Luis Aracil Boned edited this page Apr 6, 2026 · 1 revision

Federation

TLS Federation connects multiple Portal instances into a distributed network. Remote paths are transparent — /node/peer1/health routes to the health path on peer1 as if it were local.

Topology

                    ┌──────────────────┐
                    │   Hub Node       │
                    │   (cloud/DMZ)    │
                    │   portal-hub     │
                    └───┬──────────┬───┘
                        │          │
            TLS/9090    │          │    TLS/9090
                        │          │
              ┌─────────▼┐    ┌───▼──────────┐
              │  Office   │    │   Factory    │
              │  portal-a │    │   portal-b   │
              └───────────┘    └──────────────┘

Wire Protocol — PORTAL02

Binary format, network byte order:

Offset  Size    Field
0       4       Magic: "PRT\0"
4       2       Version: 0x0002
6       1       Message type:
                  0x01 = MSG_REQUEST
                  0x02 = MSG_RESPONSE
                  0x03 = MSG_EVENT
                  0x04 = MSG_AUTH_CHALLENGE
                  0x05 = MSG_AUTH_RESPONSE
                  0x06 = MSG_PING
                  0x07 = MSG_PONG
7       4       Body length (uint32 big-endian)
11      N       Body (serialized message)

Key Authentication

SHA-256 challenge-response handshake:

  Client                              Server
    │                                    │
    │──────── TCP/TLS connect ──────────▶│
    │                                    │
    │◀──── AUTH_CHALLENGE (32B nonce) ───│
    │                                    │
    │── AUTH_RESPONSE ──────────────────▶│
    │   SHA-256(nonce + federation_key)  │
    │                                    │
    │◀──── MSG_RESPONSE (200 OK) ───────│
    │                                    │
    │◀────────── bidirectional ─────────▶│

Configuration

[mod_node]
name = portal-office
federation_key = my_shared_secret_key
listen_port = 9090
tls = true
tls_cert = /etc/portal/cert.pem
tls_key = /etc/portal/key.pem

[peer:hub]
host = hub.example.com
port = 9090
auto_connect = true

[peer:factory]
host = factory.local
port = 9090
auto_connect = true
hub = hub          # route through hub (NAT traversal)

Hub Routing

For peers behind NAT, designate a hub node:

portal-a ──▶ hub ──▶ portal-b

Messages to portal-b from portal-a are routed through hub if direct connection fails. The hub acts as a relay — it receives the message and forwards it to the destination.

Worker Pools

Each peer connection gets a dedicated worker thread pool:

  • Incoming messages are queued and processed by workers
  • Configurable pool size per peer
  • Prevents one slow peer from blocking others

Auto-Reconnect

On disconnection:

  1. Wait 1 second
  2. Attempt reconnect
  3. If failed, double the wait (exponential backoff)
  4. Max wait: 60 seconds
  5. On success, reset timer

Transparent Routing

# From portal-office CLI:
portal:/> cd /node/factory
portal:/node/factory> ls /iot/devices    # lists IoT devices on factory
portal:/node/factory> iot on plug-001    # turns on plug on factory

# From HTTP API:
curl http://portal-office:8080/api/node/factory/health

Diagnostics

portal:/> node peers
NAME         HOST              PORT  STATUS     LATENCY
hub          hub.example.com   9090  connected  12ms
factory      factory.local     9090  connected  3ms

portal:/> node status
Peers: 2 connected, 0 disconnected
Messages sent: 14,203
Messages received: 13,891

Clone this wiki locally