在 AWS Lightsail 下运行的 NodeJS 中获取正确与错误的 IPV4 地址 [IP6to4]

问题描述 投票:0回答:1

我们在 AWS Lightsail 上的 BitNami 实例下运行。

当前的 NodeJS 看起来像这样:

function getClientIPv4(req) {
  let ipAddress;
  const forwardedFor = req.headers['x-forwarded-for'];
  if (forwardedFor) {
    ipAddress = forwardedFor.split(',')[0];
  } else {
    ipAddress = req.connection.remoteAddress;
  }

  console.log(req.headers['x-forwarded-for'], "x-forwarded");
  console.log(req.connection.remoteAddress, "remoteAddress");

  if(net.isIPv6(ipAddress)) {
    ipAddress = IP6to4(ipAddress);
  }

  return ipAddress;
}

开发者在控制台添加了一些调试:

我的IP地址V6是2603:8080:c940:120:5983:c3e9:aed3:c91d 其中 应转换为 72.181.25.179(位于德克萨斯州)。

我认为他的 IP 地址转换正确(我认为他在波兰)。

但是上面的例程将其转换为 174.211.201.29,这是在纽约。

一些在线网页转换器,也犯同样的错误:

现在正在使用此转换例程,但它给出了错误的结果以及已尝试的其他库:

function IP6to4(ip6) {
  function parseIp6(ip6str) {
    const str = ip6str.toString();

    // Initialize
    const ar = new Array();
    for (var i = 0; i < 8; i++) ar[i] = 0;

    // Check for trivial IPs
    if (str == '::') return ar;

    // Parse
    const sar = str.split(':');
    let slen = sar.length;
    if (slen > 8) slen = 8;
    let j = 0;
    i = 0
    for (i = 0; i < slen; i++) {
      // This is a "::", switch to end-run mode
      if (i && sar[i] == '') {
        j = 9 - slen + i;
        continue;
      }
      ar[j] = parseInt(`0x0${sar[i]}`);
      j++;
    }

    return ar;
  }
node.js ipv6 ipv4 amazon-lightsail
1个回答
0
投票

一般来说,您无法将地址从 IPv6 转换为 IPv4。它们是两个完全独立的网络,仅通过相同的线路,但不以任何方式交互 - 网络运营商(ISP)可能拥有完全不同的 IPv4 寻址和 IPv6 寻址系统,并且只有该运营商可能知道两者之间的关系。它们不可兑换。

(就此而言,有许多服务器和设备具有 IPv6,但根本没有 IPv4 地址。甚至有整个网络没有 IPv4,只有 IPv6。) 声称可以将 IPv6“转换”为 IPv4 的工具仅在少数

非常具体的情况下才能正常工作(上述情况除外)。例如,如果 IPv6 地址是“6to4”或“Teredo”或“ISATAP”地址,则可以对其进行转换,因为它最初确实基于 IPv4 地址 – 这些都是“转换”机制,旨在跨网络提供 IPv6 连接。一个仅支持 IPv4 的网络,因此嵌入 IPv4 地址是必要的。但当谈到

本机 IPv6 连接时,情况就不再是这样了——本机 IPv6 不以任何方式依赖 IPv4。 屏幕截图中的工具过于概括,并尝试将 ISATAP 转换规则(“取最后 4 个字节”)应用于每个地址,即使它不具有 ISATAP 地址的标志。所以,当然,它得到了完全荒谬的结果。

我强烈怀疑无论哪个软件在您的请求中添加“x-forwarded-for”标头都会犯同样的错误。

我有一个IP地址数据库,我们购买了其中的IPV4地址。这是一家不同的公司,但谈论将 IPV6 转换为 IPV4。想知道我是否可以在查找数据库中添加新列和索引,或者我是否必须找到具有 IPV6 位置的提供商?

您必须找到具有“IPv6 到位置”功能的提供商。

windows IPCONFIG 命令显示:

Connection-specific DNS Suffix . : Link-local IPv6 Address . . . . . : fe80::132f:ba8:74b9:6ae3%23 IPv4 Address. . . . . . . . . . . : 172.30.96.1 Temporary IPv6 Address. . . . . . : 2603:8080:c940:120:5983:c3e9:aed3:c91d

所以我不只有一个 IP 地址。是什么决定了哪一个从浏览器传递到服务器?

浏览器总是首先对域名进行 DNS 查找,以确定

服务器
具有哪种地址,同样是因为网络是独立的,并且它必须使用与服务器相同类型的地址。因此,如果域具有 IPv6 地址(“AAAA”DNS 记录),则浏览器将尝试 IPv6;如果域有 IPv4(“A”记录),则浏览器将尝试 IPv4。当两者都可用时,浏览器通常会同时尝试两者,而其他程序则相继尝试。

虽然浏览器决定使用哪个网络,但通常是客户端操作系统选择要连接的特定地址。如果尝试使用 IPv6,则操作系统将根据多个规则选择地址,其中之一是“范围”,它排除了“链路本地”地址,因为它不能用于直接连接之外的任何用途,另一个是“作用域”。是“最长前缀匹配”,它将全球互联网地址 (2xxx:

) 与另一个全球地址相匹配,或将私有 LAN 地址 (

fdXX:

) 与另一个私有地址相匹配。此外,临时“隐私”地址优先于永久地址。
像“我的 IP 地址是什么”这样的网站如何同时显示两者,而 NodeJS 却不能?

网站欺骗浏览器建立多个连接,每种连接一个。

对网站的初始请求始终只有一种类型,即 IPv4 或 IPv6。为了获得其他类型,网站需要使用 XHR 或 iframe 来强制浏览器通过“仅 IPv4”子域或通过“仅 IPv6”子域进行连接。

例如,如果您访问

whatismyip.com

,它一开始不会显示任何地址 – 它只是显示“正在检测...” – 并且您将看到发出这两个 XHR 请求:

第一个域仅支持 IPv4,强制浏览器建立 IPv4 连接。 (第二个应该仅支持 IPv6,但显然它只有 IPv6 就足够了,因为浏览器无论如何都会首先尝试。)

所有此类网站的工作方式都相同:

这里重要的部分是服务器请求处理程序在任何时候总是只能看到其中之一。它只是将两者结合在一起的客户端 Web 应用程序。

© www.soinside.com 2019 - 2024. All rights reserved.