apache / trafficserver

Apache Traffic Server™ is a fast, scalable and extensible HTTP/1.1 and HTTP/2 compliant caching proxy server.
https://trafficserver.apache.org/
Apache License 2.0
1.82k stars 806 forks source link

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

Open Solarisbf opened 1 month ago

Solarisbf commented 1 month ago

hello !!

i want to set acl with geoip country.

so, i set header_rewrite plugin configurations about geo.

and i got always same response header below.

i tested this on browser

http://1.201.173.127/cat/cat1.jpg

header result is below.

ats-geo-asn: -1
ats-geo-asn-name: (unknown)
ats-geo-country: (unknown)
ats-geo-country-iso: -1
x-client-ip: 1.201.194.27
x-inbound-ip: 192.168.10.15
x-outbound-ip: 192.168.10.15
x-server-ip: 52.***.***.***  "masking"

my host ip is : 1.201.194.27

thus, expected header result is below

ats-geo-asn: Asia
ats-geo-asn-name: AS
ats-geo-country: South Korea
ats-geo-country-iso: KR

i checked mmdb file is correct

mmdblookup --file /opt/ts/etc/trafficserver/GeoLite2-City.mmdb --ip 1.201.194.27

  {
    "continent":
      {
        "code":
          "AS" <utf8_string>
        "geoname_id":
          6255147 <uint32>
        "names":
          {
            "de":
              "Asien" <utf8_string>
            "en":
              "Asia" <utf8_string>
            "es":
              "Asia" <utf8_string>
            "fr":
              "Asie" <utf8_string>
            "ja":
              "アジア" <utf8_string>
            "pt-BR":
              "Ásia" <utf8_string>
            "ru":
              "Азия" <utf8_string>
            "zh-CN":
              "亚洲" <utf8_string>
          }
      }
    "country":
      {
        "geoname_id":
          1835841 <uint32>
        "iso_code":
          "KR" <utf8_string>
        "names":
          {
            "de":
              "Südkorea" <utf8_string>
            "en":
              "South Korea" <utf8_string>
            "es":
              "Corea del Sur" <utf8_string>
            "fr":
              "Corée du Sud" <utf8_string>
            "ja":
              "大韓民国" <utf8_string>
            "pt-BR":
              "Coreia do Sul" <utf8_string>
            "ru":
              "Республика Корея" <utf8_string>
            "zh-CN":
              "韩国" <utf8_string>
          }
      }
    "location":
      {
        "accuracy_radius":
          200 <uint16>
        "latitude":
          37.511200 <double>
        "longitude":
          126.974100 <double>
        "time_zone":
          "Asia/Seoul" <utf8_string>
      }
    "registered_country":
      {
        "geoname_id":
          1835841 <uint32>
        "iso_code":
          "KR" <utf8_string>
        "names":
          {
            "de":
              "Südkorea" <utf8_string>
            "en":
              "South Korea" <utf8_string>
            "es":
              "Corea del Sur" <utf8_string>
            "fr":
              "Corée du Sud" <utf8_string>
            "ja":
              "大韓民国" <utf8_string>
            "pt-BR":
              "Coreia do Sul" <utf8_string>
            "ru":
              "Республика Корея" <utf8_string>
            "zh-CN":
              "韩国" <utf8_string>
          }
      }
  }

my congurations are below

records.yaml

records:
  http:
    connect_attempts_max_retries: 3
    cache:
      http: 1
      required_headers: 0
      ignore_client_no_cache: 0
      ignore_query: 1
    server_ports: 80 80:ipv6 443:ssl
    normalize_ae: 2
  reverse_proxy:
    enabled: 1
  url_remap:
    pristine_host_hdr: 0
    remap_required: 1
  log:
    logging_enabled: 3
    logfile_dir: var/log/trafficserver
    rolling_enabled: 1
    rolling_interval_sec: 300
    rolling_allow_empty: 1
    rolling_max_count: 10
  ssl:
    client:
      version:
        min: 2
        max: 3
      certification_level: 1
      verify:
        server:
          policy: PERMISSIVE
    server:
      multicert:
        exit_on_load_fail: 0
      cert:
        path: /opt/ts/etc/trafficserver/ssl
      private_key:
        path: /opt/ts/etc/trafficserver/ssl
  diags:
    debug:
      enabled: 1
  output:
    logfile_perm: rwxrwxrwx
    logfile:
      name: traffic.out
      rolling_enabled: 2
      rolling_size_mb: 500
      rolling_min_count: 2

