是公共IP地址吗?

I would like to know whether there is any easy method to check whether an IP address is publicly accessible or is private.

More specifically. I know for example, that 127.0.0.1 is a private IP address that point into the same machine, 255.255.255.255 if for broadcasting into the same network, 192.168.1.0 is for local network addresses and so on. But how can I distinguish whether a given IP address is not one of the private IP and is publicly accessible?

http://en.wikipedia.org/wiki/Private_network lists the various ranges. Just construct an if statement.

Pulic/private IPv4 addresses are defined in RFC 5735. In short:

  • 0.0.0.0/8 is invalid
  • 127.0.0.0/8 is localhost
  • 169.254.0.0/16 is an unconfigured IP. You should treat it like a local address
  • 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 are private networks
  • 224.0.0.0/4 is multicast
  • Everything else is publicly reachable, or reserved

For IPv6, refer to RFC 5165. In short:

  • ::/128 is the unspecified address, ::1/128 is localhost
  • ::ffff:0:0/96 are IPv4-mapped addresses
  • fe80::/10 and fc00::/7 are private networks
  • ff00::/8 is multicast
  • Everything else is publicly reachable, or reserved

Note that services on machines without a public IP may still be reachable from the internet with the help of port forwarding or other firewall rules.

One solution is mentioned by Ed Heal, but there is another one:

Just connect to some external host and ask it for the IP it sees, like that (example for PHP):

$my_public_ip = file_get_contents('http://ip.42.pl/raw');

This specific example I know will return single string containing only an IP address. I do not know other services offering this, although there are probably plenty of them. The main page of the above script / service is: http://ip.42.pl/.

If you know similar services, please post their URLs in the comments, so future readers have other options.

function validateIpAddress($ip_addr)
{
    $result = true;
    if(preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/",$ip_addr))
    {
        $parts=explode(".",$ip_addr);
        foreach($parts as $ip_parts)
        {
            if(intval($ip_parts)>255 || intval($ip_parts)<0)
                $result=false;
        }
        if (intval($parts[0])==0 || intval($parts[0])==10 || intval($parts[0])==127 || (intval($parts[0])>223 && intval($parts[0])<240))
        {
            $result=false;
        }
        if ((intval($parts[0])==192 && intval($parts[1])==168) || (intval($parts[0])==169 && intval($parts[1])==254))
        {
            $result=false;
        }

        if (intval($parts[0])==172 && intval($parts[1])>15 && intval($parts[1])<32 )
        {
            $result=false;
        }
    }
    else
    {
        $result = false; //if format of ip address doesn't matches 
    }
    return $result;
}