所以有几个网站会为你计算你的本地链接 ipv6 地址,就像这里的这个。
然而,对于如何计算这个地址以及输入参数是什么,它没有给出任何有用的信息。那么,如果知道 ipv4 地址、子网掩码和网关地址,那么计算链路本地 ipv6 地址的过程(或算法)是什么?我正在做一个使用 ISATAP 网络隧道的 SCTP 套接字项目,并且 LL ipv6 地址用于构建 ISATAP 地址。
所以有几个网站会为你计算你的本地链接 ipv6 地址,就像这里的这个。
然而,对于如何计算这个地址以及输入参数是什么,它没有给出任何有用的信息。那么,如果知道 ipv4 地址、子网掩码和网关地址,那么计算链路本地 ipv6 地址的过程(或算法)是什么?我正在做一个使用 ISATAP 网络隧道的 SCTP 套接字项目,并且 LL ipv6 地址用于构建 ISATAP 地址。
RFC 4291 的附录 A描述了从 MAC 地址计算修改后的 EUI-64 的方法。一旦你有了修改后的 EUI-64,你只需把它放在地址的低 64 位,然后把fe80::放在高 64 位。
基本上你翻转 MAC 地址的第 7 位,并打包它的前 24 位(包括翻转的位),然后是 fffe,然后是 MAC 地址的低 24 位,总共 64 位。
话虽如此,您的问题是如何从 IPv4 地址和子网掩码派生链接本地地址。那,你做不到。IPv4 地址和子网掩码(如果确实有一个 - IPv6 根本不需要 IPv4 在同一接口上运行)与 IPv6 地址无关,并且两者没有任何关系。IPv4 网关地址(同样,如果有的话)甚至更不相关。
链路本地地址可以基于RFC 4862的 MAC 地址,也可以根据RFC 4941随机生成。
通常这应该限制在全局范围内,但一些系统将此隐私扩展实现扩展到链接本地范围。 按照这个关于 serverfault 的问题来讨论这个话题。
The previous answers failed to note that there is a defined procedure for generating a link local IPv6 address from an IPv4 address when using ISATAP, and there is a different process for generating a link local IPv6 address from a MAC address. The two things are unrelated.
For ISATAP, the 32-bit IPv4 address is prepended wit the 96 bits of either fe80::200:5efe or fe80::200:5efe to get the 128-bit IPv6 link-local address.
For MAC to IPv6, the 48-bit MAC address is split in half, 16 bits are inserted in the middle, those bits being ff:fe, then it is prepended by the 64-bit link-local prefix fe80::, and finally the 7th bit in the 5th IPv6 segment is flipped, to get the 128-bit IPv6 link-local address.
The following code provides examples showing how to use the The IPAddress library to do the conversions in either Java or Go. Disclaimer: I am the project manager of those libraries.
These examples also help to visualize the conversions described above.
Go:
func convertToIsatap(ipv4Str string, isGlobal bool) string {
ipv4Address := ipaddr.NewIPAddressString(ipv4Str).GetAddress().ToIPv4()
zero := &ipaddr.IPv6AddressSegment{}
segments := make([]*ipaddr.IPv6AddressSegment, ipaddr.IPv6SegmentCount)
segments[1], segments[2], segments[3], segments[4] = zero, zero, zero, zero
segments[0] = ipaddr.NewIPv6Segment(0xfe80)
segments[5] = ipaddr.NewIPv6Segment(0x5efe)
if isGlobal {
segments[4] = ipaddr.NewIPv6Segment(0x200)
}
ipv6Address, _ := ipv4Address.GetIPv6Address(ipaddr.NewIPv6Section(segments))
return ipv6Address.String()
}
func convertToLinkLocalIPv6(macAddr string) string {
macAddress := ipaddr.NewMACAddressString(macAddr).GetAddress()
ipv6LinkLocal, _ := macAddress.ToLinkLocalIPv6()
return ipv6LinkLocal.String()
}
fmt.Println("1.2.3.4 becomes ISATAP " +
convertToIsatap("1.2.3.4", true))
fmt.Println("aa:bb:cc:11:22:33 becomes " +
convertToLinkLocalIPv6("aa:bb:cc:11:22:33"))
Java:
static String convertToIsatap(String ipv4Str, boolean isGlobal) {
IPv4Address ipv4Address = new IPAddressString(ipv4Str).getAddress().toIPv4();
IPv6AddressSegment zeroSeg = new IPv6AddressSegment(0);
IPv6AddressSegment segments[] =
new IPv6AddressSegment[IPv6Address.SEGMENT_COUNT - 2];
segments[1] = segments[2] = segments[3] = segments[4] = zeroSeg;
segments[0] = new IPv6AddressSegment(0xfe80);
segments[5] = new IPv6AddressSegment(0x5efe);
if(isGlobal) {
segments[4] = new IPv6AddressSegment(0x200);
}
return ipv4Address.getIPv6Address(
new IPv6AddressSection(segments)).toString();
}
static String convertToLinkLocalIPv6(String macStr) {
MACAddress macAddress = new MACAddressString(macStr).getAddress();
return macAddress.toLinkLocalIPv6().toString();
}
System.out.println("1.2.3.4 becomes ISATAP " +
convertToIsatap("1.2.3.4", true));
System.out.println("aa:bb:cc:11:22:33 becomes " +
convertToLinkLocalIPv6("aa:bb:cc:11:22:33"));
The output is the same for both examples:
1.2.3.4 becomes ISATAP fe80::200:5efe:102:304
aa:bb:cc:11:22:33 becomes fe80::a8bb:ccff:fe11:2233