Public IP enrichment: what the flags actually mean

A reproducible hierarchy for adding network, ASN, cloud, VPN and Tor context to an IP address without turning infrastructure metadata into a verdict.

The question

An application log often starts with little more than a source IP address. Public data can add useful context: the routed prefix, autonomous system number (ASN), network name, broad geography, cloud-provider range, known VPN or datacentre range, and whether the address appeared in a Tor exit list.

None of those fields answers the question “is this request abusive?” They describe infrastructure. The defensible output is a set of dated observations with provenance, not one all-purpose bad_ip label.

TipThe compact rule

Preserve each source as its own feature, record when it was observed, and let later analysis decide how much weight it deserves.

Five different kinds of information

The exploratory work for this page tested routing tables, ASN metadata, a multi-provider range aggregator, Tor exits, VPN/datacentre lists, and a hand-maintained ASN blocklist. It did not download AWS and Google Cloud’s first-party feeds directly. These sources are easy to join technically and easy to conflate conceptually.

Layer Example output What a match supports What it does not support
Route origin asn, routed prefix The ASN originating the best matching prefix in that snapshot The end user, business type, or intent
Organisation metadata network name, website, self-described type Context about the network operator An independently verified residential/hosting classification
Provider-published ranges provider, service, region The address fell inside a range the provider published for that purpose Complete coverage of the provider or proof that a customer generated the request
Observed service list tor_exit_listed The address appeared in the relevant Tor list at the observation time Abuse, identity, or historical Tor use outside that snapshot
Curated heuristic vpn_listed, datacentre_listed, hosting_asn_listed A particular maintainer classified the range or ASN that way Ground truth, completeness, or a safe automatic block decision

The distinction matters because the rows have different units. A Tor list is largely an IP-level observation. A provider feed is a set of prefixes. PeeringDB describes a network associated with an ASN. A hand-built “hosting ASN” list applies one label to every routed address associated with that ASN. Collapsing them into one boolean discards both provenance and uncertainty.

A source hierarchy

1. Start with routing, not reputation

An IP-to-ASN table answers the narrowest useful question: which ASN originated the longest matching routed prefix in a particular routing snapshot? It supplies a join key for network-level metadata. It does not establish that the ASN owns every address, operates the end host, or belongs to a particular business category.

Routing data is time-varying. Prefixes are announced, withdrawn, transferred, and sometimes originated by different ASNs. Historical event analysis therefore needs a routing snapshot close to the event, not only the current table. One suitable source is CAIDA’s RouteViews Prefix-to-AS mappings, produced daily for IPv4 and IPv6 with archives extending back to 2005 and 2007 respectively. Its Public AUA requires citation and asks users to report publications—including web pages—that use the data.

2. Add network metadata without promoting it to truth

PeeringDB exposes network names, websites, reach, traffic characteristics, and info_types through its API. These records are valuable explanatory metadata, but many of the fields are self-described and coverage is not universal. The enrichment retains all reported types and provides nullable conveniences for Educational/Research, Enterprise, and Cable/DSL/ISP. If an active record has a known type list that omits one of those labels, the corresponding field is False; if the record or its type list is unavailable, the field is NA. Neither case establishes who uses an individual address, whether it is shared, or whether its traffic is safe.

The local Stanford ASdb artifact named 2026-03_categorized_ases.csv is also joined by normalized route ASN. The filename identifies the local artifact but is not treated as evidence of an exact publication date. Its wide CSV supplies up to 68 industry category/sub-category pairs per ASN; it does not contain a separate organisation-name field. Every supplied pair is retained under asdb_ names. These inferred categories remain separate from PeeringDB’s self-reported types, and disagreement is not silently reconciled.

IPinfo Lite supplies a separate CIDR and single-address lookup for country, continent, ASN, AS name, and domain. Its ASN is normalized from values such as AS13335, but it never overwrites route_asn or asn_country. ipinfo_country is IP-range geolocation, not the country of the ASN organisation. Agreement is reported only when both sources return an ASN.

