Skip to content

Instantly share code, notes, and snippets.

@roytam1
Created May 20, 2017 23:29
Show Gist options
  • Save roytam1/2b5d5439dd241ed24009d725bf235c12 to your computer and use it in GitHub Desktop.
Save roytam1/2b5d5439dd241ed24009d725bf235c12 to your computer and use it in GitHub Desktop.
<?php
class _prepend_cf_ips {
var $cf_ipv4;
var $cf_ipv6;
function _IPv4_CIDRmatch($addr,$cidr) {
list($ip, $mask) = explode('/', $cidr);
return (ip2long($addr) >> (32 - $mask) == ip2long($ip.str_repeat('.0', 3 - substr_count($ip, '.'))) >> (32 - $mask));
}
function _inet_pton($ip){
//ipv4
if (strpos($ip, '.') !== FALSE) {
$ip = trim($ip,':f');
$ip = pack('N',ip2long($ip));
}
//ipv6
elseif (strpos($ip, ':') !== FALSE) {
//Short ipv6 fix by NewEraCracker
$_count = count(explode(':', $ip));
while($_count<8)
{
$ip = str_replace('::',':0::',$ip);
$_count++;
}
unset($_count);
//Newfags can't triforce!
$ip = explode(':', $ip);
$res = str_pad('', (4*(8-count($ip))), '0000', STR_PAD_LEFT);
foreach ($ip as $seg) {
$res .= str_pad($seg, 4, '0', STR_PAD_LEFT);
}
$ip = pack('H'.strlen($res), $res);
}
return $ip;
}
function _inet_ntop($ip){
if (strlen($ip)==4){
//ipv4
list(,$ip)=unpack('N',$ip);
$ip=long2ip($ip);
}
elseif(strlen($ip)==16){
//ipv6
$ip=bin2hex($ip);
$ip=substr(chunk_split($ip,4,':'),0,-1);
$ip=explode(':',$ip);
$res='';
foreach($ip as $seg) {
while($seg{0}=='0') $seg=substr($seg,1);
if ($seg!='') {
$res.=($res==''?'':':').$seg;
} else {
if (strpos($res,'::')===false) {
if (substr($res,-1)==':') continue;
$res.=':';
continue;
}
$res.=($res==''?'':':').'0';
}
}
$ip=$res;
}
return $ip;
}
function _IPv6_expand($ip){
$hex = unpack("H*hex", $this->_inet_pton($ip));
$ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1);
return $ip;
}
function _IPv6_compress($ip){
// Shorten first group of zeros
if(substr($ip, 0, 4) === '0000') $ip = substr_replace($ip, ':0', 0, 4);
// Shorten full groups of zeros
$ip = str_replace(':0000', ':0', $ip);
// Remove leading zeros
$ip = preg_replace('/:0{1,3}(?=\w)/', ':', $ip); //return $ip;
// Remove longest extra group of zeros per [RFC 5952](http://tools.ietf.org/html/rfc5952)
$z = ':0:0:0:0:0:0:0:'; // Set chain
while(strpos($ip, '::') === false && strlen($z) >= 5){ // While no :: and chain still possible
$pos = strpos($ip, $z);
if($pos !== false){ $ip = substr_replace($ip, '::', $pos, strlen($z)); break; } // Replace chain and break
$z = substr($z, 0, strlen($z) - 2); // cut away one '0:' to shorten the chain
}
if(substr($ip, 1, 1) !== ':') return ltrim($ip, ':'); // Remove initial : if not a ::
return $ip;
}
function _IPv6_MaskToByteArray($subnetMask) {
$addr = str_repeat("f", $subnetMask / 4);
switch ($subnetMask % 4) {
case 0:
break;
case 1:
$addr .= "8";
break;
case 2:
$addr .= "c";
break;
case 3:
$addr .= "e";
break;
}
$addr = str_pad($addr, 32, '0');
$addr = pack("H*" , $addr);
return $addr;
}
function _IPv6_CidrMatch($address, $subnetAddress, $subnetMask) {
$binMask = $this->_IPv6_MaskToByteArray($subnetMask);
return ($address & $binMask) == $subnetAddress;
}
function _prepend_cf_ips() {
$targetip = strncmp($_SERVER['REMOTE_ADDR'],'::ffff:',7) === 0 ? substr($_SERVER['REMOTE_ADDR'], 7) : $_SERVER['REMOTE_ADDR'];
$this->cf_ipv4=explode("\n",'103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
104.16.0.0/12
108.162.192.0/18
131.0.72.0/22
141.101.64.0/18
162.158.0.0/15
172.64.0.0/13
173.245.48.0/20
188.114.96.0/20
190.93.240.0/20
197.234.240.0/22
198.41.128.0/17
199.27.128.0/21');
$this->cf_ipv6=explode("\n",'2400:cb00::/32
2405:8100::/32
2405:b500::/32
2606:4700::/32
2803:f800::/32
2c0f:f248::/32
2a06:98c0::/29');
if(strpos($targetip,':') === false) { // IPv4
foreach($this->cf_ipv4 as $i) {
if($this->_IPv4_CIDRmatch($targetip,$i)) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
break;
}
}
} else { // IPv6
foreach($this->cf_ipv6 as $i) {
list($net,$maskbits)=explode('/',$i);
if($this->_IPv6_CidrMatch($this->_inet_pton($targetip),$this->_inet_pton($this->_IPv6_expand($net)),$maskbits)) {
$_SERVER['REMOTE_ADDR'] = $this->_IPv6_compress($_SERVER['HTTP_CF_CONNECTING_IP']);
break;
}
}
}
}
}
if(isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$_prep_cf_ip = new _prepend_cf_ips();
unset($_prep_cf_ip);
unset($_SERVER['HTTP_CF_CONNECTING_IP']);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment