aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/inc/common.php
diff options
context:
space:
mode:
Diffstat (limited to 'inc/common.php')
-rw-r--r--inc/common.php65
1 files changed, 20 insertions, 45 deletions
diff --git a/inc/common.php b/inc/common.php
index f0aa5b31f..e674b8097 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -19,6 +19,7 @@ use dokuwiki\Subscriptions\PageSubscriptionSender;
use dokuwiki\Subscriptions\SubscriberManager;
use dokuwiki\Extension\AuthPlugin;
use dokuwiki\Extension\Event;
+use dokuwiki\Ip;
use function PHP81_BC\strftime;
@@ -778,58 +779,32 @@ function checkwordblock($text = '')
}
/**
- * Return the IP of the client
+ * Return the IP of the client.
*
- * Honours X-Forwarded-For and X-Real-IP Proxy Headers
+ * The IP is sourced from, in order of preference:
*
- * It returns a comma separated list of IPs if the above mentioned
- * headers are set. If the single parameter is set, it tries to return
- * a routable public address, prefering the ones suplied in the X
- * headers
+ * - The X-Real-IP header if $conf[realip] is true.
+ * - The X-Forwarded-For header if all the proxies are trusted by $conf[trustedproxies].
+ * - The TCP/IP connection remote address.
+ * - 0.0.0.0 if all else fails.
*
- * @param boolean $single If set only a single IP is returned
- * @return string
- * @author Andreas Gohr <andi@splitbrain.org>
+ * The 'realip' config value should only be set to true if the X-Real-IP header
+ * is being added by the web server, otherwise it may be spoofed by the client.
+ *
+ * The 'trustedproxies' setting must not allow any IP, otherwise the X-Forwarded-For
+ * may be spoofed by the client.
+ *
+ * @param bool $single If set only a single IP is returned.
+ *
+ * @return string Returns an IP address if 'single' is true, or a comma-separated list
+ * of IP addresses otherwise.
+ * @author Zebra North <mrzebra@mrzebra.co.uk>
*
*/
function clientIP($single = false)
{
- /* @var Input $INPUT */
- global $INPUT, $conf;
-
- $ip = [];
- $ip[] = $INPUT->server->str('REMOTE_ADDR');
- if ($INPUT->server->str('HTTP_X_FORWARDED_FOR')) {
- $ip = array_merge($ip, explode(',', str_replace(' ', '', $INPUT->server->str('HTTP_X_FORWARDED_FOR'))));
- }
- if ($INPUT->server->str('HTTP_X_REAL_IP')) {
- $ip = array_merge($ip, explode(',', str_replace(' ', '', $INPUT->server->str('HTTP_X_REAL_IP'))));
- }
-
- // remove any non-IP stuff
- $cnt = count($ip);
- for ($i = 0; $i < $cnt; $i++) {
- if (filter_var($ip[$i], FILTER_VALIDATE_IP) === false) {
- unset($ip[$i]);
- }
- }
- $ip = array_values(array_unique($ip));
- if ($ip === [] || !$ip[0]) $ip[0] = '0.0.0.0'; // for some strange reason we don't have a IP
-
- if (!$single) return implode(',', $ip);
-
- // skip trusted local addresses
- foreach ($ip as $i) {
- if (!empty($conf['trustedproxy']) && preg_match('/' . $conf['trustedproxy'] . '/', $i)) {
- continue;
- } else {
- return $i;
- }
- }
-
- // still here? just use the last address
- // this case all ips in the list are trusted
- return $ip[count($ip) - 1];
+ // Return the first IP in single mode, or all the IPs.
+ return $single ? Ip::clientIp() : join(',', Ip::clientIps());
}
/**