1

I am using Cloudflare and nginx geoip directives:

geoip_country /usr/local/share/GeoIP/GeoIP.dat;
geoip_city /usr/local/share/GeoIP/GeoLiteCity.dat;

They are picking the IP up OK (as pipaddress since the request is marked as forwarded in the header), but is showing the country as SG (the cloudflare proxy location).

Is there anyway if the header HTTP_X_FORWARDED_FOR is set, to get the coutnry of the end user?

<?php
    if (getenv(HTTP_X_FORWARDED_FOR))
    {
        $pipaddress = getenv(HTTP_X_FORWARDED_FOR);
        $ipaddress = getenv(REMOTE_ADDR);
        echo "Your IP address is : ".$pipaddress. " (via proxy $ipaddress) " ;
    }
    else
    {
        $ipaddress = getenv(REMOTE_ADDR);
        echo "Your IP address is : $ipaddress";
    }

    $country = getenv(GEOIP_COUNTRY_NAME);
    $country_code = getenv(GEOIP_COUNTRY_CODE);
    echo "<br/>Your country : $country ( $country_code ) ";
?>

And /etc/nginx/fastcgi_params are below:

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_FILENAME    $request_filename;
fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# Set php-fpm geoip variables
fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
fastcgi_param GEOIP_COUNTRY_CODE3 $geoip_country_code3;
fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;
fastcgi_param GEOIP_CITY_COUNTRY_CODE $geoip_city_country_code;
fastcgi_param GEOIP_CITY_COUNTRY_CODE3 $geoip_city_country_code3;
fastcgi_param GEOIP_CITY_COUNTRY_NAME $geoip_city_country_name;
fastcgi_param GEOIP_REGION $geoip_region;
fastcgi_param GEOIP_CITY $geoip_city;
fastcgi_param GEOIP_POSTAL_CODE $geoip_postal_code;
fastcgi_param GEOIP_CITY_CONTINENT_CODE $geoip_city_continent_code;
fastcgi_param GEOIP_LATITUDE $geoip_latitude;
fastcgi_param GEOIP_LONGITUDE $geoip_longitude;
morleyc
  • 1,120
  • 13
  • 45
  • 86

3 Answers3

4

Your nginx server cannot determine the real IP of the request to pass to PHP. The workaround is to use Nginx's Real IP module.

Check this out https://support.cloudflare.com/hc/en-us/articles/200170706-How-do-I-restore-original-visitor-IP-with-Nginx-

Just add that code snippet from the link to your config file and restart nginx.

2

Extension for the answer by @the_nuts. I threw together a small script which automatically generates geoip_proxy instructions list based on the lists on cloudflare page:

#!/bin/sh
# /etc/nginx/geoip_update.sh
# Update GeoIP proxy list to the current list of cloudflare IP addresses

outfile=$(dirname "$0")/geoip_cloudflare.conf

echo "# Auto-generated by $0" > "$outfile"
(
    curl https://www.cloudflare.com/ips-v4
    curl https://www.cloudflare.com/ips-v6
) | while read ip; do
    echo "geoip_proxy $ip;"
done > "$outfile"
echo List updated.

Usage: launch this script once and it will generate /etc/nginx/geoip_cloudflare.conf file. Then add the following to your http block:

include /etc/nginx/geoip_cloudflare.conf;

Optionally, add the script to cron to update IP lists regularly. Not sure how often do they change though.

Caution: the script is not very optimized, during updates the config/include file will be empty for short time. If nginx is restarted at exactly that time then geoip_proxy instructions won't work.

user47713
  • 123
  • 4
1

The proper way is to set the CloudFlare IP ranges as trusted proxies, using the geoip_proxy directive. No additional modules are required.

As of today, it results in the following:

geoip_proxy 103.21.244.0/22;
geoip_proxy 103.22.200.0/22;
geoip_proxy 103.31.4.0/22;
geoip_proxy 104.16.0.0/12;
geoip_proxy 108.162.192.0/18;
geoip_proxy 131.0.72.0/22;
geoip_proxy 141.101.64.0/18;
geoip_proxy 162.158.0.0/15;
geoip_proxy 172.64.0.0/13;
geoip_proxy 173.245.48.0/20;
geoip_proxy 188.114.96.0/20;
geoip_proxy 190.93.240.0/20;
geoip_proxy 197.234.240.0/22;
geoip_proxy 198.41.128.0/17;
geoip_proxy 2400:cb00::/32;
geoip_proxy 2405:b500::/32;
geoip_proxy 2606:4700::/32;
geoip_proxy 2803:f800::/32;
geoip_proxy 2c0f:f248::/32;
geoip_proxy 2a06:98c0::/29;

You can find the updated list of CloudFlare IPs here: https://www.cloudflare.com/ips/

the_nuts
  • 412
  • 6
  • 18