- PHP 59.8%
- JSON 15.3%
- Yaml 13%
- Markdown 11%
- XML 0.8%
Geo & ASN Data for Kipchak
Bundled IP-to-country and IP-to-ASN databases in MaxMind DB (MMDB) format, plus a small helper for locating them and normalising the records they return.
This package carries data only — it does no lookups itself. Subashi Pro consumes it for its geo_country and asn firewall conditions. It replaces the previous dependency on the 7x geolocation API, so geo and ASN matching now happen entirely in-process with no network call on the request path.
Composer Package
kipchak/data-geo-asn
What's bundled
Two databases back each lookup type. They are consulted in order: if the first has no record for an address, the second is tried; if neither does, the lookup returns null and the caller is expected to treat that as "unknown" rather than as a match.
| Lookup | Order | Database | Provider | Licence | Upstream cadence | Size |
|---|---|---|---|---|---|---|
| Country | 1st | dbip-country.mmdb | DB-IP IP to Country Lite | CC BY 4.0 | Monthly | 8.0 MB |
| Country | 2nd | iptoasn-country.mmdb | iptoasn.com | PDDL 1.0 | Daily | 5.0 MB |
| ASN | 1st | iptoasn-asn.mmdb | iptoasn.com | PDDL 1.0 | Daily | 9.2 MB |
| ASN | 2nd | dbip-asn.mmdb | DB-IP IP to ASN Lite | CC BY 4.0 | Monthly | 9.1 MB |
iptoasn leads on ASN because it is derived from BGP announcements and rebuilt daily, so it reflects what is actually routed. DB-IP leads on country because it places addresses by observed location rather than by registration — for anycast prefixes the difference is visible (DB-IP puts 1.1.1.1 in AU, iptoasn in US).
MaxMind GeoLite2 is deliberately not bundled. Including GeoLite2 in a commercial product requires a Commercial Redistribution License from MaxMind. Both databases here are freely redistributable.
data/manifest.json records the version, build time, source URL, upstream build date, node count, size, SHA-256 and licence of every file.
Versioning
CalVer, YYYY.MM.DD, matching the day the build ran. A weekly Concourse job publishes a new version. Depend on it with a lower bound only, so composer update always picks up the newest build:
"kipchak/data-geo-asn": ">=2026.9"
Do not use a caret here. ^2026.9 stops matching at 2027.01.04, so the data would silently freeze at the last build of the year until somebody noticed and bumped the constraint. There is no API to break — the package is four data files behind a stable helper — so an upper bound buys nothing.
Usage
use Kipchak\Data\GeoAsn\GeoAsnData;
use MaxMind\Db\Reader;
foreach (GeoAsnData::asnDatabases() as $path) {
$reader = new Reader($path);
$asn = GeoAsnData::asnFromRecord($reader->get('212.58.244.20'));
if ($asn !== null) {
break; // AS2818
}
}
The two country databases do not share a record shape — DB-IP uses the GeoLite2 layout (country.iso_code), iptoasn a flat country_code. GeoAsnData::countryFromRecord() accepts either, so callers never need to know which database answered.
| Method | Returns |
|---|---|
GeoAsnData::countryDatabases() | Ordered list of absolute paths to the country databases |
GeoAsnData::asnDatabases() | Ordered list of absolute paths to the ASN databases |
GeoAsnData::path(string $database) | Absolute path to one database by name; throws if unknown or missing |
GeoAsnData::countryFromRecord(mixed $record) | ISO 3166-1 alpha-2 code, or null |
GeoAsnData::asnFromRecord(mixed $record) | AS number as int, or null |
GeoAsnData::organisationFromRecord(mixed $record) | AS organisation name, or null |
GeoAsnData::manifest() | Full build manifest as an array |
GeoAsnData::version() | Build version, e.g. 2026.09.06 |
GeoAsnData::attributions() | Attribution lines required by the bundled licences |
Reading the databases
Any MMDB reader works. maxmind-db/reader is a require-dev here rather than a hard dependency so that consumers choose their own; Subashi Pro requires it directly.
The pure-PHP reader costs roughly 0.1–0.5 ms per lookup. Under FrankenPHP worker mode the Reader should be constructed once at boot and reused across requests — Subashi Pro does this. Where lookup volume justifies it, maxmind-db/reader-ext is a drop-in C extension that is substantially faster.
Do not decompress the databases into memory. They are shipped uncompressed precisely so the reader can seek within the file.
Building
ci/build.php downloads, verifies and manifests the databases. ci/sources.json holds the source URLs, licences and per-database sanity thresholds.
composer install
php ci/build.php # download, verify, rewrite data/manifest.json
php ci/build.php --verify # verify what is already on disk, rewrite the manifest
The build fails, rather than publishing, if any database is older than its cadence allows, has fewer nodes than expected (which is what a truncated download looks like), is missing IPv6 coverage, or returns the wrong answer for a set of known addresses. Every deployment's firewall reads these files, so a silently corrupt build would fail open everywhere at once.
Run ./vendor/bin/phpunit to check the on-disk files against the manifest checksums and the same known-address expectations.
Pipeline
ci/pipeline.yml is the Concourse pipeline. Copy it into the concourse-pipelines repo and set it:
fly -t mamluk set-pipeline --pipeline kipchak-geo-asn --team mamluk \
--config pipelines/mamluk/kipchak-geo-asn.yml --check-creds
It runs weekly, rebuilds, commits the refreshed databases, tags YYYY.MM.DD, pushes, and notifies Packeton. It also prunes tags older than KEEP_WEEKS and repacks, which bounds the repository: 31 MB of largely incompressible binaries per week would otherwise grow the pack by around 1.6 GB a year.
Licences and attribution
The helper code in src/ is MIT. The databases in data/ keep their upstream licences.
DB-IP data (dbip-country.mmdb, dbip-asn.mmdb) is licensed CC BY 4.0 and requires attribution. Anything that displays results derived from it must carry:
IP geolocation by DB-IP
For a firewall that only accepts or rejects requests there is nothing user-facing to attribute, so this README and NOTICE satisfy the requirement. If you surface country or ASN data in an API response or UI, reproduce the line there too. GeoAsnData::attributions() returns it programmatically.
iptoasn.com data (iptoasn-country.mmdb, iptoasn-asn.mmdb) is PDDL 1.0 — public domain, no attribution required. The MMDB builds come from sapics/ip-location-db.