fix: resolve AS names via RIPE Stat AS overview API

This commit is contained in:
Rene Fichtmueller 2026-03-26 11:26:58 +13:00
parent 405bfd01c7
commit 967a0a827b

View File

@ -92,6 +92,24 @@ function fetchRPKIPerPrefix(asn, prefix) {
}); });
} }
async function resolveASNames(asnList) {
const names = {};
const batchSize = 10;
for (let i = 0; i < asnList.length; i += batchSize) {
const batch = asnList.slice(i, i + batchSize);
const results = await Promise.all(
batch.map((asn) =>
fetchJSON("https://stat.ripe.net/data/as-overview/data.json?resource=AS" + asn)
.then((r) => ({ asn, name: r?.data?.holder || "" }))
.catch(() => ({ asn, name: "" }))
)
);
results.forEach((r) => { names[r.asn] = r.name; });
}
return names;
}
const server = http.createServer(async (req, res) => { const server = http.createServer(async (req, res) => {
res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS"); res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
@ -180,11 +198,19 @@ const server = http.createServer(async (req, res) => {
const leftNeighbours = neighbours.filter((n) => n.type === "left"); const leftNeighbours = neighbours.filter((n) => n.type === "left");
leftNeighbours.forEach((n) => upstreamSet.add(n.asn)); leftNeighbours.forEach((n) => upstreamSet.add(n.asn));
const detectedProviders = [...upstreamSet].map((asn) => { let detectedProviders = [...upstreamSet].map((asn) => {
const nb = leftNeighbours.find((n) => n.asn === asn); const nb = leftNeighbours.find((n) => n.asn === asn);
return { asn, name: nb && nb.as_name ? nb.as_name : "" }; return { asn, name: nb && nb.as_name ? nb.as_name : "" };
}); });
// Batch-resolve AS names from RIPE Stat AS overview API
const providerASNs = detectedProviders.map((p) => p.asn);
const resolvedNames = await resolveASNames(providerASNs);
detectedProviders = detectedProviders.map((p) => ({
...p,
name: resolvedNames[p.asn] || p.name || "",
}));
// Check RIPE DB for ASPA references // Check RIPE DB for ASPA references
let aspaObjectExists = false; let aspaObjectExists = false;
try { try {
@ -216,7 +242,7 @@ const server = http.createServer(async (req, res) => {
"# AFI: ipv4, ipv6\n" + "# AFI: ipv4, ipv6\n" +
"#\n" + "#\n" +
"# Detected providers from BGP path analysis:\n" + "# Detected providers from BGP path analysis:\n" +
detectedProviders.map((p) => "# AS" + p.asn + " (" + p.name + ")").join("\n"); detectedProviders.map((p) => "# AS" + p.asn + (p.name ? " (" + p.name + ")" : "")).join("\n");
// Sample path analysis // Sample path analysis
const samplePaths = asPaths.slice(0, 10).map((p) => { const samplePaths = asPaths.slice(0, 10).map((p) => {
@ -451,17 +477,21 @@ const server = http.createServer(async (req, res) => {
const rpkiTotal = rpkiStatuses.length; const rpkiTotal = rpkiStatuses.length;
const rpkiCoverage = rpkiTotal > 0 ? Math.round((rpkiValid / rpkiTotal) * 100) : 0; const rpkiCoverage = rpkiTotal > 0 ? Math.round((rpkiValid / rpkiTotal) * 100) : 0;
// Resolve AS names for neighbours that have empty as_name
const neighboursNeedingNames = neighbours.filter((n) => !n.as_name).map((n) => n.asn);
const neighbourNames = neighboursNeedingNames.length > 0 ? await resolveASNames(neighboursNeedingNames) : {};
const upstreams = neighbours const upstreams = neighbours
.filter((n) => n.type === "left") .filter((n) => n.type === "left")
.map((n) => ({ asn: n.asn, name: n.as_name || "AS" + n.asn, power: n.power || 0 })) .map((n) => ({ asn: n.asn, name: n.as_name || neighbourNames[n.asn] || "", power: n.power || 0 }))
.sort((a, b) => b.power - a.power); .sort((a, b) => b.power - a.power);
const downstreams = neighbours const downstreams = neighbours
.filter((n) => n.type === "right") .filter((n) => n.type === "right")
.map((n) => ({ asn: n.asn, name: n.as_name || "AS" + n.asn, power: n.power || 0 })) .map((n) => ({ asn: n.asn, name: n.as_name || neighbourNames[n.asn] || "", power: n.power || 0 }))
.sort((a, b) => b.power - a.power); .sort((a, b) => b.power - a.power);
const peers = neighbours const peers = neighbours
.filter((n) => n.type === "uncertain" || n.type === "peer") .filter((n) => n.type === "uncertain" || n.type === "peer")
.map((n) => ({ asn: n.asn, name: n.as_name || "AS" + n.asn, power: n.power || 0 })) .map((n) => ({ asn: n.asn, name: n.as_name || neighbourNames[n.asn] || "", power: n.power || 0 }))
.sort((a, b) => b.power - a.power); .sort((a, b) => b.power - a.power);
let rir = ""; let rir = "";