[HttpFoundation] Add a way to anonymize IPs
This commit is contained in:
parent
585c0df909
commit
9e62330bc4
|
@ -11,7 +11,8 @@ CHANGELOG
|
||||||
make sure to run `CREATE INDEX EXPIRY ON sessions (sess_lifetime)` to update your database
|
make sure to run `CREATE INDEX EXPIRY ON sessions (sess_lifetime)` to update your database
|
||||||
to speed up garbage collection of expired sessions.
|
to speed up garbage collection of expired sessions.
|
||||||
* added `SessionHandlerFactory` to create session handlers with a DSN
|
* added `SessionHandlerFactory` to create session handlers with a DSN
|
||||||
|
* added `IpUtils::anonymize()` to help with GDPR compliance.
|
||||||
|
|
||||||
4.3.0
|
4.3.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
@ -153,4 +153,36 @@ class IpUtils
|
||||||
|
|
||||||
return self::$checkedIps[$cacheKey] = true;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,4 +101,30 @@ class IpUtilsTest extends TestCase
|
||||||
'invalid request IP with invalid proxy wildcard' => ['0.0.0.0', '*'],
|
'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
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue