【问题标题】:Validating non-private IP addresses with PHP使用 PHP 验证非私有 IP 地址
【发布时间】:2013-06-13 13:25:18
【问题描述】:

我正在尝试检查某个 IP 地址是否是仅限内部(即私有)IP,但我得到了一个奇怪的结果:

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?

确定 127.0.0.1 算作私有 IP 吗?我发现this bug report from 2010 报告这是一个问题,但它被标记为已修复。这是回归,还是我误解了这个过滤器的作用?我正在使用 PHP 5.4.6。

【问题讨论】:

  • 127.0.0.1 不在私有范围内,它是环回 IP。该文档明确指出 FILTER_FLAG_NO_PRIV_RANGE 仅拒绝 10.0.0.0/8172.16.0.0/12192.168.0.0/16
  • 对于看到此内容的其他人,您可以使用FILTER_FLAG_NO_RES_RANGE 来检查 127.0.0.1。所以filter_var('127.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE);

标签: php filter-var


【解决方案1】:

我猜那是因为 127.0.0.1 并不是真正的private IP 范围,而是loopback IP 范围,正如here 所解释的那样

通常,当 TCP/IP 应用程序想要发送信息时,该信息会沿协议层向下传输到 IP,并在 IP 数据报中封装。然后,该数据报向下传递到设备物理网络的数据链路层,以便在到达 IP 目的地的途中传输到下一跳。

但是,为回送功能预留了一个特殊的地址范围。这是 127.0.0.0 到 127.255.255.255 的范围。主机发送到 127.x.x.x 环回地址的 IP 数据报不会向下传递到数据链路层进行传输。相反,它们在 IP 级别“环回”到源设备。本质上,这代表了普通协议栈的“短路”;数据由设备的第三层 IP 实现发送,然后立即被设备接收。

环回范围的目的是测试主机上的 TCP/IP 协议实现。由于较低层是短路的,因此发送到环回地址可以有效地测试较高层(IP 及以上),而不会在较低层出现问题。 127.0.0.1 是最常用于测试目的的地址。

Filter flag 的手册对此特定问题有评论。

<?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
?>

【讨论】:

    【解决方案2】:

    现在被FILTER_FLAG_NO_RES_RANGE屏蔽了。

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

    【讨论】:

      猜你喜欢
      • 2012-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-02
      • 2014-05-13
      • 2017-06-14
      • 1970-01-01
      • 2015-06-21
      相关资源
      最近更新 更多