VectorCore DRA is a Go-based Diameter Routing Agent for carrier networks. It accepts Diameter peers over TCP, TCP+TLS, and SCTP, exposes an embedded React UI plus a REST API, and routes requests without maintaining a session database.
- Accepts inbound and outbound Diameter peers.
- Handles the standard peer lifecycle:
CER/CEA,DWR/DWA,DPR/DPA. - Routes requests in this order:
Destination-HostAVP in the message- Explicit
route_rules imsi_routes- Implicit realm routing
- Supports load balancing with
round_robinandleast_conn. - Uses
Session-Idhashing for deterministic peer selection inside a candidate set. - Exposes Prometheus metrics at
/metrics. - Serves an embedded UI at
/ui/and OpenAPI docs at/api/v1/docs.
imsi_routes are present in the config and API but are currently a work in progress and should not be considered functional.
The DRA is stateless. It forwards requests, tracks hop-by-hop IDs for answers in flight, and does not keep a persistent Diameter session table.
| Transport | Status | Notes |
|---|---|---|
tcp |
supported | listeners and peers |
tcp+tls |
supported | listeners and outbound peers share the top-level tls config |
sctp |
supported | listeners and peers |
sctp+tls |
not implemented | legacy configs currently fall back to plain SCTP with a warning |
- Go 1.25+
- Node.js 18+ for UI builds
- Linux for SCTP support
Load the SCTP kernel module if you use SCTP:
modprobe sctpmake all # UI + Go binary
make ui # build web/dist
make build # build bin/dra
make test # run Go tests
make cleanFor UI development:
make dev-uiThe Vite dev server runs on :5173 and proxies /api and /metrics to :8080.
./bin/dra -c config.yaml
./bin/dra -c config.yaml -d
./bin/dra -vFlags:
| Flag | Meaning |
|---|---|
-c |
config path; falls back to DRA_CONFIG, then config.yaml |
-d |
force debug logging and mirror logs to stderr |
-v |
print version and exit |
Shutdown on SIGINT/SIGTERM is graceful: listeners stop accepting, peers are stopped, and the process exits after a short drain period.
- UI:
http://<host>:8080/ui/ - Swagger UI:
http://<host>:8080/api/v1/docs - OpenAPI JSON:
http://<host>:8080/api/v1/openapi.json - Health:
http://<host>:8080/health - Prometheus:
http://<host>:8080/metrics
The main API groups are:
Peers: configured peers and live peer statusLB Groups: load-balancing groupsRoutes: explicit routing rulesIMSI Routes: IMSI-prefix routingOAM: status, reload, log level, recent messages, JSON metrics snapshot
See docs/API.md for endpoint details and curl examples.
Prometheus metrics use the dra_ prefix. Important series include:
dra_messages_totaldra_peer_statedra_peer_connects_totaldra_peer_disconnects_totaldra_route_hits_totaldra_route_misses_totaldra_imsi_route_hits_totaldra_forwarded_totaldra_answer_latency_secondsdra_watchdog_timeout_totaldra_reconnect_attempts_totaldra_inflight_requestsdra_rejected_connections_total
The annotated example config lives at config/dra.yaml.
Top-level sections:
dralistenerstlsapiloggingwatchdogreconnectlb_groupspeersimsi_routesroute_rules
dra.qos controls DSCP/TOS handling for TCP, TCP+TLS, and SCTP transports:
dra:
qos:
mode: clear # clear | set
dscp: 0 # 0..63, used only with mode: setQoS support is a work in progress. The currently usable modes are clear and set.
clear: send best-effort traffic class.set: force the configured DSCP value.preserve: experimental. It does not currently preserve received SCTP DSCP because Linux SCTP one-to-one stream sockets do not expose received packet DSCP to the application.
These sections are applied live when the config file changes on disk or when POST /api/v1/oam/reload is called:
lb_groupspeersimsi_routesroute_rules
The REST API also writes those sections back to the config file atomically.
lb_groups define per-group load-balancing policy.
lb_groups:
- name: hss_group
lb_policy: round_robin
- name: pcrf_group
lb_policy: least_connSupported policies:
round_robinleast_conn
Weighted balancing is not implemented.
Example:
peers:
- name: hss01
fqdn: hss01.epc.mnc435.mcc311.3gppnetwork.org
address: 10.0.0.10
port: 3868
transport: tcp
mode: active
realm: epc.mnc435.mcc311.3gppnetwork.org
lb_group: hss_group
enabled: trueNotes:
mode: activemeans the DRA dials the peer.mode: passivemeans the peer connects inbound to the DRA.- Inbound connections are allowed only from configured peer IPs.
addressmay be an IP or hostname; active peers are DNS-resolved before connect attempts.transportfor API-managed peers istcp,tcp+tls, orsctp.
Note: IMSI routing is a work in progress and is not currently functional.
IMSI routes are evaluated only after no explicit route rule matches. Longest prefix wins, then lower priority wins among equal-length prefixes.
imsi_routes:
- prefix: "311435"
dest_realm: "epc.mnc435.mcc311.3gppnetwork.org"
lb_group: hss_group
priority: 10IMSI extraction checks:
Subscription-IdwithSubscription-Id-Type = END_USER_IMSIUser-Name, stripping any@realmsuffix
dest_realm is used for routing decisions and implicit-realm fallback. The message AVP is not rewritten in place.
Route rules are matched on:
dest_realmapp_id
They do not match on dest_host. If action: route:
dest_hostmeans “send to this specific peer FQDN”lb_groupmeans “select a peer from this group”- if neither is set, the router falls back to implicit realm routing
Example:
route_rules:
- priority: 20
dest_realm: epc.mnc435.mcc311.3gppnetwork.org
app_id: 16777238
lb_group: pcrf_group
action: route
- priority: 50
dest_realm: blocked.example.com
action: reject- Message
Destination-Host route_rulesimsi_routes- Implicit realm routing against open peers
cmd/dra/main.go
config/dra.yaml
docs/API.md
internal/api/
internal/config/
internal/diameter/
internal/logging/
internal/metrics/
internal/peermgr/
internal/router/
internal/transport/
web/