如何处理IPv4地址旁边的IPv6地址
我是一名iphone开发人员 - 新开发web dev,请耐心等待!
我目前正在使用MAMP进行本地测试。如何处理IPv4地址旁边的IPv6地址
我在我的网站上有一个高度安全的部分。随着需要用户/通行证 - 它也检查用户的IP。如果该帐户之前没有从该IP使用过,则会将该IP以及唯一ID添加到保留表中,并向用户发送一封电子邮件,要求确认从该位置访问其帐户。
如果用户登录,并且他们的IP与我的“允许”表中的用户ID相关联的任何IP都不匹配,它将执行上述任务,并且他们会收到一封电子邮件。
我用它来生成他们点击链接的URL代码看起来有点像这样:
if (preg_match('/^127./',$ip)) {
// accessed from this machine
$val_url = "http://localhost:8888/mywebsite/admin/aproove_ip.php?email=$admin_email&val=$hash";
}
else if (preg_match('/^192\.168./',$ip)) {
// accessed form a local networked computer
$val_url = "http://super.local:8888/mywebsite/admin/aproove_ip.php?email=$admin_email&val=$hash";
// note super.local is my machine's address, 8888 is MAMP port
}
else {
// accessed from the WWW
$val_url = "http://www.mywebsite.com/admin/aproove_ip.php?email=$admin_email&val=$hash";
}
现在,这已经完全在我的电脑上测试时的工作。我决定(不要问为什么)从我的iPod Touch和它发给我的电子邮件(以验证IP)进行测试,它给了我完整的在线地址,就好像它已经从WWW(即没有任何正则表达式都满意)。我查看了包含请求的保留表,并且请求的IP为:fe80::da30:62ff:fe18:6681
。
我猜这是ipv6? - 我需要知道的是:
- 我应该期望ipv6地址在我的网站上线吗?
- 我怎样才能知道,如果它是一个本地请求(像我正则表达式对192.168 ...和127 ...)
我将非常感谢有这方面的意见,我觉得很困惑
如果你想确保没有发生IPv6连接,可以将Listen 0.0.0.0:80
添加到你的apache配置中。但是大多数网络主机仍然不支持IPv6(我知道,我们在2011年),所以人们甚至不可能通过IPv6连接到您。你看到这个的唯一原因是因为bonjour(什么使.local
地址工作)在IPv6上运行。
如果您想让代码IPv6准备就绪,几乎不需要进行任何更改,因为大多数IP PHP功能都适用于IPv4和IPv6。我记得的唯一改变是将MySQL表中的varchar数据类型增加到IPv6地址的最大长度(39
)。
我不确定IPv6是否按照IPv4所做的相同规则subnet播放,但我认为验证IPv6地址是本地的会比较困难。
编辑:
fe80::/10
似乎是本地链路地址,这可能是因为检查前4位一样简单。
谢谢! - 已经让我的varchar 39字符变长了 - 我想我应该不用担心bonjour,那只是为了测试,最后当它在线时它会做我想做的事情,IPv6或不! –
您不应该使用varchar来存储IP地址 - 无论是v4还是v6。它阻止了你用位掩码高效地查询它们,并浪费了很多存储空间。请使用INET_ATON()和INET_NTOA()在MySQL中分别存储和检索IP地址。 –
对于在一般应用程序中存储IP的大多数用途,只是为了跟踪用户,并且由于MySQL不能证明以可读方式存储IP的本地方式,通常我只是为了方便而使用varchar(尤其是当它可以是IPv6或IPv4 )。 –
要查看IPv6地址是否是本地的,您必须知道哪些地址在本地使用。 IPv6不会执行NAT(通常)。有些网络在内部使用ULA(唯一本地地址),但许多网络只使用从ISP内部获得的地址。
你必须考虑的一件事是,一些(大多数?这些天)使用隐私扩展。这意味着他们的IPv6地址会随着时间而改变。这会导致你的表增长很多,并且会使用户一遍又一遍地重新认证。我认为你最好的选择是只存储子网(前64位)并匹配。
以防万一您不知道IPv6地址语法:地址使用十六进制数字并且具有ssss:ssss:ssss:ssss:nnnn:nnnn:nnnn:nnnn其中s是子网,n是节点/主办。每个4位数据块中的前导零被省略,并且多个0的块被替换为::一次。所以fe80::da30:62ff:fe18:6681
实际上是fe80:0000:0000:0000:da30:62ff:fe18:6681
。我自己的网络服务器地址为2001:4038:0:16::16
,这是2001:4038:0000:0016:0000:0000:0000:0016
的简称,子网是2001:4038:0:16::/64
。
示例代码从地址获得子网:
<?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";
你能提供一些代码来从IPv6地址获取子网吗? - 然后我的代码存储在我的数据库中... –
当然!代码添加在答案中 –
+1想使你的代码的IPv6兼容!即使IPv4地址已经用完,今天编写的程序仍然不支持IPv6。 – snap