11<?php
22namespace RKA \Middleware ;
33
4+ use Psr \Http \Message \MessageInterface ;
45use Psr \Http \Message \ServerRequestInterface ;
56use Psr \Http \Message \ResponseInterface ;
67use Psr \Http \Server \MiddlewareInterface ;
@@ -106,11 +107,7 @@ public function __construct(
106107 }
107108 }
108109
109- /**
110- * @param string $ipAddress
111- * @return array
112- */
113- private function parseWildcard (string $ ipAddress )
110+ private function parseWildcard (string $ ipAddress ): array
114111 {
115112 // IPv4 has 4 parts separated by '.'
116113 // IPv6 has 8 parts separated by ':'
@@ -125,11 +122,7 @@ private function parseWildcard(string $ipAddress)
125122 return explode ($ delim , $ ipAddress , $ parts );
126123 }
127124
128- /**
129- * @param string $ipAddress
130- * @return array
131- */
132- private function parseCidr (string $ ipAddress )
125+ private function parseCidr (string $ ipAddress ): array
133126 {
134127 list ($ subnet , $ bits ) = explode ('/ ' , $ ipAddress , 2 );
135128 $ subnet = ip2long ($ subnet );
@@ -173,7 +166,7 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res
173166 $ ipAddress = $ this ->determineClientIpAddress ($ request );
174167 $ request = $ request ->withAttribute ($ this ->attributeName , $ ipAddress );
175168
176- return $ response = $ next ($ request , $ response );
169+ return $ next ($ request , $ response );
177170 }
178171
179172 /**
@@ -194,80 +187,86 @@ protected function determineClientIpAddress($request)
194187 }
195188 }
196189
197- $ checkProxyHeaders = false ;
198- if ($ this ->checkProxyHeaders ) {
199- // Exact Match
200- if ($ this ->trustedProxies && in_array ($ ipAddress , $ this ->trustedProxies )) {
201- $ checkProxyHeaders = true ;
202- }
203-
204- // Wildcard Match
205- if ($ this ->checkProxyHeaders && $ this ->trustedWildcards ) {
206- // IPv4 has 4 parts separated by '.'
207- // IPv6 has 8 parts separated by ':'
208- if (strpos ($ ipAddress , '. ' ) > 0 ) {
209- $ delim = '. ' ;
210- $ parts = 4 ;
211- } else {
212- $ delim = ': ' ;
213- $ parts = 8 ;
214- }
215-
216- $ ipAddrParts = explode ($ delim , $ ipAddress , $ parts );
217- foreach ($ this ->trustedWildcards as $ proxy ) {
218- if (count ($ proxy ) !== $ parts ) {
219- continue ; // IP version does not match
220- }
221- $ match = true ;
222- foreach ($ proxy as $ i => $ part ) {
223- if ($ part !== '* ' && $ part !== $ ipAddrParts [$ i ]) {
224- $ match = false ;
225- break ; // IP does not match, move to next proxy
226- }
227- }
228- if ($ match ) {
229- $ checkProxyHeaders = true ;
190+ if ($ this ->shouldCheckProxyHeaders ($ ipAddress )) {
191+ foreach ($ this ->headersToInspect as $ header ) {
192+ if ($ request ->hasHeader ($ header )) {
193+ $ ip = $ this ->getFirstIpAddressFromHeader ($ request , $ header );
194+ if ($ this ->isValidIpAddress ($ ip )) {
195+ $ ipAddress = $ ip ;
230196 break ;
231197 }
232198 }
233199 }
200+ }
234201
235- // CIDR Match
236- if ($ this ->checkProxyHeaders && $ this ->trustedCidrs ) {
237- // Only IPv4 is supported for CIDR matching
238- $ ipAsLong = ip2long ($ ipAddress );
239- if ($ ipAsLong ) {
240- foreach ($ this ->trustedCidrs as $ proxy ) {
241- if ($ proxy [0 ] <= $ ipAsLong && $ ipAsLong <= $ proxy [1 ]) {
242- $ checkProxyHeaders = true ;
243- break ;
244- }
245- }
246- }
247- }
202+ return empty ($ ipAddress ) ? null : $ ipAddress ;
203+ }
248204
249- if (!$ this ->trustedProxies && !$ this ->trustedWildcards && !$ this ->trustedCidrs ) {
250- $ checkProxyHeaders = true ;
205+ /**
206+ * Determine whether we should check proxy headers for specified ip address
207+ */
208+ protected function shouldCheckProxyHeaders (string $ ipAddress ): bool
209+ {
210+ //do not check if configured to not check
211+ if (!$ this ->checkProxyHeaders ) {
212+ return false ;
213+ }
214+
215+ //if configured to check but no constraints
216+ if (!$ this ->trustedProxies && !$ this ->trustedWildcards && !$ this ->trustedCidrs ) {
217+ return true ;
218+ }
219+
220+ // Exact Match for trusted proxies
221+ if ($ this ->trustedProxies && in_array ($ ipAddress , $ this ->trustedProxies )) {
222+ return true ;
223+ }
224+
225+ // Wildcard Match
226+ if ($ this ->trustedWildcards ) {
227+ // IPv4 has 4 parts separated by '.'
228+ // IPv6 has 8 parts separated by ':'
229+ if (strpos ($ ipAddress , '. ' ) > 0 ) {
230+ $ delim = '. ' ;
231+ $ parts = 4 ;
232+ } else {
233+ $ delim = ': ' ;
234+ $ parts = 8 ;
251235 }
252236
253- if ($ checkProxyHeaders ) {
254- foreach ($ this ->headersToInspect as $ header ) {
255- if ($ request ->hasHeader ($ header )) {
256- $ ip = $ this ->getFirstIpAddressFromHeader ($ request , $ header );
257- if ($ this ->isValidIpAddress ($ ip )) {
258- $ ipAddress = $ ip ;
259- break ;
260- }
237+ $ ipAddrParts = explode ($ delim , $ ipAddress , $ parts );
238+ foreach ($ this ->trustedWildcards as $ proxy ) {
239+ if (count ($ proxy ) !== $ parts ) {
240+ continue ; // IP version does not match
241+ }
242+ $ match = true ;
243+ foreach ($ proxy as $ i => $ part ) {
244+ if ($ part !== '* ' && $ part !== $ ipAddrParts [$ i ]) {
245+ $ match = false ;
246+ break ; // IP does not match, move to next proxy
261247 }
262248 }
249+ if ($ match ) {
250+ return true ;
251+ }
263252 }
264253 }
265254
266- if (empty ($ ipAddress )) {
267- $ ipAddress = null ;
255+ // CIDR Match
256+ if ($ this ->trustedCidrs ) {
257+ // Only IPv4 is supported for CIDR matching
258+ $ ipAsLong = ip2long ($ ipAddress );
259+ if ($ ipAsLong ) {
260+ foreach ($ this ->trustedCidrs as $ proxy ) {
261+ if ($ proxy [0 ] <= $ ipAsLong && $ ipAsLong <= $ proxy [1 ]) {
262+ return true ;
263+ }
264+ }
265+ }
268266 }
269267
270- return $ ipAddress ;
268+ //default - not check
269+ return false ;
271270 }
272271
273272 /**
@@ -296,14 +295,9 @@ protected function extractIpAddress($ipAddress)
296295 * @param string $ip
297296 * @return boolean
298297 */
299- protected function isValidIpAddress ($ ip )
298+ protected function isValidIpAddress (string $ ip ): bool
300299 {
301- $ flags = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 ;
302- if (filter_var ($ ip , FILTER_VALIDATE_IP , $ flags ) === false ) {
303- return false ;
304- }
305-
306- return true ;
300+ return filter_var ($ ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 ) !== false ;
307301 }
308302
309303 /**
@@ -313,7 +307,7 @@ protected function isValidIpAddress($ip)
313307 * @param string $header Header name
314308 * @return string
315309 */
316- private function getFirstIpAddressFromHeader ($ request , $ header )
310+ private function getFirstIpAddressFromHeader (MessageInterface $ request , string $ header ): string
317311 {
318312 $ items = explode (', ' , $ request ->getHeaderLine ($ header ));
319313 $ headerValue = trim (reset ($ items ));
0 commit comments