From 9e62330bc45bae92d9046edc75e0d78e25a73fe3 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 26 Jun 2019 16:20:24 +0200 Subject: [PATCH] [HttpFoundation] Add a way to anonymize IPs --- .../Component/HttpFoundation/CHANGELOG.md | 3 +- .../Component/HttpFoundation/IpUtils.php | 32 +++++++++++++++++++ .../HttpFoundation/Tests/IpUtilsTest.php | 26 +++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index 10eaa0ac5a0f6..e33b33ccbe4c7 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -11,7 +11,8 @@ CHANGELOG make sure to run `CREATE INDEX EXPIRY ON sessions (sess_lifetime)` to update your database to speed up garbage collection of expired sessions. * added `SessionHandlerFactory` to create session handlers with a DSN - + * added `IpUtils::anonymize()` to help with GDPR compliance. + 4.3.0 ----- diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index 67d13e57aafce..72c53a4710815 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -153,4 +153,36 @@ public static function checkIp6($requestIp, $ip) return self::$checkedIps[$cacheKey] = true; } + + /** + * Anonymizes an IP/IPv6. + * + * Removes the last byte for v4 and the last 8 bytes for v6 IPs + */ + public static function anonymize(string $ip): string + { + $wrappedIPv6 = false; + if ('[' === substr($ip, 0, 1) && ']' === substr($ip, -1, 1)) { + $wrappedIPv6 = true; + $ip = substr($ip, 1, -1); + } + + $packedAddress = inet_pton($ip); + if (4 === \strlen($packedAddress)) { + $mask = '255.255.255.0'; + } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff:ffff'))) { + $mask = '::ffff:ffff:ff00'; + } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff'))) { + $mask = '::ffff:ff00'; + } else { + $mask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; + } + $ip = inet_ntop($packedAddress & inet_pton($mask)); + + if ($wrappedIPv6) { + $ip = '['.$ip.']'; + } + + return $ip; + } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php index d3b262e048526..13b5743794f8e 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php @@ -101,4 +101,30 @@ public function invalidIpAddressData() 'invalid request IP with invalid proxy wildcard' => ['0.0.0.0', '*'], ]; } + + /** + * @dataProvider anonymizedIpData + */ + public function testAnonymize($ip, $expected) + { + $this->assertSame($expected, IpUtils::anonymize($ip)); + } + + public function anonymizedIpData() + { + return [ + ['192.168.1.1', '192.168.1.0'], + ['1.2.3.4', '1.2.3.0'], + ['2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603::'], + ['2a01:198:603:10:396e:4789:8e99:890f', '2a01:198:603:10::'], + ['::1', '::'], + ['0:0:0:0:0:0:0:1', '::'], + ['1:0:0:0:0:0:0:1', '1::'], + ['0:0:603:50:396e:4789:8e99:0001', '0:0:603:50::'], + ['[0:0:603:50:396e:4789:8e99:0001]', '[0:0:603:50::]'], + ['[2a01:198::3]', '[2a01:198::]'], + ['::ffff:123.234.235.236', '::ffff:123.234.235.0'], // IPv4-mapped IPv6 addresses + ['::123.234.235.236', '::123.234.235.0'], // deprecated IPv4-compatible IPv6 address + ]; + } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy