convert "::1" and other pseudo-IPv6 addresses that Apache may throw at us to their IPv4 counterparts

This commit is contained in:
Ilmari Karonen 2006-11-29 08:08:57 +00:00
parent 7c21394c41
commit fd989dcea6
2 changed files with 37 additions and 3 deletions

View file

@ -10,11 +10,15 @@
// Some regex definition to "play" with IP address and IP address blocks
// An IP is made of 4 bytes from x00 to xFF which is d0 to d255
define( 'RE_IP_BYTE', '(25[0-5]|2[0-4]\d|1?\d{1,2})');
define( 'RE_IP_BYTE', '(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)');
define( 'RE_IP_ADD' , RE_IP_BYTE . '\.' . RE_IP_BYTE . '\.' . RE_IP_BYTE . '\.' . RE_IP_BYTE );
// An IP block is an IP address and a prefix (d1 to d32)
define( 'RE_IP_PREFIX' , '(3[0-2]|[12]?\d)');
define( 'RE_IP_PREFIX', '(3[0-2]|[12]?\d)');
define( 'RE_IP_BLOCK', RE_IP_ADD . '\/' . RE_IP_PREFIX);
// For IPv6 canonicalization (NOT for strict validation; these are quite lax!)
define( 'RE_IPV6_WORD', '([0-9A-Fa-f]{1,4})' );
define( 'RE_IPV6_GAP', ':(?:0+:)*(?::(?:0+:)*)?' );
define( 'RE_IPV6_V4_PREFIX', '0*' . RE_IPV6_GAP . '(?:ffff:)?' );
class IP {
@ -220,5 +224,33 @@ class IP {
return (($unsignedIP >= $start) && ($unsignedIP <= $end));
}
/**
* Convert some unusual representations of IPv4 addresses to their
* canonical dotted quad representation.
*
* This currently only checks a few IPV4-to-IPv6 related cases. More
* unusual representations may be added later.
*
* @param $addr something that might be an IP address
* @return valid dotted quad IPv4 address or null
*/
public static function canonicalize( $addr ) {
if ( IP::isValid( $addr ) )
return $addr;
// IPv6 loopback address
if ( preg_match( '/^0*' . RE_IPV6_GAP . '1$/', $addr, $m ) )
return '127.0.0.1';
// IPv4-mapped and IPv4-compatible IPv6 addresses
if ( preg_match( '/^' . RE_IPV6_V4_PREFIX . '(' . RE_IP_ADD . ')$/i', $addr, $m ) )
return $m[1];
if ( preg_match( '/^' . RE_IPV6_V4_PREFIX . RE_IPV6_WORD . ':' . RE_IPV6_WORD . '$/i', $addr, $m ) )
return long2ip( ( hexdec( $m[1] ) << 16 ) + hexdec( $m[2] ) );
return null; // give up
}
}
?>

View file

@ -33,7 +33,7 @@ function wfGetIP() {
/* collect the originating ips */
# Client connecting to this webserver
if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
$ipchain = array( $_SERVER['REMOTE_ADDR'] );
$ipchain = array( IP::canonicalize( $_SERVER['REMOTE_ADDR'] ) );
} else {
# Running on CLI?
$ipchain = array( '127.0.0.1' );
@ -47,9 +47,11 @@ function wfGetIP() {
$xff = array_reverse( $xff );
$ipchain = array_merge( $ipchain, $xff );
}
# Step through XFF list and find the last address in the list which is a trusted server
# Set $ip to the IP address given by that trusted server, unless the address is not sensible (e.g. private)
foreach ( $ipchain as $i => $curIP ) {
$curIP = IP::canonicalize( $curIP );
if ( wfIsTrustedProxy( $curIP ) ) {
if ( isset( $ipchain[$i + 1] ) && IP::isPublic( $ipchain[$i + 1] ) ) {
$ip = $ipchain[$i + 1];