Likewise, an ASN category from an inferred classification model should retain the model name and version. The former CAIDA AS Classification dataset, for example, trained on PeeringDB-derived ground truth supplemented by 500 manually classified enterprise networks. Its features included AS relationships, customer-cone size, advertised IPv4 space, popular domains mapped to the AS, and observed address activity. CAIDA reports a positive predictive value of 70% and now marks the dataset as unsupported. That is useful research context, not a timeless label.

3. Prefer first-party cloud ranges

Provider feeds are strong evidence for the specific claim their publisher makes:

These should be stored as separate provider/service/region matches. The notebook uses rezmoss’s third-party aggregation: its normalized table carries provider, service, region, and last_updated fields assembled from multiple upstream sources. cloud_matches remains the provider-only compatibility field; cloud_match_details retains the matching CIDR and those related attributes as one record. Those fields were not independently reproduced from the AWS and Google feeds in this exploration. An aggregate inherits every upstream definition, refresh schedule, overlap, and omission, so keep the aggregator, original publisher, and source URL distinct wherever possible.

Overlaps are not an error to erase blindly. A broad parent prefix may carry one provider label while a more specific prefix carries another. The provider enrichment returns every applicable record, removes exact duplicates, and orders the result deterministically; it does not discard a broader match merely because a more specific range also matched. Provider region describes the published infrastructure range, not necessarily the user’s location. A documented provider record may itself name a relay service, but the implementation does not infer relay status from an arbitrary cloud match. This is distinct from route-origin semantics.

4. Treat Tor as a dated observation

The notebook downloaded the exact endpoint https://check.torproject.org/torbulkexitlist. The Tor Project describes this default bulk artifact as addresses it has observed being used by exit relays through active measurements. Since its 2020 service change, bulk-list queries are no longer filtered by exit policy: an observed exit address is returned regardless of query parameters. It should therefore be described as a list of observed Tor exit addresses, not as proof that every listed address can reach a particular destination. Raw measurements are archived by CollecTor. See the Tor Project’s explanation of the exit-list service change.

A present-day tor_exit_listed=True match is an observation tied to that exact artifact; it cannot establish that an address was a Tor exit when an older login occurred. If the local artifact is unavailable, the notebook leaves tor_exit_listed as NA; it does not turn an unavailable source into an empty list or a checked non-match.

Do not silently substitute another Tor artifact. Different list-building methods have produced different counts, and this exploration did not compare them. Record the endpoint, destination assumptions, retrieval time, and hash with the result.

The 25 October 2026 rerun of that exact endpoint contained 1,213 distinct addresses. This is a reproducibility detail, not a stable size estimate: the live list can change after the snapshot.

Most importantly, a Tor match identifies shared privacy infrastructure. It does not identify a person and it is not evidence of abuse.

5. Keep community lists visibly heuristic

Community VPN, datacentre, and hosting-ASN lists can add coverage that first-party feeds do not provide. They can also contain stale ownership, broad labels, false positives, and undocumented judgement calls.

The explored bad-asn-list is a useful example. It is an open defensive artifact accompanied by one operator’s account of using hosting-ASN blocking against signup abuse. It is not a measured reference classification: the reported effect is single-site and anecdotal, the selection method is not documented as a reproducible study, and one ASN-level decision can affect mixed residential, enterprise, and hosted traffic. In this project it is retained as a heuristic feature and historical operator account (SRC-052), not adopted as ground truth.

The same rule applies to merged range repositories: useful for comparison and recall experiments, but label the aggregator and snapshot rather than implying that every entry is an official provider assertion.

A defensible output schema

Avoid a single is_proxy or is_bad column. The companion implementation’s enrich() call returns source-specific fields with explicit missingness:

Field Meaning Source Missing-value semantics Main limitation
ip_input, ip_normalized, ip_version Original value, canonical address, and family Input/parser Parse failures retain ip_input; normalized fields are NA IPv4-mapped IPv6 is deliberately normalized to IPv4
route_asn, asn_name, asn_country Origin ASN and route-table descriptions IPtoASN NA for invalid/IPv6/ASN 0/no route/absent source Route origin is not user identity; asn_country is not IP geolocation
ipinfo_country, ipinfo_continent IP-range geolocation labels IPinfo Lite NA for no matching row/source Approximate range geography, not the user’s location or ASN country
ipinfo_asn, ipinfo_as_name, ipinfo_as_domain Independent ASN assignment and AS metadata IPinfo Lite Individual missing fields remain NA Never overwrites route metadata
route_ipinfo_asn_agree Equality of normalized route and IPinfo ASNs Derived comparison NA unless both ASNs exist A disagreement does not say which source is right
peeringdb_name, peeringdb_website, peeringdb_info_scope, peeringdb_updated Active network-record metadata PeeringDB on route_asn NA for no record or missing field/source Community-maintained organisational context
peeringdb_info_types Every self-reported network type PeeringDB NA for no record/unavailable types; empty tuple for a known empty list Self-reported, non-exclusive, incomplete
education_network_reported, enterprise_network_reported, cable_dsl_isp_network_reported Membership in three reported PeeringDB categories PeeringDB NA if record/types unavailable; otherwise nullable Boolean Not a user, safety, usage-volume, or confirmed-NAT label
cloud_matches Compatible tuple of every matching provider name rezmoss aggregate Empty tuple means checked/no match; NA means unsupported/unavailable Third-party aggregation; overlaps retained
cloud_match_details Matching CIDR/provider/service/region/source-update records rezmoss aggregate Empty tuple means checked/no match; NA means unsupported/unavailable Region describes the published range; no generic relay inference
asdb_category_pairs, asdb_layer1_categories, asdb_layer2_categories All inferred industry category pairs and convenience projections Stanford ASdb on route_asn NA for no ASN row/source Not reconciled with PeeringDB or promoted to verified fact
tor_exit_listed Exact address in the dated Tor artifact Tor bulk list NA when family/source unavailable Dated shared-infrastructure observation, not abuse evidence
vpn_listed, datacentre_listed Separate community-range matches X4BNet NA for IPv6/invalid/absent source Broad, dependent heuristics
hosting_asn_listed Route ASN in the curated list bad-asn-list NA without route/source Maintainer heuristic, not ground truth

Source URL, genuine retrieval time when known, publisher update time, filesystem modification time, and SHA-256 live in a companion source-level manifest rather than being repeated on every event row.

Use nullable values deliberately. False should mean the address was checkable against the source and no match was found. NA should mean the lookup was not applicable or could not be performed—for example, applying an IPv4-only list to IPv6. Unknown ASN metadata should remain unknown; it is not adverse evidence.

Worked implementation

The reusable functions are in src/openbotrisk/ip_enrichment.py, with boundary and semantics checks in tests/test_ip_enrichment.py. The executed demo notebook loads named local snapshots without network access, measures coverage and disagreement, and calls enrich() on deliberately awkward inputs.

The site build embeds the notebook’s committed output; it does not download live data. Run the notebook explicitly when creating a new dated snapshot, inspect the output, and commit the notebook with its outputs. The main enrichment call is:

ip_input route_asn ipinfo_asn route_ipinfo_asn_agree peeringdb_name peeringdb_info_types education_network_reported enterprise_network_reported cable_dsl_isp_network_reported cloud_matches
0 45.88.80.1 786 786 True Janet (Educational/Research,) True False False ()
1 1.44.96.1 16509 16509 True Amazon.com (Enterprise,) False True False ()
2 52.95.110.1 16509 16509 True Amazon.com (Enterprise,) False True False (aws,)
3 8.8.8.8 15169 15169 True Google LLC (Content,) False False False (googleservices,)
4 81.2.69.142 20712 20712 True Andrews & Arnold Ltd (Cable/DSL/ISP,) False False True ()
5 2606:4700:4700::1111 <NA> 13335 <NA> <NA> <NA> <NA> <NA> <NA> (cloudflare,)
6 2001:db8::1 <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> ()
7 ::ffff:34.82.1.5 396982 396982 True Google Cloud () False False False (googlecloud,)
8 1.2.3.4:443 <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
9 not an ip <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
10 None <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
Source: Public IP enrichment: worked example

The real examples include 45.88.80.1, whose route ASN maps to Janet/Jisc (AS786) and whose PeeringDB record reports Educational/Research; 81.2.69.142, whose route ASN maps to Andrews & Arnold (AS20712) and reports Cable/DSL/ISP; and 1.44.96.1, whose route ASN maps to Amazon.com (AS16509) and reports Enterprise. Educational classification supplies network context, not evidence about how many users share one IP. Amazon also demonstrates why PeeringDB Enterprise is not a reliable shared-office indicator. None of these types attributes a user, confirms NAT, or verifies that an unmatched address is safe or residential. An empty provider tuple means the supported address family was checked and did not match. Missing values mean that the source was absent or inapplicable. Report that missingness alongside any flag rate:

ip_normalized                     0.27
ip_version                        0.27
route_asn                         0.45
asn_name                          0.45
asn_country                       0.45
cloud_matches                     0.27
cloud_match_details               0.27
ipinfo_country                    0.36
ipinfo_continent                  0.36
ipinfo_asn                        0.36
ipinfo_as_name                    0.36
ipinfo_as_domain                  0.36
route_ipinfo_asn_agree            0.45
peeringdb_name                    0.45
peeringdb_info_types              0.45
peeringdb_website                 0.45
peeringdb_info_scope              0.45
peeringdb_updated                 0.45
education_network_reported        0.45
enterprise_network_reported       0.45
cable_dsl_isp_network_reported    0.45
asdb_category_pairs               0.45
asdb_layer1_categories            0.45
asdb_layer2_categories            0.45
tor_exit_listed                   0.45
vpn_listed                        0.45
datacentre_listed                 0.45
hosting_asn_listed                0.45
Name: NA share, dtype: float64
CautionCurrent implementation limits

IPinfo and the detailed rezmoss prefix index support IPv4 and IPv6 without expanding networks. The IPtoASN route table and X4BNet interval lists remain IPv4-only, so their fields are NA for ordinary IPv6. PeeringDB and ASdb currently depend on the route_asn join; consequently they may remain unavailable for IPv6 even when IPinfo supplies an independent ASN. This page deliberately does not add an IPinfo-ASN fallback or change that lookup policy. The pipeline loads these public snapshots in memory and is intended for reproducible investigation, not an unbounded production stream.

Source inventory for the executed run

The inventory is generated from the notebook’s shared provenance records rather than a separately maintained list. It includes every input used in the run, including Tor and the community lists. Retrieval time, source publication or generation time, and filesystem modification time remain separate. A manifest retrieval time is used only when its recorded SHA-256 matches the local artifact:

source path schema status reason retrieved_at source_updated_at file_mtime prior_use
0 IPtoASN data/IP/ip2asn-combined.tsv.gz start, end, ASN, country code, description integrated None None None 2026-10-24T12:38:06+00:00 route origin/name/country
1 PeeringDB notebooks/peeringdb-net.json API network rows: ASN, name, info_types, websi... integrated None None 2026-10-24T16:21:34+00:00 2026-10-24T19:41:12+00:00 exploratory inspection only
2 IPinfo Lite data/IP/ipinfo_lite.parquet network, country/code, continent/code, ASN, AS... integrated None None None 2026-10-24T13:02:50+00:00 exploratory inspection only
3 rezmoss aggregate data/raw/ip-enrichment/2026-10-25/rezmoss_all_... CIDR, IP version, provider, service, region, l... integrated None 2026-10-25T10:54:51+00:00 None 2026-10-25T10:54:51+00:00 provider name only
4 Stanford ASdb data/IP/2026-03_categorized_ases.csv ASN plus numbered layer-1/layer-2 category pairs integrated None None None 2026-10-24T12:39:51+00:00 exploratory merge only
5 X4BNet VPN IPv4 data/raw/ip-enrichment/2026-10-25/x4bnet_vpn_i... newline-delimited IPv4 CIDRs integrated None 2026-10-25T10:54:43+00:00 None 2026-10-25T10:54:43+00:00 VPN range flag
6 X4BNet datacentre IPv4 data/raw/ip-enrichment/2026-10-25/x4bnet_datac... newline-delimited IPv4 CIDRs integrated None 2026-10-25T10:54:43+00:00 None 2026-10-25T10:54:43+00:00 datacentre range flag
7 bad-asn-list data/raw/ip-enrichment/2026-10-25/bad_asn_list... ASN and maintainer label CSV integrated None 2026-10-25T10:54:51+00:00 None 2026-10-25T10:54:51+00:00 hosting-ASN heuristic
8 Tor bulk exit list data/raw/ip-enrichment/2026-10-25/tor_bulk_exi... newline-delimited exit IP addresses integrated None 2026-10-25T10:54:51+00:00 None 2026-10-25T10:54:51+00:00 dated exact-address flag

All requested datasets were present in the executed run. The local IPtoASN, IPinfo and ASdb files still have no evidenced retrieval timestamp; the ASdb artifact also has no artifact-linked publication/update date or organisation-name field in the inspected CSV. Those values remain unknown. First-party AWS and Google feeds remain a deferred comparison; the current run uses the existing rezmoss aggregate.

Classification coverage and ASN disagreement

Record matching is not the same as useful classification coverage. The table separates absent source records, present records with missing or empty classification, and records with at least one usable classification. Its UK row is precisely the distinct non-zero ASNs attached to an IPtoASN route row whose source-defined country field is GB; it is not all networks serving UK users:

scope source denominator_asns no_record no_record_pct classification_missing_or_empty classification_missing_or_empty_pct usable_classification usable_classification_pct status reason
0 all distinct non-zero route ASNs PeeringDB 79310 50027 63.077796 8039 10.136175 21244 26.786030 available None
1 all distinct non-zero route ASNs Stanford ASdb 79310 5745 7.243727 0 0.000000 73565 92.756273 available None
2 IPtoASN country=GB distinct non-zero route ASNs PeeringDB 2072 1118 53.957529 217 10.472973 737 35.569498 available None
3 IPtoASN country=GB distinct non-zero route ASNs Stanford ASdb 2072 114 5.501931 0 0.000000 1958 94.498069 available None

Across all 79,310 route ASNs, PeeringDB supplied usable info_types for 26.79%; 63.08% had no PeeringDB record and 10.14% had a record without a usable type. In the 2,072-ASN IPtoASN GB subset, usable PeeringDB classification was 35.57%, while ASdb supplied usable categories for 94.50%. These are ASN-level diagnostics, not traffic-, user-, or address-space-weighted estimates.

The IP-level comparison uses the same fixed-seed random sampling method across the full eligible IPv4 source-row set for both the overall and IPinfo country_code=GB views:

scope metric count denominator percent status reason
0 all IPinfo IPv4 source rows sample rows 5000 1337977 0.373699 available None
1 all IPinfo IPv4 source rows route ASN supplied 4398 5000 87.960000 available None
2 all IPinfo IPv4 source rows IPinfo ASN supplied 4421 5000 88.420000 available None
3 all IPinfo IPv4 source rows both ASNs supplied 4397 5000 87.940000 available None
4 all IPinfo IPv4 source rows ASN agreements 4352 4397 98.976575 available None
5 all IPinfo IPv4 source rows ASN disagreements 45 4397 1.023425 available None
6 IPinfo country_code=GB IPv4 source rows sample rows 5000 67290 7.430525 available None
7 IPinfo country_code=GB IPv4 source rows route ASN supplied 4369 5000 87.380000 available None
8 IPinfo country_code=GB IPv4 source rows IPinfo ASN supplied 4388 5000 87.760000 available None
9 IPinfo country_code=GB IPv4 source rows both ASNs supplied 4366 5000 87.320000 available None
10 IPinfo country_code=GB IPv4 source rows ASN agreements 4345 4366 99.519011 available None
11 IPinfo country_code=GB IPv4 source rows ASN disagreements 21 4366 0.480989 available None
scope source denominator_sample_rows route_asn_unavailable route_asn_unavailable_pct no_source_record no_source_record_pct classification_missing_or_empty classification_missing_or_empty_pct usable_classification usable_classification_pct status reason
0 all IPinfo IPv4 source rows PeeringDB 5000 602 12.04 900 18.00 301 6.02 3197 63.94 available None
1 all IPinfo IPv4 source rows Stanford ASdb 5000 602 12.04 69 1.38 0 0.00 4329 86.58 available None
2 IPinfo country_code=GB IPv4 source rows PeeringDB 5000 631 12.62 525 10.50 157 3.14 3687 73.74 available None
3 IPinfo country_code=GB IPv4 source rows Stanford ASdb 5000 631 12.62 31 0.62 0 0.00 4338 86.76 available None

