SignalBridge Configuration Guide

Files and commands

MechanismPurpose
YAML (-c / --config)Anonymisation, filters, optional inputs / outputs, optional encryption_key.
CLI (run)Override or supply input/output when not taken from YAML; set metrics bind; TCP loop + hot reload.
signalbridge validate -c /path/to/conduit.yaml   # must parse as YAML the loader accepts
signalbridge run -c /path/to/conduit.yaml        # use YAML + any CLI overrides

validate only checks that the file loads successfully (see 12:66:src/config/config_loader.cc). It does not verify that PCAP paths exist or that remote URLs are reachable. Invalid YAML or parse failures return “Invalid config file” (135:138:apps/signalbridge.cc).

If run cannot load the config file, it prints a warning and continues with in-memory defaults (176:180:apps/signalbridge.cc).


YAML top-level structure

Supported keys (see 53:60:include/signalbridge/config.h and 12:66:src/config/config_loader.cc):

KeyTypeDescription
encryption_keystringIf non-empty, hex-encoded 32-byte key; used for AES-256-GCM on HTTP(S) streaming output.
anonymisationmapIMSI handling and optional mapping file.
filtermapProtocol, procedure, IP rules; encrypted NAS handling.
inputslist of mapsDeclarative inputs (see below).
outputslist of mapsDeclarative outputs (see below).

encryption_key

  • Root-level string, loaded into ConduitConfig::encryption_key (60:61:src/config/config_loader.cc).
  • When the resolved output is an HTTP(S) URL, it is passed into the HTTP stream writer (221:223:apps/signalbridge.cc).
  • Example format (64 hex chars = 32 bytes): see 126:134:test/unit/config_loader_test.cc.

anonymisation

FieldTypeDefault if omitted (see loader / struct)
enabledboolIf the anonymisation map is present: true when enabled is omitted (as<bool>(true)). If the whole section is missing, the struct default is enabled true (30:38:include/signalbridge/config.h, 17:18:src/config/config_loader.cc, 63:64:test/unit/config_loader_test.cc).
mccstring"999" if key missing after section exists (19:19:src/config/config_loader.cc).
mncstring"99".
imsi_map_pathstringOptional path for original → anonymised mapping output when processing completes (35:36:include/signalbridge/config.h).
replacement_byteint (0–255)Only applied when the key is present; used in legacy zero-fill mode when MCC is empty (37:38:include/signalbridge/config.h, 22:23:src/config/config_loader.cc).

The sample file at 7:12:config/conduit.yaml sets enabled: false for local experimentation; production behaviour depends on your policy and whether you omit or include the section.


filter

FieldTypeDefault
protocol_includelist of stringsEmpty → no protocol include restriction (all pass include stage). Values are compared case-insensitively as S1AP / NGAP (26:31:src/pipeline/protocol_filter.cc).
protocol_excludelist of stringsEmpty → nothing excluded by protocol. Exclude is evaluated before include (40:44:src/pipeline/protocol_filter.cc).
procedure_includelist of intsEmpty → all procedure codes allowed through the include stage.
procedure_excludelist of intsPer-procedure in a frame: excluded codes are skipped; if any remaining procedure matches include rules, the frame passes (21:33:src/pipeline/procedure_filter.cc).
ip_allowlist of stringsEmpty with empty deny → IP filter allows all.
ip_denylist of stringsIf either IP matches deny → drop.
drop_encrypted_nasboolIf the filter map is present but key omitted → true (39:39:src/config/config_loader.cc). If the entire filter section is missing → struct default true (27:27:include/signalbridge/config.h, 71:71:test/unit/config_loader_test.cc).

IP allow semantics: when ip_allow is non-empty, both src_ip and dst_ip must appear in the allow set, else the packet fails (25:27:src/pipeline/ip_filter.cc). Deny is checked first (24:24:src/pipeline/ip_filter.cc).

Encrypted NAS: when drop_encrypted_nas is true and the frame has encrypted NAS, the pipeline drops it (36:36:src/pipeline/pipeline.cc—exact condition line referenced).


inputs (list)

Each item:

FieldRole
typeString; loader default "file" (45:45:src/config/config_loader.cc).
pathUsed for type: file.
addressUsed for TCP-style listeners (host:port).

What run actually uses from YAML (when you do not pass -i, -l, or --stdin):

  • Stdin: first entry with type: stdin (109:114:apps/signalbridge.cc).
  • TCP listen: first entry with type: **tcp** or type: **tcp_listen** and a non-empty address (101:106:apps/signalbridge.cc).
  • File: first entry with type: file and non-empty path (93:98:apps/signalbridge.cc).

Precedence when multiple modes could apply: the binary checks stdin → TCP listen → file in that order (303:342:apps/signalbridge.cc).

The header comments mention types like grpc, kafka, etc. (41:45:include/signalbridge/config.h). Those strings may load from YAML, but run does not resolve them into an input source—you would still need a matching CLI input or an implementation that reads them.


outputs (list)

Each item:

FieldRole
typeDefault "file". For streaming, use http, https, tcp, udp as in tests (117:121:test/unit/config_loader_test.cc).
pathFile path for file, or full URL for HTTP in samples (50:52:config/conduit.yaml).
addressAlternative for http / https / tcp / udp (e.g. full https://… URL).

Resolution when -o is omitted (79:90:apps/signalbridge.cc): walk outputs in order and take the first match:

  1. type: file with non-empty path
  2. type: tcp with non-empty address → becomes tcp://…
  3. type: udp with non-empty address → becomes udp://…
  4. type: http or https → URL is address if set, otherwise path

So only one output destination is chosen from the list for a given run. Extra list entries are not multiplexed in the current run implementation.

The final string is classified by URL scheme: http(s):// → HTTP stream; tcp:// → TCP PCAP stream; udp:// → UDP; else treated as PCAP file path (221:287:apps/signalbridge.cc).


CLI options (run)

From 41:48:apps/signalbridge.cc:

OptionEffect
-i / --inputPCAP path; overrides config file input resolution.
-l / --listenTCP listen address; overrides config.
--stdinRead PCAP from stdin; overrides config stdin flag.
-o / --outputDestination string; overrides config output resolution.
-c / --configYAML path.
-m / --metricsPrometheus bind address (default 127.0.0.1:9090 if omitted). Not in YAML.
--loopTCP: accept multiple connections; if -c is set, reload config from disk when the file’s mtime changes between accepts (315:332:apps/signalbridge.cc).

Related files

  • Example / template: config/conduit.yaml (comments show common patterns).
  • Ingest server routes (reference receiver): config/ingest_endpoints.yaml — documents paths like /frames/{uuid} for the Python ingest server, not the C++ parser itself.
# SignalBridge configuration
# Anonymises, filters, and forwards S1AP/NGAP signalling

# 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

# Example: S1AP only
# filter:
#   protocol_include: [S1AP]
#   protocol_exclude: []
#
# Example: exclude NGAP
# filter:
#   protocol_exclude: [NGAP]
#
# Example: mobility procedures only
# filter:
#   procedure_include: [0, 1, 2, 3, 4]  # Handover procedures
#   drop_encrypted_nas: true

inputs:
  - type: file
    path: ""
    # For TCP: type: tcp, address: "0.0.0.0:50051"
    # For gRPC: type: grpc, address: "0.0.0.0:50052"

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"


Quick reference: defaults from an empty YAML document

From unit test expectations (54:73:test/unit/config_loader_test.cc): empty file still loads; anonymisation enabled; no filter lists; drop_encrypted_nas: true.