Mendapatkan IP Pengunjung pada Apache

Posted in Know-How on December 3rd, 2008 – Tags: 1 Comment

Adakalanya ketika memanggil variabel REMOTE_ADDR, IP yang didapat bukanlah IP sebenarnya dari client (pengunjung). Ini mungkin terjadi bila server menggunakan aplikasi seperti Squid, berada di belakang firewall, atau client mengakses situs kita melalui proxy (seperti Google WebAccelerator); yang membuat IP yang tersimpan pada variabel REMOTE_ADDR merupakan IP dari Squid, firewall server atau proxy server.

You can find the English version here: Determine Client IP on Apache Httpd Configuration.

On PHP

Untuk mendapatkan IP sebenarnya dari client (bukan IP proxy), dalam PHP kita bisa membuat suatu fungsi, misalkan ‘get_real_client_ip’, seperti berikut:

function get_real_client_ip() {
    $ip = false;
    if (isset($_SERVER)) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } else {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
    } else {
        if (getenv('HTTP_X_FORWARDED_FOR')) {
            $ip = getenv('HTTP_X_FORWARDED_FOR');
        } elseif (getenv('HTTP_CLIENT_IP')) {
            $ip = getenv('HTTP_CLIENT_IP');
        } else {
            $ip = getenv('REMOTE_ADDR');
        }
    }
    //watch this line below
    if ($ip) {
        $ipa = explode(',', $ip);
        $ip = trim($ipa[0]);
    }
    return $ip;
}

Dan akhirnya kita bisa mendapatkan ‘real’ IP dari client:

$client_ip = get_real_client_ip();
echo $client_ip;

Jika HTTP request yang diterima server datang setelah melewati beberapa proxy, sangat mungkin nilai HTTP_X_FORWARDED_FOR memiliki beberapa IP. Karenanya dalam contoh diatas kita menggunakan ‘explode’ untuk mendapatkan satu IP pertama, yang dipastikan merupakan IP dari client.

On Apache

Hal serupa diatas bisa juga diterapkan untuk Apache. Saya pernah mengalami masalah ini ketika membangun situs Telkom (http://www.telkom.co.id), yang servernya berada di balik firewall. Semua IP yang masuk diterjemahkan menjadi IP firewal internal Telkom, dan bukan IP dari client.

Dengan mengambil contoh PHP diatas, kita bisa melakukannya pula untuk Apache dengan menggunakan directive SetEnvIf untuk mentranslate nilai REMOTE_ADDR.

SetEnvIf X-Forwarded-For "([0-9]{1,3}\.)([0-9]{1,3}\.)([0-9]{1,3}\.)([0-9]{1,3})" REMOTE_ADDR=$1$2$3$4

Sebagaimana disinggung sebelumnya, HTTP_X_FORWARDED_FOR dapat menimpan nilai beberapa IP (tergantung banyaknya proxy/firewall yang dilewati). Dalam contoh diatas, kita menggunakan regex ketika menggunakan directive SetEnvIf untuk mendapatkan nilai IP yang sebenarnya, dan kemudian mengoverwrite nilai REMOTE_ADDR dengan nilai IP yang diperoleh.

Hal lain yang harus diperhatikan, dalam Apache semua parameter HTTP header, seperti HTTP_X_FORWARDED_FOR, ditulis dalam format %{HTTP:X-Forwarded-For}; dimana underscore (”_”) diganti dengan dash (”-”).

Setelah nilai REMOTE_ADDR didapat, maka kita sekarang mendapatkan nilai IP sebenarnya dari client dan dapat dipergunakan untuk membuat log Apache:

LogFormat "%h %u %t" common

dimana %h adalah nilai untuk remote_host, %u untuk remote_user dan %t untuk time acces. Berbagai format untuk membuat log (LogFormat) dapat dilihat di manual Apache.

Others…

Beberapa proxy server atau firewall adakalanya menyimpan nilai IP dari client dalam berbagai variable. Tetapi yang paling umum digunakan adalah HTTP_X_FORWARDED_FOR dan HTTP_CLIENT_IP. Berikut adalah beberapa variable lain yang kadang digunakan:

HTTP_X_FORWARDED_FOR
HTTP_CLIENT_IP
HTTP_X_COMING_FROM
HTTP_X_FORWARDED
HTTP_FORWARDED_FOR
HTTP_FORWARDED
HTTP_FROM
HTTP_VIA
HTTP_COMING_FROM

Dalam Apache, semua variable diatas dapat diperiksa dalam format %{HTTP:variable-name}.


Catatan: Seringkali saya mengalami kesulitan untuk membuat tulisan teknis dalam bahasa Indonesia. Mungkin saya keliru, tapi rasanya menulis hal teknis dalam bahasa Inggris lebih mudah. Atau mungkin saya pribadi harus belajar lebih menuliskan hal-hal teknis dalam bahasa Indonesia; demi memasyarakatkan pengetahuan dalam bahasa sendiri.


One Comment

  1. Salam Mas Zaenal. Terima kasih atas sharingnya. Menarik juga bisa mengetahui IP sebenarnya dari user.
    Thanks atas pelajarannya beberapa tahun lalu sehingga saya kenal PHP dan MySQL dan berhasil menjalankan simulasi bisnis online di http://www.simulasibisnis.com
    Sayang domain-nya tidak diperpanjang dengan baik oleh pengganti saya dan sekarang sudah diambil orang lain.

Leave a Reply