一、IPv6地址的概述
IPv6是IP(Internet Protocol)的第六版,它被设计为IPV4(Internet Protocol Version 4)的后继者。IPv6采用128位地址长度,相对于IPv4的32位地址长度,IPv6能够支持更多的地址,IPv6地址不仅包含本地网络的地址,而且包含了全球惟一的地址。
二、IPv6地址的组成
IPv6地址由8组16进制数构成,每组之间用冒号“:”分隔。<br>例如:2001:0db8:85a3:0000:0000:8a2e:0370:7334
1. 简化地址表示
IPv6的地址长度为128位,如果每组都写满16位,则会非常冗长,不便于人类阅读和记忆。为了简化IPv6的地址,有两种方式可以使用:
(1)用一组双冒号“::”代替多个连续的0,这种方法只能使用一次,例如:
2001:0db8:85a3:0000:0000:8a2e:0370:7334 可以简写成: 2001:0db8:85a3::8a2e:0370:7334
(2)将每组地址前导的0省略掉,例如:
2001:0db8:0123:0045:5678:09ab:cdef:0123 可以简写成: 2001:db8:123:45:5678:9ab:cdef:123
2. 地址的类型
IPv6地址有几种类型,包括:
(1)单播地址:只有一个接口需要接收该地址。
(2)组播地址:多个接口需要接收该地址,组播地址的范围根据地址的第一字节定义。
(3)任播地址:多个接口都可以接收该地址,数据报将被路由转发到距离最近的接收端口。
数据包中的源地址可以是任何地址,但只能指定一个目标地址。
三、IPv6地址规划的注意事项
规划IPv6地址需要注意以下几点:
1. 子网划分
IPv6子网划分采用了类似于CIDR(无类型域间路由)的方式,即将前缀或者后缀用斜杠“/”分成两个部分,前者为消息中地址的的位数,后者则表示组ID的位数。
例如,将一个组ID为16位的前缀(48位)分为两个部分,每个部分各为24位,则可表示成“/24/24”。
2. 路由协议
IPv6路由协议包括:
(1)RIPng协议:基于距离向量的路由协议。
(2)OSPFv3协议:构建在OSPFv2的基础上,适用于IPv6的OSPF协议。
(3)BGP4+协议:IPv6版本的BGP协议。
3. 安全性
IPv6提供了以下安全性策略:
(1)IPSec:对IPv6数据包进行加密和身份验证。
(2)防火墙:对传入和传出的IPv6数据包进行控制。
(3)访问控制列表(ACL):对特定接口或地址执行ACL。
四、示例代码
1. IPv6地址的简化表示
// 完整IPv6地址示例 const char* ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; // IPv6地址的简化表示 const char* ipv6_simple = "2001:0db8:85a3::8a2e:0370:7334";
2. IPv6地址的类型
// 设定IPv6单播地址 struct in6_addr myaddr; inet_pton(AF_INET6, "2001:db8:85a3::8a2e:370:7334", &myaddr); // 设定IPv6组播地址 struct sockaddr_in6 mAddr; inet_pton(AF_INET6, "ff02::1:ff00:1234", &mAddr.sin6_addr); mAddr.sin6_family = AF_INET6; mAddr.sin6_port = 8080; // 设定IPv6任播地址 struct sockaddr_in6 anycastAddr; in6_addr addr; inet_pton(AF_INET6, "2001:0db8:85a3:08d3:1319:8a2e:0370:7344", &addr); memcpy(&anycastAddr.sin6_addr, &addr, sizeof(addr)); anycastAddr.sin6_family = AF_INET6; anycastAddr.sin6_port = htons(80); anycastAddr.sin6_scope_id = 2;
3. IPv6子网划分
为了将前缀48位的地址分成两个24位的前缀,需要使用位运算(需要注意网络字节序):
uint16_t sitesid = 0x1020; uint32_t site1 = BE32(nc_get_ipv4_addr("192.168.100.1")); uint32_t site2 = BE32(nc_get_ipv4_addr("192.168.101.1")); in6_addr prefix; inet_pton(AF_INET6, "2001:db8:85a3::", &prefix); uint64_t net1 = ((uint64_t)prefix.s6_addr32[0] << 32) | site1; uint64_t net2 = ((uint64_t)prefix.s6_addr32[0] << 32) | site2; prefix.s6_addr16[4] = htons(sitesid); prefix.s6_addr32[1] = htonl(net1); prefix.s6_addr32[2] = htonl(net2); // 将前缀48位地址划分成两个24位的前缀 char buf[256]; inet_ntop(AF_INET6, &prefix, buf, sizeof(buf)); printf("%s/n", buf);
4. IPv6的安全性
使用IPSec来保护数据包的安全性和身份验证:
// 使用IPSec来保护数据包 ipsec_policy_t ipsec_policy; ipsec_policy.apply_to = NET_IF_IN; ipsec_policy.pkt_len = 0; ipsec_policy.input = true; ipsec_policy.output = true; ipsec_policy.tunnel_mode = false; // IPSec密钥 ipsec_key_t ipsec_key = {0}; memcpy(&ipsec_key.key_octet, "12345", 5); ipsec_key.key_len = 5; int rc = ipsec_apply_policy(&ipsec_key, &ipsec_policy); if (rc) { printf("Failed to apply IPSec policy (%d)/n", rc); }