Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validating non-private IP addresses with PHP

Tags:

php

filter-var

I'm trying to check whether or not an IP address is an internal-only (i.e. private) IP, but I'm getting a curious result:

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?

Surely 127.0.0.1 counts as a private IP? I found this bug report from 2010 which reports this as an issue, but it's marked as fixed. Is this a regression, or am I misunderstanding what this filter does? I'm using PHP 5.4.6.

like image 565
Tim Fountain Avatar asked Jun 17 '13 14:06

Tim Fountain


People also ask

How do you check IP address is valid or not in PHP?

The FILTER_VALIDATE_IP filter validates an IP address. Possible flags: FILTER_FLAG_IPV4 - The value must be a valid IPv4 address. FILTER_FLAG_IPV6 - The value must be a valid IPv6 address.

How do you check if an IP is public or private?

To check if your IP address is public, you can use myip.com (or any similar service). You will be shown the IP address that was used for accessing the site; and if it matches the IP address that your Internet service provider assigned you, then you have a public IP address.

What is Filter_var function in PHP?

filter_var() is a PHP function used to filters a variable with the help of a specified filter. In PHP programming language we can use filter_var() function to validate and sanitize a data such as email id, IP address etc.


1 Answers

I guess thats because 127.0.0.1 is not realy a private IP range, but a loopback IP range, as explained here

Normally, when a TCP/IP application wants to send information, that information travels down the protocol layers to IP where it is encapsulated in an IP datagram. That datagram then passes down to the data link layer of the device's physical network for transmission to the next hop, on the way to the IP destination.

However, one special range of addresses is set aside for loopback functionality. This is the range 127.0.0.0 to 127.255.255.255. IP datagrams sent by a host to a 127.x.x.x loopback address are not passed down to the data link layer for transmission. Instead, they “loop back” to the source device at the IP level. In essence, this represents a “short-circuiting” of the normal protocol stack; data is sent by a device's layer three IP implementation and then immediately received by it.

The purpose of the loopback range is testing of the TCP/IP protocol implementation on a host. Since the lower layers are short-circuited, sending to a loopback address allows the higher layers (IP and above) to be effectively tested without the chance of problems at the lower layers manifesting themselves. 127.0.0.1 is the address most commonly used for testing purposes.

The manual for Filter flag has a comment on this specific issue.

<?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, array('options' => 'FILTER_FLAG_NO_LOOPBACK_RANGE'));
// Returns FALSE

$var = filter_var('74.125.19.103', FILTER_CALLBACK, array('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, array('options' => 'FILTER_FLAG_NO_LOOPBACK_RANGE'));
// Returns FALSE
?>
like image 171
Hugo Delsing Avatar answered Sep 25 '22 19:09

Hugo Delsing