Changes
- Source attribution now has an ASN fallback. Every IP source record carries three new fields —
asn(integer, e.g.15169),asn_name("Google LLC"), andasn_domain("google.com") — sourced from the bundled IPinfo Lite MMDB. When an IP has no reverse DNS,get_ip_address_info()usesasn_domainas a lookup into the samereverse_dns_map, and if that misses, falls back to the rawasn_name.reverse_dnsandbase_domainstay null on ASN-derived rows so consumers can still distinguish PTR-derived from ASN-derived attribution. - Added
source_asn,source_asn_name,source_asn_domainto CSV output (aggregate + forensic), JSON output, and the Elasticsearch / OpenSearch / Splunk integrations.source_asnis mapped asIntegerat the schema level so consumers can do range queries and numeric sorts; dashboards can prepend"AS"at display time. - Expanded
base_reverse_dns_map.csvwith 500 ASN-domain aliases for the most-routed IPv4 ranges. IPv4-weighted coverage of the bundledipinfo_lite.mmdbwent from ~34% of routed space matching a map entry via ASN domain to ~85%. Every alias is a brand that was already in the map under a different rDNS-base key (e.g. addingcomcast.comalongside the existingcomcast.net), plus a small number of large operators that previously had no entry. 11 entries were also promoted out ofknown_unknown_base_reverse_dns.txtbecause ASN context made their identity unambiguous. - Added
get_ip_address_db_record()inparsedmarc.utils, a single-open MMDB reader that returns country + ASN fields together.get_ip_address_country()is now a thin wrapper. Supports both IPinfo Lite's schema (country_code,asnas"AS15169",as_name,as_domain) and MaxMind's (country.iso_code,autonomous_system_numberas int,autonomous_system_organization) in one pass; ASN is normalized to a plain int from either. MaxMind users who drop in their own ASN MMDB getasn+asn_namepopulated;asn_domainstays null because MaxMind doesn't carry it.
Fixed
get_ip_address_info()now caches entries for IPs without reverse DNS. Previously the cache write was inside theif reverse_dns is not Nonebranch, so every no-PTR IP re-did the MMDB read and DNS attempt on every call.- Fixed three bugs in
parsedmarc/resources/maps/sortlists.pythat silently disabled thetype-column validator and sorted the map case-sensitively, contrary to its documented behavior:- Validator allowed-values map was keyed on
"Type"(capital T), but the CSV header is"type"(lowercase), so every row bypassed validation. - Types were read with trailing newlines via
f.readlines(), so comparisons would not have matched even if the column name had been right. sort_csv()was called withoutcase_insensitive_sort=True, which moved the sole mixed-case key (United-domains.de) to the top of the file instead of into its alphabetical position.
- Validator allowed-values map was keyed on
- Fixed eight pre-existing map rows with invalid or inconsistent
typevalues that the now-working validator surfaced: casing corrections fordhl.com(logistics→Logistics),ghm-grenoble.fr(healthcare→Healthcare), andregusnet.com(Real estate→Real Estate); reclassifiedlodestonegroup.comfrom the nonexistentInsurancetype toFinance; added missingReligionandUtilitiesentries tobase_reverse_dns_types.txtso it matches the README's industry list. - Fixed the
rt.rumap entry: was classified asRT,Government Media, which conflated Rostelecom (the Russian telco that owns and usesrt.ru) with RT / Russia Today (which usesrt.com). Corrected toRostelecom,ISP.
Upgrade notes
- Output schema change: CSV, JSON, Elasticsearch, OpenSearch, and Splunk all gain three new fields per row (
source_asn,source_asn_name,source_asn_domain). Existing queries and dashboards keep working; dashboards that want to consume the new fields will need to be updated. Elasticsearch / OpenSearch will add the new mappings on next document write. - Rows for IPs without reverse DNS now populate
source_name/source_typevia ASN fallback. If downstream dashboards treated "nullsource_name" as a signal for "no rDNS", switch to checkingsource_reverse_dns IS NULLinstead — that remains the unambiguous signal.