【问题标题】:How to convert an address from IPv4 to IPv6如何将地址从 IPv4 转换为 IPv6
【发布时间】:2010-12-06 01:12:02
【问题描述】:

这可能吗?如何将 ipv4 转换为 ipv6 地址?

这里有几个例子:

0.0.0.0   -> ::
127.0.0.1 -> ::1

我正在用 Java 寻找解决方案。

谢谢,

【问题讨论】:

    标签: java ipv6


    【解决方案1】:

    有多种方法可以将 IPv4 映射到 IPv6。对于大多数此类方法,转换后的 IPv4 地址位于 16 字节 IPv6 地址的低 4 字节中。

    The IPAddress Java library 有方法可以帮助将 IPv4 转换为 IPv6 的许多最常见的方法。免责声明:我是该库的项目经理。

    例如,给定一个 IPv4 地址,您可以使用 IPv6 映射转换将其转换为 IPv6:

    IPv6Address ipv6Address = new IPAddressString("1.2.3.4").getAddress().toIPv4().
        getIPv4MappedAddress();
    System.out.println(ipv6Address); // ::ffff:102:304
    System.out.println(ipv6Address.toMixedString()); // ::ffff:1.2.3.4
    

    使用 IPv6Address 实例,您可以检查地址是否为 IPv4 映射、IPv4 兼容、IPv4 转换等(这些是 IPv6 表示 IPv4 地址的多种可能方式中的一部分)。之后,您可以转换回 IPv4。

    if(addr.isIPv4Compatible() || addr.isIPv4Mapped()) {
        IPv4Address derivedIpv4Address = ipv6Address.getEmbeddedIPv4Address();
        byte ipv4Bytes[] = ipv4Address.getBytes();
        ...
     }
    

    【讨论】:

      【解决方案2】:

      这是Javascript中的转换代码

      /** IPV4 CIDR to IPV6 CIDR conversion **/
      function covertIPv6(x){
      let ipV4 = x;
      let address = ipV4.split('/');
      let classValues = [];
      
      if(address.length){
        classValues = address[0].split('.');
      }
      if(classValues.length){  
        let str = classValues.reduce((acc, val, ind)=>{
          let mod = +val >= 16 ? +val%16 : +val;
          let divider = +val >= 16 ? (val-mod)/16 : 0;
          const hexaCode = (hexaVal)=>{
            switch(hexaVal){
            case 10:
              hexaVal = 'A';
              break;
            case 11:
              hexaVal = 'B';
              break;
            case 12:
              hexaVal = 'C';
              break;
            case 13:
              hexaVal = 'D';
              break;
            case 14:
              hexaVal = 'E';
              break;
            case 15:
              hexaVal = 'F';
              break;
            default:
              hexaVal = hexaVal;
              break;
          }
            return hexaVal;
          }
          mod = hexaCode(mod);
          divider = hexaCode(divider);
          return ind === 1 ? `${acc}${divider}${mod}:`:`${acc}${divider}${mod}`
        },'')
        return `2002:${str}::/${address[1]}`;
      }
        return "Invalid Address";
      }
      
      // Run the function
      
      console.log(covertIPv6("0.0.0.0/12"));

      【讨论】:

        【解决方案3】:

        IPv6 与 IPv4 兼容。

        一个 IPv4 地址:例如 192.168.99.1

        第一步 >

        将第一个八位字节 (192) 除以 16(因为 Hex 是 Base-16) IE : 192/16 = 12 次,剩下 0 – 十六进制的 12 表示为 C – 十六进制中的 0(零)是,你猜对了,0 因此十六进制中的 192 是 C0

        第二步>

        使用第二个八位字节 (168) 重复步骤 1, IE:168/16 = 10 次,剩余 8 次,因为 10*6 = 160, – 十六进制中的 10 是 A – 十六进制中的 8 是 8 因此十六进制中的 168 是 A8

        第三步 >

        重复规则!!!第三个八位字节 (99) IE:99/16 = 6 次,剩余 3 次 – 十六进制中的 6 是 6 – 十六进制中的 3 是 3 因此,HEX 中的 99 是 63

        第四步 >

        最后一个八位字节 IE:1/16 = 0 次,剩余 1 次 – 十六进制中的 0 是,是的,它是 0 – 十六进制中的 1 是 1 因此十六进制中的 1 是 01

        因此,在 IPv6 地址部分中表示的 IPv4 地址 192.168.99.1 将是 C0A8:6301。但是您必须使用小写并添加所有缺少的字节 IPv6,所以正确的代码是:

        ::c0a8:6301

        或者你可以使用现在总是被接受的语法:

        ::192.168.99.1

        所以最后一个 IPv6 地址可以是旧地址,旧地址前有 :: 字符。

        【讨论】:

          【解决方案4】:

          混合双栈 IPv6/IPv4 实现通常支持一类特殊的地址,即 IPv4 映射地址。更多内容请查看以下链接:

          http://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses

          要将 IPv4 转换为映射的 IPv6,您可以使用以下方法:

          String ip = "127.0.0.1"; 
          String[] octets = ip.split("\\.");
          byte[] octetBytes = new byte[4];
           for (int i = 0; i < 4; ++i) {
                      octetBytes[i] = (byte) Integer.parseInt(octets[i]);
          }
          
          byte ipv4asIpV6addr[] = new byte[16];
          ipv4asIpV6addr[10] = (byte)0xff;
          ipv4asIpV6addr[11] = (byte)0xff;
          ipv4asIpV6addr[12] = octetBytes[0];
          ipv4asIpV6addr[13] = octetBytes[1];
          ipv4asIpV6addr[14] = octetBytes[2];
          ipv4asIpV6addr[15] = octetBytes[3];
          

          同时检查this

          【讨论】:

            【解决方案5】:

            过去在 IPv6 中为 IPv4 地址保留了一个地址空间,您只需在 IPv4 地址前面加上 96 个 0 位即可。例如。 192.168.10.13 -&gt; ::C0A8:0A0D。据我所知,这已被弃用,并且不再提供直接转换。

            【讨论】:

            • 我认为仍然存在未弃用的 IPv4 映射 IPv6 地址。您在此方案中的示例是 ::ffff:c0a8:0a0d。其中带 0 的称为 IPv4 兼容的 IPv6 地址。
            【解决方案6】:

            没有有意义的 IPv4 到 IPv6 映射。 0.0.0.0 和 127.0.0.1 之类的东西在规范中是特殊情况,因此它们具有相同的含义。但是给定一个 IPv4 地址,它不会告诉您它的特定 IPv6 地址是什么。您可以使用 DNS 查找来查看给定的 IP 地址是否解析为主机,该主机又解析为 IPv6 地址和 IPv4 地址,但必须将 DNS 服务器配置为支持特定机器。

            【讨论】:

            • 在双栈系统中,其实有一个IPv4到IPv6的映射,在::ffff:XXXX:XXXX空间;这通常显示为“::ffff:192.168.1.1”——因此在 IPv6 地址空间中存在有意义的 IPv4 地址表示。
            • @DoktorJ,我认为这不是问题所在。我认为请求是针对正确的 IP6 地址,而不是在 IP6 堆栈上引用 IP4 地址的方法。
            • @DoktorJ 但是除非你有某种路由工具,否则这个映射并不能真正帮助你。
            • 我不同意这种说法:我在几个应用程序中看到 IPv4 地址映射到 IPv6,在这些应用程序中,开发人员希望所有地址都采用统一格式,以便进行排序、搜索等,无一例外它是 ::ffff:0:0/96。我不知道它是否严格意义上的,但它肯定是有用的。 Wikipedia 在权衡方面做得很好:en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses