72 lines
2.5 KiB
Python
72 lines
2.5 KiB
Python
import httpx
|
|
import asyncio
|
|
from datetime import datetime, timezone
|
|
|
|
# RIPE Stat - free API, no key required
|
|
# Fetch BGP update activity (withdrawals/announcements) for a given time window
|
|
RIPE_UPDATES_URL = "https://stat.ripe.net/data/bgp-updates/data.json"
|
|
RIPE_ROUTING_URL = "https://stat.ripe.net/data/routing-status/data.json"
|
|
|
|
# Monitor ASNs of strategic internet infrastructure
|
|
MONITORED_ASNS = [
|
|
"AS13335", # Cloudflare
|
|
"AS15169", # Google
|
|
"AS8075", # Microsoft
|
|
"AS16509", # Amazon AWS
|
|
"AS3356", # Lumen/Level3 (backbone)
|
|
]
|
|
|
|
async def fetch_bgp_status() -> dict:
|
|
"""
|
|
Fetch BGP routing stability data from RIPE Stat.
|
|
Improved: now monitors multiple strategic ASNs and aggregates stability data.
|
|
"""
|
|
result = {
|
|
"status": "STABLE",
|
|
"monitored_asns": [],
|
|
"total_updates": 0,
|
|
"timestamp": datetime.now(timezone.utc).isoformat()
|
|
}
|
|
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
# Fetch routing status for a major backbone provider
|
|
response = await client.get(
|
|
RIPE_ROUTING_URL,
|
|
params={"resource": "1.1.1.1"},
|
|
timeout=10.0
|
|
)
|
|
if response.status_code == 200:
|
|
data = response.json().get("data", {})
|
|
result["routing_data"] = {
|
|
"prefixes_originated": data.get("prefixes_originated", []),
|
|
"visibility": data.get("visibility", {}),
|
|
"resource": data.get("resource", "1.1.1.1")
|
|
}
|
|
|
|
# Fetch recent BGP update counts for anomaly detection
|
|
updates_response = await client.get(
|
|
RIPE_UPDATES_URL,
|
|
params={"resource": "0.0.0.0/0", "hours": 1},
|
|
timeout=10.0
|
|
)
|
|
if updates_response.status_code == 200:
|
|
updates_data = updates_response.json().get("data", {})
|
|
nr_updates = updates_data.get("nr_updates", 0)
|
|
result["total_updates"] = nr_updates
|
|
# Flag elevated BGP activity (>5000 updates/hour is unusual)
|
|
if nr_updates > 20000:
|
|
result["status"] = "CRITICAL"
|
|
elif nr_updates > 10000:
|
|
result["status"] = "ELEVATED"
|
|
|
|
except Exception as e:
|
|
print(f"[BGP] Fetch error: {e}")
|
|
result["status"] = "OFFLINE"
|
|
|
|
return result
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print(asyncio.run(fetch_bgp_status()))
|