Adres IP odwiedzającego stronę przechowywany jest w zmiennej $_SERVER['REMOTE_ADDR']
. Jednak w sytuacji, gdy klient korzysta z serwera proxy w zmiennej tej pojawi się adres IP proxy, a nie klienta. W dużej części przypadków serwer proxy przekazuje adres klienta, można go więc odczytać w PHP.
W PHP adres IP klienta używającego serwera proxy zwykle znajduje się w tablicy $_SERVER
pod pozycją HTTP_X_FORWARDED_FOR
(dane te są zapisane w następującej postaci: IPclient, IPproxy1, IPproxy2
). Jednak niektóre serwery proxy nie przekazują go wcale – dostępny jest jedynie adres serwera. Jeszcze inne przekazują adres klienta w innym nagłówku HTTP. W takim przypadku adres możemy znaleźć w tablicy $_SERVER
pod jedną z następujących pozycji: HTTP_CLIENT_IP
, HTTP_X_CLUSTER_CLIENT_IP
, HTTP_X_FORWARDED
, HTTP_FORWARDED_FOR
, HTTP_FORWARDED
. Natomiast w $_SERVER['HTTP_VIA']
zawarta jest informacja (zwykle jego nazwa) o serwerze proxy.
W celu sprawdzenia wartości tych zmiennych możemy napisać w PHP prosty skrypt:
/** * Zwraca w postaci ciągu znaków (nadającego się np. do dołączenia do nagłówka e-maila) * informacje o IP klienta przekazane przez serwer proxy w odpowiednich zmiennych * * @return string */ function get_client_info() { $info = ''; foreach ( array('REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'HTTP_VIA') as $key) { if (array_key_exists($key, $_SERVER) === true) { $info .= $key . ': ' . $_SERVER[$key] . PHP_EOL; } } return $info; }
Jako wynik działania funkcji zobaczymy np. coś takiego:
REMOTE_ADDR: 84.10.1.42
HTTP_X_FORWARDED_FOR: 70.8.128.16, 127.0.0.1,84.10.1.42
HTTP_VIA: 1.1 (frontal)serwer.profuturo.edu.pl (squid/3.1.19), 1.1 (external)serwer.profuturo.edu.pl (squid/3.1.19)
Gdzie 84.10.1.42
jest adresem IP serwera proxy, natomiast 70.8.128.16
adresem klienta.
Do praktycznego zastosowania można napisać funkcję która zwraca pojedynczy adres IP:
/** * Zwraca w postaci ciągu znaków adres IP klienta * * @return string */ function get_ip() { foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) { if (array_key_exists($key, $_SERVER) === true) { foreach (explode(',', $_SERVER[$key]) as $ip) { $ip = trim($ip); //sprawdzamy czy zawartość $ip jest adresem IP, //nie jest prywatnym adresem IP (IPv4: 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16; IPv6: zaczynające się od FD lub FC) //nie jest innym zarezerwowanym zakresem IP (IPv4: 0.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24 i 224.0.0.0/4) if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) { return $ip; } } } } }
Jako wynik działania funkcji zobaczymy adres IP klienta:
Należy mieć na uwadze, że najbardziej wiarygodna jest zawartość $_SERVER['REMOTE_ADDR']
, pozostałe wartości mogą być w bardzo prosty sposób ustawione przez użytkownika (chociażby przez instalację wtyczki modyfikującej nagłówki wysyłane do serwera).