In the 5,000-row IPinfo GB sample, 4,366 rows supplied both ASNs; 21 disagreed, or 0.48% of comparable rows. PeeringDB supplied a usable classification for 73.74% of all sampled rows and ASdb for 86.76%; these denominators include the 12.62% without a route ASN, for which route-joined classifications could not be attempted. IPinfo country here is IP-range geolocation, not ASN country. The disagreement count is a prompt to inspect snapshot timing, range specificity, and source methodology, not evidence that either ASN source is generally wrong.

The identifiers in the synchrony experiment, such as ip_res_000607, are deliberately synthetic and are not submitted to these public lookup services. A separate authored fixture in notebooks/methodology_synchrony.ipynb demonstrates how network context can be joined to those scenario identifiers. It is labelled as scenario data and does not measure public-list accuracy or real-world detection performance.

Lookup mechanics that change the result

Provider overlap and route-origin semantics

IP ranges are nested, so a lexical join is insufficient, but the correct policy depends on the source. Provider enrichment returns all matching detailed records so overlaps remain visible. IPinfo contains both CIDRs and single-address rows, so its index applies longest-prefix matching. Raw routing prefixes generally require source-defined best-match semantics; the IPtoASN input used by the companion implementation is already a resolved, non-overlapping address-range table, so the code looks up its containing interval rather than inventing another longest-prefix rule.

IPv4 and IPv6 are separate paths

Converting IPv4 to a 32-bit integer gives a fast interval lookup, but that implementation does not generalise unchanged to IPv6. The IPinfo and provider indexes use integer prefixes for both families; IPv4-mapped IPv6 addresses are deliberately normalized to IPv4. The route table and community interval lists remain IPv4-only. An IPv6 address presented to one of those sources produces NA, not False.

Snapshot before transform

For every mutable download:

  1. save the original bytes under a dated path;
  2. record the URL, actual retrieval time, publisher update time if supplied, and SHA-256;
  3. parse into a derived table without modifying the raw artifact;
  4. version the lookup policy as well as the data;
  5. retain the snapshot needed to reproduce an event-time result.

Filesystem modification time is recorded separately when useful. It is not a substitute for retrieval time: a copied local file with no retrieval record keeps retrieved_at missing.

This is especially important for Tor exits, BGP-derived route origins, and cloud feeds, all of which change over time.

Test meaning, not just code

A lookup implementation needs boundary cases: first and last address in a prefix, addresses immediately outside it, overlapping prefixes, malformed input, private and reserved space, IPv4-mapped IPv6, ordinary IPv6, and duplicate source rows. It also needs semantic checks: a missing source record must not become a risk flag, and a match must not become an abuse label.

Dated coverage measurements

The executed notebook calculates these figures from the available, hash-recorded local artifacts. “Addresses” counts the union represented by each internally non-overlapping IPv4 CIDR file; it is not a count of observed users or active hosts. If a source is missing, its row is explicitly unavailable rather than zero:

networks addresses pct_of_ipv4 status reason
source
X4BNet VPN 10931 3170072 0.07 available None
X4BNet datacentre 44584 395597872 9.21 available None
rezmoss provider union (IPv4) 12842 255279702 5.94 available None

Expanding the X4BNet datacentre ranges to one dotted IPv4 address per line would produce about 5.55 GB of text (5.17 GiB), calculated from the ranges without materialising that file. Range lookup avoids that expansion.

The lists are not independent. X4BNet defines its datacentre output as VPNs and datacentres, while its VPN output is intended to be the narrower list. The overlap calculation is also guarded against missing inputs and empty denominators:

