From f35044dbab4b75f2d9fa62c1509efe3b0494bfdf Mon Sep 17 00:00:00 2001 From: Keller Martin Date: Tue, 28 Nov 2023 16:54:56 -0500 Subject: [PATCH 1/3] Allow Trusting Multiple Proxy Layers With Wildcards --- .../Http/Middleware/TrustProxies.php | 40 +++++++++++++- tests/Http/Middleware/TrustProxiesTest.php | 52 +++++++++++++++++-- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Http/Middleware/TrustProxies.php b/src/Illuminate/Http/Middleware/TrustProxies.php index 81906c1f1951..ce2806b0f1a5 100644 --- a/src/Illuminate/Http/Middleware/TrustProxies.php +++ b/src/Illuminate/Http/Middleware/TrustProxies.php @@ -14,6 +14,13 @@ class TrustProxies */ protected $proxies; + /** + * The number of proxy layers to trust + * + * @var int + */ + protected $layers = 1; + /** * The proxy header mappings. * @@ -50,7 +57,7 @@ protected function setTrustedProxyIpAddresses(Request $request) $trustedIps = $this->proxies() ?: config('trustedproxy.proxies'); if ($trustedIps === '*' || $trustedIps === '**') { - return $this->setTrustedProxyIpAddressesToTheCallingIp($request); + return $this->setTrustedProxyIpAddressesToLayers($request, $this->layers()); } $trustedIps = is_string($trustedIps) @@ -85,6 +92,27 @@ protected function setTrustedProxyIpAddressesToTheCallingIp(Request $request) $request->setTrustedProxies([$request->server->get('REMOTE_ADDR')], $this->getTrustedHeaderNames()); } + /** + * Trust the most recent $layers number of proxies + * + * @param Request $request + * @param int $layers + * @return void + */ + protected function setTrustedProxyIpAddressesToLayers(Request $request, int $layers): void + { + $trustedIps = array_slice( + array_reverse(array_filter(explode(', ', $request->headers->get('X_FORWARDED_FOR')))), + 0, + $layers - 1, + ); + + $request->setTrustedProxies( + array_merge([$request->server->get('REMOTE_ADDR')], $trustedIps), + $this->getTrustedHeaderNames() + ); + } + /** * Retrieve trusted header name(s), falling back to defaults if config not set. * @@ -117,4 +145,14 @@ protected function proxies() { return $this->proxies; } + + /** + * Get the number of proxy layers to trust + * + * @return int + */ + protected function layers() + { + return $this->layers; + } } diff --git a/tests/Http/Middleware/TrustProxiesTest.php b/tests/Http/Middleware/TrustProxiesTest.php index 7ad01d1b98cf..6c1fc4593ed1 100644 --- a/tests/Http/Middleware/TrustProxiesTest.php +++ b/tests/Http/Middleware/TrustProxiesTest.php @@ -79,6 +79,50 @@ public function test_trusted_proxy_sets_trusted_proxies_with_double_wildcard_for }); } + /** + * Test that TrustedProxies will apply a wildcard up to two layers of proxies deep + */ + public function test_trusted_proxy_sets_trusted_proxies_for_2_layers() + { + $trustedProxy = $this->createTrustedProxy($this->headerAll, '*', 2); + $forwardedFor = [ + '' => '192.168.10.10', + '192.0.2.2' => '192.0.2.2', + '192.0.2.2, 192.0.2.199' => '192.0.2.2', + '192.0.2.2, 192.0.2.199, 99.99.99.99' => '192.0.2.199', + ]; + + foreach ($forwardedFor as $forwardedForHeader => $expected) { + $request = $this->createProxiedRequest(['HTTP_X_FORWARDED_FOR' => $forwardedForHeader]); + + $trustedProxy->handle($request, function ($request) use ($expected) { + $this->assertSame($expected, $request->getClientIp(), 'Assert trusted proxy x-forwarded-for header used 2 layers deep'); + }); + } + } + + /** + * Test that TrustedProxies will apply a wildcard up to n layers of proxies deep + */ + public function test_trusted_proxy_sets_trusted_proxies_for_n_layers() + { + $forwardedFor = '192.0.2.2, 192.0.2.199, 99.99.99.99'; + $layers = [ + 1 => '99.99.99.99', + 2 => '192.0.2.199', + 3 => '192.0.2.2', + ]; + + foreach ($layers as $layer => $expected) { + $trustedProxy = $this->createTrustedProxy($this->headerAll, '*', $layer); + $request = $this->createProxiedRequest(['HTTP_X_FORWARDED_FOR' => $forwardedFor]); + + $trustedProxy->handle($request, function ($request) use ($expected) { + $this->assertSame($expected, $request->getClientIp(), 'Assert trusted proxy x-forwarded-for header used n layers deep'); + }); + } + } + /** * Test the most typical usage of TrustProxies: * Trusted X-Forwarded-For header. @@ -392,16 +436,18 @@ protected function createProxiedRequest($serverOverrides = []) * * @param null|string|int $trustedHeaders * @param null|array|string $trustedProxies + * @param int $layers * @return \Illuminate\Http\Middleware\TrustProxies */ - protected function createTrustedProxy($trustedHeaders, $trustedProxies) + protected function createTrustedProxy($trustedHeaders, $trustedProxies, $layers = 1) { - return new class($trustedHeaders, $trustedProxies) extends TrustProxies + return new class($trustedHeaders, $trustedProxies, $layers) extends TrustProxies { - public function __construct($trustedHeaders, $trustedProxies) + public function __construct($trustedHeaders, $trustedProxies, $layers) { $this->headers = $trustedHeaders; $this->proxies = $trustedProxies; + $this->layers = $layers; } }; } From 7ccdea3484191586e5dc31fabae19cb210cca7df Mon Sep 17 00:00:00 2001 From: Keller Martin Date: Tue, 28 Nov 2023 17:48:54 -0500 Subject: [PATCH 2/3] PR Formatting Updates --- src/Illuminate/Http/Middleware/TrustProxies.php | 6 +++--- tests/Http/Middleware/TrustProxiesTest.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Http/Middleware/TrustProxies.php b/src/Illuminate/Http/Middleware/TrustProxies.php index ce2806b0f1a5..befb98656b9e 100644 --- a/src/Illuminate/Http/Middleware/TrustProxies.php +++ b/src/Illuminate/Http/Middleware/TrustProxies.php @@ -15,7 +15,7 @@ class TrustProxies protected $proxies; /** - * The number of proxy layers to trust + * The number of proxy layers to trust. * * @var int */ @@ -93,7 +93,7 @@ protected function setTrustedProxyIpAddressesToTheCallingIp(Request $request) } /** - * Trust the most recent $layers number of proxies + * Trust the most recent $layers number of proxies. * * @param Request $request * @param int $layers @@ -147,7 +147,7 @@ protected function proxies() } /** - * Get the number of proxy layers to trust + * Get the number of proxy layers to trust. * * @return int */ diff --git a/tests/Http/Middleware/TrustProxiesTest.php b/tests/Http/Middleware/TrustProxiesTest.php index 6c1fc4593ed1..380a36d0b316 100644 --- a/tests/Http/Middleware/TrustProxiesTest.php +++ b/tests/Http/Middleware/TrustProxiesTest.php @@ -80,7 +80,7 @@ public function test_trusted_proxy_sets_trusted_proxies_with_double_wildcard_for } /** - * Test that TrustedProxies will apply a wildcard up to two layers of proxies deep + * Test that TrustedProxies will apply a wildcard up to two layers of proxies deep. */ public function test_trusted_proxy_sets_trusted_proxies_for_2_layers() { @@ -102,7 +102,7 @@ public function test_trusted_proxy_sets_trusted_proxies_for_2_layers() } /** - * Test that TrustedProxies will apply a wildcard up to n layers of proxies deep + * Test that TrustedProxies will apply a wildcard up to n layers of proxies deep. */ public function test_trusted_proxy_sets_trusted_proxies_for_n_layers() { From 1df7b84ee9769878bba8408dd942030ba4e1ca27 Mon Sep 17 00:00:00 2001 From: Keller Martin Date: Tue, 28 Nov 2023 17:50:26 -0500 Subject: [PATCH 3/3] PR Formatting Updates 2 --- src/Illuminate/Http/Middleware/TrustProxies.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Http/Middleware/TrustProxies.php b/src/Illuminate/Http/Middleware/TrustProxies.php index befb98656b9e..86d0d45b5455 100644 --- a/src/Illuminate/Http/Middleware/TrustProxies.php +++ b/src/Illuminate/Http/Middleware/TrustProxies.php @@ -97,7 +97,7 @@ protected function setTrustedProxyIpAddressesToTheCallingIp(Request $request) * * @param Request $request * @param int $layers - * @return void + * @return void */ protected function setTrustedProxyIpAddressesToLayers(Request $request, int $layers): void {