$_SERVER['REMOTE_ADDR']的IPV6表示法

5

我有许多项目的功能依赖于$_SERVER['REMOTE_ADDR]$_SERVER['HTTP_X_FORWARDED_FOR']$_SERVER['CLIENT_IP']提供的IP地址。

由于我们总是以相同的格式接收它们,因此IPv4地址很容易匹配:4个整数,没有前导0,由点.分隔。

而IPv6地址可以被压缩。例如:FF01:0:0:0:0:0:0:101 -> FF01::101

我一直在研究这个问题,但没有找到任何相关信息,所以我想问问你的经验。 $_SERVER['REMOTE_ADDR]是否使用标准?可以安全地假设它始终会以压缩或未压缩的形式接收到吗?

还是应该在尝试测试之前压缩所有我的IPv6字符串?

注意:

理想情况下,我希望将IPv6地址处理为字符串,而不是二进制结构,以提高数据库/源代码的可读性并允许更轻松的IP范围匹配。


我没有使用过IPv6,但我的印象是你应该使用inet_pton()来操作任何地址。 - Álvaro González
@ÁlvaroG.Vicario 感谢您的评论,我一定会研究这个函数。但如果可能的话,我想保留字符串表示法。 - Tchoupi
3个回答

5
如果您先使用inet_pton(),然后再用inet_ntop()将其转换回字符串,那么您应该获得一致的字符串表示。我不会依赖于输入的一致性...

1
我已经测试过了,它似乎给出了一致的结果。这可能正是我正在寻找的。我将在实际项目中进行测试,看看它是否可行。 - Tchoupi
我已经测试过了,它完美地工作了。而且它足够简单。谢谢! - Tchoupi
1
@Sander inet_pton()inet_ntop()... 你能在你的回答中加入这些链接吗? - Doktor J

2
"

CGI规范清楚地说明,任何符合RFC标准的IPv6地址都是有效的:

"
4.1.8.  REMOTE_ADDR

   The REMOTE_ADDR variable MUST be set to the network address of the
   client sending the request to the server.

      REMOTE_ADDR  = hostnumber
      hostnumber   = ipv4-address | ipv6-address
      ipv4-address = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit
      ipv6-address = hexpart [ ":" ipv4-address ]
      hexpart      = hexseq | ( [ hexseq ] "::" [ hexseq ] )
      hexseq       = 1*4hex *( ":" 1*4hex )

  The format of an IPv6 address is described in RFC 3513 [15].

一位明智的程序员会验证所有输入。因此,您应该将任何环境变量视为有污染的输入并进行验证/转换。由客户端提供的标头,例如X-Forward-For等,应始终持怀疑态度。
那么,如何扩展IPv6地址呢?
这个问题以前曾经被问过,并且有几种解决方案,包括一个PEAR解决方案
希望这可以帮到您!

谢谢!当然,我会先验证它是否是一个有效的IP地址。实际上,我正在使用https://dev59.com/_HRB5IYBdhLWcg3w-8Ho中提供的函数来将IPV4和IPV6存储在数据库中。PEAR解决方案似乎是一个不错的选择,我一定会尝试一下。 - Tchoupi
即使有Pear函数,尝试在字符串格式中(即使是完全展开的情况下)进行IPv6范围匹配仍然非常困难,特别是如果范围不落在一个nybble边界上(即/62)。 - Alnitak
@Alnitak 很好的观点。我的IP范围可以缩小到nibble边界,因此一个简单的strpos应该就可以解决问题,假设我的输入是一致的。 - Tchoupi

1

IPv6地址的推荐格式在RFC 5952中。

然而,您不能指望所有地址都采用该格式,并且字符串格式对于范围比较特别糟糕。阅读RFC将使您了解有多少种合法表示相同IPv6地址的方式。

您真的应该解析地址(使用其他地方提到的inet_pton)并在生成的128位字段上执行范围比较。

往往您只关心最重要的64位,这可以很好地适配大多数架构上的long


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接