CloudFlare và ghi địa chỉ IP của khách truy cập thông qua bằng PHP


82

Tôi đang cố gắng theo dõi và ghi nhật ký người dùng / khách truy cập đang truy cập trang web của tôi bằng PHP $_SERVER['REMOTE_ADDR']để làm như vậy. Một phương pháp điển hình để theo dõi địa chỉ IP trong PHP.

Tuy nhiên, tôi đang sử dụng CloudFlare để lưu vào bộ nhớ đệm và như vậy và nhận địa chỉ IP của chúng dưới dạng CloudFlare của:

108.162.212. * - 108.162.239. *

Phương pháp chính xác để truy xuất địa chỉ IP của người dùng / khách truy cập thực tế trong khi vẫn sử dụng CloudFlare là gì?

Câu trả lời:


239

Các biến máy chủ bổ sung có sẵn cho đám mây bùng phát là:

$_SERVER["HTTP_CF_CONNECTING_IP"] địa chỉ ip của khách truy cập thực, đây là những gì bạn muốn

$_SERVER["HTTP_CF_IPCOUNTRY"] đất nước của du khách

$_SERVER["HTTP_CF_RAY"]

$_SERVER["HTTP_CF_VISITOR"] điều này có thể giúp bạn biết liệu http hay https của nó

bạn có thể sử dụng nó như thế này:

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

Nếu bạn làm điều này và tính hợp lệ của địa chỉ IP truy cập là quan trọng, bạn có thể cần xác minh rằng địa chỉ $_SERVER["REMOTE_ADDR"]này có chứa địa chỉ IP cloudflare hợp lệ thực tế hay không, vì bất kỳ ai cũng có thể giả mạo tiêu đề nếu họ có thể kết nối trực tiếp với IP máy chủ.


15
+1 để thay thế REMOTE_ADDR bằng IP thực, vì vậy không cần sửa đổi mã nào khác.
aalaap

11
Nếu vấn đề Bảo mật, bạn nên kiểm tra xem yêu cầu có đến từ Dải IP Cloudflare ( cloudflare.com/ips ) hay không. Ví dụ như trong Joomla này! Plugin: github.com/piccaso/joomla-cf/blob/master/cf/cf.php
Florian Fida

Cloudflare cũng có mã này được liệt kê trên trang web của họ. support.cloudflare.com/hc/en-us/articles/…
C0nw0nk

Câu trả lời hay nhất, cũng như kudo về việc bao gồm HTTP_CF_IPCOUNTRY, tôi chưa gặp câu trả lời đó trước đây.
David Bell,

http_cf_connecting_ip đôi khi đưa ra những thứ như: 2a01: 6500: a043: 33a6: b36a: 7259: 4de5: 2500, bạn có biết tại sao không?
michael

15

Cập nhật : CloudFlare đã phát hành một mô-đun mod_cloudflarecho apache, mô-đun này sẽ ghi nhật ký và hiển thị Địa chỉ IP của khách truy cập thực tế chứ không phải là những địa chỉ được cloudflare truy cập! https://www.cloudflare.com/resources-downloads#mod_cloudflare (Trả lời bởi: olimortimer )

Nếu bạn không có quyền truy cập vào thời gian chạy apache, bạn có thể sử dụng tập lệnh bên dưới, điều này sẽ cho phép bạn kiểm tra xem kết nối có thông qua cloudflare hay không và lấy ip của người dùng.

Tôi đang viết lại câu trả lời của mình mà tôi đã sử dụng cho một câu hỏi khác " CloudFlare DNS / định danh IP trực tiếp "

Các ips của Cloudflare được lưu trữ công khai nên bạn có thể xem chúng tại đây sau đó kiểm tra xem ip có phải từ cloudflare hay không (điều này sẽ cho phép chúng tôi lấy ip thực từ tiêu đề http HTTP_CF_CONNECTING_IP).

Nếu bạn đang sử dụng điều này để tắt tất cả các kết nối không phải cf hoặc ngược lại, tôi khuyên bạn nên có một tệp tập lệnh php duy nhất được gọi trước mọi tập lệnh khác chẳng hạn như common.php hoặc pagestart.php, v.v.

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'];
    }
}

Để sử dụng script, nó khá đơn giản:

$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'];

Tập lệnh này sẽ hiển thị cho bạn địa chỉ ip thực và yêu cầu có phải là CF hay không!


Đây là câu trả lời chính xác, tuy nhiên, hãy nhớ rằng bạn cần phải cập nhật IP thường xuyên. Những cái hiện tại trong mã trên đã không hợp lệ và do đó mã sẽ bị lỗi. Bạn có thể tải các IP mới nhất tại đây: cloudflare.com/ips Tốt nhất, bạn nên lưu trữ các IP này trong một tệp để bạn chỉ phải cập nhật tệp bên ngoài hoặc thậm chí tốt hơn, định kỳ tìm nạp chúng từ đây: cloudflare.com/ips-v4
rafark

