From 708b4d919ce8915e15d61cce8b844a1eea4f5cb2 Mon Sep 17 00:00:00 2001 From: k Date: Sun, 3 Dec 2023 12:25:49 +0100 Subject: [PATCH 1/2] - feat: support for RR in Docker being behind a proxy --- src/RoadRunnerBridge/HttpFoundationWorker.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/RoadRunnerBridge/HttpFoundationWorker.php b/src/RoadRunnerBridge/HttpFoundationWorker.php index 148493e..7215e47 100644 --- a/src/RoadRunnerBridge/HttpFoundationWorker.php +++ b/src/RoadRunnerBridge/HttpFoundationWorker.php @@ -95,6 +95,8 @@ private function configureServer(RoadRunnerRequest $request): array $components = parse_url($request->uri); + $components["scheme"] = $request->headers["X-Forwarded-Proto"][0] ?? $components["scheme"] ?? null; + if ($components === false) { throw new \Exception('Failed to parse RoadRunner request URI'); } @@ -121,7 +123,7 @@ private function configureServer(RoadRunnerRequest $request): array $server['REQUEST_TIME'] = $this->timeInt(); $server['REQUEST_TIME_FLOAT'] = $this->timeFloat(); - $server['REMOTE_ADDR'] = $request->getRemoteAddr(); + $server['REMOTE_ADDR'] = $request->headers["X-Forwarded-For"][0] ?? $request->getRemoteAddr(); $server['REQUEST_METHOD'] = $request->method; $server['SERVER_PROTOCOL'] = $request->protocol; From 898dc871235b1075f24aaba3f1f99cf72823d98e Mon Sep 17 00:00:00 2001 From: k Date: Sun, 3 Dec 2023 12:48:40 +0100 Subject: [PATCH 2/2] - feat: be a bit more secure about forwarded headers --- config/services.php | 5 ++- src/RoadRunnerBridge/HttpFoundationWorker.php | 38 +++++++++++++++++-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/config/services.php b/config/services.php index 730829d..e3533f6 100644 --- a/config/services.php +++ b/config/services.php @@ -60,7 +60,10 @@ // Bundle services $services->set(HttpFoundationWorkerInterface::class, HttpFoundationWorker::class) - ->args([service(HttpWorkerInterface::class)]); + ->args([ + service(HttpWorkerInterface::class), + service(KernelRebootStrategyInterface::class), + ]); $services->set(WorkerRegistryInterface::class, WorkerRegistry::class) ->public(); diff --git a/src/RoadRunnerBridge/HttpFoundationWorker.php b/src/RoadRunnerBridge/HttpFoundationWorker.php index 7215e47..acc9dcf 100644 --- a/src/RoadRunnerBridge/HttpFoundationWorker.php +++ b/src/RoadRunnerBridge/HttpFoundationWorker.php @@ -9,19 +9,41 @@ use Spiral\RoadRunner\WorkerInterface; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; use Symfony\Component\HttpFoundation\Response as SymfonyResponse; use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpKernel\KernelInterface; final class HttpFoundationWorker implements HttpFoundationWorkerInterface { private HttpWorkerInterface $httpWorker; private array $originalServer; + private array $trustedHeaders; - public function __construct(HttpWorkerInterface $httpWorker) + public function __construct( + HttpWorkerInterface $httpWorker, + KernelInterface $kernel + ) { $this->httpWorker = $httpWorker; $this->originalServer = $_SERVER; + + $container = $kernel->getContainer(); + if ($container->hasParameter('kernel.trusted_proxies') && $container->hasParameter('kernel.trusted_headers')) { + $trustedHeaders = $container->getParameter('kernel.trusted_headers'); + + $headerNames = []; + + if ($trustedHeaders & Request::HEADER_X_FORWARDED_FOR) { + $headerNames[] = 'x-forwarded-for'; + } + if ($trustedHeaders & Request::HEADER_X_FORWARDED_PROTO) { + $headerNames[] = 'x-forwarded-proto'; + } + + $this->trustedHeaders = $headerNames; + } } public function waitRequest(): ?SymfonyRequest @@ -95,7 +117,11 @@ private function configureServer(RoadRunnerRequest $request): array $components = parse_url($request->uri); - $components["scheme"] = $request->headers["X-Forwarded-Proto"][0] ?? $components["scheme"] ?? null; + $scheme = $components["scheme"] ?? null; + if(isset($request->headers["X-Forwarded-Proto"][0]) && in_array("x-forwarded-proto", $this->trustedHeaders, true)) { + $scheme = $request->headers["X-Forwarded-Proto"][0]; + } + $components["scheme"] = $scheme; if ($components === false) { throw new \Exception('Failed to parse RoadRunner request URI'); @@ -123,7 +149,13 @@ private function configureServer(RoadRunnerRequest $request): array $server['REQUEST_TIME'] = $this->timeInt(); $server['REQUEST_TIME_FLOAT'] = $this->timeFloat(); - $server['REMOTE_ADDR'] = $request->headers["X-Forwarded-For"][0] ?? $request->getRemoteAddr(); + + $remoteAddr = $request->getRemoteAddr(); + if(isset($request->headers["X-Forwarded-For"][0]) && in_array("x-forwarded-for", $this->trustedHeaders, true)) { + $remoteAddr = $request->headers["X-Forwarded-For"][0]; + } + $server['REMOTE_ADDR'] = $remoteAddr; + $server['REQUEST_METHOD'] = $request->method; $server['SERVER_PROTOCOL'] = $request->protocol;