Skip to content

Commit

Permalink
[HttpClient] Filter private IPs before connecting when Host == IP
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Oct 25, 2024
1 parent 54118c6 commit ebcaeea
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
13 changes: 12 additions & 1 deletion NoPrivateNetworkHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,20 @@ public function request(string $method, string $url, array $options = []): Respo
}

$subnets = $this->subnets;
$lastUrl = '';
$lastPrimaryIp = '';

$options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use ($onProgress, $subnets, &$lastPrimaryIp): void {
$options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use ($onProgress, $subnets, &$lastUrl, &$lastPrimaryIp): void {
if ($info['url'] !== $lastUrl) {
$host = trim(parse_url($info['url'], PHP_URL_HOST) ?: '', '[]');

if ($host && IpUtils::checkIp($host, $subnets ?? self::PRIVATE_SUBNETS)) {
throw new TransportException(sprintf('Host "%s" is blocked for "%s".', $host, $info['url']));
}

$lastUrl = $info['url'];
}

if ($info['primary_ip'] !== $lastPrimaryIp) {
if ($info['primary_ip'] && IpUtils::checkIp($info['primary_ip'], $subnets ?? self::PRIVATE_SUBNETS)) {
throw new TransportException(sprintf('IP "%s" is blocked for "%s".', $info['primary_ip'], $info['url']));
Expand Down
27 changes: 25 additions & 2 deletions Tests/NoPrivateNetworkHttpClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ public static function getExcludeData(): array
/**
* @dataProvider getExcludeData
*/
public function testExclude(string $ipAddr, $subnets, bool $mustThrow)
public function testExcludeByIp(string $ipAddr, $subnets, bool $mustThrow)
{
$content = 'foo';
$url = sprintf('http://%s/', 0 < substr_count($ipAddr, ':') ? sprintf('[%s]', $ipAddr) : $ipAddr);
$url = sprintf('http://%s/', strtr($ipAddr, '.:', '--'));

if ($mustThrow) {
$this->expectException(TransportException::class);
Expand All @@ -85,6 +85,29 @@ public function testExclude(string $ipAddr, $subnets, bool $mustThrow)
}
}

/**
* @dataProvider getExcludeData
*/
public function testExcludeByHost(string $ipAddr, $subnets, bool $mustThrow)
{
$content = 'foo';
$url = sprintf('http://%s/', str_contains($ipAddr, ':') ? sprintf('[%s]', $ipAddr) : $ipAddr);

if ($mustThrow) {
$this->expectException(TransportException::class);
$this->expectExceptionMessage(sprintf('Host "%s" is blocked for "%s".', $ipAddr, $url));
}

$previousHttpClient = $this->getHttpClientMock($url, $ipAddr, $content);
$client = new NoPrivateNetworkHttpClient($previousHttpClient, $subnets);
$response = $client->request('GET', $url);

if (!$mustThrow) {
$this->assertEquals($content, $response->getContent());
$this->assertEquals(200, $response->getStatusCode());
}
}

public function testCustomOnProgressCallback()
{
$ipAddr = '104.26.14.6';
Expand Down

0 comments on commit ebcaeea

Please sign in to comment.