From dc833e2eb12a93355be1bbb9a35f2cd8acc2eb3e Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Thu, 11 Dec 2025 18:03:56 +0100 Subject: [PATCH 1/5] feat: allow to pass list of headers to getIp --- src/Request.php | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/Request.php b/src/Request.php index 2cd008e..06301c8 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 = ['x-forwarded-for']; + /** * Get Param * @@ -160,17 +167,34 @@ public function setServer(string $key, string $value): static /** * 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; } /** From 71caddbfc3c18aeca2fa749a49125df0a517c7fa Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Thu, 11 Dec 2025 18:05:57 +0100 Subject: [PATCH 2/5] chore: remove trailing whitespace --- src/Request.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Request.php b/src/Request.php index 06301c8..264a307 100755 --- a/src/Request.php +++ b/src/Request.php @@ -55,7 +55,7 @@ class Request /** * List of trusted proxy header names to check for client IP address - * + * * @var array */ protected array $trustedIpHeaders = ['x-forwarded-for']; From 0d40cd0ce31d9444ad420af49e350d93e7326ee5 Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Thu, 11 Dec 2025 19:03:08 +0100 Subject: [PATCH 3/5] chore: enforce suggested improvements --- src/Request.php | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Request.php b/src/Request.php index 264a307..b2e6ab6 100755 --- a/src/Request.php +++ b/src/Request.php @@ -58,7 +58,7 @@ class Request * * @var array */ - protected array $trustedIpHeaders = ['x-forwarded-for']; + protected array $trustedIpHeaders = []; /** * Get Param @@ -164,6 +164,24 @@ 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 + { + $this->trustedIpHeaders = array_filter( + array_map('trim', + array_map('strtolower', $headers)) + ); + return $this; + } + /** * Get IP * @@ -175,7 +193,7 @@ public function setServer(string $key, string $value): static */ public function getIP(): string { - $remoteAddr = $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); From 2d91e669293ae3969379a5b84a6e80da603f09fc Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Thu, 11 Dec 2025 20:32:22 +0100 Subject: [PATCH 4/5] chore: prevent linter errors --- src/Request.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Request.php b/src/Request.php index b2e6ab6..ac30638 100755 --- a/src/Request.php +++ b/src/Request.php @@ -166,7 +166,7 @@ public function setServer(string $key, string $value): static /** * 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. * @@ -175,10 +175,10 @@ public function setServer(string $key, string $value): static */ public function setTrustedIpHeaders(array $headers): static { - $this->trustedIpHeaders = array_filter( - array_map('trim', - array_map('strtolower', $headers)) - ); + $normalized = array_map('strtolower', $headers); + $trimmed = array_map('trim', $normalized); + $this->trustedIpHeaders = array_filter($trimmed); + return $this; } From 8a164cfbbdc5f62f33dd1fb5c68fcf22869b101f Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Thu, 11 Dec 2025 20:33:57 +0100 Subject: [PATCH 5/5] chore: prevent linter errors --- src/Request.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Request.php b/src/Request.php index ac30638..3710ddb 100755 --- a/src/Request.php +++ b/src/Request.php @@ -178,7 +178,7 @@ public function setTrustedIpHeaders(array $headers): static $normalized = array_map('strtolower', $headers); $trimmed = array_map('trim', $normalized); $this->trustedIpHeaders = array_filter($trimmed); - + return $this; }