Fix inet_pton() Unrecognized address

Viktor Dite, Autor des Beitrags

Von - Publiziert in Webdevelopment Blog über MySQL & PHP
Dipl. Informatiker und Tech-Blogger seit 2006.


If the PHP function inet_pton() throws an error or warning: „Unrecognized address“, then you probably use $_SERVER[‚HTTP_X_FORWARDED_FOR‘] to get the IP address. The IP address read with this may represent an unreadable value for inet_pton() when accessing via a proxy.

Specifically, $_SERVER[‚HTTP_X_FORWARDED_FOR‘] returns a comma-separated list of IP addresses through certain constellations, instead of a single IP address that inet_pton() expects as input.

Two Examples:
„9.6.3.45, 86.56.1.23“ oder
„2001:0db8:85a3:0000:0000:8a2e:0370:7334, 86.56.1.23“

inet_pton(„9.6.3.45, 88.56.1.23“) throws a warning, because the input is unexpected and inet_pton() cannot do anything with it. With certain server constellation the error can even lead to a serverfault and thus poses a potential danger for the accessibility of the page/app.

So if you want to safely process the IP address in your script using inet_pton(), you have to make sure that the input contains only an IPV4 or IPV6 address instead of a comma-separated list.

Here is a simple example which ensures that only the first part of the comma-separated list is processed as the IP address:

$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
inet_pton(array_shift(explode(",", $ip)));

This way you can test if it is an IPV4 or IPV6 address:

$ip = array_shift(explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']));
if(strlen(inet_pton($ip)) == 4){
  echo $ip . ' is an IPV4 address';
}elseif(strlen(inet_pton($ip))==16){
  echo $ip . ' is an IPV6 address';
}

It would be even better to exclude with filter_var() all possible incorrect entries and only allow actual IP addresses:

$ip = array_shift(explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']));

if(filter_var($ip, FILTER_VALIDATE_IP)){
  if(strlen(inet_pton($ip)) == 4){
    echo $ip . ' is an IPV4 address';
  }elseif(strlen(inet_pton($ip))==16){
    echo $ip . ' is an IPV6 address';
  }
}else{
  // No IP address
}

Deutsche Lösung für inet_pton() unrecognized address

Wenn die PHP Funktion inet_pton() einen Fehler oder Warnung wirft: „Unrecognized address“, dann nutzt Du sicher $_SERVER[‚HTTP_X_FORWARDED_FOR‘] zur Ermittlung der IP-Adresse. Die damit gelesene IP Adresse kann bei Zugriffen über einen Proxy einen für inet_pton() nicht lesbaren Wert darstellen.

Konkret liefert $_SERVER[‚HTTP_X_FORWARDED_FOR‘] durch bestimmte Konstellationen eine kommagetrennte Liste von IP-Adressen, statt einer einzelnen IP Adresse, die inet_pton() als Eingabe erwartet.

Hier ein Beispiel:
„9.6.3.45, 86.56.1.23“ oder
„2001:0db8:85a3:0000:0000:8a2e:0370:7334, 86.56.1.23“

inet_pton(„9.6.3.45, 88.56.1.23“) schmeißt aber eine Warnung, da die Eingabe unerwartet ist und inet_pton() damit nichts anfangen kann. Bei bestimmter Server Konstellation kann der Fehler sogar zu einem Serverfault führen und stellt damit eine potenzielle Gefahr für die Erreichbarkeit der Seite /App.

Wenn Du in Deinem Skript also mit Hilfe von inet_pton() die IP Adresse sicher verarbeiten willst, musst Du sicherstellen, dass die Eingabe nur eine IPV4 oder IPV6 Adresse enthält, statt einer kommegetrennten Liste.

Hier ein einfaches Beispiel, welches sicherstellt, dass nur der erste Teil der kommagetrennten Liste als IP Adresse verarbeitet wird:

$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
inet_pton(array_shift(explode(",", $ip)));

Auf diese Weise könntest Du bspw. testen, ob es sich um eine IPV4 oder IPV6 Adresse handelt:

$ip = array_shift(explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']));
if(strlen(inet_pton($ip)) == 4){
  echo $ip . ' ist eine IPV4 Adresse';
}elseif(strlen(inet_pton($ip))==16){
  echo $ip . ' ist eine IPV6 Adresse';
}

Noch besser wäre es mit Hilfe von filter_var() alle möglichen Fehleingaben auszuschließen und nur tatsächliche IP ADressen zuzulassen:

$ip = array_shift(explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']));

if(filter_var($ip, FILTER_VALIDATE_IP)){
  if(strlen(inet_pton($ip)) == 4){
    echo $ip . ' ist eine IPV4 Adresse';
  }elseif(strlen(inet_pton($ip))==16){
    echo $ip . ' ist eine IPV6 Adresse';
  }
}else{
  // Keine IP Adresse
}

Weiterlesen:


Letzte Änderung: