Fix header_rewrite MaxMind geo lookups for GeoIP2/GeoLite2 mmdb databases#12948
Fix header_rewrite MaxMind geo lookups for GeoIP2/GeoLite2 mmdb databases#12948bryancall wants to merge 8 commits intoapache:masterfrom
Conversation
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
|
[approve ci autest 1] |
There was a problem hiding this comment.
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_ISOin the string lookup function. - Improve robustness by validating
entry_databefore reading values and ensuring MMDB entry data lists are freed on more return paths. - Fix a retry reliability issue by nulling
gMaxMindDBafterdeleteonMMDB_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
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.
zwoop
left a comment
There was a problem hiding this comment.
Looks good. I made a comment, but it's no big deal.
Check gai_error from MMDB_lookup_string() in the unit test instead of silently ignoring it (per zwoop review comment). Add comments explaining the nested MMDB field paths, nullptr-after-delete fix, data type validation guards, and the dual error code API.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
You can also share your feedback on Copilot code review. Take the survey.
|
[approve ci autest 0] |
Some vendor MMDB databases use flat top-level fields (country_code), while standard GeoLite2/GeoIP2/DBIP databases use nested paths (country/iso_code). Detect the schema on the first successful lookup by probing for the nested path first, then falling back to flat. Cache the result in an atomic for the process lifetime. Add a Python script to generate test MMDB files with both schemas, and rewrite the unit test to verify lookups work against both.
Probe the database at load time with well-known IPs (8.8.8.8, 1.1.1.1, 128.0.0.1) instead of detecting lazily on first lookup. Removes the need for std::atomic and simplifies the hot path.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.
You can also share your feedback on Copilot code review. Take the survey.
- Check for mmdb-writer/netaddr Python modules at CMake configure time before adding the MMDB generation target (prevents Ninja failures when declared outputs are not produced) - Exit non-zero from generate_test_mmdb.py on missing dependencies - Fix skip message to mention both required packages (mmdb-writer netaddr) - Add missing <cstdlib> include for getenv() - Remove unused <arpa/inet.h> and <netdb.h> includes from test file
|
[approve ci autest 2] |
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-1evenwhen the mmdb file loaded successfully. The code queried flat field names
like
"country_code"that don't exist -- these databases use nestedstructures like
country -> iso_code.Changes
GEO_QUAL_COUNTRYfrom flat"country_code"to nested"country", "iso_code"path, returningthe ISO country code (e.g. "KR", "US") consistent with the old GeoIP
backend's
GeoIP_country_code_by_ipnum()behaviorinitLibrary-- setgMaxMindDB = nullptrafterdeleteonMMDB_openfailure toavoid leaving a dangling global pointer
entry_data.has_dataandentry_data.typebefore accessing entry values to avoid readinguninitialized data
MMDB_get_entry_data_listallocation -- theMMDB_get_value()API works directly fromresult.entry, so theexpensive list allocation/traversal was unnecessary overhead on every
geo lookup
paths against a real MaxMind/DBIP database with
gai_errorchecking;skips gracefully when no MMDB file is available
Testing
Country Lite and ASN Lite databases on eris (ASAN build)
COUNTRY: KRCOUNTRY: USASN-NAME: KINX,ASN: 9286(unknown)/-1mmdblookupconfirms paths match database structureFixes: #11812