Operator Guide: Running SignalBridge at the Edge

What you’re operating

SignalBridge sits in the operator environment: it ingests S1AP/NGAP signalling (from file, TCP PCAP stream, or stdin), filters what you allow, anonymises subscriber identities when configured, and exports to PCAP, TCP, UDP, or HTTP(S) NDJSON batches—typically toward analysis or a platform like Signal Cloud. Your job is to wire capture → policy → egress safely and observably.

Before you start

  • Data governance: Confirm what may leave the core (raw vs anonymised, retention, lawful basis).
  • Network: Inbound path to your capture source (file mount, mirror port, or TCP listener); outbound to ingest (HTTPS URL, TCP/UDP peer). Firewall and TLS termination as required.
  • Secrets: If you use encrypted HTTP output, the config includes a hex encryption key (32-byte). Treat it like any key material—vault, rotation policy, no plain-text tickets.

Deploy the binary

Operators usually take a released signalbridge from the build pipeline. If you must build on-site, use the same dependency list as in the README (libpcap, yaml-cpp, curl, OpenSSL, zlib). The public bundle vendors parsers under third_party/s1see/ so a standard clone builds without a separate S1-SEE checkout.

Configuration (config/conduit.yaml)

The sample file shows the knobs you actually turn:

# When set (hex-encoded 32-byte key), HTTP output is encrypted with AES-256-GCM.
encryption_key: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"

anonymisation:
  enabled: false
  mcc: "999"
  mnc: "99"
  # imsi_map_path: ""  # Optional: write "original -> anonymised" mapping when done
  replacement_byte: 0  # Legacy: used when mcc empty (zero-fill mode)

filter:
  # Include only these protocols (empty = all). Values: S1AP, NGAP
  protocol_include: []
  # Exclude these protocols
  protocol_exclude: []
  # Include only these procedure codes (empty = all)
  procedure_include: []
  # Exclude these procedure codes
  procedure_exclude: []
  # IP allow list (empty = allow all)
  ip_allow: []
  # IP deny list
  ip_deny: []
  # Drop encrypted NAS (cannot anonymise without keys)
  drop_encrypted_nas: false

Operator checklist:

AreaWhat to decide
AnonymisationOn/off, synthetic MCC/MNC, optional imsi_map_path for audit/debug (protect that file).
FiltersS1AP-only vs NGAP vs both; procedure allow/deny lists to cut volume; IP allow/deny to scope eNB/gNB or probes.
Encrypted NASdrop_encrypted_nas: true when you cannot decrypt—avoids leaking opaque payloads you can’t anonymise.
HTTP(S) securityReal encryption_key in prod; HTTPS URL to trusted ingest; path must match what the receiver expects (e.g. /frames/{uuid}).
Inputsfile with path, or tcp listener address, or stdin (often used under a supervisor). Comments in YAML mention grpc as a type—confirm against your release notes if present.
Outputshttp/https URL, or file, or tcp/udp peer per your downstream.

Example output stanza from the same file:

outputs:
  - type: "http"
    path: "http://127.0.0.1:9876/frames/550e8400-e29b-41d4-a716-446655440000"
    # Set to file path, or use type: https with address for HTTP streaming
    # For HTTP streaming: type: https, address: "https://ingest.example.com/frames/{uuid}"
    # For TCP output: type: tcp, address: "host:port"
    # For UDP output: type: udp, address: "host:port"

Ingest path conventions are also summarized in config/ingest_endpoints.yaml.

Validate, then run

Dry-run config parsing (no traffic processing):

./signalbridge validate -c /path/to/conduit.yaml

Live run:

./signalbridge run -c /path/to/conduit.yaml

CLI override for a one-off file test:

./signalbridge run -i capture.pcap -o anonymised.pcap

Prometheus metrics

Metrics bind is CLI, not YAML: -m / --metrics <addr>, default 127.0.0.1:9090. For scraping from another host, set an interface/IP your monitoring can reach and open the port in policy. Endpoint is /metrics (see apps/signalbridge.cc help string and metrics server startup).

Local smoke test (optional)

To verify HTTP streaming before pointing at production, a reference Python ingest exists under server/ (signalvault_ingest.py); use only on controlled lab networks. Details: README.md § HTTP streaming.

Run as a service (typical pattern)

  • Run signalbridge run -c ... under systemd (or equivalent) with Restart=on-failure, explicit user, read-only config path, and locked-down permissions on YAML and any imsi_map_path output.
  • Redirect logs to your aggregator; rely on metrics for throughput and error trending.
  • Align capture restart (TCP reconnect, file rotation) with your input mode—use --loop for TCP if your deployment expects repeated connections and config reload (per root README).