Skip to content

Fix header_rewrite MaxMind geo lookups for GeoIP2/GeoLite2 mmdb databases#12948

Open
bryancall wants to merge 3 commits intoapache:masterfrom
bryancall:fix-header-rewrite-maxmind-geo
Open

Fix header_rewrite MaxMind geo lookups for GeoIP2/GeoLite2 mmdb databases#12948
bryancall wants to merge 3 commits intoapache:masterfrom
bryancall:fix-header-rewrite-maxmind-geo

Conversation

@bryancall
Copy link
Contributor

@bryancall bryancall commented Mar 6, 2026

Problem

The header_rewrite plugin's MaxMind geo lookup code used incorrect MMDB
field paths that don't match the structure of standard MaxMind GeoIP2
databases (GeoLite2, GeoIP2, DBIP). All geo lookups (%{GEO:COUNTRY},
%{GEO:ASN}, %{GEO:ASN-NAME}) returned (unknown) or -1 even
when the mmdb file loaded successfully. The code queried flat field names
like "country_code" that don't exist -- these databases use nested
structures like country -> iso_code.

Changes

  • Fix country code lookup -- change GEO_QUAL_COUNTRY from flat
    "country_code" to nested "country", "iso_code" path, returning
    the ISO country code (e.g. "KR", "US") consistent with the old GeoIP
    backend's GeoIP_country_code_by_ipnum() behavior
  • Fix null-after-delete bug in initLibrary -- set
    gMaxMindDB = nullptr after delete on MMDB_open failure so
    subsequent calls can retry instead of seeing a dangling pointer
  • Add data validation -- check entry_data.has_data and
    entry_data.type before accessing entry values to avoid reading
    uninitialized data
  • Remove unnecessary MMDB_get_entry_data_list allocation -- the
    MMDB_get_value() API works directly from result.entry, so the
    expensive list allocation/traversal was unnecessary overhead on every
    geo lookup

Testing

  • Standalone MMDB test program verified field paths against DBIP
    Country Lite and ASN Lite databases on eris (ASAN build)
  • Korean IP (1.201.194.27): COUNTRY: KR
  • Google DNS (8.8.8.8): COUNTRY: US
  • ASN db (1.201.194.27): ASN-NAME: KINX, ASN: 9286
  • Loopback (127.0.0.1): correctly returns (unknown) / -1
  • mmdblookup confirms paths match database structure

Fixes: #11812

The MaxMind geo lookup code used incorrect field paths that don't match
the structure of standard GeoLite2 and DBIP mmdb databases. Country
lookups used a flat "country_code" field that doesn't exist; the correct
path is "country" -> "names" -> "en" for country name and "country" ->
"iso_code" for the ISO code.

Changes:
- Fix GEO_QUAL_COUNTRY to use nested path "country/names/en"
- Add missing GEO_QUAL_COUNTRY_ISO support using "country/iso_code"
- Add has_data and type checks before accessing entry data
- Fix memory leak: set gMaxMindDB to nullptr after delete on open failure
- Ensure entry_data_list is freed on all code paths

Verified with DBIP Country Lite and ASN Lite databases using the same
MMDB_get_value paths. Matches the field paths used by maxmind_acl plugin.

Fixes: apache#11812
@bryancall bryancall added this to the 11.0.0 milestone Mar 6, 2026
@bryancall bryancall self-assigned this Mar 6, 2026
@bryancall bryancall added Bug header_rewrite header_rewrite plugin labels Mar 6, 2026
@bryancall
Copy link
Contributor Author

[approve ci autest 1]

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the header_rewrite plugin’s MaxMind (MMDB) geo lookup implementation to better match the field layout used by standard GeoLite2 / DBIP databases, and improves cleanup/error-handling around lookups and initialization.

Changes:

  • Adjust MMDB lookup paths for geo string fields and add handling for GEO_QUAL_COUNTRY_ISO in the string lookup function.
  • Improve robustness by validating entry_data before reading values and ensuring MMDB entry data lists are freed on more return paths.
  • Fix a retry reliability issue by nulling gMaxMindDB after delete on MMDB_open() failure.

You can also share your feedback on Copilot code review. Take the survey.

- GEO_QUAL_COUNTRY now returns iso_code ("KR") instead of English
  name ("South Korea"), matching the GeoIP backend behavior
- Remove dead GEO_QUAL_COUNTRY_ISO case from get_geo_string() since
  the dispatcher routes it to get_geo_int()
- Remove unnecessary MMDB_get_entry_data_list() allocation -- the
  MMDB_get_value() API works directly from result.entry
@bryancall bryancall changed the title Fix header_rewrite MaxMind geo lookups for standard mmdb databases Fix header_rewrite MaxMind geo lookups for GeoIP2/GeoLite2 mmdb databases Mar 6, 2026
Adds a test that verifies the MMDB lookup paths used by the
geo conditions (country/iso_code, country/names/en) work correctly
against a real MaxMind or DBIP database. The test skips gracefully
if no MMDB file is available, and can be pointed at a specific file
via MMDB_COUNTRY_PATH environment variable.
int gai_error, mmdb_error;
MMDB_lookup_result_s result = MMDB_lookup_string(&mmdb, "8.8.8.8", &gai_error, &mmdb_error);

if (MMDB_SUCCESS != mmdb_error || !result.found_entry) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bike shed, but do we not want to use the gai_error here (and in the other place) ? Should it be in the error message? I don't know what it contains, but we collect it and never use it.

Copy link
Contributor

@zwoop zwoop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I made a comment, but it's no big deal.

@bryancall bryancall requested a review from cmcfarlen March 9, 2026 22:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug header_rewrite header_rewrite plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ATS 10.0.0, header_rewrite plugin does not work with geoip file (maxmind mmdb)

3 participants