Saya tahu ada sejumlah besar variabel $ _SERVER header tersedia untuk pencarian alamat IP. Saya bertanya-tanya apakah ada konsensus umum tentang bagaimana cara paling akurat mengambil alamat IP asli pengguna (juga mengetahui tidak ada metode yang sempurna) menggunakan variabel tersebut?
Saya menghabiskan waktu mencoba mencari solusi yang mendalam dan menghasilkan kode berikut berdasarkan sejumlah sumber. Saya akan senang jika seseorang bisa menyodok jawaban atau memberi penjelasan tentang sesuatu yang mungkin lebih akurat.
sunting mencakup optimisasi dari @Alix
/**
* Retrieves the best guess of the client's actual IP address.
* Takes into account numerous HTTP proxy headers due to variations
* in how different ISPs handle IP addresses in headers between hops.
*/
public function get_ip_address() {
// Check for shared internet/ISP IP
if (!empty($_SERVER['HTTP_CLIENT_IP']) && $this->validate_ip($_SERVER['HTTP_CLIENT_IP']))
return $_SERVER['HTTP_CLIENT_IP'];
// Check for IPs passing through proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// Check if multiple IP addresses exist in var
$iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
foreach ($iplist as $ip) {
if ($this->validate_ip($ip))
return $ip;
}
}
}
if (!empty($_SERVER['HTTP_X_FORWARDED']) && $this->validate_ip($_SERVER['HTTP_X_FORWARDED']))
return $_SERVER['HTTP_X_FORWARDED'];
if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && $this->validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && $this->validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
return $_SERVER['HTTP_FORWARDED_FOR'];
if (!empty($_SERVER['HTTP_FORWARDED']) && $this->validate_ip($_SERVER['HTTP_FORWARDED']))
return $_SERVER['HTTP_FORWARDED'];
// Return unreliable IP address since all else failed
return $_SERVER['REMOTE_ADDR'];
}
/**
* Ensures an IP address is both a valid IP address and does not fall within
* a private network range.
*
* @access public
* @param string $ip
*/
public function validate_ip($ip) {
if (filter_var($ip, FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4 |
FILTER_FLAG_IPV6 |
FILTER_FLAG_NO_PRIV_RANGE |
FILTER_FLAG_NO_RES_RANGE) === false)
return false;
self::$ip = $ip;
return true;
}
Words of Warning (pembaruan)
REMOTE_ADDR
masih merupakan sumber alamat IP yang paling dapat diandalkan . $_SERVER
Variabel lain yang disebutkan di sini dapat dipalsukan oleh klien jarak jauh dengan sangat mudah. Tujuan solusi ini adalah untuk mencoba menentukan alamat IP klien yang duduk di belakang proxy. Untuk tujuan umum Anda, Anda dapat mempertimbangkan menggunakan ini dalam kombinasi dengan alamat IP yang dikembalikan langsung dari $_SERVER['REMOTE_ADDR']
dan menyimpan keduanya.
Untuk 99,9% pengguna solusi ini akan sesuai dengan kebutuhan Anda dengan sempurna. Itu tidak akan melindungi Anda dari 0,1% pengguna jahat yang ingin menyalahgunakan sistem Anda dengan menyuntikkan header permintaan mereka sendiri. Jika mengandalkan alamat IP untuk sesuatu misi penting, gunakan REMOTE_ADDR
dan jangan repot-repot melayani mereka yang berada di belakang proxy.