How to handle IPv6 addresses alongside IPv4 PHP

扶醉桌前 提交于 2019-12-05 20:18:49

If you want to ensure that no IPv6 connections happen can add Listen 0.0.0.0:80 to your apache configuration. But most web hosts don't support IPv6 yet anyway (ya I know, we're in 2011), so it's very unlikely that people can even connect to you via IPv6. The only reason your seeing this is because bonjour (what makes .local address work) runs over IPv6.

If you want to get your code IPv6 ready, almost no changes need to be made as most IP PHP function work on both IPv4 and IPv6. The only change I remember making was increasing the varchar datatype in the MySQL table to the max length of a IPv6 address (39).

I'm not sure that IPv6 plays by the same rules of subnet that IPv4 does, but I expect it would be quite a bit harder to validate a IPv6 address is local.

EDIT:

fe80::/10 appears to be local link addresses, it might be as simple as checking the first 4 digits.

To see if an IPv6 address is local you must know which addresses are used locally. IPv6 doesn't do NAT (usually). Some networks use ULA (unique local addresses) internally, but many just use the addresses they get from the ISP internally.

One thing you have to take into account is that some (most? These days) use privacy extensions. This means that their IPv6 addresses will change over time. This will cause your table to grow a lot, and it will make user re-authenticate over and over again. I think your best option is to store only the subnet (the first 64 bits) and match on that.

Just in case you don't know the IPv6 address syntax: addresses use hexadecimal digits and have the form ssss:ssss:ssss:ssss:nnnn:nnnn:nnnn:nnnn where s is the subnet and n is the node/host. Leading zeroes in each block of 4 digits are omitted, and multiple blocks of 0 are replaced with :: once. So fe80::da30:62ff:fe18:6681 is actually fe80:0000:0000:0000:da30:62ff:fe18:6681. My own webserver has address 2001:4038:0:16::16, which is short for 2001:4038:0000:0016:0000:0000:0000:0016, and the subnet is 2001:4038:0:16::/64.

Example code to get the subnet from the address:

<?php

# Get the original IP address, for example from the command line
$original_ip_str = $argv[1];

# Converto to binary form (suppress errors, we handle them)
$original_ip_bin = @inet_pton($original_ip_str);
if ($original_ip_bin === FALSE) {
  $subnet_str = FALSE;
  $subnet_bin = FALSE;
} else {
  if (strlen($original_ip_bin) == 16) {
    # IPv6: Replace the last 64 bits with zeroes
    $subnet_bin = substr_replace($original_ip_bin, str_repeat("\000", 8), -8);
  }

  # Convert the result back to readable form (optional)
  $subnet_str = inet_ntop($subnet_bin);
}

# Show the result
echo "IPv6 address: $original_ip_str\n";
echo "IPv6 subnet: $subnet_str\n";
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!