如何与 IPv4 PHP 一起处理 IPv6 地址

发布于 2024-12-03 06:35:45 字数 1265 浏览 1 评论 0原文

我是一名 iPhone 开发人员 - 网络开发新手,所以请耐心等待!
我目前正在使用 MAMP 进行本地测试。

我的网站上有一个高度安全的部分。除了需要用户/通行证之外,它还会检查用户的 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...)

我非常感谢对此的任何建议,因为我发现它真的很令人困惑

I'm an iphone developer - new to web dev, so please be patient!
I'm currently using MAMP for local testing.

I have a highly secure section on my site. Along with requiring a user/pass - it also checks the user's 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.

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.

The code I use to generate the url of the link they click on looks a bit like this:

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 (i.e. neither of the regexs were satisfied). I looked in the holding table which contains the requests, and the requested IP was: fe80::da30:62ff:fe18:6681.

I'm guessing that's ipv6? - What I need to know is the following:

  • Should I expect ipv6 addressess to hit my site when it goes live?
  • How can I tell if it was a local request (like my regex's for 192.168... and 127...)

I would very much appreciate any advice on this as I find it really confusing

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

淤浪 2024-12-10 06:35:46

如果你想确保没有 IPv6 连接发生,可以添加 Listen 0.0.0.0:80< /a> 到你的 apache 配置。但无论如何,大多数网络主机尚不支持 IPv6(是的,我知道,我们已经是 2011 年了),因此人们甚至不太可能通过 IPv6 连接到您。您看到此情况的唯一原因是 bonjour(使 .local 地址起作用的原因)通过 IPv6 运行。

如果您想让代码为 IPv6 做好准备,几乎不需要进行任何更改,因为大多数 IP PHP 函数都可以在 IPv4 和 IPv6 上运行。我记得所做的唯一更改是将 MySQL 表中的 varchar 数据类型增加到 IPv6 地址的最大长度 (39)。

我不确定 IPv6 是否遵循与 IPv4 相同的子网规则,但我预计这将是一个相当大的变化。验证 IPv6 地址是本地地址有点困难。

编辑:

fe80::/10 似乎是本地链接地址,它可能就像检查前 4 位数字一样简单。

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.

久光 2024-12-10 06:35:46

要查看 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::162001: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";

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";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文