Convalidare gli indirizzi IP non privati ​​con PHP

Sto cercando di verificare se un indirizzo IP è un IP solo interno (cioè privato), ma sto ottenendo un risultato curioso:

filter_var('173.194.66.94', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE); // returns 173.194.66.94 filter_var('192.168.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE); // returns false filter_var('127.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE); // returns 127.0.0.1? 

Sicuramente 127.0.0.1 conta come un IP privato? Ho trovato questo bug report dal 2010 che riport questo come un problema, ma è contrassegnato come fisso. È una regressione, o sto fraintendendo cosa fa questo filter? Sto usando PHP 5.4.6.

Immagino che questo perché 127.0.0.1 non è davvero un intervallo IP private , ma un intervallo IP di loopback , come spiegato qui

Normalmente, quando un'applicazione TCP / IP vuole submit informazioni, tali informazioni viaggiano verso il basso i livelli del protocollo verso IP where è incapsulato in un datagramma IP. Tale datagramma passa quindi al livello di collegamento dati della networking fisica del dispositivo per la trasmissione all'hop successivo, sulla strada verso la destinazione IP.

Tuttavia, una gamma speciale di indirizzi è riservata alla funzionalità di loopback. Questo è il range da 127.0.0.0 a 127.255.255.255. I datagrammi IP inviati da un host a un indirizzo di loopback 127.xxx non vengono passati al livello di collegamento dati per la trasmissione. Invece, "ricollegano" al dispositivo sorgente a livello IP. In sostanza, ciò rappresenta un "cortocircuito" del normale stack di protocollo; i dati vengono inviati dall'implementazione IP del livello tre del dispositivo e quindi ricevuti immediatamente da esso.

Lo scopo dell'intervallo di loopback è il test dell'implementazione del protocollo TCP / IP su un host. Poiché gli strati inferiori sono cortocircuitati, l'invio a un indirizzo di loopback consente di testare efficacemente gli strati superiori (IP e superiori) senza la possibilità che si manifestino problemi agli strati inferiori. 127.0.0.1 è l'indirizzo più comunemente utilizzato a scopo di test.

Il manuale per Flag filter ha un commento su questo specifico problema.

 <?php function FILTER_FLAG_NO_LOOPBACK_RANGE($value) { // Fails validation for the following loopback IPv4 range: 127.0.0.0/8 // This flag does not apply to IPv6 addresses return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? $value : (((ip2long($value) & 0xff000000) == 0x7f000000) ? FALSE : $value); } $var = filter_var('127.0.0.1', FILTER_CALLBACK, arrays('options' => 'FILTER_FLAG_NO_LOOPBACK_RANGE')); // Returns FALSE $var = filter_var('74.125.19.103', FILTER_CALLBACK, arrays('options' => 'FILTER_FLAG_NO_LOOPBACK_RANGE')); // Returns '74.125.19.103' // To filter Private IP ranges and Loopback ranges $var = filter_var('127.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) && filter_var('127.0.0.1', FILTER_CALLBACK, arrays('options' => 'FILTER_FLAG_NO_LOOPBACK_RANGE')); // Returns FALSE ?> 

Ora è bloccato da FILTER_FLAG_NO_RES_RANGE .

Vedi https://bugs.php.net/bug.php?id=53150