remap.config

** even i set

map http://1.201.173.127 https://jinyong-test-3.s3.ap-northeast-2.amazonaws.com @plugin=compress.so @pparam=compress.config @plugin=header_rewrite.so @pparam=svc/test2222.kinxzone.com/header_rewrite.conf @plugin=conf_remap.so @pparam=svc/test2222.kinxzone.com/conf_remap.yaml
** this point, i did this setting as well but does not work 
........... @plugin=header_rewrite.so @pparam=--geo-db-path=/opt/ts/etc/trafficserver/GeoLite2-City.mmdb @pparam=svc/test2222.kinxzone.com/header_rewrite.conf ...................

plugin.config

header_rewrite.so --geo-db-path=/opt/ts/etc/trafficserver/GeoLite2-City.mmdb

svc/test2222.kinxzone.com/header_rewrite.conf


cond %{REMAP_PSEUDO_HOOK}
set-header X-Kinx-Cdn "LOCAL"

cond %{SEND_REQUEST_HDR_HOOK}
set-header X-Kinx-Cdn "LOCAL"

cond %{READ_RESPONSE_HDR_HOOK} [AND]
cond %{HEADER:Cache-Control} ="" [AND]
cond %{STATUS} >199 [AND]
cond %{STATUS} <400
set-header Cache-Control "max-age=22, public"

cond %{SEND_REQUEST_HDR_HOOK}
set-header Host %{CLIENT-HEADER:Host}
set-header User-Agent %{CLIENT-HEADER:User-Agent}

cond %{SEND_RESPONSE_HDR_HOOK}
set-header name1234 "1234"
set-header name5555 "5555"

cond %{REMAP_PSEUDO_HOOK} [AND]
cond %{HEADER:Content-Type} ="image/bmp" [OR]
cond %{HEADER:Content-Type} ="image/jpeg" [OR]
cond %{HEADER:Content-Type} ="image/gif" [OR]
cond %{HEADER:Content-Type} ="image/png" [OR]
cond %{HEADER:Content-Type} ="video/x-msvideo"
set-header Cache-Control "no-cache"

cond %{SEND_REQUEST_HDR_HOOK}
rm-header Cache-Control

cond %{SEND_RESPONSE_HDR_HOOK}
set-header ATS-Geo-Country %{GEO:COUNTRY}
set-header ATS-Geo-Country-ISO %{GEO:COUNTRY-ISO}
set-header ATS-Geo-ASN %{GEO:ASN}
set-header ATS-Geo-ASN-NAME %{GEO:ASN-NAME}
set-header X-Client-IP %{IP:CLIENT}
set-header X-Inbound-IP %{IP:INBOUND}
set-header X-Server-IP %{IP:SERVER}
set-header X-Outbound-IP %{IP:OUTBOUND}

maybe ATS 10.0.0 does not load mmdb file at all.

please give me any information !

@bneradt @calavera @janfrode @biilmann @jpeach @sekimura @cmcfarlen @bryancall @mlibbey @brbzull0

thanks a lot !

Solarisbf commented 1 month ago

hello !

i am testing header_rewrite acl with geoip (.mmdb file) again and again

but failed always like upside comment.

i checked header_rewrite.so library link as well

root@ats-dev2:/opt/ts/libexec/trafficserver# ldd header_rewrite.so linux-vdso.so.1 (0x00007ffc336f3000) libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f7415e1e000) libswoc-1.5.12.so => /opt/ts/lib/libswoc-1.5.12.so (0x00007f7415d93000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f7415cfc000) libcap.so.2 => /lib/x86_64-linux-gnu/libcap.so.2 (0x00007f7415cf1000) libmaxminddb.so.0 => /lib/x86_64-linux-gnu/libmaxminddb.so.0 (0x00007f7415cea000) libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f7415abc000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7415a9c000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7415873000) /lib64/ld-linux-x86-64.so.2 (0x00007f7415f8e000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f741578c000)

