From 6f72d719bf7b7f7e87406868f33741857a5ab0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Preu=C3=9F?= Date: Fri, 1 Jan 2021 16:06:59 +0100 Subject: [PATCH] Fix http/s protocol headers Improve request ids --- app/Client/Client.php | 19 +++++-------- app/Client/Http/HttpClient.php | 27 +++++++++++++------ app/Server/Connections/ConnectionManager.php | 6 ++--- app/Server/Connections/ControlConnection.php | 1 + .../Controllers/TunnelMessageController.php | 8 ++++-- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/app/Client/Client.php b/app/Client/Client.php index fccb13e..889a13a 100644 --- a/app/Client/Client.php +++ b/app/Client/Client.php @@ -45,7 +45,7 @@ class Client $sharedUrl = $this->prepareSharedUrl($sharedUrl); foreach ($subdomains as $subdomain) { - $this->connectToServer($sharedUrl, $subdomain, $this->configuration->auth()); + $this->connectToServerAndShareHttp($sharedUrl, $subdomain, $this->configuration->auth()); } } @@ -61,18 +61,13 @@ class Client } $url = Arr::get($parsedUrl, 'host', Arr::get($parsedUrl, 'path')); + $scheme = Arr::get($parsedUrl, 'scheme'); + $port = Arr::get($parsedUrl, 'port', $scheme === 'https' ? 443 : 80); - if (Arr::get($parsedUrl, 'scheme') === 'https') { - $url .= ':443'; - } - if (! is_null($port = Arr::get($parsedUrl, 'port'))) { - $url .= ":{$port}"; - } - - return $url; + return sprintf('%s:%s:%s', $scheme, $url, $port); } - public function connectToServer(string $sharedUrl, $subdomain, $authToken = ''): PromiseInterface + public function connectToServerAndShareHttp(string $sharedUrl, $subdomain, $authToken = ''): PromiseInterface { $deferred = new Deferred(); $promise = $deferred->promise(); @@ -93,7 +88,7 @@ class Client $this->logger->error('Connection to server closed.'); $this->retryConnectionOrExit(function () use ($sharedUrl, $subdomain, $authToken) { - $this->connectToServer($sharedUrl, $subdomain, $authToken); + $this->connectToServerAndShareHttp($sharedUrl, $subdomain, $authToken); }); }); @@ -126,7 +121,7 @@ class Client }, function (\Exception $e) use ($deferred, $sharedUrl, $subdomain, $authToken) { if ($this->connectionRetries > 0) { $this->retryConnectionOrExit(function () use ($sharedUrl, $subdomain, $authToken) { - $this->connectToServer($sharedUrl, $subdomain, $authToken); + $this->connectToServerAndShareHttp($sharedUrl, $subdomain, $authToken); }); return; diff --git a/app/Client/Http/HttpClient.php b/app/Client/Http/HttpClient.php index 2505a16..1ed5e9f 100644 --- a/app/Client/Http/HttpClient.php +++ b/app/Client/Http/HttpClient.php @@ -6,6 +6,8 @@ use App\Client\Configuration; use App\Client\Http\Modifiers\CheckBasicAuthentication; use App\Logger\RequestLogger; use Clue\React\Buzz\Browser; +use Psr\Http\Message\UriInterface; +use React\Stream\ReadableStreamInterface; use function GuzzleHttp\Psr7\parse_request; use function GuzzleHttp\Psr7\str; use Laminas\Http\Request; @@ -84,22 +86,19 @@ class HttpClient protected function sendRequestToApplication(RequestInterface $request, $proxyConnection = null) { (new Browser($this->loop, $this->createConnector())) - ->withOptions([ - 'followRedirects' => false, - 'obeySuccessCode' => false, - 'streaming' => true, - ]) - ->send($request) + ->withFollowRedirects(false) + ->withRejectErrorResponse(false) + ->requestStreaming($request->getMethod(), $this->getExposeUri($request), $request->getHeaders(), $request->getBody()) ->then(function (ResponseInterface $response) use ($proxyConnection) { if (! isset($response->buffer)) { - $response = $this->rewriteResponseHeaders($response); + //$response = $this->rewriteResponseHeaders($response); $response->buffer = str($response); } $this->sendChunkToServer($response->buffer, $proxyConnection); - /* @var $body \React\Stream\ReadableStreamInterface */ + /* @var $body ReadableStreamInterface */ $body = $response->getBody(); $this->logResponse(str($response)); @@ -108,6 +107,7 @@ class HttpClient $response->buffer .= $chunk; $this->sendChunkToServer($chunk, $proxyConnection); + }); $body->on('close', function () use ($proxyConnection, $response) { @@ -156,4 +156,15 @@ class HttpClient return $response->withHeader('Location', $location); } + + private function getExposeUri(RequestInterface $request): UriInterface + { + $exposeProto = $request->getHeader('x-expose-proto')[0]; + $exposeHost = explode(':', $request->getHeader('x-expose-host')[0]); + + return $request->getUri() + ->withScheme($exposeProto) + ->withHost($exposeHost[0]) + ->withPort($exposeHost[1]); + } } diff --git a/app/Server/Connections/ConnectionManager.php b/app/Server/Connections/ConnectionManager.php index 3978d4d..ab5fe1e 100644 --- a/app/Server/Connections/ConnectionManager.php +++ b/app/Server/Connections/ConnectionManager.php @@ -45,15 +45,13 @@ class ConnectionManager implements ConnectionManagerContract public function storeConnection(string $host, ?string $subdomain, ConnectionInterface $connection): ControlConnection { - $clientId = (string) uniqid(); - - $connection->client_id = $clientId; + $connection->client_id = sha1(uniqid('', true)); $storedConnection = new ControlConnection( $connection, $host, $subdomain ?? $this->subdomainGenerator->generateSubdomain(), - $clientId, + $connection->client_id, $this->getAuthTokenFromConnection($connection) ); diff --git a/app/Server/Connections/ControlConnection.php b/app/Server/Connections/ControlConnection.php index 80b1d31..6b09a0e 100644 --- a/app/Server/Connections/ControlConnection.php +++ b/app/Server/Connections/ControlConnection.php @@ -3,6 +3,7 @@ namespace App\Server\Connections; use Evenement\EventEmitterTrait; +use Illuminate\Support\Str; use Ratchet\ConnectionInterface; class ControlConnection diff --git a/app/Server/Http/Controllers/TunnelMessageController.php b/app/Server/Http/Controllers/TunnelMessageController.php index a592868..7d2a016 100644 --- a/app/Server/Http/Controllers/TunnelMessageController.php +++ b/app/Server/Http/Controllers/TunnelMessageController.php @@ -113,9 +113,13 @@ class TunnelMessageController extends Controller $host .= ":{$this->configuration->port()}"; } - $request->headers->set('Host', $controlConnection->host); + $exposeUrl = parse_url($controlConnection->host); + + $request->headers->set('Host', "{$controlConnection->subdomain}.{$host}"); $request->headers->set('X-Forwarded-Proto', $request->isSecure() ? 'https' : 'http'); - $request->headers->set('X-Expose-Request-ID', uniqid()); + $request->headers->set('X-Expose-Request-ID', sha1(uniqid('', true))); + $request->headers->set('X-Expose-Host', sprintf('%s:%s', $exposeUrl['host'], $exposeUrl['port'])); + $request->headers->set('X-Expose-Proto', $exposeUrl['scheme']); $request->headers->set('Upgrade-Insecure-Requests', 1); $request->headers->set('X-Exposed-By', config('app.name').' '.config('app.version')); $request->headers->set('X-Original-Host', "{$controlConnection->subdomain}.{$host}");