Daily route-origin security snapshots from public BGP RIB dumps and validated RPKI VRPs.
RouteSentinel builds an auditable dataset for RPKI coverage, RPKI-invalid route announcements, and conservative origin-anomaly signals. It is designed as a batch pipeline: no internet scanning, no per-prefix API fan-out, and no dependency on a live stream for the v1 dataset.
The default dataset is deduplicated to unique (prefix, origin ASN) route-origin pairs
and records which collectors saw each pair. This keeps daily releases focused on route-origin
state instead of peer-level duplicate visibility rows.
Last successful snapshot: 2026-05-23 Release assets: 2026-05-23 Release updated: 2026-05-23 14:35 UTC
| Metric | Value |
|---|---|
| Collectors | rrc00, rrc01, rrc10 |
| Unique prefixes | 1,392,533 |
| Unique prefix-origin pairs | 1,403,098 |
| RPKI valid | 909,911 |
| RPKI invalid | 3,601 |
| Unique invalid prefixes | 3,585 |
| RPKI not-found | 489,586 |
| RPKI coverage ratio | 64.85% |
This block is updated after the GitHub Release is successfully published.
rpki-summary.json: aggregate counts and RPKI coverage ratio.route-origin-status.csv: normalized status for every unique prefix-origin pair.rpki-invalids.csv: prefix-origin pairs covered by ROAs but originated by an unexpected ASN.rpki-covered-prefixes.csv: prefixes with at least one covering ROA.top-invalid-asns.csv: ASNs ranked by invalid prefix-origin pair count.daily-diff.json: machine-readable diff against the previous release, when available.changelog.md: human-readable daily diff and snapshot summary.suspected-events.jsonl: conservative event signals such asrpki-invalid,multi-origin, andmulti-origin-invalid.- Daily GitHub Release assets tagged by date.
flowchart LR
rib["RIPE RIS / RouteViews MRT RIB dumps"] --> parse["bgpdump parse"]
csv["Normalized announcements CSV"] --> validate["local RPKI validation"]
vrp["Validated ROA Payload JSON"] --> validate
parse --> csv
validate --> summary["rpki-summary.json"]
validate --> status["route-origin-status.csv"]
validate --> invalids["rpki-invalids.csv"]
validate --> diff["daily-diff.json + changelog.md"]
validate --> events["suspected-events.jsonl"]
summary --> release["GitHub Release"]
status --> release
invalids --> release
diff --> release
events --> release
RouteSentinel compares each BGP announcement against a local VRP table:
valid: a covering VRP exists and the origin ASN matches.invalid: a covering VRP exists, but the origin ASN does not match.not-found: no covering VRP exists.
RouteSentinel expects two source types:
- BGP RIB dumps in MRT format, for example RIPE RIS or RouteViews snapshots.
- Validated ROA Payload JSON, produced by an RPKI validator or a trusted public VRP feed.
The included daily workflow uses a multi-collector RIPE RIS perspective: rrc00, rrc01,
and rrc10. This is broader than a single collector, but still a collector-based view of
the routing system. To expand toward a more global view, add RouteViews collectors such as
route-views2 and route-views6 to the workflow and pass their normalized CSV files to
routesentinel snapshot.
The project does not perform RPKI cryptographic validation itself in v1. It consumes already validated VRPs and performs local route-origin validation against them.
Requirements:
- Python 3.11+
bgpdumpfor MRT parsing when usingroutesentinel parse-mrt
Install for local development:
python -m pip install -e ".[dev]"Run tests:
python -m pytestBuild a snapshot from normalized announcements and a VRP JSON file:
routesentinel snapshot \
--announcements data/normalized/rrc00.csv \
--announcements data/normalized/rrc01.csv \
--vrps data/raw/vrps.json \
--out outNormalized announcements CSV:
prefix,origin_asn,as_path,peer,collector
203.0.113.0/24,64496,64497 64496,192.0.2.1,rrc00VRP JSON:
{
"roas": [
{
"prefix": "203.0.113.0/24",
"maxLength": 24,
"asn": "AS64496"
}
]
}Download source files with a responsible User-Agent:
routesentinel fetch \
https://data.ris.ripe.net/rrc00/latest-bview.gz \
data/raw/rrc00-latest-bview.gzConvert an MRT dump to normalized CSV:
routesentinel parse-mrt \
data/raw/rrc00-latest-bview.gz \
data/normalized/rrc00.csv \
--collector rrc00parse-mrt deduplicates by (prefix, origin ASN, collector) by default. snapshot then
merges collectors into unique (prefix, origin ASN) route-origin pairs. Use
--no-dedupe only when you explicitly need peer-level visibility rows.
The included workflow at .github/workflows/release.yml runs daily at 06:00 UTC and:
- Installs Python and
bgpdump. - Downloads RIPE RIS RIB dumps and one public VRP JSON file.
- Normalizes MRT announcements to deduplicated CSV files.
- Builds summary, route-origin status, invalids, suspected events, and top invalid ASNs.
- Downloads the previous release state when available.
- Builds a daily diff/changelog.
- Publishes the files as GitHub Release assets tagged by date.
For broader visibility, add more collectors and pass each normalized CSV as another
--announcements option.
Long-running CLI commands print progress to stderr. In GitHub Actions logs you will see messages such as:
[routesentinel] download progress 250.0 MiB / 800.0 MiB (31.2%)
[routesentinel] parse progress bgpdump_lines=1000000 raw_announcements=999999 unique_announcements=120000 duplicates_skipped=879999
[routesentinel] aggregate progress rows_seen=1000000 unique_prefix_origin_pairs=120000
[routesentinel] validate progress rows_seen=1000000 unique_prefix_origin_pairs=120000 duplicates_collapsed=880000
rpki-summary.json:
{
"coverage_ratio": 0.5,
"invalid": 1,
"not_found": 0,
"total_announcements": 2,
"unique_invalid_prefixes": 1,
"unique_prefix_origin_pairs": 2,
"unique_prefixes": 2,
"valid": 1
}route-origin-status.csv:
prefix,origin_asn,status,expected_origins,collectors
203.0.113.0/24,64496,valid,64496,rrc00 rrc01
198.51.100.0/24,64499,invalid,64500,rrc00rpki-invalids.csv:
prefix,origin_asn,status,expected_origins,collectors
198.51.100.0/24,64499,invalid,64500,rrc00top-invalid-asns.csv:
origin_asn,invalid_prefix_origin_pairs
64499,1daily-diff.json tracks:
- new RPKI-invalid prefix-origin pairs;
- resolved RPKI-invalid prefix-origin pairs;
- new origin ASNs for prefixes;
- newly RPKI-covered prefixes.
suspected-events.jsonl:
{"confidence":"medium","prefix":"198.51.100.0/24","seen_origins":[64499],"signal":"rpki-invalid"}- Batch-first: daily snapshots before realtime stream processing.
- Source-aware: every event keeps collector and peer context where available.
- Conservative labels: the dataset reports signals, not definitive hijack claims.
- Operator-friendly: outputs are small, stable, and suitable for GitHub Releases.
- v1 does not implement route-leak valley-free validation.
- v1 does not ingest RIS Live or Kafka update streams.
- Multi-origin prefixes can be legitimate, especially with anycast and complex traffic-engineering setups.
- Accuracy depends on collector visibility and the freshness of the selected VRP feed.
MIT. See LICENSE.