Telecom
A reachable NRF shouldn't be able to impersonate any network function in the core.
Inside the 5G service-based architecture, one function authenticates another with mutual TLS at the handshake. But the identity it proves is a certificate signed by an operator-private CA, verifiable only to that operator, and the authorization step above it is optional by spec. Whisper closes the gap with one primitive: the network function's address is its identity, bound to the nfInstanceId the NF already carries in its certificate SAN, DNSSEC/DANE-anchored, and publicly verifiable across operators. This page is the telecom front door to the Whisper docs. The full technical library (DNSSEC, DANE, RDAP, the control-plane API) sits one click down the sidebar, shared verbatim with whisper.online/docs.
The problem: reachability ≈ authorization
The 5G core is a flat, all-IP mesh of HTTP/2 + JSON microservices: AMF, SMF, UPF, PCF, UDM, AUSF, each registering a NFProfile with the NRF and discovering peers through it (3GPP TS 29.510). Mutual TLS on the service-based interface is mandatory; OAuth2 token-based authorization between an NF and the NRF is not. TS 33.501 §13.3.1.3 makes it optional, and GSMA's 5G Interconnect Security group flagged this as a structural weakness. The consequence is blunt: reachability becomes authorization. Any NF that can reach the NRF can pull any other NF's profile and impersonate it, or deregister a live NF for a clean, stealthy denial of service. The mesh inherits the entire web-and-API threat model: broken object-level authorization (OWASP BOLA), over-scoped tokens, exposed SBIs, all one microservice hop from the subscriber plane.
And the identity that does exist doesn't travel. Every NF certificate chains to a private, per-operator root, so no roaming partner, IPX carrier, regulator, or other operator can independently confirm "this really is operator X's AMF." Trust is asserted, never provable. The modern stack is weakest at the N32 roaming interface between two SEPPs, mediated by semi-trusted IPX hubs, and at the legacy SS7 / Diameter / GTP interconnect, which trusts by default and lives on indefinitely for backward compatibility. That unverifiable identity is exactly the seam an attacker works.
The bill is not theoretical. The CFCA puts global telecom fraud at $38.95B in 2023, roughly 2.5% of revenue. $6.23B a year of that is International Revenue Share Fraud, a category that rides entirely on interconnect trust. The roaming fix built to harden this, the SEPP, is barely deployed: industry analysis reports ~70% of operators lack the cloud-native capability a SEPP needs. Independent pentesting has found the legacy planes wide open: one vendor assessment reported every one of 28 tested operator networks vulnerable to GTP-based impersonation, fraud, or denial of service (Positive Technologies, ~2020, vendor pentest, dated). Detection will always trail a credential or a signaling peer that is genuinely trusted. The strictly-stronger move is to change what the counterparty trusts.
The cure: the address is the NF
Shipped & live. Deriving an NF /128 from the network function's own SBA key + the nfInstanceId it already carries is in production today. Provision one with the control-plane call below and verify it from the DNSSEC root, across operators, with tools already on your machine.
Whisper gives each network function (AMF, SMF, UPF, PCF, a SEPP, an O-RAN component) a routable IPv6 /128 out of 2a04:2a01::/32 (announced by AS219419), derived deterministically from the NF's public key: its SubjectPublicKeyInfo, the public half of the SBA certificate the NF already presents on mutual TLS, with the nfInstanceId as the domain separator. That UUID is not incidental. TS 33.310 §6.1.3c mandates the SBA certificate carry a subjectAltName URI-ID of urn:uuid:<nfInstanceId>, so the key ↔ instance-id ↔ endpoint binding already exists, just sealed inside the operator's private CA. The private key never leaves the NF; only its public SPKI is an input. The result is DNSSEC-anchored, DANE-EE 3 1 1 pinned to that same certificate, and RDAP-registered: re-derivable and verifiable by anyone with dig.
nfInstanceId is already a URI-ID in the NF's certificate SAN (TS 33.310), an identity trapped in a private, per-operator CA. Whisper binds the same UUID, from the NF's own key, to a routable, publicly verifiable /128 that drops straight into NFProfile.ipv6Addresses, and gives it the cross-operator off-switch the private root never had.Because the derivation is tenant-bound, the same NF key under two operators yields two unrelated /128s: an outsider cannot link a function across networks, which sits naturally alongside the topology hiding a SEPP already performs. Because the domain separator is the nfInstanceId, the instance-id alone yields nothing: it flows through every discovery response and is not a secret, yet you cannot go nfInstanceId → /128 without the key, there is no enumerable directory, and RDAP and reverse-DNS return the registry object, never the NF's operational whereabouts.
What becomes true the moment an NF holds one:
- "Reachable ⇒ impersonable" becomes false. You cannot present an NF identity whose key you don't hold; every forgery is a DNSSEC/DANE inconsistency any counterparty catches, even one that reached the NRF.
- The private-CA blind spot closes at the boundary. A roaming partner, an IPX peer, or a regulator resolves the
/128, pulls the DANE pin, and confirms "this address is NF X", without cross-certifying your operator CA and without any NRF access. - The DNS-spoofing / rogue-NRF gap closes. 3GPP mandates mTLS and OAuth2 but not DNSSEC/DANE on the SBA name layer; spoof the DNS under NF discovery and you redirect to a rogue NRF or a forged token-issuer URL. A DNSSEC-signed, DANE-pinned name→address→expected-cert binding is exactly what mTLS alone does not cover.
- One
revokekills a compromised NF worldwide at DNS-TTL speed: a cross-operator kill-switch that a per-operator CRL or OCSP responder can't provide, because those don't cross the operator boundary.
Additive, never a replacement. Whisper complements the controls 3GPP already mandates: mutual TLS on the SBI, OAuth2 authorization with the NRF as authorization server, the operator-private CA and CMPv2 enrolment, SEPP N32-c/N32-f and PRINS topology hiding, O-RAN WG11's mTLS + CMPv2. It is the publicly verifiable, DNSSEC/DANE-anchored layer on top, anchoring the trust boundaries where independent verification actually matters: NF discovery and the DNS beneath it, the N32 roaming border, NEF/CAMARA exposure, and management, all at the IP, DNS, and transport layer. You can even DANE-pin your existing SBA endpoint's certificate to DNSSEC and cut single-CA mis-issuance risk out-of-band. Whisper never reaches into the mTLS session on the SBI itself, the 5G-AKA / SUCI subscriber plane, or the O-RAN fronthaul; it keeps the nfInstanceId's existing cert binding and adds the two things a private root lacks: public cross-operator verifiability and DNS-TTL revocation, with no NRF OpenAPI change and no re-key.
Nothing is issued in the dark: every mint and every revoke lands in a public, append-only Merkle transparency log, Ed25519-signed and anchored to Bitcoin via OpenTimestamps, that you, a peer operator, and a regulator can audit. (Honest status: tamper-evident and Bitcoin-anchored today; independent third-party witnessing is the next step, and the log already speaks the witness protocol.)
Provision an NF identity
Provisioning is one control-plane call over the public API: POST https://graph.whisper.security/api/query with your X-API-Key. Hand it the NF's base64 SPKI and its nfInstanceId; it returns the deterministic /128 and a WireGuard config for source-bound egress:
CALL whisper.agents({op:'connect', args:{
tier:'wireguard',
identity_public_key:'<base64 SPKI of the NF's SBA key>',
device_id:'3f2504e0-4f89-11d3-9a0c-0305e82c3301' // the nfInstanceId (urn:uuid in the cert SAN)
}}) YIELD op, ok, status, result, error
RETURN op, ok, status, result, error
Send it with your key. The heredoc keeps the single-quoted Cypher literals intact, so this runs as-is:
curl -s https://graph.whisper.security/api/query \
-H "X-API-Key: whisper_live_xxx" \
-H 'content-type: application/json' \
--data @- <<'JSON'
{"query":"CALL whisper.agents({op:'connect', args:{tier:'wireguard', identity_public_key:'<base64 SPKI>', device_id:'3f2504e0-4f89-11d3-9a0c-0305e82c3301'}}) YIELD op, ok, status, result, error RETURN op, ok, status, result, error"}
JSON
# response
{ "op": "connect", "ok": true, "status": "created",
"result": {
"address": "2a04:2a01:5e0::a3f",
"fqdn": "nf-3f2504e0.amf.<tenant>.agents.whisper.online",
"wireguard": { /* peer, keys, allowed-ips */ }
} }
The call is idempotent and liberal in what it accepts, strict in what it returns: re-running with the same key and nfInstanceId returns the same /128; a different instance-id for a key already registered on your tenant is a clear 409, not a silent overwrite; a non-string device_id is a 400 that tells you exactly what was wrong, not an opaque 500. That's the same Postel discipline the NRF itself shows when it answers bad JSON with a ProblemDetails object instead of a stack trace. The device_id argument is generic: pass the nfInstanceId, the OAuth2 client_id (which is the nfInstanceId), or a SEPP's identity, whatever native identifier the function carries.
The returned /128 drops straight into the NF's NFProfile.ipv6Addresses at the NRF: no OpenAPI change, no re-registration, no new key. A dedicated --nf-instance-id CLI flag is on the roadmap; today, NF provisioning is the control-plane call above (which is live). The shipped CLI verbs are whisper verify --trustless, whisper create --register, whisper kill --revoke, whisper policy, and whisper logs. See CLI & one-command.
Verify it yourself, no account needed
Every NF identity is checkable with no key and no login, from the internet's own records. That's the whole point at a trust boundary, where the party checking is a different operator. The whisper CLI does the full walk in one call:
whisper verify --trustless nf-3f2504e0.amf.<tenant>.agents.whisper.online
✓ DNSSEC chain valid to the IANA root
✓ DANE-EE (TLSA 3 1 1) leaf matches the NF's SBA certificate
✓ RDAP: registered under AS219419 · 2a04:2a01::/32
identity: VERIFIED, and our own API was never trusted
Or reach for the raw records directly: the same answer, from stock tools:
# the public verify endpoint: evidence chain in JSON
curl -s https://whisper.online/verify-identity/2a04:2a01:5e0::a3f | jq
{ "is_whisper_agent": true, "dane_ok": true, "jws_ok": true, "evidence": { /* … */ } }
# the address is the NF: forward-confirmed reverse DNS names it
dig -x 2a04:2a01:5e0::a3f +short
nf-3f2504e0.amf.<tenant>.agents.whisper.online.
# the registry object: who holds the address, and under which allocation
curl -s https://whisper.online/ip/2a04:2a01:5e0::a3f | jq
None of these calls Whisper as an authority. --trustless re-derives the proof against the public DNSSEC root, exactly as any resolver could. A home operator can verify a visited network's peer NF or SEPP against a public anchor instead of trusting the SEPP's assertion or an IPX hub in between. See Verify an agent for the full keyless check and DANE & TLSA for the pin, byte for byte.
Revoke worldwide and govern in between
A compromised NF, a decommissioned function, a rotated key, a de-peered interconnect partner: one call tears down the /128, its PTR, and its DANE pin everywhere at DNS-TTL speed:
CALL whisper.agents({op:'revoke', args:{agent:'2a04:2a01:5e0::a3f'}})
# after the TTL: dig -x returns nothing, verify returns false
whisper kill --revoke 2a04:2a01:5e0::a3f
This is a cross-operator kill-switch that propagates at cache-TTL: no bilateral PKI exchange, no per-operator CRL you hope every peer fetched. Honest boundary: this revokes the identity, its route, and its egress authorization faster than CRL/OCSP; it does not revoke the operator's SBA TLS certificate. That stays your operator CA's job. Sell it as an additional, faster kill-switch, not a replacement for CMPv2 revocation. Revocation is the endpoint; the same control plane also governs what a live NF may reach in between. Egress is source-bound to the NF's /128, so policy is enforced by name and by address:
# default-deny: this NF may reach ONLY its NRF and its peer SEPP
whisper policy set --default deny --allow nrf.5gc.example-mno.net,sepp.5gc.example-mno.net
# per-NF firewall (allow/deny by host, cidr or port) and a traffic budget + kill-switch
CALL whisper.agents({op:'firewall', args:{agent:'2a04:2a01:5e0::a3f', deny:['0.0.0.0/0'], allow:['nrf.5gc.example-mno.net:443']}})
CALL whisper.agents({op:'budget', args:{agent:'2a04:2a01:5e0::a3f', max_mb_per_day:500}})
Per-NF /128 plus egress governance is a network-layer micro-perimeter against lateral movement: the isolate-workloads posture NSA/CISA's ESF 5G Cloud guidance asks for, and the Identity and Visibility pillars of the CISA Zero-Trust Maturity Model, expressed as one call to provision and one to revoke. Because each record and telemetry stream can be bound to, and signed under, the NF's forge-proof /128, a peer operator, an interconnect partner, or your own settlement can trust the numbers came from the real function, not a spoofed feed. See Egress governance for the full policy surface.
Attribution: name whoever already reached you
Identity stops the next forgery; the graph names the operator behind the sessions already in your logs: attribution that survives IP rotation because it fingerprints the operator and the tooling, not the ephemeral egress IP behind an IPX hub, a cloud VM, or a residential proxy. Run it as read-only Cypher over the same public API with your key (there is no CLI subcommand for this; it is the graph API directly):
curl -s https://graph.whisper.security/api/query \
-H "X-API-Key: whisper_live_xxx" \
-H 'content-type: application/json' \
-d '{"query":"CALL whisper.identify(\"185.x.x.x\")"}'
# operator fingerprinted across IPX / cloud / residential; egress swarm collapsed by JA4
The read-only verbs (identify, origins, walk, variants, history) each return a reproducible, replayable JSON evidence chain your core-NF SOC, your PSIRT, and a regulator can replay. Cryptographic attribution is exactly what the NIS2 incident-reporting clock needs (Art. 23: early warning within 24h, notification within 72h, final report within a month), so you can name who and where instead of shipping a meaningless last IP. More in Graph & cognition.
Lookups: see who's enumerating your core
An identity you can prove is also an identity you can watch. Because every NF's name resolves through Whisper's own authoritative DNS and RDAP, the owner can ask who looked: a reconnaissance tripwire the private, out-of-band NRF registry never gave you. op:lookups returns who resolved or RDAP-queried an NF's identity, so you see a roaming partner or a would-be peer enumerating your core before an N32 message lands, not in the post-mortem afterward:
CALL whisper.agents({op:'lookups', args:{agent:'2a04:2a01:5e0::a3f', window:'24h'}})
# the same reverse-observability view, keyless, per address
curl -s https://whisper.online/ip/2a04:2a01:5e0::a3f/lookups | jq
# → who resolved this NF's PTR/AAAA/TLSA and hit its RDAP object, and when
Paired with op:logs (the NF's own outbound activity) and /ip/<addr>/transparency (its ordered lifecycle in the Merkle log), you have both halves of the picture: what an NF reaches out to, and who is reaching in to look at it.
What ships today, and what's on the roadmap
We label these honestly so you can plan against them.
| Shipped & live | On the roadmap |
|---|---|
NF /128 from the NF's SBA key + nfInstanceId: DNSSEC + DANE-EE + RDAP |
A dedicated --nf-instance-id CLI flag (provision via the control-plane call today) |
Control-plane provision, verify, revoke; egress governance (policy/firewall/budget); op:lookups; the Merkle transparency log; the attribution graph over the public API |
STIX 2.1 over TAXII export |
| The Splunk, Microsoft Sentinel and OpenCTI connectors (signed, replayable JSON → CEF / ECS fields) | telecom-ISAC machine-readable JSON export |
The integration guides below describe proposed integrations at the SBI, roaming, and IP boundary, designed to complement the stack you already run, not endorsed by 3GPP, GSMA, or any vendor, and never named against a specific operator as a breach victim. Two honest boundaries worth stating plainly: this is not a GSMA NESAS / SCAS certification control and not an EU CRA conformity route. It is a defense-in-depth differentiator and a PSIRT attribution tool. It does nothing for FCC rip-and-replace, which is a supply-chain-provenance problem of a different class. Nation-state router and edge implants live below the identity layer; we cite those campaigns only as class-level proof that cross-operator attribution and fast eviction remain unsolved, never as something an identity layer alone would have stopped.
The five Telecom guides
The telecom story, in depth: each page is self-contained and copy-paste runnable.
/128 from the nfInstanceId a network function already carries in its cert SAN. Deterministic, tenant-bound, DNSSEC + DANE-EE pinned (the NF-identity spine).
NF-impersonation cure →Why a reachable NRF and OAuth2-optional-by-spec let any NF impersonate any other, and how a forge-proof address ends it (the reachability≈authorization root cause, cured at the identity layer).
NRF · SEPP · CAMARA · O-RAN →Proposed integrations at the SBI/IP boundary: the /128 into NFProfile.ipv6Addresses, DANE-pinned peer identity at N32/SEPP, CAMARA / Open Gateway, O-RAN ZTA Identity. Complements, never replaces.
NESAS · NIS2 · 5G Toolbox →Map identity and attribution evidence to NIS2 Art. 21/23, the EU 5G Toolbox (TM02), GSMA NESAS/FS.36, and NSA/CISA ESF 5G Cloud, as a network primitive, not a binder.
Verify · attribute · govern →Runnable recipes: DANE-pin a peer SEPP at the N32 border, default-deny a compromised NF's egress, back-trace a rotating IPX egress on the graph.
The full technical library
Telecom rides on the same address-is-identity platform as every other agent on the network, so the whole shared library applies here unchanged, and every page has a clean Markdown twin at the same path + .md. Start with these; the rest is in the sidebar.
dig, curl, and openssl.
DANE & TLSA →The 3 1 1 pin that makes an address forge-proof, byte for byte, no CA in the path.
Control plane →The full whisper.agents API (provision, connect, policy, logs, revoke) over the public endpoint.