From 64d28783fd5bc85a149aac6f40d6efc03dc63aaa Mon Sep 17 00:00:00 2001 From: Thomas Brierley Date: Mon, 14 Oct 2024 19:25:49 +0100 Subject: [PATCH] Configurable forwarded IPs Provide option to ignore forwarded IP headers for those not running Tsugi behind a reverse proxy. Defaults to trusting headers, following the principle of least surprise, and not altering default behaviour. --- src/Config/ConfigInfo.php | 17 +++++++++++++++++ src/Util/Net.php | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/src/Config/ConfigInfo.php b/src/Config/ConfigInfo.php index 00228114..1363c923 100644 --- a/src/Config/ConfigInfo.php +++ b/src/Config/ConfigInfo.php @@ -730,6 +730,23 @@ class ConfigInfo { public $websocket_url = false; public $websocket_proxyport = false; + /** + * If the web server is NOT behind a reverse proxy, you may optionally wish + * to ignore forwarded IP headers such as x-forwarded-for and variations by + * setting this to false. This will help to preserve authenticity of IPs by + * only trusting IP addresses directly seen by the server. + * + * Never set this to false if you ARE behind a reverse proxy, otherwise all + * requests will appear to originate from the same IP address (the proxy). + * + * If behind a reverse proxy, set to `true`: + * $CFG->trust_forwarded_ip = true; // (default) + * + * If not using a reverse proxy, set to `false`: + * $CFG->trust_forwarded_ip = false; + */ + public $trust_forwarded_ip = true; + /* * This is the internal version of the datbase. This is an internal * value and set in setup.php and read in migrate.php - you should not diff --git a/src/Util/Net.php b/src/Util/Net.php index d035a9b5..88c387a6 100644 --- a/src/Util/Net.php +++ b/src/Util/Net.php @@ -476,6 +476,8 @@ public static function send400($msg='Malformed request', $detail=null) { */ public static function getIP() { + global $CFG; + //Just get the headers if we can or else use the SERVER global if ( function_exists( 'apache_request_headers' ) ) { $rawheaders = apache_request_headers(); @@ -497,6 +499,11 @@ public static function getIP() { $the_ip = false; + // When not behind proxy, trust IP from web server over headers + if ( $CFG->trust_forwarded_ip === false && array_key_exists( 'REMOTE_ADDR', $_SERVER ) ) { + $the_ip = filter_var( $_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, $filter_option ); + } + // Check Cloudflare headers if ( $the_ip === false && array_key_exists( 'http_cf_connecting_ip', $headers ) ) { $pieces = explode(',',$headers['http_cf_connecting_ip']);