IPv6 validieren

Ich möchte euch heute zeigen wie ihr mit einfachen Mitteln eine IPv6 Adresse in PHP validieren könnt.

Es gibt mehrere Möglichkeiten. Ich möchte euch 3 davon vorstellen.

Vorbereitung

Wer seine PHP Script IPv6 Ready machen möchte der muss einiges umstellen.

IP Adressen können mit IPv6 nicht mehr als Long Int gespeichert werden, denn IPv6 ist 2^128 Bit groß. Dies könnte man vielleicht noch in eine Datenbank speichern, aber spätestens PHP steigt bei dieser Größe aus. Also müsst Ihr alle IP Adressen wieder als Varchar bzw. Char in die Datenbank speichen. Schöne Funktionen wie ip2long gehören nun auch der Vergangenheit an und müssen aus euren scripten raus.

Validierungsmöglichkeiten:

Option 1

Option 1 ist die einfachste und die schnellste Validierungsart, denn wir können dirket PHP Boardmittel verwenden und müssen nicht auf langsame Regex Anweisungen zurück greifen. Das einzige Problem besteht darin, dies ist ber erst  ab der PHP Version 5.2.0 verfügbar.

Wir verwenden dafür Filter-Funktionen. Ich nutze in unserem Beispiel die Funktion filter_var(). Diese Funktion validiert eine Variable anhand eines Filters.

Für eine IPv6 Adresse brauchen wir den FILTER_VALIDATE_IP Filter und optional den FILTER_FLAG_IPV6 Flag.

Ich zeig es euch einfach mal an einem Beispiel

1
2
3
4
5
6
7
8
9
10
$ipv6_addr = '2001:0db8:85a3:08d3:1319:8a2e:0370:7347';
 
if(filter_var($ipv6_addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false)
{
	echo 'IP ist gültig';
}
else
{
	echo 'IP ist nicht gültig';
}

Der Vorteil liegt klar auf der Hand. Mit einer Funktion/Filter können wir sehr schnell IPv6 und IPv4 Adressen validieren

Option 2

Option 2 ist schon langsamer und brauch viel mehr Zeilen code. Denn wir müssen die Funktion von filter_var, die in c geschieben ist, in PHP schreiben.

Hier der PHP Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?php
function ipv6_validieren($ip)
{
	//Länge der IPv6 addr könnte ja ::127 sein oder 1234:1241:...
	$ip_len = strlen($ip);
 
	//IPv6 Komprimiert
	$compress = 0;
 
	//Enthält den aktuellen Block
	$bock = 0;
 
	//Wird kein : gefunden dann ist es keine IPv6 Addr
	if(strstr($ip, ':') === false)
		return 0;
 
	while($i < $ip_len)
	{
		if($ip{$i} == ':')
		{
			//Nach dem : muss eine Zahl folgen
			if(++$i >= $ip_len)
				return 0;
 
			//Zwei :: IP Adresse ist Komprimiert
			if($ip{$i} == ':')
			{
				//IPv6 darf nur einmal Komprimiert werden
				if($compress)
					return 0;
 
				$compress = 1;
				$block++;
 
				if(++$i >= $ip_len)
				{
					return (block <= 8) ? 1 : 0;
				}
			}
			elseif($ip{($i-1)} == $ip{0})
			{
				return 0;
			}
		}
 
		$n = 0;
 
		while(($i < $ip_len) && (($ip{$i} >= '0' && $ip{$i} <= '9') || ($ip{$i} >= 'a' && $ip{$i} <= 'f') || ($ip{$i} >= 'A' && $ip{$i} <= 'F')))
		{
			$i++;
			$n++;
		}
 
		if($n < 1 || $n > 4)
			return 0;
 
		if(++$block > 8)
			return 0;
	}
 
	return (($compress && $block <= 8) || $block == 8) ? 1 : 0;
}
 
$ipv6_addr = "::127";
var_dump(ipv6_validieren($ipv6_addr)); // 1
 
$ipv6_addr = "fe80::204:61ff:9:d:f1:5:6:3";
var_dump(ipv6_validieren($ipv6_addr)); // 0
 
?>

Die ipv6_validieren Funktion geht jedes Zeichen durch und prüft es.

Option 3

Jetzt bleibt nur noch die Möglichkeit eines regulären Ausdrucks.

Ich zeig ihn euch einfach mal

1
2
3
4
5
6
7
8
9
10
11
/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|
((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|
(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)
(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|
((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|
(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)
(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|
((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))
|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)
(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}
:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/

Danke Stephen für diesen Regex Ausdruck.
Der Vorteil bei diesem Ausdruck ist er erlaubt auch IP Mischformen:

fe80:0000:0000:0000:0204:61ff:fe9d:f156 // IPv6
fe80:0:0:0:204:61ff:fe9d:f156 // Führende Nullen entfernt
fe80::204:61ff:fe9d:f156 // Komprimierte Adressen
fe80:0000:0000:0000:0204:61ff:254.157.241.86 // IPv4 Mischformen
fe80:0:0:0:0204:61ff:254.157.241.86 // IPv4 Mischformen
fe80::204:61ff:254.157.241.86 // IPv4 Mischformen

Schlusswort

Ihr solltet bei neuen Projekten auf jeden Fall IPv6 Unterstützung mit einbauen, denn es gibt schon genug Probleme IPv6 einzuführen, da müssen wir nicht noch mit unseren PHP Skripten mitmachen.

Wer PHP >= 5.2.0 nutzt sollte auf die Filterfunktionen setzten, denn diese sind direkt in C geschieben und sind somit am schnellsten.

Schlagwörter: , ,

Hinterlasse einen Kommentar

Name: (erforderlich)

eMail: (erforderlich)

Website:

Kommentar: