diff --git a/app/Server/Connections/ConnectionManager.php b/app/Server/Connections/ConnectionManager.php index fefeeb1..743c6e9 100644 --- a/app/Server/Connections/ConnectionManager.php +++ b/app/Server/Connections/ConnectionManager.php @@ -5,6 +5,7 @@ namespace App\Server\Connections; use App\Contracts\ConnectionManager as ConnectionManagerContract; use App\Contracts\SubdomainGenerator; use App\Http\QueryParameters; +use App\Server\Exceptions\NoFreePortAvailable; use Ratchet\ConnectionInterface; use React\EventLoop\LoopInterface; use React\Socket\Server; @@ -82,8 +83,10 @@ class ConnectionManager implements ConnectionManagerContract protected function getSharedTcpServer(): Server { - $portRange = [50000, 62000]; - $port = $portRange[0]; + $portRange = config('expose.admin.tcp_port_range'); + + $port = $portRange['from'] ?? 50000; + $maxPort = $portRange['to'] ?? 60000; do { try { @@ -92,6 +95,10 @@ class ConnectionManager implements ConnectionManagerContract } catch (\RuntimeException $exception) { $portFound = false; $port++; + + if ($port > $maxPort) { + throw new NoFreePortAvailable(); + } } } while (! $portFound); diff --git a/app/Server/Exceptions/NoFreePortAvailable.php b/app/Server/Exceptions/NoFreePortAvailable.php new file mode 100644 index 0000000..45428d8 --- /dev/null +++ b/app/Server/Exceptions/NoFreePortAvailable.php @@ -0,0 +1,8 @@ +connectionManager->storeTcpConnection($data->port, $connection); + try { + $connectionInfo = $this->connectionManager->storeTcpConnection($data->port, $connection); + } catch (NoFreePortAvailable $exception) { + $connection->send(json_encode([ + 'event' => 'authenticationFailed', + 'data' => [ + 'message' => config('expose.admin.messages.no_free_tcp_port_available'), + ], + ])); + $connection->close(); + return; + } $connection->send(json_encode([ 'event' => 'authenticated', diff --git a/config/expose.php b/config/expose.php index 7835ceb..cec8b0e 100644 --- a/config/expose.php +++ b/config/expose.php @@ -151,6 +151,24 @@ return [ */ 'validate_auth_tokens' => false, + /* + |-------------------------------------------------------------------------- + | TCP Port Range + |-------------------------------------------------------------------------- + | + | Expose allows you to also share TCP ports, for example when sharing your + | local SSH server with the public. This setting allows you to define the + | port range that Expose will use to assign new ports to the users. + | + | Note: Do not use port ranges below 1024, as it might require root + | privileges to assign these ports. + | + */ + 'tcp_port_range' => [ + 'from' => 50000, + 'to' => 50003 + ], + /* |-------------------------------------------------------------------------- | Maximum connection length @@ -232,6 +250,8 @@ return [ 'subdomain_taken' => 'The chosen subdomain :subdomain is already taken. Please choose a different subdomain.', 'custom_subdomain_unauthorized' => 'You are not allowed to specify custom subdomains. Please upgrade to Expose Pro.', + + 'no_free_tcp_port_available' => 'There are no free TCP ports available on this server. Please try again later.' ], ], ];