乐于分享
好东西不私藏

跨平台底层网络库libdnet源码分析系列(十六)

跨平台底层网络库libdnet源码分析系列(十六)

官网:http://securitytech.cc

源码分析mettle后门工具学习 所使用的依赖库

第 16 章:IPv6 完整支持探析

16.1 IPv6 协议概述

16.1.1 IPv6 的产生背景

随着互联网的飞速发展,IPv4 地址空间逐渐枯竭。IPv6(Internet Protocol version 6)作为 IPv4 的继任者,由 IETF 于 1995 年标准化(RFC 2460),提供了以下关键改进:

  • 巨大的地址空间:从 IPv4 的 32 位扩展到 128 位,提供 2^128 个地址
  • 简化的报文头:固定 40 字节头部,提高路由处理效率
  • 内置安全性:原生支持 IPsec
  • 自动配置:无状态地址自动配置(SLAAC)
  • 更好的 QoS 支持:流标签字段支持

16.1.2 libdnet 中的 IPv6 支持架构

libdnet 库在底层网络编程层面提供了完整的 IPv6 支持,主要包含以下模块:

  1. IPv6支持模块结构
  2. ├──IPv6地址处理(addr.c, addr-util.c
  3. ├──IPv6报文头封装(ip6.h
  4. ├──ICMPv6协议支持(icmpv6.h
  5. ├──IPv6校验和计算(ip6.c
  6. └──跨平台接口适配(intf-win32.c, intf-linux.等)

16.2 IPv6 数据结构深度分析

16.2.1 IPv6 地址结构定义

源码位置: include/dnet/ip6.h

  1. #define IP6_ADDR_LEN    16/* IPv6 地址长度(128 位/8 = 16 字节) */
  2. #define IP6_ADDR_BITS   128/* IPv6 地址位数 */
  3. typedefstruct ip6_addr {
  4. uint8_t data[IP6_ADDR_LEN];
  5. } __attribute__((__packed__))ip6_addr_t;

关键技术点

  1. 紧凑内存布局:使用 __packed__ 属性确保结构体无内存对齐填充
  2. 灵活的访问方式:可通过 data 数组直接访问原始字节
  3. 跨平台兼容:支持大端和小端字节序

16.2.2 IPv6 报文头结构

源码分析

  1. struct ip6_hdr {
  2. union{
  3. struct ip6_hdr_ctl {
  4. uint32_t ip6_un1_flow;/* 20 位流标识符 + 8 位流量类别 */
  5. uint16_t ip6_un1_plen;/* 有效载荷长度 */
  6. uint8_t  ip6_un1_nxt;/* 下一个头部类型 */
  7. uint8_t  ip6_un1_hlim;/* 跳数限制 */
  8. } ip6_un1;
  9. uint8_t ip6_un2_vfc;/* 4 位版本 + 4 位流量类别高 4 位 */
  10. } ip6_ctlun;
  11. ip6_addr_t ip6_src;/* 源 IPv6 地址 */
  12. ip6_addr_t ip6_dst;/* 目的 IPv6 地址 */
  13. } __attribute__((__packed__));

字段详解

字段
位数
说明
Version
4
IPv6 版本号(固定为 6)
Traffic Class
8
流量类别(类似 IPv4 的 ToS)
Flow Label
20
流标签,用于 QoS
Payload Length
16
有效载荷长度(不包括 IPv6 头部)
Next Header
8
下一个头部类型(TCP/UDP/ICMPv6 等)
Hop Limit
8
跳数限制(类似 IPv4 的 TTL)
Source Address
128
源 IPv6 地址
Destination Address
128
目的 IPv6 地址

16.2.3 统一的地址结构

源码位置: include/dnet/addr.h

  1. struct addr {
  2. uint16_t addr_type;/* 地址类型:ADDR_TYPE_IP6 = 3 */
  3. uint16_t addr_bits;/* 地址前缀长度 */
  4. union{
  5. eth_addr_t __eth;
  6. ip_addr_t __ip;
  7. ip6_addr_t __ip6;/* IPv6 地址 */
  8. uint8_t __data8[16];
  9. uint16_t __data16[8];
  10. uint32_t __data32[4];
  11. } __addr_u;
  12. };

设计优势

  • 统一接口:通过 addr_type 区分 IPv4/IPv6/MAC 地址
  • 灵活访问:支持按 8 位、16 位、32 位、64 位访问地址数据
  • 多播支持:可方便地判断组播地址(首字节为 0xFF)

16.3 IPv6 核心功能实现分析

16.3.1 IPv6 报文头快速打包函数

源码位置: include/dnet/ip6.h

  1. staticinlinevoid ip6_pack_hdr(void*buf,uint8_t c,uint32_t l,
  2. uint16_t plen,uint8_t nxt,uint8_t hlim,void*src,void*dst)
  3. {
  4. struct ip6_hdr {
  5. uint32_t ip6_v_c_l;/* 版本 + 流量类别 + 流标签 */
  6. uint32_t ip6_plen_nxt_hlim;/* 载荷长度 + 下一头部 + 跳限制 */
  7. ip6_addr_t ip6_src;
  8. ip6_addr_t ip6_dst;
  9. }*hdr =(struct ip6_hdr *)buf;
  10.     hdr->ip6_v_c_l =(6<<28)|(<<20)|(IP6_FLOWLABEL_MASK & l);
  11.     hdr->ip6_plen_nxt_hlim =(htons(plen)<<16)|(nxt <<8)| hlim;
  12.     memcpy(&hdr->ip6_src, src, IP6_ADDR_LEN);
  13.     memcpy(&hdr->ip6_dst, dst, IP6_ADDR_LEN);
  14. }

实现要点

  1. 内联优化:使用 inline 减少函数调用开销
  2. 字节序转换: plen 使用 htons() 转换为网络字节序
  3. 位域操作:精确控制每个字段的位偏移
  4. 内存拷贝:直接使用 memcpy 复制 128 位地址

16.3.2 IPv6 地址字符串转换

(1)IPv6 地址转字符串(ip6_ntop)

源码位置: src/addr-util.c

  1. char*ip6_ntop(constip6_addr_t*ip6,char*dst,size_t len)
  2. {
  3. uint16_t data[IP6_ADDR_LEN /2];
  4. struct{int base, len;} best, cur;
  5. char*= dst;
  6. int i;
  7. // 复制到 16 位数组(网络字节序)
  8. for(=0; i < IP6_ADDR_LEN /2; i++){
  9.         data[i]= ip6->data[2* i]<<8;
  10.         data[i]|= ip6->data[2* i +1];
  11. }
  12. // 查找最长的连续零段(RFC 5952)
  13.     best.len = cur.len =0;
  14.     best.base = cur.base =-1;
  15. for(=0; i < IP6_ADDR_LEN; i +=2){
  16. if(data[/2]==0){
  17. if(cur.base ==-1){
  18.                 cur.base = i;
  19.                 cur.len =0;
  20. }else
  21.                 cur.len +=2;
  22. }else{
  23. if(cur.base !=-1){
  24. if(best.base ==-1|| cur.len > best.len)
  25.                     best = cur;
  26.                 cur.base =-1;
  27. }
  28. }
  29. }
  30. // 生成压缩格式的 IPv6 字符串
  31. if(best.base !=-1&& best.len <2)
  32.         best.base =-1;
  33. if(best.base ==0)
  34. *p++=':';
  35. for(=0; i < IP6_ADDR_LEN; i +=2){
  36. if(== best.base){
  37. *p++=':';
  38.             i += best.len;
  39. }elseif(==12&& best.base ==0&&
  40. (best.len ==10||(best.len ==8&& data[5]==0xffff))){
  41. // IPv4 映射地址 (::ffff:10.0.0.1)
  42. if(ip_ntop((ip_addr_t*)&data[6], p, len -(- dst))== NULL)
  43. return(NULL);
  44. return(dst);
  45. }else
  46.             p += sprintf(p,"%x:", data[/2]);
  47. }
  48. // 处理末尾字符
  49. if(best.base +2+ best.len == IP6_ADDR_LEN){
  50. *='\0';
  51. }else
  52.         p[-1]='\0';
  53. return(dst);
  54. }

算法亮点

  • 零压缩算法:自动查找最长连续零段并使用 :: 压缩
  • RFC 5952 合规:遵循 IPv6 地址文本表示最佳实践
  • IPv4 映射支持:自动识别并转换为 ::ffff:x.x.x.x 格式
  • 边界检查:确保输出缓冲区足够大(至少 46 字节)

(2)字符串转 IPv6 地址(ip6_pton)

  1. int ip6_pton(constchar*p,ip6_addr_t*ip6)
  2. {
  3. uint16_t data[8],*=(uint16_t*)ip6->data;
  4. int i, j, n, z =-1;// z 记录 :: 的位置
  5. char*ep;
  6. long l;
  7. if(*==':')
  8.         p++;
  9. for(=0; n <8; n++){
  10.         l = strtol(p,&ep,16);
  11. if(ep == p){
  12. // 遇到 :: 压缩标记
  13. if(ep[0]==':'&& z ==-1){
  14.                 z = n;
  15.                 p++;
  16. }elseif(ep[0]=='\0'){
  17. break;
  18. }else{
  19. return(-1);
  20. }
  21. }elseif(ep[0]=='.'&& n <=6){
  22. // IPv4 后缀格式(如 ::ffff:192.168.1.1)
  23. if(ip_pton(p,(ip_addr_t*)(data + n))<0)
  24. return(-1);
  25.             n +=2;
  26.             ep ="";
  27. break;
  28. }elseif(>=0&& l <=0xffff){
  29.             data[n]= htons((uint16_t)l);
  30. if(ep[0]=='\0'){
  31.                 n++;
  32. break;
  33. }elseif(ep[0]!=':'|| ep[1]=='\0')
  34. return(-1);
  35.             p = ep +1;
  36. }else
  37. return(-1);
  38. }
  39. // 验证格式并填充零段
  40. if(==0||*ep !='\0'||(==-1&& n !=8))
  41. return(-1);
  42. // 复制 :: 之前的部分
  43. for(=0; i < z; i++){
  44.         u[i]= data[i];
  45. }
  46. // 填充零段
  47. while(<8-(- z -1)){
  48.         u[i++]=0;
  49. }
  50. // 复制 :: 之后的部分
  51. for(= z +1; i <8; i++, j++){
  52.         u[i]= data[j];
  53. }
  54. return(0);
  55. }

关键技术

  • 灵活的输入解析:支持完整格式、压缩格式、IPv4 映射格式
  • 错误检测:严格验证输入格式,防止非法地址
  • 零填充算法:正确计算并填充 :: 代表的零段

16.3.3 IPv6 校验和计算

源码位置: src/ip6.c

  1. void ip6_checksum(void*buf,size_t len)
  2. {
  3. struct ip6_hdr *ip6 =(struct ip6_hdr *)buf;
  4. struct ip6_ext_hdr *ext;
  5.     u_char *p, nxt;
  6. int i, sum;
  7.     nxt = ip6->ip6_nxt;
  8. // 跳过所有扩展头部
  9. for(= IP6_HDR_LEN; IP6_IS_EXT(nxt); i +=(ext->ext_len +1)<<3){
  10. if(>=(int)len)return;
  11.         ext =(struct ip6_ext_hdr *)((u_char *)buf + i);
  12.         nxt = ext->ext_nxt;
  13. }
  14.     p =(u_char *)buf + i;
  15.     len -= i;
  16. // 根据下一头部类型计算校验和
  17. if(nxt == IP_PROTO_TCP){
  18. struct tcp_hdr *tcp =(struct tcp_hdr *)p;
  19. if(len >= TCP_HDR_LEN){
  20.             tcp->th_sum =0;
  21.             sum = ip_cksum_add(tcp, len,0)+ htons(nxt +(u_short)len);
  22.             sum = ip_cksum_add(&ip6->ip6_src,32, sum);// 伪头部
  23.             tcp->th_sum = ip_cksum_carry(sum);
  24. }
  25. }elseif(nxt == IP_PROTO_UDP){
  26. struct udp_hdr *udp =(struct udp_hdr *)p;
  27. if(len >= UDP_HDR_LEN){
  28.             udp->uh_sum =0;
  29.             sum = ip_cksum_add(udp, len,0)+ htons(nxt +(u_short)len);
  30.             sum = ip_cksum_add(&ip6->ip6_src,32, sum);
  31. if((udp->uh_sum = ip_cksum_carry(sum))==0)
  32.                 udp->uh_sum =0xffff;// UDP 校验和不能为 0
  33. }
  34. }elseif(nxt == IP_PROTO_ICMPV6){
  35. struct icmp_hdr *icmp =(struct icmp_hdr *)p;
  36. if(len >= ICMP_HDR_LEN){
  37.             icmp->icmp_cksum =0;
  38.             sum = ip_cksum_add(icmp, len,0)+ htons(nxt +(u_short)len);
  39.             sum = ip_cksum_add(&ip6->ip6_src,32, sum);
  40.             icmp->icmp_cksum = ip_cksum_carry(sum);
  41. }
  42. }
  43. }

IPv6 校验和特点

  1. 伪头部包含源和目的地址:增强端到端完整性检查
  2. 扩展头部处理:自动跳过 Hop-by-Hop、Routing、Fragment 等扩展头
  3. UDP 特殊处理:校验和为 0 时设置为 0xFFFF(RFC 2460 要求)
  4. 16 位反码求和:使用标准的 Internet 校验和算法

16.4 ICMPv6 协议支持

16.4.1 ICMPv6 头部结构

源码位置: include/dnet/icmpv6.h

  1. struct icmpv6_hdr {
  2. uint8_t icmpv6_type;/* 消息类型 */
  3. uint8_t icmpv6_code;/* 子代码 */
  4. uint16_t icmpv6_cksum;/* 校验和 */
  5. };

16.4.2 ICMPv6 重要消息类型

类型值
名称
说明
1
ICMPV6_UNREACH
目的地不可达
3
ICMPV6_TIMEXCEED
超时消息
4
ICMPV6_PARAMPROBLEM
参数问题
128
ICMPV6_ECHO
Echo Request(Ping)
129
ICMPV6_ECHOREPLY
Echo Reply(Ping 响应)
135
ICMPV6NEIGHBORSOLICITATION
邻居请求(NS)
136
ICMPV6NEIGHBORADVERTISEMENT
邻居通告(NA)

16.4.3 邻居发现协议(NDP)支持

NDP 消息结构

  1. struct icmpv6_msg_nd {
  2. uint32_t icmpv6_flags;/* NS/NA 标志位 */
  3. ip6_addr_t icmpv6_target;/* 目标地址 */
  4. uint8_t icmpv6_option_type;/* 选项类型 */
  5. uint8_t icmpv6_option_length;/* 选项长度 */
  6. eth_addr_t icmpv6_mac;/* MAC 地址 */
  7. };

NDP 核心功能

  • 无 ARP:使用 ICMPv6 NS/NA 消息替代 ARP
  • 重复地址检测(DAD):发送 NS 消息检测地址冲突
  • 路由器发现:RS/RA 消息实现无状态自动配置

16.5 IPv6 扩展头部机制

16.5.1 扩展头部结构

源码分析

  1. struct ip6_ext_hdr {
  2. uint8_t ext_nxt;/* 下一个头部类型 */
  3. uint8_t ext_len;/* 长度(以 8 字节为单位,不包括前 8 字节) */
  4. union{
  5. struct ip6_ext_data_routing routing;
  6. struct ip6_ext_data_fragment fragment;
  7. } ext_data;
  8. } __attribute__((__packed__));

16.5.2 推荐的扩展头部顺序

根据 RFC 2460 第 4.1 节:

  1. IPv6基本头部
  2. Hop-by-HopOptions(IP_PROTO_HOPOPTS)
  3. DestinationOptions(IP_PROTO_DSTOPTS)-第一个
  4. RoutingHeader(IP_PROTO_ROUTING)
  5. FragmentHeader(IP_PROTO_FRAGMENT)
  6. AuthenticationHeader(IP_PROTO_AH)
  7. EncapsulatingSecurityPayload(IP_PROTO_ESP)
  8. DestinationOptions(IP_PROTO_DSTOPTS)-第二个
  9. 上层协议头部(TCP/UDP/ICMPv6等)

16.5.3 Fragment 扩展头部

  1. struct ip6_ext_data_fragment {
  2. uint16_t offlg;/* 分片偏移 + 保留位 + 标志 */
  3. uint32_t ident;/* 分片标识符 */
  4. };
  5. /* 分片相关宏定义 */
  6. #define IP6_OFF_MASK      0xfff8/* 分片偏移掩码 */
  7. #define IP6_RESERVED_MASK 0x0006/* 保留位 */
  8. #define IP6_MORE_FRAG     0x0001/* 更多分片标志 */

16.6 特殊 IPv6 地址

16.6.1 预定义地址常量

源码位置: include/dnet/ip6.h

  1. /* 未指定地址 */
  2. #define IP6_ADDR_UNSPEC \
  3. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  4. /* 环回地址 */
  5. #define IP6_ADDR_LOOPBACK \
  6. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"

16.6.2 常见特殊地址

地址
表示
用途
::
全 0
未指定地址(类似 0.0.0.0)
::1
0…01
环回地址(类似 127.0.0.1)
::ffff:x.x.x.x
IPv4 映射地址
表示 IPv4 节点
fe80::/10
链路本地地址
同一链路上通信
ff00::/8
组播地址
一对多通信
2000::/3
全球单播地址
全球可达地址

16.7 跨平台 IPv6 实现差异

16.7.1 Windows平台 IPv6 支持

特点

  • 使用 Winsock 2 API 提供 IPv6 支持
  • 需要链接 ws2_32.lib 和 iphlpapi.lib
  • Raw Socket 权限限制(需管理员权限)
  • 不支持某些低级 IPv6 操作

示例代码片段( src/ip-win32.c 风格):

  1. #include<winsock2.h>
  2. #include<ws2tcpip.h>
  3. SOCKET sock = socket(AF_INET6, SOCK_RAW, IPPROTO_IPV6);
  4. if(sock == INVALID_SOCKET){
  5. // 错误处理
  6. }

16.7.2 Linux 平台 IPv6 支持

特点

  • 完整的 Raw Socket 支持
  • 需要 CAPNETRAW 能力或 root 权限
  • 支持 IPv6 扩展头部操作
  • 内核提供丰富的 IPv6 选项

示例代码

  1. #include<sys/socket.h>
  2. #include<netinet/in.h>
  3. #include<netinet/ip6.h>
  4. int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
  5. setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS,...);

16.7.3 BSD 平台 IPv6 支持

特点

  • 最早的 IPv6 实现之一
  • 提供高级 IPv6 Socket 选项
  • 支持 BPF(Berkeley Packet Filter)过滤 IPv6 包

16.8 实战案例:IPv6 Ping 工具实现

16.8.1 完整代码示例

  1. /*
  2.  * ipv6_ping.c - IPv6 Ping 工具
  3.  * 功能:向目标 IPv6 地址发送 ICMPv6 Echo Request 并接收响应
  4.  * 编译:gcc -o ipv6_ping ipv6_ping.c -ldnet
  5.  * 运行:ipv6_ping 2001:db8::1
  6.  */
  7. #include<stdio.h>
  8. #include<stdlib.h>
  9. #include<string.h>
  10. #include"dnet.h"
  11. #define ICMPV6_ECHO_REQUEST 128
  12. #define ICMPV6_ECHO_REPLY   129
  13. int main(int argc,char*argv[])
  14. {
  15. struct ip6_hdr *ip6;
  16. struct icmpv6_hdr *icmp;
  17. char packet[IP6_HDR_LEN + ICMP_HDR_LEN +64];
  18. ip6_addr_t dst;
  19. struct addr src_addr, dst_addr;
  20. char addr_str[INET6_ADDRSTRLEN];
  21. int sock;
  22. if(argc !=2){
  23.         fprintf(stderr,"用法:%s <目标 IPv6 地址>\n", argv[0]);
  24.         exit(EXIT_FAILURE);
  25. }
  26. /* 解析目标地址 */
  27. if(ip6_pton(argv[1],&dst)<0){
  28.         fprintf(stderr,"无效的 IPv6 地址:%s\n", argv[1]);
  29.         exit(EXIT_FAILURE);
  30. }
  31. /* 获取本地 IPv6 地址 */
  32. struct intf_entry intf;
  33.     strlcpy(intf.intf_name,"eth0",sizeof(intf.intf_name));
  34. struct intf_handle *intf_hdl = intf_open();
  35. if(intf_get(intf_hdl,&intf)<0){
  36.         fprintf(stderr,"无法获取网卡信息\n");
  37.         intf_close(intf_hdl);
  38.         exit(EXIT_FAILURE);
  39. }
  40. /* 构造 IPv6 头部 */
  41.     memset(packet,0,sizeof(packet));
  42.     ip6 =(struct ip6_hdr *)packet;
  43.     ip6_pack_hdr(packet,
  44. 0,/* 流量类别 */
  45. 0,/* 流标签 */
  46.                  ICMP_HDR_LEN +64,/* 载荷长度 */
  47.                  IP_PROTO_ICMPV6,/* 下一头部 */
  48. 64,/* 跳限制 */
  49.                  intf.intf_addr.addr_ip6.data,/* 源地址 */
  50.                  dst.data);/* 目的地址 */
  51. /* 构造 ICMPv6 Echo Request */
  52.     icmp =(struct icmpv6_hdr *)(packet + IP6_HDR_LEN);
  53.     icmp->icmpv6_type = ICMPV6_ECHO_REQUEST;
  54.     icmp->icmpv6_code =0;
  55.     icmp->icmpv6_cksum =0;
  56. /* 设置 Echo 数据 */
  57. struct icmpv6_msg_echo *echo =(struct icmpv6_msg_echo *)(icmp +1);
  58.     echo->icmpv6_id = htons(getpid()&0xFFFF);
  59.     echo->icmpv6_seq = htons(1);
  60. /* 填充数据 */
  61.     memset(echo->icmpv6_data,'A',64);
  62. /* 计算 ICMPv6 校验和 */
  63.     ip6_checksum(packet,sizeof(packet));
  64. /* 发送数据包 */
  65. struct ip6_handle *ip6_hdl = ip6_open();
  66. if(ip6_send(ip6_hdl, packet,sizeof(packet))<0){
  67.         fprintf(stderr,"发送失败\n");
  68.         ip6_close(ip6_hdl);
  69.         exit(EXIT_FAILURE);
  70. }
  71.     printf("已发送 ICMPv6 Echo Request 到 %s\n", argv[1]);
  72. /* 接收响应(简化版) */
  73. // 实际应用中需要使用 select/poll 等待响应
  74.     ip6_close(ip6_hdl);
  75.     intf_close(intf_hdl);
  76. return0;
  77. }

16.8.2 编译和运行

Windows 编译

  1. gcc -I../include -L../src/.libs -o ipv6_ping.exe ipv6_ping.-ldnet -lws2_32 -liphlpapi

Linux 编译

  1. gcc -o ipv6_ping ipv6_ping.-ldnet

运行示例

  1. # Windows(需要管理员权限)
  2. ipv6_ping.exe 2001:db8::1
  3. # Linux(需要 root 权限)
  4. sudo ./ipv6_ping 2001:db8::1

16.9 IPv6 编程最佳实践

16.9.1 地址处理最佳实践

  1. 始终检查地址类型
  1. if(addr->addr_type == ADDR_TYPE_IP6){
  2. // 处理 IPv6
  3. }elseif(addr->addr_type == ADDR_TYPE_IP){
  4. // 处理 IPv4
  5. }
  1. 使用统一的地址转换函数
  1. char buf[INET6_ADDRSTRLEN];
  2. addr_ntop(addr, buf,sizeof(buf));// 自动处理 IPv4/IPv6
  1. 正确处理地址前缀长度
  1. struct addr network;
  2. addr_net(addr,&network);// 计算网络地址

16.9.2 校验和计算注意事项

  1. 必须在发送前计算
  1. ip6_checksum(packet, packet_len);
  1. UDP 特殊处理:校验和为 0 时自动设置为 0xFFFF
  2. 扩展头部自动跳过:无需手动处理

16.9.3 跨平台兼容性建议

  1. 使用 libdnet 抽象层:避免直接使用平台特定 API
  2. 测试地址族支持
  1. #ifdef HAVE_SOCKADDR_IN6
  2. // IPv6 可用
  3. #endif
  1. 处理权限差异:Windows 需要管理员,Linux 需要 CAPNETRAW

16.10 IPv6 安全考虑

16.10.1 常见安全风险

  1. 扩展头部攻击:恶意构造的扩展头链可能导致拒绝服务
  2. NDP 欺骗:伪造 NS/NA 消息进行中间人攻击
  3. 组播监听滥用:利用 IPv6 组播进行网络侦察

16.10.2 防护建议

  1. 验证扩展头部链:限制最大扩展头数量
  2. 实施 RA Guard:防止 rogue 路由器
  3. 使用 SEND 协议:安全邻居发现(RFC 3971)

16.11 总结与展望

16.11.1 libdnet IPv6 支持特性总结

✅ 完整的 IPv6 头部封装✅ ICMPv6 协议支持✅ 邻居发现协议(NDP)✅ 扩展头部处理✅ 跨平台地址转换✅ 自动校验和计算✅ IPv4 映射地址支持

16.11.2 IPv6 发展趋势

  • IPv6 普及率持续增长:全球已超过 30% 的互联网流量使用 IPv6
  • IPv6-only 网络兴起:移动运营商率先部署
  • IoT 设备默认 IPv6:6LoWPAN 等低功耗协议推动
  • 5G 核心网基于 IPv6:网络切片依赖 IPv6 扩展头

16.11.3 进一步学习资源

  • RFC 文档
  • RFC 8200: IPv6 规范
  • RFC 4443: ICMPv6
  • RFC 4861: 邻居发现
  • RFC 5952: IPv6 地址文本表示
  • 实验环境
  • GNS3 / EVE-NG 网络模拟器
  • Wireshark IPv6 抓包分析
  • Linux IPv6 协议栈源码研究

下一章预告:第 17 章将深入分析 libdnet 在 Windows 和 Linux 平台上的内核交互机制,揭示 Raw Socket 在不同操作系统中的实现差异。

  • 公众号:安全狗的自我修养

  • vx:2207344074

  • http://gitee.com/haidragon

  • http://github.com/haidragon

  • bilibili:haidragonx