diff --git a/src/Request.php b/src/Request.php index 2cd008e..3710ddb 100755 --- a/src/Request.php +++ b/src/Request.php @@ -53,6 +53,13 @@ class Request */ protected $headers = null; + /** + * List of trusted proxy header names to check for client IP address + * + * @var array + */ + protected array $trustedIpHeaders = []; + /** * Get Param * @@ -157,20 +164,55 @@ public function setServer(string $key, string $value): static return $this; } + /** + * Set trusted ip headers + * + * WARNING: Only set these headers if your application is behind a trusted proxy. + * Trusting these headers when accepting direct client connections is a security risk. + * + * @param array $headers List of header names to trust (e.g., ['x-forwarded-for', 'x-real-ip']) + * @return static + */ + public function setTrustedIpHeaders(array $headers): static + { + $normalized = array_map('strtolower', $headers); + $trimmed = array_map('trim', $normalized); + $this->trustedIpHeaders = array_filter($trimmed); + + return $this; + } + /** * Get IP * - * Returns users IP address. - * Support HTTP_X_FORWARDED_FOR header usually return - * from different proxy servers or PHP default REMOTE_ADDR + * Extracts the client's IP address from trusted headers or falls back to the remote address. + * Prioritizes headers like X-Forwarded-For when behind proxies or load balancers, + * defaulting to REMOTE_ADDR when trusted headers are unavailable. * - * @return string + * @return string The validated client IP address or '0.0.0.0' if unavailable */ public function getIP(): string { - $ips = explode(',', $this->getHeader('HTTP_X_FORWARDED_FOR', $this->getServer('REMOTE_ADDR') ?? '0.0.0.0')); + $remoteAddr = $this->getServer('REMOTE_ADDR') ?? '0.0.0.0'; + + foreach ($this->trustedIpHeaders as $header) { + $headerValue = $this->getHeader($header); + + if (empty($headerValue)) { + continue; + } + + // Leftmost IP address is the address of the originating client + $ips = explode(',', $headerValue); + $ip = trim($ips[0]); + + // Validate IP format (supports both IPv4 and IPv6) + if (filter_var($ip, FILTER_VALIDATE_IP)) { + return $ip; + } + } - return trim($ips[0] ?? ''); + return $remoteAddr; } /**