libmaxminddb.so is linked properly

please give me any information when you guys have time !

thanks a lot !!

bryancall commented 1 month ago

@cmcfarlen is going to see if he can reproduce it.

Solarisbf commented 1 month ago

hello guys

i checked traffic.out log as well

root@ats-dev2:/opt/ts/var/log/trafficserver# cat traffic.out | grep geo
[Oct 21 16:40:24.202] traffic_server DIAG: <header_rewrite.cc:454 (TSRemapNewInstance)> (header_rewrite) Remap geo db /opt/ts/etc/trafficserver/GeoLite2-City.mmdb
[Oct 21 17:04:51.998] traffic_server DIAG: <header_rewrite.cc:454 (TSRemapNewInstance)> (header_rewrite) Remap geo db /opt/ts/etc/trafficserver/GeoLite2-City.mmdb
[Oct 21 17:29:20.162] traffic_server DIAG: <header_rewrite.cc:454 (TSRemapNewInstance)> (header_rewrite) Remap geo db /opt/ts/etc/trafficserver/GeoLite2-City.mmdb
[Oct 22 09:51:24.940] traffic_server DIAG: <header_rewrite.cc:454 (TSRemapNewInstance)> (header_rewrite) Remap geo db /opt/ts/etc/trafficserver/GeoLite2-City.mmdb
[Oct 22 09:51:39.052] [ET_NET 1] DIAG: <conditions_geo_maxmind.cc:66 (get_geo_string)> (header_rewrite) MaxMind not initialized; using default value
[Oct 22 09:51:39.052] [ET_NET 1] DIAG: <conditions_geo_maxmind.cc:131 (get_geo_int)> (header_rewrite) MaxMind not initialized; using default value
[Oct 22 09:51:39.052] [ET_NET 1] DIAG: <conditions_geo_maxmind.cc:131 (get_geo_int)> (header_rewrite) MaxMind not initialized; using default value
[Oct 22 09:51:39.052] [ET_NET 1] DIAG: <conditions_geo_maxmind.cc:66 (get_geo_string)> (header_rewrite) MaxMind not initialized; using default value

traffic.out shows header_rewrite module MaxMind not initialized

so, i checked apache traffic server code ( conditions_geo_maxmind.cc )

mgMaxMindDB is not initialized, so it's nullptr

gMaxMindDB = new MMDB_s;
//////////////////////////////////////////////////////////////////////////////////////////////
// conditions_geo_maxmind.cc: Implementation of the ConditionGeo class based on MaxMindDB
//
//

#include <unistd.h>
#include <arpa/inet.h>

#include "ts/ts.h"

#include "conditions_geo.h"

#include <maxminddb.h>

MMDB_s *gMaxMindDB = nullptr;

void
MMConditionGeo::initLibrary(const std::string &path)
{
  if (path.empty()) {
    Dbg(pi_dbg_ctl, "Empty MaxMind db path specified. Not initializing!");
    return;
  }

  if (gMaxMindDB != nullptr) {
    Dbg(pi_dbg_ctl, "Maxmind library already initialized");
    return;
  }

  gMaxMindDB = new MMDB_s;

  int status = MMDB_open(path.c_str(), MMDB_MODE_MMAP, gMaxMindDB);
  if (MMDB_SUCCESS != status) {
    Dbg(pi_dbg_ctl, "Cannot open %s - %s", path.c_str(), MMDB_strerror(status));
    delete gMaxMindDB;
    return;
  }
  Dbg(pi_dbg_ctl, "Loaded %s", path.c_str());
}