overlap_addresses denominator_addresses overlap_share status reason
comparison
provider union also in X4BNet datacentre 234191767 255279702 0.917393 available None
X4BNet VPN also in X4BNet datacentre 3145854 3170072 0.992360 available None

In this run:

  • 3,145,854 of 3,170,072 VPN addresses (99.24%) were also covered by the X4BNet datacentre list;
  • 8,249 of 10,931 VPN network starts fell inside a datacentre network, and 8,242 whole VPN networks were contained there;
  • 234,191,767 of the 255,279,702 rezmoss merged IPv4 addresses (91.74%) were covered by X4BNet datacentre.

The address-intersection figures are exact for these three normalized snapshots. The 8,249 start-point figure is retained only as a rough network-level diagnostic; it is not evidence that one file is a strict CIDR-level superset of the other. Agreement analysis must account for this construction instead of treating the lists as independent votes.

Other profiles help explain the source limitations:

Artifact Snapshot result Interpretation
rezmoss all_providers.json 466,400 rows; 299,342 IPv6 (64.18%) Row count is not address-space coverage; IPv4 and IPv6 need separate lookup paths
IPinfo Lite 4,275,771 network/single-address rows; 835,909 missing ASN values Row count is not address-space coverage; longest-prefix matching preserves more-specific rows
PeeringDB active networks 35,735 rows; 10,370 known empty info_types lists A known empty list supports checked category False; an absent record still remains NA
Stanford ASdb 115,490 ASN rows; 137 columns Multiple category pairs apply and their ordering has no significance
bad-asn-list.csv 742 rows; 723 unique ASNs Duplicate ASNs must be removed before matching
bad-asn-list.csv, 16-bit ASN 641 rows; 623 unique ASNs The older-ASN skew is consistent with dated coverage, but does not by itself measure freshness or recall
source path retrieved_at source_updated_at file_mtime sha256 url status reason
0 IPtoASN data/IP/ip2asn-combined.tsv.gz None None 2026-10-24T12:38:06+00:00 7336abc7611351b0261023c6268293bc9d4a02fb32a3ea... https://iptoasn.com/data/ip2asn-combined.tsv.gz available None
1 PeeringDB notebooks/peeringdb-net.json None 2026-10-24T16:21:34+00:00 2026-10-24T19:41:12+00:00 ccdcaea36cef0b2752c1b53abafae8c06c3d4684ad39e2... https://www.peeringdb.com/api/net available None
2 IPinfo Lite data/IP/ipinfo_lite.parquet None None 2026-10-24T13:02:50+00:00 9972cc59727492fec87ddb1da55c14faeabb75362401d3... https://ipinfo.io/developers/ipinfo-lite-database available None
3 rezmoss aggregate data/raw/ip-enrichment/2026-10-25/rezmoss_all_... 2026-10-25T10:54:51+00:00 None 2026-10-25T10:54:51+00:00 fa5c03243d283b27af15bf7cad73f42cf768e21f9c0654... https://raw.githubusercontent.com/rezmoss/clou... available None
4 Stanford ASdb data/IP/2026-03_categorized_ases.csv None None 2026-10-24T12:39:51+00:00 00ba179031d6eac793638c9ad1dd2ff03f71424b53a2f4... https://asdb.stanford.edu/about available None
5 X4BNet VPN IPv4 data/raw/ip-enrichment/2026-10-25/x4bnet_vpn_i... 2026-10-25T10:54:43+00:00 None 2026-10-25T10:54:43+00:00 d5555f06a151141d08d79bbbcb96150f979860b48d8bfd... https://raw.githubusercontent.com/X4BNet/lists... available None
6 X4BNet datacentre IPv4 data/raw/ip-enrichment/2026-10-25/x4bnet_datac... 2026-10-25T10:54:43+00:00 None 2026-10-25T10:54:43+00:00 380eccc1e05d05b3535dff6c380a0fb9d8bd6978018c97... https://raw.githubusercontent.com/X4BNet/lists... available None
7 bad-asn-list data/raw/ip-enrichment/2026-10-25/bad_asn_list... 2026-10-25T10:54:51+00:00 None 2026-10-25T10:54:51+00:00 0af8e58dc07ba070a10c9083a1a9f5c9fc76be35fab32b... https://raw.githubusercontent.com/brianhama/ba... available None
8 Tor bulk exit list data/raw/ip-enrichment/2026-10-25/tor_bulk_exi... 2026-10-25T10:54:51+00:00 None 2026-10-25T10:54:51+00:00 6756af70704aa18c358c48563b54ec27c962b86f0dc2b5... https://check.torproject.org/torbulkexitlist available None

