General; $clientHeaders = @$general['proxy_client_headers']; if (!is_array($clientHeaders)) { $clientHeaders = array(); } $default = '0.0.0.0'; if (isset($_SERVER['REMOTE_ADDR'])) { $default = $_SERVER['REMOTE_ADDR']; } $ipString = self::getNonProxyIpFromHeader($default, $clientHeaders); return IPUtils::sanitizeIp($ipString); } /** * Returns a non-proxy IP address from header. * * @param string $default Default value to return if there no matching proxy header. * @param array $proxyHeaders List of proxy headers. * @return string */ public static function getNonProxyIpFromHeader($default, $proxyHeaders) { $proxyIps = array(); $config = Config::getInstance()->General; if (isset($config['proxy_ips'])) { $proxyIps = $config['proxy_ips']; } if (!is_array($proxyIps)) { $proxyIps = array(); } $proxyIps[] = $default; // examine proxy headers foreach ($proxyHeaders as $proxyHeader) { if (!empty($_SERVER[$proxyHeader])) { // this may be buggy if someone has proxy IPs and proxy host headers configured as // `$_SERVER[$proxyHeader]` could be eg $_SERVER['HTTP_X_FORWARDED_HOST'] and // include an actual host name, not an IP $proxyIp = self::getFirstIpFromList($_SERVER[$proxyHeader], $proxyIps); if (strlen($proxyIp) && stripos($proxyIp, 'unknown') === false) { return $proxyIp; } } } return $default; } /** * Returns the last IP address in a comma separated list, subject to an optional exclusion list. * * @param string $csv Comma separated list of elements. * @param array $excludedIps Optional list of excluded IP addresses (or IP address ranges). * @return string Last (non-excluded) IP address in the list or an empty string if all given IPs are excluded. */ public static function getFirstIpFromList($csv, $excludedIps = null) { $p = strrpos($csv, ','); if ($p !== false) { $elements = explode(',', $csv); foreach ($elements as $ipString) { $element = trim(Common::sanitizeInputValue($ipString)); if(empty($element)) { continue; } $ip = \Piwik\Network\IP::fromStringIP(IPUtils::sanitizeIp($element)); if (empty($excludedIps) || (!in_array($element, $excludedIps) && !$ip->isInRanges($excludedIps))) { return $element; } } return ''; } return trim(Common::sanitizeInputValue($csv)); } }