std::string
MMConditionGeo::get_geo_string(const sockaddr *addr) const
{
  std::string ret = "(unknown)";
  int         mmdb_error;

  if (gMaxMindDB == nullptr) {
    Dbg(pi_dbg_ctl, "MaxMind not initialized; using default value");
    return ret;
  }

  MMDB_lookup_result_s result = MMDB_lookup_sockaddr(gMaxMindDB, addr, &mmdb_error);

  if (MMDB_SUCCESS != mmdb_error) {
    Dbg(pi_dbg_ctl, "Error during sockaddr lookup: %s", MMDB_strerror(mmdb_error));
    return ret;
  }

  MMDB_entry_data_list_s *entry_data_list = nullptr;
  if (!result.found_entry) {
    Dbg(pi_dbg_ctl, "No entry for this IP was found");
    return ret;
  }

  int status = MMDB_get_entry_data_list(&result.entry, &entry_data_list);
  if (MMDB_SUCCESS != status) {
    Dbg(pi_dbg_ctl, "Error looking up entry data: %s", MMDB_strerror(status));
    return ret;
  }

  if (entry_data_list == nullptr) {
    Dbg(pi_dbg_ctl, "No data found");
    return ret;
  }

  const char *field_name;
  switch (_geo_qual) {
  case GEO_QUAL_COUNTRY:
    field_name = "country_code";
    break;
  case GEO_QUAL_ASN_NAME:
    field_name = "autonomous_system_organization";
    break;
  default:
    Dbg(pi_dbg_ctl, "Unsupported field %d", _geo_qual);
    return ret;
    break;
  }

  MMDB_entry_data_s entry_data;

  status = MMDB_get_value(&result.entry, &entry_data, field_name, NULL);
  if (MMDB_SUCCESS != status) {
    Dbg(pi_dbg_ctl, "ERROR on get value asn value: %s", MMDB_strerror(status));
    return ret;
  }
  ret = std::string(entry_data.utf8_string, entry_data.data_size);

  if (nullptr != entry_data_list) {
    MMDB_free_entry_data_list(entry_data_list);
  }

  return ret;
}

int64_t
MMConditionGeo::get_geo_int(const sockaddr *addr) const
{
  int64_t ret = -1;
  int     mmdb_error;

  if (gMaxMindDB == nullptr) {
    Dbg(pi_dbg_ctl, "MaxMind not initialized; using default value");
    return ret;
  }

  MMDB_lookup_result_s result = MMDB_lookup_sockaddr(gMaxMindDB, addr, &mmdb_error);

  if (MMDB_SUCCESS != mmdb_error) {
    Dbg(pi_dbg_ctl, "Error during sockaddr lookup: %s", MMDB_strerror(mmdb_error));
    return ret;
  }

  MMDB_entry_data_list_s *entry_data_list = nullptr;
  if (!result.found_entry) {
    Dbg(pi_dbg_ctl, "No entry for this IP was found");
    return ret;
  }

  int status = MMDB_get_entry_data_list(&result.entry, &entry_data_list);
  if (MMDB_SUCCESS != status) {
    Dbg(pi_dbg_ctl, "Error looking up entry data: %s", MMDB_strerror(status));
    return ret;
  }

  if (entry_data_list == nullptr) {
    Dbg(pi_dbg_ctl, "No data found");
    return ret;
  }

  const char *field_name;
  switch (_geo_qual) {
  case GEO_QUAL_ASN:
    field_name = "autonomous_system_number";
    break;
  default:
    Dbg(pi_dbg_ctl, "Unsupported field %d", _geo_qual);
    return ret;
    break;
  }

  MMDB_entry_data_s entry_data;

  status = MMDB_get_value(&result.entry, &entry_data, field_name, NULL);
  if (MMDB_SUCCESS != status) {
    Dbg(pi_dbg_ctl, "ERROR on get value asn value: %s", MMDB_strerror(status));
    return ret;
  }
  ret = entry_data.uint32;

  if (nullptr != entry_data_list) {
    MMDB_free_entry_data_list(entry_data_list);
  }

  return ret;
}

trafficserver/plugins/header_rewrite/CMakeLists.txt code is below

maybe TS_USE_HRW_MAXMINDDB is NOT 1

if(maxminddb_FOUND)
  target_compile_definitions(header_rewrite PUBLIC TS_USE_HRW_MAXMINDDB=1)
  target_sources(header_rewrite PRIVATE conditions_geo_maxmind.cc)
  target_link_libraries(header_rewrite PRIVATE maxminddb::maxminddb)
endif()

