1
1
<?php
2
2
namespace RKA \Middleware ;
3
3
4
+ use Psr \Http \Message \MessageInterface ;
4
5
use Psr \Http \Message \ServerRequestInterface ;
5
6
use Psr \Http \Message \ResponseInterface ;
6
7
use Psr \Http \Server \MiddlewareInterface ;
@@ -106,11 +107,7 @@ public function __construct(
106
107
}
107
108
}
108
109
109
- /**
110
- * @param string $ipAddress
111
- * @return array
112
- */
113
- private function parseWildcard (string $ ipAddress )
110
+ private function parseWildcard (string $ ipAddress ): array
114
111
{
115
112
// IPv4 has 4 parts separated by '.'
116
113
// IPv6 has 8 parts separated by ':'
@@ -125,11 +122,7 @@ private function parseWildcard(string $ipAddress)
125
122
return explode ($ delim , $ ipAddress , $ parts );
126
123
}
127
124
128
- /**
129
- * @param string $ipAddress
130
- * @return array
131
- */
132
- private function parseCidr (string $ ipAddress )
125
+ private function parseCidr (string $ ipAddress ): array
133
126
{
134
127
list ($ subnet , $ bits ) = explode ('/ ' , $ ipAddress , 2 );
135
128
$ subnet = ip2long ($ subnet );
@@ -173,7 +166,7 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res
173
166
$ ipAddress = $ this ->determineClientIpAddress ($ request );
174
167
$ request = $ request ->withAttribute ($ this ->attributeName , $ ipAddress );
175
168
176
- return $ response = $ next ($ request , $ response );
169
+ return $ next ($ request , $ response );
177
170
}
178
171
179
172
/**
@@ -194,80 +187,86 @@ protected function determineClientIpAddress($request)
194
187
}
195
188
}
196
189
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 ;
230
196
break ;
231
197
}
232
198
}
233
199
}
200
+ }
234
201
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
+ }
248
204
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 ;
251
235
}
252
236
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
261
247
}
262
248
}
249
+ if ($ match ) {
250
+ return true ;
251
+ }
263
252
}
264
253
}
265
254
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
+ }
268
266
}
269
267
270
- return $ ipAddress ;
268
+ //default - not check
269
+ return false ;
271
270
}
272
271
273
272
/**
@@ -296,14 +295,9 @@ protected function extractIpAddress($ipAddress)
296
295
* @param string $ip
297
296
* @return boolean
298
297
*/
299
- protected function isValidIpAddress ($ ip )
298
+ protected function isValidIpAddress (string $ ip ): bool
300
299
{
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 ;
307
301
}
308
302
309
303
/**
@@ -313,7 +307,7 @@ protected function isValidIpAddress($ip)
313
307
* @param string $header Header name
314
308
* @return string
315
309
*/
316
- private function getFirstIpAddressFromHeader ($ request , $ header )
310
+ private function getFirstIpAddressFromHeader (MessageInterface $ request , string $ header ): string
317
311
{
318
312
$ items = explode (', ' , $ request ->getHeaderLine ($ header ));
319
313
$ headerValue = trim (reset ($ items ));
0 commit comments