diff options
author | Andreas Gohr <andi@splitbrain.org> | 2006-03-11 19:57:52 +0100 |
---|---|---|
committer | Andreas Gohr <andi@splitbrain.org> | 2006-03-11 19:57:52 +0100 |
commit | 6d8affe6a4c62d13d1cd6051c23ab305145f9db6 (patch) | |
tree | 6dc7a98c995c8dda1c90322b47c16ca587b95950 | |
parent | 21ed2ba400e22a21f7356caf84c837e7a724429e (diff) | |
download | rpg-6d8affe6a4c62d13d1cd6051c23ab305145f9db6.tar.gz rpg-6d8affe6a4c62d13d1cd6051c23ab305145f9db6.tar.bz2 |
enhanced clientIP() function
The function now can optinally return a single IP address and tries
to be clever about which one to choose if multiple were supplied
through X-Forwarded-For headers
darcs-hash:20060311185752-7ad00-085bbed7eeffcff0be8f45417d73c13b733c4332.gz
-rw-r--r-- | _test/cases/inc/common_clientIP.test.php | 147 | ||||
-rw-r--r-- | inc/common.php | 43 |
2 files changed, 184 insertions, 6 deletions
diff --git a/_test/cases/inc/common_clientIP.test.php b/_test/cases/inc/common_clientIP.test.php new file mode 100644 index 000000000..257229811 --- /dev/null +++ b/_test/cases/inc/common_clientIP.test.php @@ -0,0 +1,147 @@ +<?php + +require_once DOKU_INC.'inc/init.php'; +require_once DOKU_INC.'inc/common.php'; + +class common_clientIP_test extends UnitTestCase { + + function test_simple_all(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = ''; + $out = '123.123.123.123'; + $this->assertEqual(clientIP(),$out); + } + + function test_proxy1_all(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = '77.77.77.77'; + $_SERVER['HTTP_X_FORWARDED_FOR'] = ''; + $out = '123.123.123.123,77.77.77.77'; + $this->assertEqual(clientIP(),$out); + } + + function test_proxy2_all(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '77.77.77.77'; + $out = '123.123.123.123,77.77.77.77'; + $this->assertEqual(clientIP(),$out); + } + + function test_proxyhops_all(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '77.77.77.77,66.66.66.66'; + $out = '123.123.123.123,77.77.77.77,66.66.66.66'; + $this->assertEqual(clientIP(),$out); + } + + function test_simple_single(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = ''; + $out = '123.123.123.123'; + $this->assertEqual(clientIP(true),$out); + } + + function test_proxy1_single(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = '77.77.77.77'; + $_SERVER['HTTP_X_FORWARDED_FOR'] = ''; + $out = '77.77.77.77'; + $this->assertEqual(clientIP(true),$out); + } + + function test_proxy2_single(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '77.77.77.77'; + $out = '77.77.77.77'; + $this->assertEqual(clientIP(true),$out); + } + + function test_proxyhops_single(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '77.77.77.77,66.66.66.66'; + $out = '66.66.66.66'; + $this->assertEqual(clientIP(true),$out); + } + + function test_local_all(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1'; + $out = '123.123.123.123,127.0.0.1'; + $this->assertEqual(clientIP(),$out); + } + + function test_local1_single(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1'; + $out = '123.123.123.123'; + $this->assertEqual(clientIP(true),$out); + } + + function test_local2_single(){ + $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '123.123.123.123'; + $out = '123.123.123.123'; + $this->assertEqual(clientIP(true),$out); + } + + function test_local3_single(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1,10.0.0.1,192.168.0.2,172.17.1.1,172.21.1.1,172.31.1.1'; + $out = '123.123.123.123'; + $this->assertEqual(clientIP(true),$out); + } + + function test_local4_single(){ + $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '192.168.0.5'; + $out = '192.168.0.5'; + $this->assertEqual(clientIP(true),$out); + } + + function test_garbage_all(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = 'some garbage, or something, 222'; + $out = '123.123.123.123'; + $this->assertEqual(clientIP(),$out); + } + + function test_garbage_single(){ + $_SERVER['REMOTE_ADDR'] = '123.123.123.123'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = 'some garbage, or something, 222'; + $out = '123.123.123.123'; + $this->assertEqual(clientIP(true),$out); + } + + function test_garbageonly_all(){ + $_SERVER['REMOTE_ADDR'] = 'argh'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = 'some garbage, or something, 222'; + $out = '0.0.0.0'; + $this->assertEqual(clientIP(),$out); + } + + function test_garbageonly_single(){ + $_SERVER['REMOTE_ADDR'] = 'argh'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = 'some garbage, or something, 222'; + $out = '0.0.0.0'; + $this->assertEqual(clientIP(true),$out); + } + + +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/inc/common.php b/inc/common.php index 636b26f0b..ffb78f432 100644 --- a/inc/common.php +++ b/inc/common.php @@ -398,16 +398,47 @@ function checkwordblock(){ /** * Return the IP of the client * - * Honours X-Forwarded-For Proxy Headers + * Honours X-Forwarded-For and X-Real-IP Proxy Headers * + * It returns a comma separated list of IPs if the above mentioned + * headers are set. If the single parameter is set, it tries to return + * a routable public address, prefering the ones suplied in the X + * headers + * + * @param boolean $single If set only a single IP is returned * @author Andreas Gohr <andi@splitbrain.org> */ -function clientIP(){ - $my = $_SERVER['REMOTE_ADDR']; - if($_SERVER['HTTP_X_FORWARDED_FOR']){ - $my .= ' ('.$_SERVER['HTTP_X_FORWARDED_FOR'].')'; +function clientIP($single=false){ + $ip = array(); + $ip[] = $_SERVER['REMOTE_ADDR']; + if($_SERVER['HTTP_X_FORWARDED_FOR']) + $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_FORWARDED_FOR'])); + if($_SERVER['HTTP_X_REAL_IP']) + $ip = array_merge($ip,explode(',',$_SERVER['HTTP_X_REAL_IP'])); + + // remove any non-IP stuff + $cnt = count($ip); + for($i=0; $i<$cnt; $i++){ + $ip[$i] = preg_replace('/[^0-9\.]+/','',$ip[$i]); + if(!preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/',$ip[$i])) $ip[$i] = ''; + if(empty($ip[$i])) unset($ip[$i]); + } + $ip = array_values(array_unique($ip)); + if(!$ip[0]) $ip[0] = '0.0.0.0'; // for some strange reason we don't have a IP + + if(!$single) return join(',',$ip); + + // decide which IP to use, trying to avoid local addresses + $ip = array_reverse($ip); + foreach($ip as $i){ + if(preg_match('/^(127\.|10\.|192\.168\.|172\.((1[6-9])|(2[0-9])|(3[0-1]))\.)/',$i)){ + continue; + }else{ + return $i; + } } - return $my; + // still here? just use the first (last) address + return $ip[0]; } /** |