Detect · RPKI & bogon routing

Routing health, validated in the open.

GeoQ surfaces three routing signals from public BGP: rpki (valid / invalid / unknown), is_bogon, and is_announced. We run our own validator against the published trust anchors and publish the weights — RPKI-invalid adds +20, bogon adds +30.

Fact + limit: an invalid RPKI state is often a benign misconfiguration, not an attack. That's why it's weighted +20, not a verdict.

Three routing signals

FieldValuesWeight
rpkivalid / invalid / unknown+20 if invalid
is_bogonunallocated / reserved space+30
is_announcedcovering prefix visible in BGPcontext only

In your code

const res = await fetch("https://api.geoq.io/v1/check?ip=203.0.113.10", {
  headers: { "x-api-key": process.env.GEOQ_KEY },
});
const { network, risk } = await res.json();

if (network.is_bogon) flagSpoofed();          // +30: should never source traffic
if (network.rpki === "invalid") addReview();  // +20: origin fails validation
// risk.reasons[] lists exactly which routing checks fired.

We run our own validator

RPKI route-origin validation is computed with a self-run Routinator against the published RPKI trust anchors, combined with origins observed in public BGP from the RouteViews and RIPE NCC RIS projects. We don't relay someone else's verdict — we derive it, and we refresh it daily. The weights are published on the risk-score methodology page; the sources and cadence are on the methodology page.

Reading the states

  • rpki: "valid" — a ROA authorises this origin. No weight.
  • rpki: "invalid" — a ROA exists but the origin/prefix contradicts it. +20. Often a misconfig; treat as one input.
  • rpki: "unknown" — no ROA covers the prefix. No weight; common for unsigned space.
  • is_bogon: true — source space that should never route. +30.

FAQ

RPKI & bogon routing — FAQ

What does the rpki field mean?

network.rpki is the route-origin validation state for the IP's covering prefix: "valid" (a ROA authorises this origin AS), "invalid" (a ROA exists but the announcing AS or prefix length contradicts it — a sign of a hijack or misconfiguration), or "unknown" (no ROA covers the prefix). Only "invalid" scores: it adds +20.

Where does the RPKI data come from?

We run our own Routinator validator against the published RPKI trust anchors and combine it with route origins observed in public BGP from RouteViews and RIPE RIS. We don't depend on a third party's validation verdict — we compute it. Refreshed daily. See the methodology and attributions.

What is a bogon and why does it matter?

A bogon is an IP in space that should never appear as a source on the public internet — unallocated ranges and reserved blocks (RFC 1918, RFC 5737, and so on). Legitimate traffic doesn't originate from bogon space, so is_bogon === true is a strong signal of spoofing or a misconfigured network. It adds +30 to the risk score.

What does is_announced tell me?

is_announced is true when a covering prefix for the IP is visible in the global routing table (per public BGP). If an address claims to be a real host but no prefix announces it, that's suspicious. is_announced === false adds no weight on its own — the bogon check already covers the hostile case — but it's surfaced so you have the routing context.

Is RPKI-invalid always malicious?

No. An invalid state often means a benign misconfiguration — a stale ROA, a more-specific announcement, a transit mistake — not an attack. That's why it's weighted +20, not a hard block, and why it's one input among several. Read reasons[] and combine it with the other signals before acting.

How fresh is the routing data?

BGP-derived fields (is_announced, rpki) and the validator output refresh daily; bogon constants change rarely and refresh monthly. We state the cadence rather than claiming real-time routing.

Related

Get a free key — 5,000 lookups/day, no card.

Every signal and the same risk score as every paid plan. Upgrade only when you outgrow it.