Skip to content
alexblaeuerPublic

About

Measurement and Analysis Framework for Analyzing RPKI Adoption and Routing Security.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

NetLens

NetLens is a data-driven analysis framework developed to support the empirical investigation of Resource Public Key Infrastructure (RPKI) adoption and its impact on routing security within the Swiss Internet ecosystem. The system is designed to systematically collect, aggregate, and analyze publicly available routing and RPKI data in order to assess the extent of Route Origin Authorization (ROA) deployment and its practical effectiveness in mitigating routing security threats.

The framework integrates multiple data sources, including BGP routing information from route collectors, RPKI validation data derived from local validator instances, and auxiliary metadata from publicly available registries. Based on these inputs, NetLens constructs a unified data model that links Autonomous Systems (AS), announced IP prefixes, and their corresponding RPKI validation states.

A key feature of NetLens is its ability to correlate routing data with organizational and sectoral information, enabling differentiated analysis across industry sectors and critical infrastructures. This allows for the identification of structural patterns in RPKI adoption and highlights disparities between different types of network operators.

Through the aggregation and analysis of these datasets, NetLens supports the quantitative evaluation of RPKI coverage as well as the qualitative assessment of its effectiveness in real-world routing scenarios. In particular, the framework enables the examination of whether invalid routing announcements are propagated within the observed network and to what extent RPKI contributes to reducing the exposure to origin hijacks.

By providing a reproducible and extensible data processing pipeline, NetLens forms the technical foundation for the empirical analysis conducted in this thesis and contributes to a better understanding of routing security practices in Switzerland.

Data Sources

RIPEstat

  • AS
  • Prefix
  • Relationship
  • Ownership

Routinator

  • RPKI validation results

BGPKIT

  • BGP routing information from route collectors

MANRS

  • Organization is MANRS participant

RoVista

  • AS Rank
  • ROV Ratio
  • Cone Size

Cloudflare

  • Prefix Visibility
  • Origin Hijacks
  • Route Leaks

Docker

Build and publish Image

Build

docker build -t alexblaeuer/netlens:latest .

Publish

docker push alexblaeuer/netlens:latest

Docker Compose

.env

# Django settings for netlens project.
DEBUG=False
SECRET_KEY=your_secret_key_here
ALLOWED_HOSTS="*"
TIME_ZONE=Europe/Zurich

# Database configuration
DB_NAME=netlens
DB_USER=netlens
DB_PASSWORD=your_db_password_here
DB_HOST=postgres
DB_PORT=5432

# NetLens
NETLENS_VERSION=latest

# Routinator RPKI validator configuration
ROUTINATOR_URL=http://localhost:8323
ROUTINATOR_API_KEY=your_api_key_here

# RoVista configuration
ROVISTA_USER=your_username_here
ROVISTA_PASSWORD=your_password_here

# MANRS configuration
MANRS_API_KEY=your_api_key_here

# Cloudflare configuration
CLOUDFLARE_API_KEY=your_api_key_here

# Gunicorn configuration
GUNICORN_WORKERS=4

docker-compose.yaml

---
services:
  postgres:
    image: postgres:17-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    ports:
      - "${DB_PORT}:5432"
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

  netlens:
    image: alexblaeuer/netlens:${NETLENS_VERSION}
    restart: unless-stopped
    ports:
      - "8000:8000"
    env_file:
      - ./.env
    volumes:
      - ./data/export:/app/export
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8000/ || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s

Run management commands in Docker

Fetch data

docker compose exec netlens ./manage.py fetch_data
docker compose exec netlens ./manage.py fetch_data --force

Fetch related prefixes

docker compose exec netlens ./manage.py fetch_related_prefixes
docker compose exec netlens ./manage.py fetch_related_prefixes --force

Load data

docker compose exec netlens ./manage.py load_data

Fetch organization information

docker compose exec netlens ./manage.py fetch_orgs
docker compose exec netlens ./manage.py fetch_orgs --force

Fetch unannounced data

docker compose exec netlens ./manage.py fetch_unannounced
docker compose exec netlens ./manage.py fetch_unannounced --model asn
docker compose exec netlens ./manage.py fetch_unannounced --model prefix

Clean data

