Skip to content

Commit 82b139f

Browse files
authored
Merge pull request #196 from utopia-php/CLO-3704-trusted-ip-headers
feat: allow to pass list of headers to getIp
2 parents 76def92 + 8a164cf commit 82b139f

1 file changed

Lines changed: 48 additions & 6 deletions

File tree

src/Request.php

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ class Request
5353
*/
5454
protected $headers = null;
5555

56+
/**
57+
* List of trusted proxy header names to check for client IP address
58+
*
59+
* @var array
60+
*/
61+
protected array $trustedIpHeaders = [];
62+
5663
/**
5764
* Get Param
5865
*
@@ -157,20 +164,55 @@ public function setServer(string $key, string $value): static
157164
return $this;
158165
}
159166

167+
/**
168+
* Set trusted ip headers
169+
*
170+
* WARNING: Only set these headers if your application is behind a trusted proxy.
171+
* Trusting these headers when accepting direct client connections is a security risk.
172+
*
173+
* @param array $headers List of header names to trust (e.g., ['x-forwarded-for', 'x-real-ip'])
174+
* @return static
175+
*/
176+
public function setTrustedIpHeaders(array $headers): static
177+
{
178+
$normalized = array_map('strtolower', $headers);
179+
$trimmed = array_map('trim', $normalized);
180+
$this->trustedIpHeaders = array_filter($trimmed);
181+
182+
return $this;
183+
}
184+
160185
/**
161186
* Get IP
162187
*
163-
* Returns users IP address.
164-
* Support HTTP_X_FORWARDED_FOR header usually return
165-
* from different proxy servers or PHP default REMOTE_ADDR
188+
* Extracts the client's IP address from trusted headers or falls back to the remote address.
189+
* Prioritizes headers like X-Forwarded-For when behind proxies or load balancers,
190+
* defaulting to REMOTE_ADDR when trusted headers are unavailable.
166191
*
167-
* @return string
192+
* @return string The validated client IP address or '0.0.0.0' if unavailable
168193
*/
169194
public function getIP(): string
170195
{
171-
$ips = explode(',', $this->getHeader('HTTP_X_FORWARDED_FOR', $this->getServer('REMOTE_ADDR') ?? '0.0.0.0'));
196+
$remoteAddr = $this->getServer('REMOTE_ADDR') ?? '0.0.0.0';
197+
198+
foreach ($this->trustedIpHeaders as $header) {
199+
$headerValue = $this->getHeader($header);
200+
201+
if (empty($headerValue)) {
202+
continue;
203+
}
204+
205+
// Leftmost IP address is the address of the originating client
206+
$ips = explode(',', $headerValue);
207+
$ip = trim($ips[0]);
208+
209+
// Validate IP format (supports both IPv4 and IPv6)
210+
if (filter_var($ip, FILTER_VALIDATE_IP)) {
211+
return $ip;
212+
}
213+
}
172214

173-
return trim($ips[0] ?? '');
215+
return $remoteAddr;
174216
}
175217

176218
/**

0 commit comments

Comments
 (0)