【问题标题】:PHP $_SERVER['REMOTE_ADDR'] shows IPv6PHP $_SERVER['REMOTE_ADDR'] 显示 IPv6
【发布时间】:2023-03-03 06:36:20
【问题描述】:

我在 PHP 中遇到了 $_SERVER['REMOTE_ADDR'] 的问题 即使服务器使用的是 IPv4,它也会提供类似 IPv6 的值。

谁能帮我解决这个问题。

【问题讨论】:

  • 您确定您的服务器在 IPv4 上运行吗?
  • 这是因为您的 Web 服务器绑定到 [::],而不是 0.0.0.0。

标签: php ipv6


【解决方案1】:

服务器随后接受 IPv6 套接字上的连接。某些操作系统可以在 IPv6 套接字上同时执行 IPv4 和 IPv6。发生这种情况时,IPv6 地址将类似于::ffff:192.0.2.123::ffff:c000:027b,它们是相同的地址,但以十六进制形式编写。

如果您看到像 2a00:8640:1::224:36ff:feef:1d89 这样的 IPv6 地址,那么您的网络服务器确实可以通过 IPv6 访问 :-)

无论如何,要将所有内容转换回规范形式,您可以使用以下内容:

// Known prefix
$v4mapped_prefix_hex = '00000000000000000000ffff';
$v4mapped_prefix_bin = pack("H*", $v4mapped_prefix_hex);

// Or more readable when using PHP >= 5.4
# $v4mapped_prefix_bin = hex2bin($v4mapped_prefix_hex); 

// Parse
$addr = $_SERVER['REMOTE_ADDR'];
$addr_bin = inet_pton($addr);
if( $addr_bin === FALSE ) {
  // Unparsable? How did they connect?!?
  die('Invalid IP address');
}

// Check prefix
if( substr($addr_bin, 0, strlen($v4mapped_prefix_bin)) == $v4mapped_prefix_bin) {
  // Strip prefix
  $addr_bin = substr($addr_bin, strlen($v4mapped_prefix_bin));
}

// Convert back to printable address in canonical form
$addr = inet_ntop($addr_bin);

使用此代码,当您输入以下内容之一时:

::ffff:192.000.002.123
::ffff:192.0.2.123
0000:0000:0000:0000:0000:ffff:c000:027b
::ffff:c000:027b
::ffff:c000:27b
192.000.002.123
192.0.2.123

您总是得到规范的 IPv4 地址 192.0.2.123 作为输出。

当然,IPv6 地址会作为规范的 IPv6 地址返回:2a00:8640:0001:0000:0224:36ff:feef:1d89 变为 2a00:8640:1::224:36ff:feef:1d89 等等。

【讨论】:

  • 谢谢。我会做一些事情来过滤 IP。
  • 我尝试将您的所有示例添加到我的测试脚本中,但我从不执行前缀条带化。对于所有示例,您的示例代码中是否有太多的 0?
  • 不,所有示例都有效。你能展示你的测试脚本吗?
  • inet_pton("192.000.002.123") 在 PHP 5.3.6-10 上给出警告并返回 false。
  • qbolec:那是您平台上的错误...请转到bugs.php.net 并提交错误报告以便修复。
猜你喜欢
  • 2012-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 1970-01-01
  • 2011-10-06
  • 1970-01-01
  • 2021-03-12
相关资源
最近更新 更多