CloudFlare 및 PHP를 통해 방문자 IP 주소 로깅


82

PHP를 사용하여 내 웹 사이트에 액세스하는 사용자 / 방문자를 추적하고 기록하려고합니다 $_SERVER['REMOTE_ADDR']. PHP에서 IP 주소를 추적하는 일반적인 방법입니다.

그러나 저는 캐싱 등에 CloudFlare를 사용하고 있으며 CloudFlare의 IP 주소를 수신하고 있습니다.

108.162.212. *-108.162.239. *

CloudFlare를 계속 사용하면서 실제 사용자 / 방문자 IP 주소를 검색하는 올바른 방법은 무엇입니까?

답변:


239

클라우드 플레어에 사용할 수있는 추가 서버 변수는 다음과 같습니다.

$_SERVER["HTTP_CF_CONNECTING_IP"] 실제 방문자의 IP 주소, 이것은 당신이 원하는 것입니다

$_SERVER["HTTP_CF_IPCOUNTRY"] 방문자 국가

$_SERVER["HTTP_CF_RAY"]

$_SERVER["HTTP_CF_VISITOR"] http 또는 https인지 알 수 있습니다.

다음과 같이 사용할 수 있습니다.

if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
  $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}

이 작업을 수행하고 방문 IP 주소의 유효성이 중요한 $_SERVER["REMOTE_ADDR"]경우 서버 IP에 직접 연결할 수 있으면 누구나 헤더를 위조 할 수 있으므로에 실제 유효한 cloudflare IP 주소 가 포함되어 있는지 확인해야 할 수 있습니다 .


15
REMOTE_ADDR을 실제 IP로 바꾸면 +1이므로 코드를 수정할 필요가 없습니다.
aalaap

11
보안이 중요한 경우에 한 한다 요청이 Cloudflare IP 범위 (에서 오는 있는지 확인 cloudflare.com/ips ). 예를 들어이 Joomla! 플러그인 : github.com/piccaso/joomla-cf/blob/master/cf/cf.php
Florian Fida

Cloudflare는 사이트에도이 코드가 나열되어 있습니다. support.cloudflare.com/hc/en-us/articles/…
C0nw0nk 2015-06-30

최고의 답변이지만 HTTP_CF_IPCOUNTRY를 포함하는 것에 대한 찬사도 전에는 본 적이 없습니다.
David Bell

http_cf_connecting_ip는 때때로 다음과 같은 것을 제공합니다. 2a01 : 6500 : a043 : 33a6 : b36a : 7259 : 4de5 : 2500 이유를 알 수 있습니까?
michael

15

업데이트 : CloudFlare는 mod_cloudflare아파치 용 모듈 을 출시했습니다. 모듈 은 cloudflare가 액세스하는 것이 아닌 실제 방문자 IP 주소를 기록하고 표시합니다! https://www.cloudflare.com/resources-downloads#mod_cloudflare (답변 : olimortimer )

아파치 런타임에 액세스 할 수없는 경우 아래 스크립트를 사용할 수 있습니다. 이렇게하면 연결이 cloudflare를 통해 이루어 졌는지 확인하고 사용자 IP를 얻을 수 있습니다.

다른 질문 " CloudFlare DNS / 직접 IP 식별자 "에 사용한 내 답변을 다시 작성하고 있습니다.

Cloudflare의 ip는 공개되어 있으므로 여기에서 확인한 다음 ip가 cloudflare에서 온 것인지 확인할 수 있습니다 (이를 통해 http 헤더에서 실제 IP를 가져올 수 있습니다 HTTP_CF_CONNECTING_IP).

이것을 사용하여 모든 비 cf 연결을 비활성화하거나 그 반대의 경우 common.php 또는 pagestart.php 등과 같은 다른 모든 스크립트보다 먼저 호출되는 단일 PHP 스크립트 파일을 갖는 것이 좋습니다.

function ip_in_range($ip, $range) {
    if (strpos($range, '/') == false)
        $range .= '/32';

    // $range is in IP/CIDR format eg 127.0.0.1/24
    list($range, $netmask) = explode('/', $range, 2);
    $range_decimal = ip2long($range);
    $ip_decimal = ip2long($ip);
    $wildcard_decimal = pow(2, (32 - $netmask)) - 1;
    $netmask_decimal = ~ $wildcard_decimal;
    return (($ip_decimal & $netmask_decimal) == ($range_decimal & $netmask_decimal));
}

function _cloudflare_CheckIP($ip) {
    $cf_ips = array(
        '199.27.128.0/21',
        '173.245.48.0/20',
        '103.21.244.0/22',
        '103.22.200.0/22',
        '103.31.4.0/22',
        '141.101.64.0/18',
        '108.162.192.0/18',
        '190.93.240.0/20',
        '188.114.96.0/20',
        '197.234.240.0/22',
        '198.41.128.0/17',
        '162.158.0.0/15',
        '104.16.0.0/12',
    );
    $is_cf_ip = false;
    foreach ($cf_ips as $cf_ip) {
        if (ip_in_range($ip, $cf_ip)) {
            $is_cf_ip = true;
            break;
        }
    } return $is_cf_ip;
}

function _cloudflare_Requests_Check() {
    $flag = true;

    if(!isset($_SERVER['HTTP_CF_CONNECTING_IP']))   $flag = false;
    if(!isset($_SERVER['HTTP_CF_IPCOUNTRY']))       $flag = false;
    if(!isset($_SERVER['HTTP_CF_RAY']))             $flag = false;
    if(!isset($_SERVER['HTTP_CF_VISITOR']))         $flag = false;
    return $flag;
}

