IPV6 notation of $_SERVER['REMOTE_ADDR']

2019-04-09 08:27发布

问题:

I have many projects with functionalities relying on IP addresses provided by $_SERVER['REMOTE_ADDR], $_SERVER['HTTP_X_FORWARDED_FOR'], and $_SERVER['CLIENT_IP'].

IPV4 addresses are easy to match since we always receive them in the same format: 4 integers without the leading 0s, separated by a dot ..

Whereas IPV6 addresses can be compressed. Ex: FF01:0:0:0:0:0:0:101 -> FF01::101

I've been researching this issue but haven't found anything relevant, so I'm asking for your experience. Is $_SERVER['REMOTE_ADDR] using a standard? Is it safe to assume that it will always be received as compressed or uncompressed?

Or should I compress all my IPV6 string before I try to try test them?

Note:

Ideally I would like to handle IPV6 addresses as strings rather than binary structure, to improve readability in Databases / Source code and allow easier IP range matching.

回答1:

If you use inet_pton() first, and then convert it back to a string with inet_ntop() you should have a consistent string representation. I wouldn't rely on the input to be consistent...



回答2:

The CGI spec is clear that any RFC compliant IPv6 address is valid:

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].

A sane programmer validates all inputs. Therefore you should treat any environment variable as tainted input and validate/transform. Headers provided by a client, such as X-Forward-For et al should ALWAYS be treated with suspicion.

So what about expanding IPv6 addresses?

This question has been asked before and there are several solutions including a PEAR one

Hope this helps!



回答3:

The recommended format for IPv6 address is in RFC 5952.

However you cannot rely on all addresses being in that format, and the string format is particularly lousy for range comparisons. Reading the RFC will give you some idea as to just how many ways it's possible to legally represent the same IPv6 address.

You really should parse the address (using inet_pton as mentioned elsewhere) and perform your range comparisons on the resulting 128 bit field.

More often than not you'll only care about the 64 most significant bits, which fits nicely into a long on most architectures.



标签: php ipv6