From 4a6f5869e5df2433643199d2ab239569b3ece6b2 Mon Sep 17 00:00:00 2001 From: Dries Buytaert Date: Fri, 25 May 2007 15:04:42 +0000 Subject: - Patch #142773 by kbahey: made Drupal work correctly when behind a reverse proxy. --- includes/bootstrap.inc | 37 +++++++++++++++++++++++++++++++++---- includes/common.inc | 5 +++-- includes/session.inc | 4 ++-- 3 files changed, 38 insertions(+), 8 deletions(-) (limited to 'includes') diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc index 505c3872e..d3c35b5f2 100644 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -703,7 +703,7 @@ function watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NO 'user' => $user, 'request_uri' => $base_root . request_uri(), 'referer' => referer_uri(), - 'ip' => $_SERVER['REMOTE_ADDR'], + 'ip' => ip_address(), 'timestamp' => time(), ); @@ -819,7 +819,7 @@ function drupal_is_denied($type, $mask) { function drupal_anonymous_user($session = '') { $user = new stdClass(); $user->uid = 0; - $user->hostname = $_SERVER['REMOTE_ADDR']; + $user->hostname = ip_address(); $user->roles = array(); $user->roles[DRUPAL_ANONYMOUS_RID] = 'anonymous user'; $user->session = $session; @@ -881,9 +881,9 @@ function _drupal_bootstrap($phase) { case DRUPAL_BOOTSTRAP_ACCESS: // Deny access to hosts which were banned - t() is not yet available. - if (drupal_is_denied('host', $_SERVER['REMOTE_ADDR'])) { + if (drupal_is_denied('host', ip_address())) { header('HTTP/1.1 403 Forbidden'); - print 'Sorry, '. $_SERVER['REMOTE_ADDR'] .' has been banned.'; + print 'Sorry, '. ip_address() .' has been banned.'; exit(); } break; @@ -1056,3 +1056,32 @@ function language_list($field = 'language', $reset = FALSE) { function language_default() { return variable_get('language_default', (object) array('language' => 'en', 'name' => 'English', 'native' => 'English', 'direction' => 0, 'enabled' => 1, 'plurals' => 0, 'formula' => '', 'domain' => '', 'prefix' => '', 'weight' => 0)); } + + +/** + * If Drupal is behind a reverse proxy, we use the X-Forwarded-For header + * instead of $_SERVER['REMOTE_ADDR'], which would be the IP address + * of the proxy server, and not the client's. + * + * @return + * IP address of client machine, adjusted for reverse proxy. + */ +function ip_address() { + static $remote_ip; + + if ($remote_ip) { + // We have been here before, so just return the one we processed before + return $remote_ip; + } + else { + $remote_ip = $_SERVER['REMOTE_ADDR']; + if (variable_get('reverse_proxy', FALSE) && array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) { + $ip_array = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); + // If there are several arguments, the leftmost one is the farthest client + $remote_ip = $ip_array[0]; + } + } + // Store the satnized version in the static variable + $remote_ip = check_plain($remote_ip); + return $remote_ip; +} diff --git a/includes/common.inc b/includes/common.inc index fb7f21a41..7af684578 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -801,7 +801,7 @@ function valid_url($url, $absolute = FALSE) { * The name of the event. */ function flood_register_event($name) { - db_query("INSERT INTO {flood} (event, hostname, timestamp) VALUES ('%s', '%s', %d)", $name, $_SERVER['REMOTE_ADDR'], time()); + db_query("INSERT INTO {flood} (event, hostname, timestamp) VALUES ('%s', '%s', %d)", $name, ip_address(), time()); } /** @@ -817,7 +817,7 @@ function flood_register_event($name) { * True if the user did not exceed the hourly threshold. False otherwise. */ function flood_is_allowed($name, $threshold) { - $number = db_num_rows(db_query("SELECT event FROM {flood} WHERE event = '%s' AND hostname = '%s' AND timestamp > %d", $name, $_SERVER['REMOTE_ADDR'], time() - 3600)); + $number = db_num_rows(db_query("SELECT event FROM {flood} WHERE event = '%s' AND hostname = '%s' AND timestamp > %d", $name, ip_address(), time() - 3600)); return ($number < $threshold ? TRUE : FALSE); } @@ -2805,3 +2805,4 @@ function watchdog_severity_levels() { WATCHDOG_DEBUG => t('debug'), ); } + diff --git a/includes/session.inc b/includes/session.inc index 103209671..e9464c20a 100644 --- a/includes/session.inc +++ b/includes/session.inc @@ -69,11 +69,11 @@ function sess_write($key, $value) { // and gives more useful statistics. We can't eliminate anonymous session // table rows without breaking throttle module and "Who's Online" block. if ($user->uid || $value || count($_COOKIE)) { - db_query("INSERT INTO {sessions} (sid, uid, cache, hostname, session, timestamp) VALUES ('%s', %d, %d, '%s', '%s', %d)", $key, $user->uid, isset($user->cache) ? $user->cache : '', $_SERVER["REMOTE_ADDR"], $value, time()); + db_query("INSERT INTO {sessions} (sid, uid, cache, hostname, session, timestamp) VALUES ('%s', %d, %d, '%s', '%s', %d)", $key, $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time()); } } else { - db_query("UPDATE {sessions} SET uid = %d, cache = %d, hostname = '%s', session = '%s', timestamp = %d WHERE sid = '%s'", $user->uid, isset($user->cache) ? $user->cache : '', $_SERVER["REMOTE_ADDR"], $value, time(), $key); + db_query("UPDATE {sessions} SET uid = %d, cache = %d, hostname = '%s', session = '%s', timestamp = %d WHERE sid = '%s'", $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time(), $key); // TODO: this can be an expensive query. Perhaps only execute it every x minutes. Requires investigation into cache expiration. if ($user->uid) { -- cgit v1.2.3