header_rewrite.cc code is below

So, MMConditionGeo::initLibrary(dbPath) is not compiled maybe ?

static void
initHRWLibraries(const std::string &dbPath)
{
  header_rewrite_ns::plugin_factory.setRuntimeDir(RecConfigReadRuntimeDir()).addSearchDir(RecConfigReadPluginDir());

  if (dbPath.empty()) {
    return;
  }

  Dbg(pi_dbg_ctl, "Loading geo db %s", dbPath.c_str());

#if TS_USE_HRW_GEOIP
  GeoIPConditionGeo::initLibrary(dbPath);
#elif TS_USE_HRW_MAXMINDDB
  MMConditionGeo::initLibrary(dbPath);
#endif
}

AND i checked header_rewrite Makefile

root@ats-dev2:/usr/local/trafficserver/build/plugins/header_rewrite# vim Makefile
        @echo "... test"
        @echo "... header_rewrite"
        @echo "... header_rewrite_parser"
        @echo "... test_header_rewrite"
        @echo "... condition.o"
        @echo "... condition.i"
        @echo "... condition.s"
        @echo "... conditions.o"
        @echo "... conditions.i"
        @echo "... conditions.s"
        @echo "... conditions_geo_maxmind.o"
        @echo "... conditions_geo_maxmind.i"
        @echo "... conditions_geo_maxmind.s"
        @echo "... factory.o"
        @echo "... factory.i"
        @echo "... factory.s"
        @echo "... header_rewrite.o"
        @echo "... header_rewrite.i"
        @echo "... header_rewrite.s"
        @echo "... header_rewrite_test.o"
        @echo "... header_rewrite_test.i"
        @echo "... header_rewrite_test.s"
.............

there is conditions_geo_maxmind, NOT conditions_geo_geoip !!!

### Thus, my expectation is that ATS 10.0.0 does not load maxmind geoip database file or could not find libmaxminddb

** i checked whether libmaxminddb-dev exists or not

root@ats-dev2:/opt/ts/var/log/trafficserver# dpkg -l | grep maxmind
ii  libmaxminddb-dev:amd64             1.5.2-1build2                           amd64        IP geolocation database library (development headers)
ii  libmaxminddb0:amd64                1.5.2-1build2                           amd64        IP geolocation database library

** ats host os is ubuntu 22.04

root@ats-dev2:/opt/ts/libexec/trafficserver# cat /etc/issue
Ubuntu 22.04.4 LTS \n \l

waiting for ATS TEAM Support !!

thanks a lot !

Solarisbf commented 1 month ago

hello ATS Team !

i set header_rewrite option --geo-db-path on plugin.config for global setting

root@ats-dev2:/opt/ts/etc/trafficserver# cat plugin.config
xdebug.so --enable=x-remap,x-cache
regex_revalidate.so -c regex_revalidate.config -l rr_log -f rr_state
header_rewrite.so --geo-db-path=dbip-country-lite-2024-10.mmdb

traffic.out

[Oct 24 14:19:25.400] traffic_server DIAG: <header_rewrite.cc:367 (TSPluginInit)> (header_rewrite) Global geo db /opt/ts/etc/trafficserver/dbip-country-lite-2024-10.mmdb
[Oct 24 14:19:25.400] traffic_server DIAG: <header_rewrite.cc:59 (initHRWLibraries)> (header_rewrite) Loading geo db /opt/ts/etc/trafficserver/dbip-country-lite-2024-10.mmdb
[Oct 24 14:19:25.400] traffic_server DIAG: <conditions_geo_maxmind.cc:56 (initLibrary)> (header_rewrite) Loaded /opt/ts/etc/trafficserver/dbip-country-lite-2024-10.mmdb
[Oct 24 14:19:54.377] [ET_NET 1] DIAG: <conditions_geo_maxmind.cc:66 (get_geo_string)> (header_rewrite) MaxMind not initialized; using default value
[Oct 24 14:19:54.825] [ET_NET 1] DIAG: <conditions_geo_maxmind.cc:66 (get_geo_string)> (header_rewrite) MaxMind not initialized; using default value

same maxmind not initialized.

thanks a lot