IPv6-tuki IP-rajoitukseen
Vaihdettu ip2long() -> inet_pton() joka tukee sekä IPv4 että IPv6. CIDR-alueet toimivat molemmilla (esim. 2001:db8::/32). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
31
api.php
31
api.php
@@ -140,29 +140,36 @@ function getClientIp(): string {
|
||||
/**
|
||||
* Tarkista onko IP sallittujen listalla.
|
||||
* Tyhjä lista = ei rajoitusta (kaikki sallittu).
|
||||
* Tukee yksittäisiä IP-osoitteita ja CIDR-alueita (esim. 192.168.1.0/24).
|
||||
* Tukee IPv4 ja IPv6, yksittäisiä osoitteita ja CIDR-alueita.
|
||||
*/
|
||||
function isIpAllowed(string $ip, string $allowedIps): bool {
|
||||
$allowedIps = trim($allowedIps);
|
||||
if ($allowedIps === '' || strtolower($allowedIps) === 'kaikki') return true; // ei rajoitusta
|
||||
if ($allowedIps === '' || strtolower($allowedIps) === 'kaikki') return true;
|
||||
$entries = preg_split('/[\s,]+/', $allowedIps, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$ipLong = ip2long($ip);
|
||||
if ($ipLong === false) return false;
|
||||
$ipBin = @inet_pton($ip);
|
||||
if ($ipBin === false) return false;
|
||||
foreach ($entries as $entry) {
|
||||
$entry = trim($entry);
|
||||
if ($entry === '') continue;
|
||||
if (strpos($entry, '/') !== false) {
|
||||
// CIDR-alue (esim. 192.168.1.0/24)
|
||||
// CIDR-alue (IPv4 tai IPv6)
|
||||
[$subnet, $bits] = explode('/', $entry, 2);
|
||||
$bits = (int)$bits;
|
||||
if ($bits < 0 || $bits > 32) continue;
|
||||
$subnetLong = ip2long($subnet);
|
||||
if ($subnetLong === false) continue;
|
||||
$mask = $bits === 0 ? 0 : (~0 << (32 - $bits));
|
||||
if (($ipLong & $mask) === ($subnetLong & $mask)) return true;
|
||||
$subnetBin = @inet_pton($subnet);
|
||||
if ($subnetBin === false) continue;
|
||||
// IPv4 = 4 tavua, IPv6 = 16 tavua — pitää olla sama perhe
|
||||
if (strlen($ipBin) !== strlen($subnetBin)) continue;
|
||||
$maxBits = strlen($ipBin) * 8;
|
||||
if ($bits < 0 || $bits > $maxBits) continue;
|
||||
// Rakenna bittimask
|
||||
$mask = str_repeat("\xff", intdiv($bits, 8));
|
||||
if ($bits % 8) $mask .= chr(0xff << (8 - ($bits % 8)));
|
||||
$mask = str_pad($mask, strlen($ipBin), "\x00");
|
||||
if (($ipBin & $mask) === ($subnetBin & $mask)) return true;
|
||||
} else {
|
||||
// Yksittäinen IP
|
||||
if (ip2long($entry) === $ipLong) return true;
|
||||
// Yksittäinen IP (IPv4 tai IPv6)
|
||||
$entryBin = @inet_pton($entry);
|
||||
if ($entryBin !== false && $ipBin === $entryBin) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user