function isCloudflare() {
    $ipCheck        = _cloudflare_CheckIP($_SERVER['REMOTE_ADDR']);
    $requestCheck   = _cloudflare_Requests_Check();
    return ($ipCheck && $requestCheck);
}

// Use when handling ip's
function getRequestIP() {
    $check = isCloudflare();

    if($check) {
        return $_SERVER['HTTP_CF_CONNECTING_IP'];
    } else {
        return $_SERVER['REMOTE_ADDR'];
    }
}

스크립트를 사용하려면 매우 간단합니다.

$ip = getRequestIP();
$cf = isCloudflare();

if($cf) echo "Connection is through cloudflare: <br>";
else    echo "Connection is not through cloudflare: <br>";

echo "Your actual ip address is: ". $ip;
echo "The server remote address header is: ". $_SERVER['REMOTE_ADDR'];

이 스크립트는 실제 IP 주소와 요청이 CF인지 여부를 보여줍니다!


이것은 정답이지만 IP를 정기적으로 업데이트해야합니다. 위 코드의 현재 코드는 이미 유효하지 않으므로 코드가 실패합니다. 여기에서 최신 IP를 얻을 수 있습니다. cloudflare.com/ips 이상적으로는 외부 파일 만 업데이트하거나 더 나은 방법으로 여기에서 주기적으로 가져 오도록 파일에 저장해야합니다. cloudflare.com/ips-v4
rafark

11

이 질문에 대한 질문과 답변 이후, CloudFlare는 CloudFlare mod_cloudflare주소가 아닌 실제 방문자 IP 주소를 기록하고 표시하는 Apache 용으로 출시 되었습니다.

https://www.cloudflare.com/resources-downloads#mod_cloudflare


2019-더 이상 지원하지 않지만 mod_cloudflare사용할 수 있습니다. 라는 새로운 것이 있습니다 mod_remoteip. 참조 : support.cloudflare.com/hc/en-us/articles/…
sinaza

@sinaza는 아마도 내 대답 mod_cloudflare이 4 년 전 이었기 때문에 새로운 대답을 만드는 것이 가장 좋습니다
olimortimer

@sjagr 편집과 관련하여 잘못되었습니다. CloudFlare는 실제로 Cloudflare입니다. 내가 처음 게시
한대로

10

Cloudflare는 정의 된 경우 다음과 같은 간단한 한 줄을 사용하여에 CF-Connecting-IP저장할 수있는 몇 가지 추가 요청 헤더를 서버에 보냅니다 $user_ip.

$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"])?$_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);

이것의 문제는 그것이 단순한 헤더이기 때문에 누구나 원하는 IP로 설정할 수 있다는 것입니다. 이는 엄청난 보안 취약점입니다.
rafark

@rafark 서버가 적절하게 구성되어 있고 Cloudflare 뒤에 있지 않은 경우.
Sainan

네, 물론입니다. 이것은 그 자체로 좋은 솔루션이지만 Callum의 답변
rafark

@rafark 나도 동의하지만 아파치 설정에 이미 다른 형태로 존재하는 PHP 코드가 엄청나게 많습니다. 처리해야 할 더 중요한 문제가 있습니다.
Sainan

2

HTTP_CF_CONNECTING_IP를 REMOTE_ADDR로 변환하는 것은 어렵습니다. 따라서 아파치 (.htaccess) 자동 추가를 사용하여이를 수행 할 수 있습니다. 따라서 $_SERVER['REMOTE_ADDR']모든 PHP 스크립트에서에 올바른 값이 있는지 생각할 필요가 없습니다 .

.htaccess 코드

php_value auto_prepend_file "/path/to/file.php"

PHP 코드 (file.php)

<?php

define('CLIENT_IP', isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? $_SERVER['HTTP_CF_CONNECTING_IP'] : $_SERVER['REMOTE_ADDR']);

여기에서 더 알아보기


1

HTTP_CF_CONNECTING_IP는 cloudflare를 사용하는 경우에만 작동합니다. 사이트를 전송하거나 cloudflare를 제거하면 값을 잊어 버릴 수 있으므로이 코드를 사용하십시오.

$ip=$_SERVER["HTTP_CF_CONNECTING_IP"];
if (!isset($ip)) {
  $ip = $_SERVER['REMOTE_ADDR'];
}


0

CloudFlare를 사용하는 경우 서버와 사용자 간의 모든 요청은 CloudFlare 서버를 통해 라우팅됩니다.

이 경우 사용자의 실제 IP 주소를 가져 오는 방법에는 두 가지가 있습니다.

  1. CloudFlare 서버에 의해 추가 된 추가 서버 헤더를 통해
  2. 서버에 CloudFlare Apache / NGINX 모듈 추가.

방법 1 : 추가 서버 헤더를 통해 IP 가져 오기

다음 코드를 사용하여 사용자의 IP 주소를 가져올 수 있습니다.

$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"]) $_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);

어떻게 작동합니까?

CloudFlare는 다음과 같이 요청에 몇 가지 추가 서버 변수를 추가합니다.

$_SERVER["HTTP_CF_CONNECTING_IP"] -사용자의 실제 IP 주소

$_SERVER["HTTP_CF_IPCOUNTRY"] -사용자의 ISO2 국가

$_SERVER["HTTP_CF_RAY"] loggin 목적을위한 특수 문자열

위 코드에서 $_SERVER["HTTP_CF_CONNECTING_IP"]설정 여부를 확인하고 있습니다. 존재하는 경우 사용자의 IP 주소로 간주하고 그렇지 않으면 기본 코드를 다음과 같이 사용합니다.$_SERVER['REMOTE_ADDR']

방법 2 : 서버에 Cloudflare 모듈 설치

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.