Martin AJ Martin AJ - 4 months ago 22
PHP Question

How can I track IPs to block malicious users?

Here is a few theories to get user's IP

Theory1: If you don't use a load balancer, use

REMOTE_ADDR
. If you use a load balancer, use whatever it uses. In 99% of cases that appears to be
HTTP_X_FORWARDED_FOR
. So:

function get_ip_address(){
$id = '';
if (isset($_SERVER['REMOTE_ADDR']))
$ip = $_SERVER['REMOTE_ADDR'];
else if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
else
$ip = 'UNKNOWN';
return $ip;
}


Theory2: There is some other HTTP header information (ie.
$_SERVER['HTTP_...]
)
which might be containing the IP. So:

function get_ip_address(){
foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', '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); // just to be safe
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
return $ip;
}
}
}
}
}


Theory3: Storing both one of
$_SERVER['HTTP_...]
and
$_SERVER['REMOTE_ADDR']
. So there is two variables:

function get_ip_address(){
foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED') as $key){
if (array_key_exists($key, $_SERVER) === true){
foreach (explode(',', $_SERVER[$key]) as $ip2){
$ip2 = trim($ip2); // just to be safe
if (filter_var($ip2, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
$ip1 = $_SERVER['REMOTE_ADDR'];
return array($ip2, ip1);
}
}
}
}
}





Well honestly I'm confused a little bit. How many column (in the database) do I need to store the user's IP? I mean should I store both
REMOTE_ADDR
and a
HTTP_...
? Or just one of them?

Actually I have a query which inserts the user's IP per each page loading in the database. So that query will be executed every time before loading of the page. Surely an
INSERT
query (everytime for each request, and each user) has a cost. So I don't want it be useless. I mean I want to store a correct/real IP or at least I want to do the best work which is possible to detect the user's IP * .

* When an user uses a proxy like HSS then detecting him would be impossible. That's why I said "at least".

Ok well, which theory is the best?

Answer

You need to decide when you're storing the IP whether you trust the remote address that's sending the X-FORWARDED-FOR address. If you do, then you store the forwarded address, otherwise you store the remote address. So it could be like this:

$load_balancer = '10.20.30.40';
$ip = $_SERVER['REMOTE_ADDR'];
if (isset($_SERVER['X_FORWARDED_FOR'] && $ip = $load_balancer) {
    $ip = $_SERVER['X_FORWARDED_FOR'];
}

Then log $ip in the database.

I don't see any point in storing the load balancer IP in the database as well. Performing the trust check when processing the database data would require you to have another table that says what the load balancer IP was during different time periods.