11

Vì câu hỏi này đã được hỏi và trả lời, CloudFlare đã phát hành mod_cloudflarecho Apache, ghi nhật ký và hiển thị địa chỉ IP của khách truy cập thực tế chứ không phải địa chỉ CloudFlare:

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


2019 - Họ không còn hỗ trợ mod_cloudflare, nhưng nó có thể được sử dụng. Có một cái gì đó mới được gọi là mod_remoteip. Tham khảo: support.cloudflare.com/hc/en-us/articles/…
sinaza

@sinaza có lẽ tốt nhất nên tạo một câu trả lời mới, vì câu trả lời của tôi mod_cloudflarelà từ 4 năm trước
olimortimer

@sjagr liên quan đến các chỉnh sửa của bạn, chúng không chính xác - CloudFlare thực sự là Cloudflare, như tôi đã đăng ban đầu
olimortimer

10

Cloudflare gửi một số tiêu đề yêu cầu bổ sung đến máy chủ của bạn, bao gồm cả tiêu đề CF-Connecting-IPmà chúng tôi có thể lưu trữ vào $user_ip, nếu được xác định, bằng cách sử dụng một lớp lót đơn giản sau:

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

Vấn đề với điều này là đó chỉ là một tiêu đề đơn giản, vì vậy bất kỳ ai cũng có thể đặt nó thành bất kỳ IP nào họ muốn, đây là một lỗ hổng bảo mật rất lớn.
rafark

@rafark Không nếu máy chủ của bạn được định cấu hình đúng và chạy sau Cloudflare.
Sainan

Phải, tất nhiên. Đây là một giải pháp tốt nhưng vẫn nên kiểm tra trước khi sử dụng HTTP_CF_CONNECTING_IP, giống như trong câu trả lời của Callum
rafark

@rafark Tôi cũng đồng ý nhưng đó là rất nhiều mã PHP khủng khiếp đã xuất hiện ở dạng khác trong cấu hình Apache của bạn (tôi hy vọng) và mã này nhiều hơn để cho phép gỡ lỗi dễ dàng và nếu kẻ tấn công có quyền truy cập vào môi trường gỡ lỗi của bạn, tôi nghĩ bạn có nhiều vấn đề quan trọng hơn để giải quyết.
Sainan

2

Sẽ khó chuyển đổi HTTP_CF_CONNECTING_IP sang REMOTE_ADDR. Vì vậy, bạn có thể sử dụng apache (.htaccess) tự động điền trước để làm điều đó. Vì vậy, bạn không cần phải suy nghĩ về việc liệu $_SERVER['REMOTE_ADDR']có giá trị chính xác trong tất cả các tập lệnh PHP hay không.

mã .htaccess

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

mã php (file.php)

<?php

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

Tìm hiểu thêm tại đây


1

HTTP_CF_CONNECTING_IP chỉ hoạt động nếu bạn đang sử dụng cloudflare có thể bạn chuyển trang web của mình hoặc xóa cloudflare, bạn sẽ quên giá trị vì vậy hãy sử dụng mã này.

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


0

Khi bạn đang sử dụng CloudFlare, tất cả các yêu cầu của bạn giữa máy chủ và người dùng của bạn sẽ được định tuyến thông qua các máy chủ CloudFlare.

Trong trường hợp này, có hai phương pháp để lấy Địa chỉ IP thực của người dùng:

  1. Thông qua Tiêu đề máy chủ bổ sung được thêm bởi Máy chủ CloudFlare
  2. Thêm Mô-đun CloudFlare Apache / NGINX trên máy chủ của bạn.

Phương pháp 1: Nhận IP thông qua các tiêu đề máy chủ bổ sung

Bạn có thể sử dụng mã sau để lấy Địa chỉ IP của người dùng:

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

Nó đang hoạt động như thế nào?

CloudFlare thêm một số biến máy chủ bổ sung trong yêu cầu như sau:

$_SERVER["HTTP_CF_CONNECTING_IP"] - Địa chỉ IP thực của người dùng

$_SERVER["HTTP_CF_IPCOUNTRY"] - ISO2 Quốc gia của Người dùng

$_SERVER["HTTP_CF_RAY"] Một chuỗi đặc biệt cho mục đích đăng nhập

Trong đoạn mã trên, chúng tôi đang kiểm tra xem $_SERVER["HTTP_CF_CONNECTING_IP"]có được đặt hay không. Nếu nó ở đó, chúng tôi sẽ coi đó là Địa chỉ IP của người dùng, nếu không, chúng tôi sẽ sử dụng mã mặc định là$_SERVER['REMOTE_ADDR']

Phương pháp 2: Cài đặt Mô-đun Cloudflare trên máy chủ của bạn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.