@@ -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