leev / ngx_http_geoip2_module

Nginx GeoIP2 module
BSD 2-Clause "Simplified" License
961 stars 182 forks source link

country names don't match iso code with cloutflare frontend #121

Open sitnikov opened 10 months ago

sitnikov commented 10 months ago

There's an nginx with the geoip2 module set up.

geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
auto_reload 24h;
$geoip2_country default=XX country iso_code;
$geoip2_country_name country names en;
}

It receives traffic from Cloudflare, and real_ip is configured.

However, in X_GEOIP2_COUNTRY_NAME, the country is correct, but in X_GEOIP2_COUNTRY_CODE, it's not (it shows the country of Cloudflare)."

image

#> mmdblookup --file  /var/lib/GeoIP/GeoLite2-Country.mmdb --ip 212.7.1.5 country  iso_code

  "EE" <utf8_string>

#> mmdblookup --file  /var/lib/GeoIP/GeoLite2-Country.mmdb --ip 212.7.1.5 country names en

  "Estonia" <utf8_string>
OSPanel commented 6 months ago

212.7.1.5 and 212.7.5.1 are different addresses...

sitnikov commented 6 months ago

Ok :)

this is same newtork

$ mmdblookup --file /var/lib/GeoIP/GeoLite2-Country.mmdb --ip 212.7.5.1 country iso_code "EE"

$ mmdblookup --file /var/lib/GeoIP/GeoLite2-Country.mmdb --ip 212.7.5.1 country names en "Estonia"

OSPanel commented 6 months ago

EE = Estonia, everything is displayed correctly.

sitnikov commented 6 months ago

image

OSPanel commented 6 months ago

The ngx_http_geoip2_module module does not set these headers, look for the problem elsewhere.

sitnikov commented 6 months ago

As far as I remember the configuration was something like this

params.d/proxy.conf: proxy_set_header X-Geoip2-Country-Code $geoip2_country; params.d/proxy.conf: proxy_set_header X-Geoip2-Country-Name $geoip2_country_name;

But half a year has passed since then ...

sitnikov commented 6 months ago

simple index.html with ssi

<pre>
1: <!--# echo var="date_local"  default="???"-->
2: <!--#echo var="HTTP_USER_AGENT"-->
3: <!--#echo var="geoip2_country"-->
4: <!--#echo var="geoip2_country_name"-->
5: <!--#echo var="remote_addr"-->
</pre>

result

image

nginx.conf

geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 24h;
        $geoip2_country_name country names en;
        $geoip2_country default=XX country iso_code;
}

geoip2 /var/lib/GeoIP/GeoLite2-City.mmdb{
        $geoip2_city default=Unknown city names en;
}

geoip2 /var/lib/GeoIP/GeoLite2-ASN.mmdb{
        $geoip2_asn autonomous_system_number;
}

P.S. Let me remind that I use realip and site behind Coudflare.

OSPanel commented 6 months ago

Add _source=$remoteaddr + update .mmdb databases + update and recompile module.

$geoip2_data_country_code default=- source=$remote_addr country iso_code; $geoip2_data_country_name default=- source=$remote_addr country names en;

sitnikov commented 6 months ago
  1. let's go back to the beginning. The meaning of this ticket is that the country code and its name do not match (with the default configuration + realip)

Add _source=$remoteaddr + update .mmdb databases + update and recompile module.

  1. this strangely breaks the realip_module

access.log before this changes 85.253.117.127 - - [25/Mar/2024:08:51:37 +0200] "GET /test/ HTTP/2.0" 200 194 "-" "..." rt=0.000 ut=- isbot=0 https=on cache=- up=- country=DE asn=2586

access.log after this changes 172.70.243.14 - - [25/Mar/2024:08:55:05 +0200] "GET /test/ HTTP/2.0" 200 194 "-" "..." rt=0.000 ut=- isbot=0 https=on cache=- up=- country=DE asn=2586

85.253.117.127 - my ip 172.70.243.14 - cloudflare proxy ip

leev commented 6 months ago

What if you try:

geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 24h;
        $geoip2_country_name source=$http_cf_connecting_ip country names en;
        $geoip2_country source=$http_cf_connecting_ip default=XX country iso_code;
}
sitnikov commented 6 months ago

What if you try:

geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 24h;
        $geoip2_country_name source=$http_cf_connecting_ip country names en;
        $geoip2_country source=$http_cf_connecting_ip default=XX country iso_code;
}

With this configuration, the iso code and name are equal. but my ticket is not about how to fix it at the configuration level, but about why with default configurations they are different. imho It looks like compatibility problem with the reailip module and your module somehow affects its operation.

leev commented 6 months ago

If you can provide a small fully working config that can replicate the issue, I could take a look. But I've tried to replicate locally and can't:

config:

lee@debian:~/nginx-1.24.0/install$ cat conf/nginx.conf
load_module "modules/ngx_http_geoip2_module.so";

events {}

daemon off;

http {
    geoip2 GeoIP2-City.mmdb {
        auto_reload 6h;
        $geoip2_country_name country names en;
        $geoip2_country default=XX country iso_code;
    }

    log_format city '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
            '"$realip_remote_addr" "$http_x_ip" "$geoip2_country_name, $geoip2_country"';

    server {
        listen       8080;
        access_log   logs/access.log city;

        set_real_ip_from  0.0.0.0/0;
    set_real_ip_from ::/0;
        real_ip_header    X-IP;
        real_ip_recursive on;

        location / {
            return 200 "$geoip2_country_name, $geoip2_country\n";
        }
    }
}
lee@debian:~/nginx-1.24.0/install$

request:

lee@debian:~$ curl http://127.0.0.1:8080 -H "X-IP: 85.253.117.127"
Estonia, EE
lee@debian:~$

logs:

lee@debian:~/nginx-1.24.0/install$ tail -f logs/access.log
85.253.117.127 - - [04/Apr/2024:14:20:48 +0000] "GET / HTTP/1.1" 200 12 "-" "curl/8.5.0" "127.0.0.1" "85.253.117.127" "Estonia, EE"
^C
lee@debian:~/nginx-1.24.0/install$
sitnikov commented 6 months ago

I'll try it, it'll take a while

OSPanel commented 3 months ago

What if you try:

geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 24h;
        $geoip2_country_name source=$http_cf_connecting_ip country names en;
        $geoip2_country source=$http_cf_connecting_ip default=XX country iso_code;
}

With this configuration, the iso code and name are equal. but my ticket is not about how to fix it at the configuration level, but about why with default configurations they are different. imho It looks like compatibility problem with the reailip module and your module somehow affects its operation.

There is no issue with the default config. The source IP address must be explicitly specified in the module configuration. You didn't set the correct source initially, which is why you got this result.

I would recommend using this config:

map $http_cf_connecting_ip $x_real_ip {
    '' $remote_addr;
    default $http_cf_connecting_ip;
}

geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
    auto_reload 24h;
    $geoip2_country_name source=$x_real_ip country names en;
    $geoip2_country source=$x_real_ip default=XX country iso_code;
}

I noticed that, for some reason, you think that the ngx_http_realip_module module settings somehow affect the ngx_http_geoip2_module module, but that's not the case.

sitnikov commented 2 months ago

map $http_cf_connecting_ip $x_real_ip { '' $remote_addr; default $http_cf_connecting_ip; }

geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb { auto_reload 24h; $geoip2_country_name source=$x_real_ip country names en; $geoip2_country source=$x_real_ip default=XX country iso_code; }



I noticed that, for some reason, you think that the ngx_http_realip_module module settings somehow affect the ngx_http_geoip2_module module, but that's not the case.

Your configuration is insecure because anyone can set this header and spoof their IP.

Please re-read my first post and check that the module sets the country name - properly and country code - not

How can this be?