The provenance evidence and source manifest are recorded in notebooks/public_ip_enrichment_demo.ipynb; the earlier exploratory audit remains in notebooks/temp_ips.ipynb and notebooks/ip_enrichment_snapshot.py. The notebook keeps genuine hash-matched manifest retrieval times, evidenced publisher generation/update times, and filesystem modification times separate, and leaves unknown values missing. No new raw dataset is added as a site asset or branch change.

What the exploration established

The notebook proved that the source families can be downloaded, parsed, and joined locally. It also exposed the design decisions that need to precede a reusable pipeline:

  • a current Tor list is simple to match but inappropriate for historical claims;
  • the rezmoss aggregate carries provider, service, and region fields from its upstream inputs, but this exploration did not validate them against the first-party feeds;
  • multi-provider aggregates contain IPv4, IPv6, and overlapping entries, so row counts are not address-space coverage;
  • PeeringDB adds readable organisational context but uses self-reported types and incomplete coverage;
  • broad VPN/datacentre lists cover hundreds of millions of addresses and should be stored as ranges, not expanded into individual IP addresses;
  • a curated hosting-ASN list is a heuristic whose incremental coverage and false-positive exposure should be measured before use.

This produces design guidance and coverage measurements, not a predictive finding. Building a universal “bad infrastructure” detector from these sources would overstate what the data can support.

What to measure next

The next useful experiment is comparative, not additive. Given a dated set of login IPs:

  1. enrich it with route origin and first-party provider/Tor snapshots;
  2. apply each community range or ASN heuristic separately;
  3. measure agreement, unique additions, missingness, and stability across snapshots;
  4. inspect disagreements by network type and prefix size;
  5. only then test whether any feature adds predictive value against an independently obtained outcome label.

Without the last step, the output remains infrastructure description. That is still useful—as long as it is named honestly.

Sources used on this page

Source Use here Licence or access note checked for this draft
X4BNet lists_vpn VPN and combined VPN/datacentre IPv4 lists Repository says the scripts, source files, and generated output are MIT licensed
rezmoss cloud-provider-ip-addresses Unified provider table and merged IPv4 comparison list Repository is dedicated under CC0 1.0; that does not remove any separate conditions attached to upstream feeds
IPtoASN Exploratory IP-to-ASN and country table Site labels the downloadable database PDDL 1.0
Stanford ASdb Local multi-label ASN industry-category artifact Public research download; no artifact-linked publication date or explicit dataset licence is recorded here, so further raw redistribution is not assumed
IPinfo Lite CIDR country/continent and independent ASN metadata CC BY-SA 4.0 with attribution to IPinfo; adaptations distributed from it must preserve the share-alike terms
PeeringDB Network metadata and self-described info_types The AUP permits Internet research and analysis but restricts bulk onward distribution; the pre-existing local snapshot is not copied into site assets
CAIDA RouteViews Prefix-to-AS Historical routing source Public AUA requires citation and publication reporting
CAIDA AS Classification Legacy classifier example Unsupported legacy dataset; no download access
Tor Project exit-list service Interpretation of the default bulk list and CollecTor pointer Exact notebook endpoint named in the text; unavailable retrieval remains NA
Hamachek bad-asn-list Curated hosting-ASN heuristic (SRC-052) MIT; treated as an anecdotal defensive artifact, not ground truth
AWS IP ranges First-party alternative not tested in this run Documentation says ip-ranges.json omits some services and BYOIP ranges
Google Cloud IP ranges First-party alternative not tested in this run Documentation describes cloud.json as customer-usable global and regional external ranges

Related reading