# Delete data
docker compose exec netlens ./manage.py clean_data
docker compose exec netlens ./manage.py clean_data --dry-run
docker compose exec netlens ./manage.py clean_data --target foreign-prefixes
docker compose exec netlens ./manage.py clean_data --target unannounced-prefixes
docker compose exec netlens ./manage.py clean_data --target prefixes-without-asn
docker compose exec netlens ./manage.py clean_data --target unannounced-asn
docker compose exec netlens ./manage.py clean_data --target asn-without-prefixes
docker compose exec netlens ./manage.py clean_data --target empty-organizations

# Show data
docker compose exec netlens ./manage.py clean_data --target contains-unannounced
docker compose exec netlens ./manage.py clean_data --target prefixes-without-organization
docker compose exec netlens ./manage.py clean_data --target prefixes-without-organization --json

Map Organizations

docker compose exec netlens ./manage.py map_orgs --model type
docker compose exec netlens ./manage.py map_orgs --model prefix
docker compose exec netlens ./manage.py map_orgs --model prefix --dry-run

Validate Prefix RPKI

docker compose exec netlens ./manage.py validate_prefix_rpki
docker compose exec netlens ./manage.py validate_prefix_rpki --dry-run

Extend Data

docker compose exec netlens ./manage.py extend_data --source rovista
docker compose exec netlens ./manage.py extend_data --source manrs
docker compose exec netlens ./manage.py extend_data --source cloudflare

Collect BGP Events

docker run --rm -d \
  --network "netlens_default" \
  --env-file "./.env" \
  --entrypoint "" \
  alexblaeuer/netlens:0.8.0 \
  ./manage.py collect_bgp_events \
    --from-time "2026-05-01T00:00:00Z" \
    --until-time "2026-05-01T13:59:59Z"

docker run --rm -d \
  --network "netlens_default" \
  --env-file "./.env" \
  --entrypoint "" \
  alexblaeuer/netlens:0.8.0 \
  ./manage.py collect_bgp_events \
    --from-time "2026-05-01T00:00:00Z" \
    --until-time "2026-05-01T13:59:59Z" \
    --fill-gaps 15

collect_bgp_events.sh

#!/bin/bash
set -e

# Load .env file
source "/opt/netlens/.env"

# Use provided args or default to the past hour (UTC)
FROM_TIME="${1:-$(date -u -d "1 hour ago" '+%Y-%m-%dT%H:00:00Z')}"
UNTIL_TIME="${2:-$(date -u -d "1 hour ago" '+%Y-%m-%dT%H:59:59Z')}"

echo "Collecting BGP Events"
echo "From:  $FROM_TIME"
echo "Until: $UNTIL_TIME"

docker run --rm \
  --network "netlens_default" \
  --env-file "/opt/netlens/.env" \
  --entrypoint "" \
  alexblaeuer/netlens:${NETLENS_VERSION} \
  ./manage.py collect_bgp_events \
    --from-time "$FROM_TIME" \
    --until-time "$UNTIL_TIME"

crontab

5 * * * * /opt/netlens/collect_bgp_events.sh

Collect Cloudflare Incidents

Hijacks:

docker run --rm -d \
  --network "netlens_default" \
  --env-file "./.env" \
  --entrypoint "" \
  alexblaeuer/netlens:0.8.0 \
  ./manage.py fetch_bgp_incidents \
  --type hijacks \
  --from-time "2026-05-01T00:00:00Z" \
  --until-time "2026-05-10T23:59:59Z"

# --asn 211452,51252

Leaks:

docker run --rm -d \
  --network "netlens_default" \
  --env-file "./.env" \
  --entrypoint "" \
  alexblaeuer/netlens:0.8.0 \
  ./manage.py fetch_bgp_incidents \
  --type leaks \
  --from-time "2026-05-01T00:00:00Z" \
  --until-time "2026-05-10T23:59:59Z"

# --asn 211452,51252

BGP Analysis

docker compose exec netlens ./manage.py bgp_analysis --from-time "2026-05-01T00:00:00Z" --until-time "2026-05-10T23:59:59Z"

Backup DB

Backup

docker compose exec postgres bash
pg_dump -U netlens netlens > /var/lib/postgresql/data/netlens_0_5_1.sql

Restore

docker compose exec postgres bash
dropdb -U netlens netlens
createdb -U netlens netlens
psql -U netlens -d netlens < /var/lib/postgresql/data/netlens_0_5_1.sql

About

Measurement and Analysis Framework for Analyzing RPKI Adoption and Routing Security.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages