8000 [HttpFoundation] Add IpUtils::isPrivateIp · symfony/symfony@6471582 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6471582

Browse files
danielburger1337nicolas-grekas
authored andcommitted
[HttpFoundation] Add IpUtils::isPrivateIp
1 parent 17a88cf commit 6471582

File tree

5 files changed

+59
-16
lines changed

5 files changed

+59
-16
lines changed

src/Symfony/Component/HttpClient/NoPrivateNetworkHttpClient.php

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,6 @@ final class NoPrivateNetworkHttpClient implements HttpClientInterface, LoggerAwa
3030
{
3131
use HttpClientTrait;
3232

33-
private const PRIVATE_SUBNETS = [
34-
'127.0.0.0/8',
35-
'10.0.0.0/8',
36-
'192.168.0.0/16',
37-
'172.16.0.0/12',
38-
'169.254.0.0/16',
39-
'0.0.0.0/8',
40-
'240.0.0.0/4',
41-
'::1/128',
42-
'fc00::/7',
43-
'fe80::/10',
44-
'::ffff:0:0/96',
45-
'::/128',
46-
];
47-
4833
private HttpClientInterface $client;
4934
private string|array|null $subnets;
5035

@@ -74,7 +59,7 @@ public function request(string $method, string $url, array $options = []): Respo
7459

7560
$options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use ($onProgress, $subnets, &$lastPrimaryIp): void {
7661
if ($info['primary_ip'] !== $lastPrimaryIp) {
77-
if ($info['primary_ip'] && IpUtils::checkIp($info['primary_ip'], $subnets ?? self::PRIVATE_SUBNETS)) {
62+
if ($info['primary_ip'] && IpUtils::checkIp($info['primary_ip'], $subnets ?? IpUtils::PRIVATE_SUBNETS)) {
7863
throw new TransportException(sprintf('IP "%s" is blocked for "%s".', $info['primary_ip'], $info['url']));
7964
}
8065

src/Symfony/Component/HttpClient/composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
"symfony/process": "^5.4|^6.0",
4343
"symfony/stopwatch": "^5.4|^6.0"
4444
},
45+
"conflict": {
46+
"symfony/http-foundation": "<6.3"
47+
},
4548
"autoload": {
4649
"psr-4": { "Symfony\\Component\\HttpClient\\": "" },
4750
"exclude-from-classmap": [

src/Symfony/Component/HttpFoundation/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CHANGELOG
1010
* Create migration for session table when pdo handler is used
1111
* Add support for Relay PHP extension for Redis
1212
* The `Response::sendHeaders()` method now takes an optional HTTP status code as parameter, allowing to send informational responses such as Early Hints responses (103 status code)
13+
* Add `IpUtils::isPrivateIp`
1314
* Deprecate conversion of invalid values in `ParameterBag::getInt()` and `ParameterBag::getBoolean()`,
1415
* Deprecate ignoring invalid values when using `ParameterBag::filter()`, unless flag `FILTER_NULL_ON_FAILURE` is set
1516

src/Symfony/Component/HttpFoundation/IpUtils.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@
1818
*/
1919
class IpUtils
2020
{
21+
public const PRIVATE_SUBNETS = [
22+
'127.0.0.0/8', // RFC1700 (Loopback)
23+
'10.0.0.0/8', // RFC1918
24+
'192.168.0.0/16', // RFC1918
25+
'172.16.0.0/12', // RFC1918
26+
'169.254.0.0/16', // RFC3927
27+
'0.0.0.0/8', // RFC5735
28+
'240.0.0.0/4', // RFC1112
29+
'::1/128', // Loopback
30+
'fc00::/7', // Unique Local Address
31+
'fe80::/10', // Link Local Address
32+
'::ffff:0:0/96', // IPv4 translations
33+
'::/128', // Unspecified address
34+
];
35+
2136
private static array $checkedIps = [];
2237

2338
/**
@@ -191,4 +206,12 @@ public static function anonymize(string $ip): string
191206

192207
return $ip;
193208
}
209+
210+
/**
211+
* Checks if an IPv4 or IPv6 address is contained in the list of private IP subnets.
212+
*/
213+
public static function isPrivateIp(string $requestIp): bool
214+
{
215+
return self::checkIp($requestIp, self::PRIVATE_SUBNETS);
216+
}
194217
}

src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,35 @@ public static function getIp4SubnetMaskZeroData()
154154
[false, '1.2.3.4', '256.256.256/0'], // invalid CIDR notation
155155
];
156156
}
157+
158+
/**
159+
* @dataProvider getIsPrivateIpData
160+
*/
161+
public function testIsPrivateIp(string $ip, bool $matches)
162+
{
163+
$this->assertSame($matches, IpUtils::isPrivateIp($ip));
164+
}
165+
166+
public static function getIsPrivateIpData(): array
167+
{
168+
return [
169+
// private
170+
['127.0.0.1', true],
171+
['10.0.0.1', true],
172+
['192.168.0.1', true],
173+
['172.16.0.1', true],
174+
['169.254.0.1', true],
175+
['0.0.0.1', true],
176+
['240.0.0.1', true],
177+
['::1', true],
178+
['fc00::1', true],
179+
['fe80::1', true],
180+
['::ffff:0:1', true],
181+
['fd00::1', true],
182+
183+
// public
184+
['104.26.14.6', false],
185+
['2606:4700:20::681a:e06', false],
186+
];
187+
}
157188
}

0 commit comments

Comments
 (0)
0