Added the ability to trust XFF (X-Forwarded-For) headers.
--- a/includes/common.php Sat May 15 03:05:43 2010 -0400
+++ b/includes/common.php Sun May 16 21:35:43 2010 -0400
@@ -256,6 +256,8 @@
profiler_log('Config fetched');
+do_xff_check();
+
if ( defined('ENANO_EXIT_AFTER_CONFIG') )
{
return true;
--- a/includes/functions.php Sat May 15 03:05:43 2010 -0400
+++ b/includes/functions.php Sun May 16 21:35:43 2010 -0400
@@ -2874,14 +2874,32 @@
function is_valid_ip($ip)
{
+ return is_valid_ipv4($ip) || is_valid_ipv6($ip);
+}
+
+/**
+ * Test validity of IPv4 address
+ * @param string
+ * @return bool
+ */
+
+function is_valid_ipv4($ip)
+{
// This next one came from phpBB3.
$ipv4 = '(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])';
+ return preg_match("/^{$ipv4}$/", $ip) ? true : false;
+}
+
+/**
+ * Test validity of IPv6 address
+ * @param string
+ * @return bool
+ */
+
+function is_valid_ipv6($ip)
+{
$ipv6 = '(?:[a-f0-9]{0,4}):(?:[a-f0-9]{0,4}):(?:[a-f0-9]{0,4}:|:)?(?:[a-f0-9]{0,4}:|:)?(?:[a-f0-9]{0,4}:|:)?(?:[a-f0-9]{0,4}:|:)?(?:[a-f0-9]{0,4}:|:)?(?:[a-f0-9]{1,4})';
-
- if ( preg_match("/^{$ipv4}$/", $ip) || preg_match("/^{$ipv6}$/", $ip) )
- return true;
- else
- return false;
+ return preg_match("/^{$ipv6}$/", $ip) ? true : false;
}
/**
@@ -5339,3 +5357,28 @@
return $crypto_backend;
}
+/**
+ * Perform X-Forwarded-For check and apply it as the REMOTE_ADDR if the settings tell us to
+ */
+
+function do_xff_check()
+{
+ if ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) && getConfig('trust_xff', 'none') != 'none' )
+ {
+ switch(getConfig('trust_xff', 'none'))
+ {
+ case 'both':
+ if ( is_valid_ip($_SERVER['HTTP_X_FORWARDED_FOR']) )
+ $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
+ break;
+ case 'ipv4':
+ if ( is_valid_ip($_SERVER['HTTP_X_FORWARDED_FOR']) && is_valid_ipv4($_SERVER['REMOTE_ADDR']) )
+ $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
+ break;
+ case 'ipv6':
+ if ( is_valid_ip($_SERVER['HTTP_X_FORWARDED_FOR']) && is_valid_ipv6($_SERVER['REMOTE_ADDR']) )
+ $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
+ break;
+ }
+ }
+}
--- a/language/english/admin.json Sat May 15 03:05:43 2010 -0400
+++ b/language/english/admin.json Sun May 16 21:35:43 2010 -0400
@@ -344,6 +344,8 @@
field_breadcrumb_mode_always: 'Always',
field_breadcrumb_mode_never: 'Never',
+ heading_server_settings: 'Server settings',
+
// Section: CDN
field_cdn_path: 'URL to <acronym title="Content Delivery Network">CDN</acronym> server:',
field_cdn_path_hint: 'A CDN, or Content Delivery Network, allows downloading of shared Enano components from a server designed to serve out only images, CSS, and script files. Since a browser can open separate connections for the page and for images and scripts, the page loads faster. Leave this blank to just use Enano\'s local files (default).',
@@ -361,6 +363,14 @@
field_gzip_check_msg_success: 'Success - all server checks passed. You can enable gzip support.',
field_gzip_check_msg_failure: 'Server check failed. Unless you think Enano is wrong, don\'t enable gzip below.',
+ // Section: Trust XFF
+ field_xff: 'Trust X-Forwarded-For header:',
+ field_xff_hint: 'If your server is behind a proxying cache such as Squid or Varnish, turn this on to trust the IP addresses sent from the proxy. The remote address reported by your webserver, not the value of X-Forwarded-For, is the source address used to decide whether to trust the header or not.',
+ field_xff_checkbox: 'Trust XFF header',
+ field_xff_radio_both: 'Both IPv4 and IPv6 (default)',
+ field_xff_radio_ipv4: 'IPv4 source addresses only',
+ field_xff_radio_ipv6: 'IPv6 source addresses only',
+
// Main section: users and communication
heading_users: 'Users and communication',
--- a/plugins/SpecialAdmin.php Sat May 15 03:05:43 2010 -0400
+++ b/plugins/SpecialAdmin.php Sun May 16 21:35:43 2010 -0400
@@ -273,6 +273,15 @@
setConfig('userpage_grant_acl', ( isset($_POST['userpage_grant_acl']) ? '1' : '0' ));
setConfig('gzip_output', ( isset($_POST['gzip_output']) ? '1' : '0' ));
+ if ( isset($_POST['trust_xff']) )
+ {
+ setConfig('trust_xff', $_POST['trust_xff_type']);
+ }
+ else
+ {
+ setConfig('trust_xff', 'none');
+ }
+
// Allow plugins to save their changes
$code = $plugins->setHook('acp_general_save');
foreach ( $code as $cmd )
@@ -572,7 +581,9 @@
</td>
</tr>
- <!-- CDN settings -->
+ <!-- CDN URL -->
+
+ <tr><th class="subhead" colspan="2"><?php echo $lang->get('acpgc_heading_server_settings'); ?></th></tr>
<tr>
<td class="row2">
@@ -607,6 +618,37 @@
</td>
</tr>
+ <!-- XFF -->
+
+ <tr>
+ <td class="row2">
+ <b><?php echo $lang->get('acpgc_field_xff'); ?></b><br />
+ <small><?php echo $lang->get('acpgc_field_xff_hint'); ?></small>
+ </td>
+ <td class="row2">
+ <label>
+ <input type="checkbox" name="trust_xff" onclick="$('#trust_xff_body').toggle('blind');"<?php if ( in_array(getConfig('trust_xff', 'none'), array('ipv4', 'ipv6', 'both'))) echo ' checked="checked"'; ?> />
+ <?php echo $lang->get('acpgc_field_xff_checkbox'); ?>
+ </label>
+ <div id="trust_xff_body" style="margin: 5px 0 0 10px; display: <?php echo ( in_array(getConfig('trust_xff', 'none'), array('ipv4', 'ipv6', 'both')) ) ? "block" : "none"; ?>;">
+ <label>
+ <input type="radio" name="trust_xff_type" value="both"<?php if ( getConfig('trust_xff', 'none') == 'both' || getConfig('trust_xff', 'none') == 'none' ) echo ' checked="checked"'; ?> />
+ <?php echo $lang->get('acpgc_field_xff_radio_both'); ?>
+ </label>
+ <br />
+ <label>
+ <input type="radio" name="trust_xff_type" value="ipv4"<?php if ( getConfig('trust_xff', 'none') == 'ipv4' ) echo ' checked="checked"'; ?> />
+ <?php echo $lang->get('acpgc_field_xff_radio_ipv4'); ?>
+ </label>
+ <br />
+ <label>
+ <input type="radio" name="trust_xff_type" value="ipv6"<?php if ( getConfig('trust_xff', 'none') == 'ipv6' ) echo ' checked="checked"'; ?> />
+ <?php echo $lang->get('acpgc_field_xff_radio_ipv6'); ?>
+ </label>
+ </div>
+ </td>
+ </tr>
+
<!-- Allow plugins to add code -->
<?php
$code = $plugins->setHook('acp_general_basic');