Index: install/step_templates/sys_config.tpl =================================================================== --- install/step_templates/sys_config.tpl (revision 15552) +++ install/step_templates/sys_config.tpl (working copy) @@ -13,6 +13,7 @@ 'WebsiteCharset' => Array ('type' => 'text', 'title' => 'Website Charset', 'section' => 'Misc', 'required' => 1, 'default' => 'utf-8'), 'EnableSystemLog' => Array ('type' => 'radio', 'title' => 'Enable "System Log"', 'section' => 'Misc', 'required' => 1, 'default' => '0'), 'SystemLogMaxLevel' => Array ('type' => 'select', 'title' => 'Highest "Log Level", that will be saved in "System Log"', 'section' => 'Misc', 'required' => 1, 'default' => '5'), + 'TrustProxy' => Array ('type' => 'radio', 'title' => 'Trust Proxy', 'section' => 'Misc', 'required' => 1, 'default' => '0'), ); $settings['CacheHandler']['options'] = $this->toolkit->getWorkingCacheHandlers(); @@ -22,6 +23,7 @@ 0 => 'emergency', 1 => 'alert', 2 => 'critical', 3 => 'error', 4 => 'warning', 5 => 'notice', 6 => 'info', 7 => 'debug' ); + $settings['TrustProxy']['options'] = Array (1 => 'Yes', 0 => 'No'); $row_class = 'table-color2'; Index: install/steps_db.xml =================================================================== --- install/steps_db.xml (revision 15552) +++ install/steps_db.xml (working copy) @@ -152,6 +152,9 @@ Errors and Warnings, and User defined messages that happened on your website. It has 3 modes - Enabled (logs everything, including user defined messages), User-only (user defined messages only), and Disabled (don't log anything at all - default setting).

+

Trust Proxy - whatever to trust information provided by provided by proxy server (if any) located between web server + and client browser.

+
]]> Index: kernel/application.php =================================================================== --- kernel/application.php (revision 15552) +++ kernel/application.php (working copy) @@ -3038,4 +3038,15 @@ { $this->_logger->delete($unique_id, $storage_medium); } + + /** + * Returns the client IP address. + * + * @return string The client IP address + * @access public + */ + public function getClientIp() + { + return $this->HttpQuery->getClientIp(); + } } \ No newline at end of file Index: kernel/globals.php =================================================================== --- kernel/globals.php (revision 15517) +++ kernel/globals.php (working copy) @@ -491,16 +491,18 @@ */ public static function ipMatch($ip_list, $separator = ';') { - if ( !isset($_SERVER['REMOTE_ADDR']) ) { - // PHP CLI used -> never match + if ( php_sapi_name() == 'cli' ) { return false; } $ip_match = false; $ip_addresses = $ip_list ? explode($separator, $ip_list) : Array (); + $application =& kApplication::Instance(); + $client_ip = $application->getClientIp(); + foreach ($ip_addresses as $ip_address) { - if (self::netMatch($ip_address, $_SERVER['REMOTE_ADDR'])) { + if ( self::netMatch($ip_address, $client_ip) ) { $ip_match = true; break; } Index: kernel/managers/cache_manager.php =================================================================== --- kernel/managers/cache_manager.php (revision 15437) +++ kernel/managers/cache_manager.php (working copy) @@ -340,7 +340,7 @@ $this->getToCache() ); - $cache_rebuild_by = SERVER_NAME . ' (' . getenv('REMOTE_ADDR') . ') - ' . adodb_date('d/m/Y H:i:s'); + $cache_rebuild_by = SERVER_NAME . ' (' . $this->Application->getClientIp() . ') - ' . adodb_date('d/m/Y H:i:s'); if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { $this->Application->setCache('master:configs_parsed', serialize($cache)); Index: kernel/session/inp_session_storage.php =================================================================== --- kernel/session/inp_session_storage.php (revision 15437) +++ kernel/session/inp_session_storage.php (working copy) @@ -55,6 +55,7 @@ 'Theme' => $this->Application->GetDefaultThemeId(), 'GroupId' => $this->Application->ConfigValue('User_GuestGroup'), 'GroupList' => $this->Application->ConfigValue('User_GuestGroup'), + 'IpAddress' => $this->Application->getClientIp(), ); if ( !$this->Application->isAdmin ) { @@ -62,10 +63,6 @@ $fields_hash['GroupList'] .= ',' . $this->Application->ConfigValue('User_LoggedInGroup'); } - if( isset($_SERVER['REMOTE_ADDR']) ) { - $fields_hash['IpAddress'] = $_SERVER['REMOTE_ADDR']; // getenv('REMOTE_ADDR') won't work on IIS, so use $_SERVER instead - } - return array_merge($fields_hash, parent::GetSessionDefaults()); } Index: kernel/session/session_storage.php =================================================================== --- kernel/session/session_storage.php (revision 15437) +++ kernel/session/session_storage.php (working copy) @@ -168,7 +168,7 @@ return false; } - if ($this->Application->ConfigValue('SessionIPAddressCheck') && ($result['IpAddress'] != $_SERVER['REMOTE_ADDR'])) { + if ($this->Application->ConfigValue('SessionIPAddressCheck') && ($result['IpAddress'] != $this->Application->getClientIp())) { // most secure, except for cases where NAT (Network Address Translation) // is used and two or more computers can have same IP address return false; Index: kernel/utility/debugger.php =================================================================== --- kernel/utility/debugger.php (revision 15552) +++ kernel/utility/debugger.php (working copy) @@ -22,6 +22,13 @@ class DebuggerUtil { /** + * Trust information, provided by proxy + * + * @var bool + */ + public static $trustProxy = false; + + /** * Checks if constant is defined and has positive value * * @param string $const_name @@ -87,15 +94,16 @@ */ public static function ipMatch($ip_list, $separator = ';') { - if ( !isset($_SERVER['REMOTE_ADDR']) ) { - // PHP CLI used -> never match + if ( php_sapi_name() == 'cli' ) { return false; } $ip_match = false; $ip_addresses = $ip_list ? explode($separator, $ip_list) : Array (); + $client_ip = self::getClientIp(); + foreach ($ip_addresses as $ip_address) { - if (self::netMatch($ip_address, $_SERVER['REMOTE_ADDR'])) { + if ( self::netMatch($ip_address, $client_ip) ) { $ip_match = true; break; } @@ -105,6 +113,37 @@ } /** + * Returns the client IP address. + * + * @return string The client IP address + * @access public + */ + public static function getClientIp() + { + if ( self::$trustProxy ) { + if ( array_key_exists('HTTP_CLIENT_IP', $_SERVER) ) { + return $_SERVER['HTTP_CLIENT_IP']; + } + + if ( array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER) ) { + $client_ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); + + foreach ($client_ip as $ip_address) { + $clean_ip_address = trim($ip_address); + + if ( false !== filter_var($clean_ip_address, FILTER_VALIDATE_IP) ) { + return $clean_ip_address; + } + } + + return ''; + } + } + + return $_SERVER['REMOTE_ADDR']; + } + + /** * Checks, that given ip belongs to given subnet * * @param string $network @@ -352,6 +391,11 @@ die('error: constant DEBUG_MODE defined directly, please use $dbg_options array instead'); } + if ( class_exists('kUtil') ) { + $vars = kUtil::getConfigVars(); + DebuggerUtil::$trustProxy = isset($vars['TrustProxy']) ? (bool)$vars['TrustProxy'] : false; + } + // check IP before enabling debug mode $ip_match = DebuggerUtil::ipMatch(isset($dbg_options['DBG_IP']) ? $dbg_options['DBG_IP'] : ''); Index: kernel/utility/http_query.php =================================================================== --- kernel/utility/http_query.php (revision 15437) +++ kernel/utility/http_query.php (working copy) @@ -92,6 +92,13 @@ var $_sidInQueryString = false; /** + * Trust information, provided by proxy + * + * @var bool + */ + protected $_trustProxy = false; + + /** * Loads info from $_POST, $_GET and * related arrays into common place * @@ -109,6 +116,10 @@ // so any logic based in it (like redirects) will not break down $_GET['ajax'] = 'yes'; } + + $vars = kUtil::getConfigVars(); + + $this->_trustProxy = isset($vars['TrustProxy']) ? (bool)$vars['TrustProxy'] : false; } /** @@ -717,7 +728,7 @@ $user_id = $session->GetField('PortalUserId'); $admin_mark = $this->Application->isAdmin ? 'ADMIN' : 'FRONT'; - $data = '[' . date('D M d H:i:s Y') . '] ' . $admin_mark . '; ip: ' . $_SERVER['REMOTE_ADDR'] . '; user_id: ' . $user_id . '; sid: ' . $this->Application->GetSID() . '; request: ' . "\n"; + $data = '[' . date('D M d H:i:s Y') . '] ' . $admin_mark . '; ip: ' . $this->getClientIp() . '; user_id: ' . $user_id . '; sid: ' . $this->Application->GetSID() . '; request: ' . "\n"; if ( $this->Get ) { $data .= "_GET:\n" . print_r($this->Get, true); } @@ -758,4 +769,34 @@ return !count($this->Get); } + /** + * Returns the client IP address. + * + * @return string The client IP address + * @access public + */ + public function getClientIp() + { + if ( $this->_trustProxy ) { + if ( array_key_exists('HTTP_CLIENT_IP', $_SERVER) ) { + return $_SERVER['HTTP_CLIENT_IP']; + } + + if ( array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER) ) { + $client_ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); + + foreach ($client_ip as $ip_address) { + $clean_ip_address = trim($ip_address); + + if ( false !== filter_var($clean_ip_address, FILTER_VALIDATE_IP) ) { + return $clean_ip_address; + } + } + + return ''; + } + } + + return $_SERVER['REMOTE_ADDR']; + } } \ No newline at end of file Index: kernel/utility/logger.php =================================================================== --- kernel/utility/logger.php (revision 15553) +++ kernel/utility/logger.php (working copy) @@ -326,6 +326,7 @@ if ( $this->Application->InitDone ) { $this->_logRecord['LogUserId'] = $this->Application->RecallVar('user_id'); $this->_logRecord['LogSessionKey'] = $this->Application->GetSID(); + $this->_logRecord['IpAddress'] = $this->Application->getClientIp(); } return $this; Index: units/forms/form_submissions/form_submissions_eh.php =================================================================== --- units/forms/form_submissions/form_submissions_eh.php (revision 15437) +++ units/forms/form_submissions/form_submissions_eh.php (working copy) @@ -282,7 +282,7 @@ $object = $event->getObject(); /* @var $object kDBItem */ - $object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']); + $object->SetDBField('IPAddress', $this->Application->getClientIp()); if ( !$object->GetDBField('ReferrerURL') ) { $referrer = $this->Application->GetVar('original_referrer'); Index: units/helpers/deployment_helper.php =================================================================== --- units/helpers/deployment_helper.php (revision 15437) +++ units/helpers/deployment_helper.php (working copy) @@ -92,7 +92,7 @@ $this->isCommandLine = isset($GLOBALS['argv']) && count($GLOBALS['argv']); if ( !$this->isCommandLine ) { - $this->ip = $_SERVER['REMOTE_ADDR']; + $this->ip = $this->Application->getClientIp(); } elseif ( isset($GLOBALS['argv'][3]) ) { $this->ip = $GLOBALS['argv'][3]; Index: units/helpers/language_import_helper.php =================================================================== --- units/helpers/language_import_helper.php (revision 15445) +++ units/helpers/language_import_helper.php (working copy) @@ -149,7 +149,7 @@ $this->_updateEventsCache(); } - $this->ip_address = getenv('HTTP_X_FORWARDED_FOR') ? getenv('HTTP_X_FORWARDED_FOR') : getenv('REMOTE_ADDR'); + $this->ip_address = $this->Application->getClientIp(); // $this->_debugMode = $this->Application->isDebugMode(); } Index: units/helpers/rating_helper.php =================================================================== --- units/helpers/rating_helper.php (revision 15437) +++ units/helpers/rating_helper.php (working copy) @@ -191,7 +191,7 @@ $fields_hash = Array ( 'ItemId' => $object->GetID(), 'RatingValue' => $rating, - 'IPAddress' => $_SERVER['REMOTE_ADDR'], + 'IPAddress' => $this->Application->getClientIp(), 'CreatedOn' => adodb_mktime(), ); $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'CatalogRatings'); Index: units/helpers/spam_helper.php =================================================================== --- units/helpers/spam_helper.php (revision 15437) +++ units/helpers/spam_helper.php (working copy) @@ -112,7 +112,7 @@ } $keys = Array ( - 'IPaddress' => $_SERVER['REMOTE_ADDR'], + 'IPaddress' => $this->Application->getClientIp(), 'PortalUserId' => $user_id, 'DataType' => $this->DataType, ); Index: units/logs/session_logs/session_log_eh.php =================================================================== --- units/logs/session_logs/session_log_eh.php (revision 15437) +++ units/logs/session_logs/session_log_eh.php (working copy) @@ -33,7 +33,7 @@ $fields_hash = Array ( 'SessionStart' => adodb_mktime(), - 'IP' => $_SERVER['REMOTE_ADDR'], + 'IP' => $this->Application->getClientIp(), 'PortalUserId' => $this->Application->RecallVar('user_id'), 'SessionId' => $this->Application->GetSID(), 'Status' => SESSION_LOG_ACTIVE, Index: units/phrases/phrases_event_handler.php =================================================================== --- units/phrases/phrases_event_handler.php (revision 15465) +++ units/phrases/phrases_event_handler.php (working copy) @@ -346,7 +346,7 @@ if ( $this->translationChanged($object) ) { $object->SetDBField('LastChanged_date', adodb_mktime() ); $object->SetDBField('LastChanged_time', adodb_mktime() ); - $object->SetDBField('LastChangeIP', $_SERVER['REMOTE_ADDR']); + $object->SetDBField('LastChangeIP', $this->Application->getClientIp()); } $this->Application->Session->SetCookie('last_module', $object->GetDBField('Module')); Index: units/reviews/reviews_event_handler.php =================================================================== --- units/reviews/reviews_event_handler.php (revision 15437) +++ units/reviews/reviews_event_handler.php (working copy) @@ -220,7 +220,7 @@ if ( $event->getEventParam('type') == 'current_user' ) { $object->addFilter('current_user', '%1$s.CreatedById = ' . $this->Application->RecallVar('user_id')); - $object->addFilter('current_ip', '%1$s.IPAddress = "' . $_SERVER['REMOTE_ADDR'] . '"'); + $object->addFilter('current_ip', '%1$s.IPAddress = "' . $this->Application->getClientIp() . '"'); } } @@ -275,7 +275,7 @@ $parent_info = $object->getLinkedInfo(); $item_type = $this->Application->getUnitOption($parent_info['ParentPrefix'], 'ItemType'); - $object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']); + $object->SetDBField('IPAddress', $this->Application->getClientIp()); $object->SetDBField('ItemType', $item_type); $object->SetDBField('Module', $this->Application->findModule('Var', $parent_info['ParentPrefix'], 'Name')); Index: units/users/users_event_handler.php =================================================================== --- units/users/users_event_handler.php (revision 15545) +++ units/users/users_event_handler.php (working copy) @@ -547,7 +547,7 @@ $object->SetError('Username', 'banned'); } - $object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']); + $object->SetDBField('IPAddress', $this->Application->getClientIp()); if ( !$this->Application->isAdmin ) { $object->SetDBField('FrontLanguage', $this->Application->GetVar('m_lang')); Index: units/visits/visits_event_handler.php =================================================================== --- units/visits/visits_event_handler.php (revision 15437) +++ units/visits/visits_event_handler.php (working copy) @@ -55,7 +55,7 @@ $object->SetDBField('VisitDate_date', adodb_mktime()); $object->SetDBField('VisitDate_time', adodb_mktime()); $object->SetDBField('Referer', getArrayValue($_SERVER, 'HTTP_REFERER')); - $object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']); + $object->SetDBField('IPAddress', $this->Application->getClientIp()); if ( $object->Create() ) { $this->Application->StoreVar('visit_id', $object->GetID());