1212use Monolog \Formatter \LineFormatter ;
1313use Monolog \Handler \RotatingFileHandler ;
1414use Monolog \Logger ;
15+ use Psr \Cache \CacheException ;
1516use Psr \Cache \InvalidArgumentException ;
1617use Psr \Log \LoggerInterface ;
1718
@@ -65,7 +66,7 @@ protected function getArraySettings(string $name): array
6566 /**
6667 * Run a bounce.
6768 *
68- * @throws Exception|InvalidArgumentException
69+ * @throws Exception|InvalidArgumentException|CacheException
6970 */
7071 public function run (): void
7172 {
@@ -112,18 +113,55 @@ protected function initLoggerHelper(string $logDirectoryPath, string $loggerName
112113 }
113114
114115 /**
115- * Decide if we use forward (default behavior) or if it depends on test settings
116+ * Handle X-Forwarded-For HTTP header to retrieve the IP to bounce
116117 *
117- * @param $settings
118- * @return bool
118+ * @param $ip
119+ * @return false|mixed
119120 */
120- protected function shouldUseForward ( $ settings )
121+ protected function handleForwardedFor ( $ ip )
121122 {
122- return empty ($ settings ['forced_test_never_use_forwarded ' ]);
123+ if (empty ($ this ->settings ['forced_test_forwarded_ip ' ])) {
124+ $ XForwardedForHeader = $ this ->getHttpRequestHeader ('X-Forwarded-For ' );
125+ if (null !== $ XForwardedForHeader ) {
126+ $ ipList = array_map ('trim ' , array_values (array_filter (explode (', ' , $ XForwardedForHeader ))));
127+ $ forwardedIp = end ($ ipList );
128+ if ($ this ->shouldTrustXforwardedFor ($ ip )) {
129+ $ ip = $ forwardedIp ;
130+ } else {
131+ $ this ->logger ->warning ('' , [
132+ 'type ' => 'NON_AUTHORIZED_X_FORWARDED_FOR_USAGE ' ,
133+ 'original_ip ' => $ ip ,
134+ 'x_forwarded_for_ip ' => $ forwardedIp ,
135+ ]);
136+ }
137+ }
138+ } else if ($ this ->settings ['forced_test_forwarded_ip ' ] === Constants::X_FORWARDED_DISABLED ) {
139+ $ this ->logger ->debug ('' , [
140+ 'type ' => 'DISABLED_X_FORWARDED_FOR_USAGE ' ,
141+ 'original_ip ' => $ ip ,
142+ ]);
143+ } else {
144+ $ forwardedIp = $ this ->settings ['forced_test_forwarded_ip ' ];
145+ if ($ this ->shouldTrustXforwardedFor ($ ip )) {
146+ $ ip = $ forwardedIp ;
147+ } else {
148+ $ this ->logger ->warning ('' , [
149+ 'type ' => 'NON_AUTHORIZED_TEST_X_FORWARDED_FOR_USAGE ' ,
150+ 'original_ip ' => $ ip ,
151+ 'x_forwarded_for_ip_for_test ' => $ forwardedIp ,
152+ ]);
153+ }
154+ }
155+
156+ return $ ip ;
123157 }
124158
125159 /**
126- * @throws Exception|InvalidArgumentException
160+ * Bounce process
161+ *
162+ * @return void
163+ * @throws InvalidArgumentException|CacheException
164+ * @throws Exception
127165 */
128166 protected function bounceCurrentIp (): void
129167 {
@@ -133,38 +171,13 @@ protected function bounceCurrentIp(): void
133171 }
134172 // Retrieve the current IP (even if it is a proxy IP) or a testing IP
135173 $ ip = !empty ($ this ->settings ['forced_test_ip ' ]) ? $ this ->settings ['forced_test_ip ' ] : $ this ->getRemoteIp ();
136- if ($ this ->shouldUseForward ($ this ->settings )) {
137- // Retrieve the forwarded IP (testing one or real)
138- if (!empty ($ this ->settings ['forced_test_forwarded_ip ' ])) {
139- $ forwardedIp = $ this ->settings ['forced_test_forwarded_ip ' ];
140- } elseif ($ XForwardedForHeader = $ this ->getHttpRequestHeader ('X-Forwarded-For ' )) {
141- $ ipList = array_map ('trim ' , array_values (array_filter (explode (', ' , $ XForwardedForHeader ))));
142- $ forwardedIp = end ($ ipList );
143- }
144- if (isset ($ forwardedIp )) {
145- if ($ this ->shouldTrustXforwardedFor ($ ip )) {
146- $ this ->logger ->debug ('' , [
147- 'type ' => 'AUTHORIZED_X_FORWARDED_FOR_USAGE ' ,
148- 'original_ip ' => $ ip ,
149- ]);
150- $ ip = $ forwardedIp ;
151- } else {
152- $ this ->logger ->warning ('' , [
153- 'type ' => 'NON_AUTHORIZED_X_FORWARDED_FOR_USAGE ' ,
154- 'original_ip ' => $ ip ,
155- 'x_forwarded_for_ip ' => $ forwardedIp ?? 'undefined ' ,
156- ]);
157- }
158- } else {
159- $ this ->logger ->debug ('' , ['type ' => 'X_FORWARDED_FOR_NOT_FOUND ' ]);
160- }
161- }
174+ $ ip = $ this ->handleForwardedFor ($ ip );
162175 $ remediation = $ this ->bouncer ->getRemediationForIp ($ ip );
163176 $ this ->handleRemediation ($ remediation , $ ip );
164177 } catch (Exception $ e ) {
165178 $ this ->logger ->warning ('' , [
166179 'type ' => 'UNKNOWN_EXCEPTION_WHILE_BOUNCING ' ,
167- 'ip ' => $ ip ,
180+ 'ip ' => $ ip ?? '' ,
168181 'message ' => $ e ->getMessage (),
169182 'code ' => $ e ->getCode (),
170183 'file ' => $ e ->getFile (),
@@ -197,6 +210,9 @@ protected function shouldTrustXforwardedFor(string $ip): bool
197210 return false ;
198211 }
199212
213+ /**
214+ * @throws InvalidArgumentException
215+ */
200216 protected function displayCaptchaWall (string $ ip ): void
201217 {
202218 $ options = $ this ->getCaptchaWallOptions ();
@@ -222,7 +238,10 @@ protected function handleBanRemediation(): void
222238 }
223239
224240 /**
241+ * @param string $ip
225242 * @return void
243+ * @throws InvalidArgumentException
244+ * @throws CacheException
226245 */
227246 protected function handleCaptchaResolutionForm (string $ ip )
228247 {
@@ -305,6 +324,8 @@ protected function handleCaptchaResolutionForm(string $ip)
305324 * @param string $ip
306325 *
307326 * @return void
327+ * @throws InvalidArgumentException
328+ * @throws CacheException
308329 */
309330 protected function handleCaptchaRemediation (string $ ip )
310331 {
@@ -344,6 +365,8 @@ protected function handleCaptchaRemediation(string $ip)
344365 * @param string $remediation
345366 * @param string $ip
346367 * @return void
368+ * @throws InvalidArgumentException
369+ * @throws CacheException
347370 */
348371 protected function handleRemediation (string $ remediation , string $ ip )
349372 {
@@ -368,7 +391,7 @@ protected function handleRemediation(string $remediation, string $ip)
368391 * @return array
369392 * @throws InvalidArgumentException
370393 */
371- public function getIpVariables (string $ cacheTag , array $ names , string $ ip )
394+ public function getIpVariables (string $ cacheTag , array $ names , string $ ip ): array
372395 {
373396 if (!$ this ->bouncer ) {
374397 throw new BouncerException ('Bouncer must be instantiated to get cache data. ' );
@@ -386,7 +409,7 @@ public function getIpVariables(string $cacheTag, array $names, string $ip)
386409 * @param string $ip
387410 * @return void
388411 * @throws InvalidArgumentException
389- * @throws \Psr\Cache\ CacheException
412+ * @throws CacheException
390413 */
391414 public function setIpVariables (string $ cacheTag , array $ pairs , string $ ip ): void
392415 {
@@ -405,7 +428,7 @@ public function setIpVariables(string $cacheTag, array $pairs, string $ip): void
405428 * @param string $ip
406429 * @return void
407430 * @throws InvalidArgumentException
408- * @throws \Psr\Cache\ CacheException
431+ * @throws CacheException
409432 */
410433 public function unsetIpVariables (string $ cacheTag , array $ names , string $ ip ): void
411434 {
0 commit comments