简体   繁体   English

如何在IPv4 PHP中处理IPv6地址

[英]How to handle IPv6 addresses alongside IPv4 PHP

I'm an iphone developer - new to web dev, so please be patient! 我是一名iphone开发者 - 网络开发者的新手,所以请耐心等待!
I'm currently using MAMP for local testing. 我目前正在使用MAMP进行本地测试。

I have a highly secure section on my site. 我的网站上有一个高度安全的部分。 Along with requiring a user/pass - it also checks the user's IP. 除了需要用户/通行证 - 它还会检查用户的IP。 If the account hasn't been used from that IP before, it will add that IP, along with a unique ID, to a holding table, and fire the user an email asking to confirm access them to their account from that location. 如果之前未使用该IP帐户,则会将该IP以及唯一ID添加到保留表中,并向用户发送电子邮件,要求确认从该位置访问其帐户。

If the user logs in, and their IP doesn't match any IPs associated with their user ID in my 'allowed' table, it performs the above task, and they receive an email. 如果用户登录,并且他们的IP与我的“允许”表中与其用户ID关联的任何IP都不匹配,则执行上述任务,他们会收到一封电子邮件。

The code I use to generate the url of the link they click on looks a bit like this: 我用来生成他们点击的链接的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";
}

Now, this has worked perfectly when testing on my computer. 现在,这在我的计算机上进行测试时非常有效。

However, I decided (don't ask why) to test from my iPod Touch and in the email it sent me (to validate the IP), it gave me the full online address as if it had been accessed from the WWW (ie neither of the regexs were satisfied). 但是,我决定(不要问为什么)从我的iPod Touch和它发送给我的电子邮件(验证IP)进行测试,它给了我完整的在线地址,好像它是从WWW访问的(即两者都没有)对正则表达式的满意度)。 I looked in the holding table which contains the requests, and the requested IP was: fe80::da30:62ff:fe18:6681 . 我查看了包含请求的保留表,请求的IP是: fe80::da30:62ff:fe18:6681

I'm guessing that's ipv6? 我猜那是ipv6? - What I need to know is the following: - 我需要知道的是以下内容:

  • Should I expect ipv6 addressess to hit my site when it goes live? 我应该期望ipv6 addressess在我的网站上线时点击我的网站吗?
  • How can I tell if it was a local request (like my regex's for 192.168... and 127...) 如何判断它是否是本地请求(如我的正则表达式为192.168 ......和127 ......)

I would very much appreciate any advice on this as I find it really confusing 我非常感谢任何有关这方面的建议,因为我觉得它真的令人困惑

If you want to ensure that no IPv6 connections happen can add Listen 0.0.0.0:80 to your apache configuration. 如果要确保不发生IPv6连接,可以将Listen 0.0.0.0:80添加到您的apache配置中。 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. 但是大多数网络主机不支持IPv6(我知道,我们是在2011年),因此人们甚至不可能通过IPv6连接到你。 The only reason your seeing this is because bonjour (what makes .local address work) runs over IPv6. 你看到这个的唯一原因是因为bonjour(使.local地址工作的原因)在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. 如果您想准备好IPv6代码,几乎不需要进行任何更改,因为大多数IP PHP功能都可以在IPv4和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 ). 我记得的唯一变化是将MySQL表中的varchar数据类型增加到IPv6地址的最大长度( 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. 我不确定IPv6是否遵循与IPv4相同的子网规则,但我认为验证IPv6地址是本地的要困难得多。

EDIT: 编辑:

fe80::/10 appears to be local link addresses, it might be as simple as checking the first 4 digits. fe80::/10似乎是本地链接地址,它可能就像检查前4位数一样简单。

To see if an IPv6 address is local you must know which addresses are used locally. 要查看IPv6地址是否为本地,您必须知道本地使用的是哪些地址。 IPv6 doesn't do NAT (usually). IPv6不执行NAT(通常)。 Some networks use ULA (unique local addresses) internally, but many just use the addresses they get from the ISP internally. 有些网络在内部使用ULA(唯一本地地址),但许多网络只使用内部从ISP获得的地址。

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. 这意味着他们的IPv6地址将随时间而变化。 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. 我认为你最好的选择是只存储子网(前64位)并匹配。

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. 如果您不知道IPv6地址语法:地址使用十六进制数字并且格式为ssss:ssss:ssss:ssss:nnnn:nnnn:nnnn:nnnn其中s是子网,n是节点/主机。 Leading zeroes in each block of 4 digits are omitted, and multiple blocks of 0 are replaced with :: once. 省略了每个4位数的块中的前导零,并且用:: once替换多个0的块。 So fe80::da30:62ff:fe18:6681 is actually fe80:0000:0000:0000:da30:62ff:fe18:6681 . 所以fe80::da30:62ff:fe18:6681实际上是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 . 我自己的网络服务器的地址是2001:4038:0:16::16 ,这是2001:4038:0000:0016:0000:0000:0000:0016缩写2001:4038:0000:0016:0000:0000:0000:0016 ,子网是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";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM