文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

一份完整的 IPv6 环境下 DNS 相关测试

2024-12-25 02:30

关注

董涛,网易游戏高级运维工程师,主要工作方向为网易集团 DNS 的运维与开发。
张欣接,网易集团 DNS 团队负责人,负责网易域名系统的架构设计及生态建设。

一、IPv6 支持度报告

IPv6 简介

IPv6(Internet Protocol version 6,互联网通信协议第 6 版)是用于数据包交换互联网络的网络层协议,是 IETF(互联网工程任务小组 Internet Engineering Task Force,简称 IETF)设计的用来替代 IPv4 协议的互联网协议版本。

随着电子技术及网络技术的发展,计算机网络已经与人们的生活密切相关,可能身边的每一样电子设备都需要连入网络,IPv4 的地址数量已经无法满足。IPv6 的应用将彻底解决这些问题。IPv6 由 128 比特位构成,单从数量级上来说,IPv6 所拥有的地址容量是 IPv4 的约 8×10 28 倍,达到 2 128(约 3.4 × 10 38)个。这不但解决了网络地址资源数量的问题,同时也为物联网的发展提供了基础。

IPv6 地址的表达形式采用 32 个十六进制数,由两个逻辑部分组成:一个 64 位的网络前缀和一个 64 位的主机地址,主机地址通常根据物理地址自动生成,叫做 EUI-64(或者 64- 位扩展唯一标识)。例如 2001:0db8:85a3:08d3:1319:8a2e:0370:7344 是一个合法的 IPv6 地址。

IPv6 全球部署更新

操作系统 IPv6 支持度

应用软件 IPv6 支持度

客户端软件

1、浏览器

服务器软件

1、程序开发软件

2、数据库

总结

毋庸置疑,下一代互联网 IPv6 是万物互连,智能化时代基础网络的重要支撑协议,但是从一个只拥有 IPv4 协议的巨型网络要全面、平稳地过渡到一个纯 IPv6 网络需要一段极为漫长的时间。从报告统计的数据来看,各种基础软件和应用软件都已基本支持 IPv6。现在在国内的环境下,IPv6 的基础环境还需要完善,为此工信部也发布了

《推进互联网协议第六版(IPv6)规模部署行动计划》(http://www.miit.gov.cn/n1146290/n4388791/c6166476/content.html)

推动各单位加快支持 IPv6。

IPv6 支持度报告的数据来源是:下一代国家互联网中心在 2017 年 11 月发布的 IPv6 支持度报告

(https://www.ipv6ready.org.cn/public/download/ipv6.pdf), 感兴趣的同学可以查看原文。

二、IPv6 环境下 DNS 相关测试

背景介绍

名词简介

A 记录是一个域名指向 IPv4 地址的解析结果,即最常见的记录类型, 例如 ipv6test.ntes53.netease.com. 1800 IN A 123.58.166.70
AAAA 是一个域名指向 IPv6 地址的解析结果。如果想要一个域名解析到 IPv6 地址,则需要设置此种类型的解析结果。同一个域名可以同时有 A 与 AAAA 两种记录类型, 例如 ipv6test.ntes53.netease.com. 1800 IN AAAA 2403:c80:100:3000::7b3a:a646
用户直接使用的 DNS 服务器,各种平台、操作系统上直接设置的 DNS 服务器,常见的有 8.8.8.8, 114.114.114.114
用于域名的管理。权威 DNS 服务器只对自己所拥有的域名进行域名解析,对于不是自己的域名则拒绝应答。例如网易的权威 DNS 服务器只会响应网易域名的请求,对于其他域名,则拒绝应答。
双栈网络环境即客户端或服务器同时拥有 IPv4、IPv6 两种网络环境,可以简单的理解为机器上既有 IPv4 地址又有 IPv6 地址

测试场景

下文中所有测试使用的程序均为测试方法中的程序

1.目前纯 IPv4 环境下,仅新增 AAAA(IPv6) 记录之后,对已有程序的影响

假定已经存在了一个程序(C 程序、python 程序、浏览器等),通过域名访问某个服务,现在在 IPv4 环境下一切工作正常。当给这个域名增加了 AAAA 记录之后,测试对目前的程序的影响。

域名解析

HTTP 请求

客户端

结论

2.客户端 IPv6/v4 双栈环境下,测试程序的行为

假定用户的环境是双栈环境,假定一个服务通过域名对外提供服务,测试这种情况下程序的行为。

域名解析

HTTP 请求

客户端

结论

3. 客户端纯 IPv6 环境下,测试能否正常工作

假定用户只有 IPv6 地址,DNS 也是使用 IPv6 地址 (DNS 必须有双栈环境,因为现在很多权威服务器没有 IPv6 地址,纯 IPv6 环境下无法正常工作),假定一个服务通过域名(同时拥有 A、AAAA 记录)对外提供服务,测试服务是否可以正常访问。

域名解析

HTTP 请求

客户端

结论
当某域名即存在 A 记录 又存在 AAAA 记录时:

4. DNS 解析测试

这里测试了缓存服务器和权威服务器在各种网络环境下,优先使用的解析链路。

结论
当权威服务器和缓存服务器均支持 ipv6 时,缓存服务器优先使用 ipv6 链路进行解析,其他情况均使用 ipv4 链路进行解析。

结论

参考资料

测试方法

解析域名

C/ C ++

Linux

 

 

  1. #include  
  2.     #include  
  3.     #include  
  4.  
  5.     int main(void
  6.         int i = 0
  7.         char str[32] = {0}; 
  8.          struct hostent* phost = NULL; 
  9.  
  10.         phost = gethostbyname("IPv6test.ntes53.netease.com"); 
  11.         printf("%s", inet_ntoa(*((struct in_addr*)phost->h_addr)));  
  12.          
  13.         return 0
  14.     } 

 

Windows

 

 

  1.  #include  
  2.     #include  
  3.     #include  
  4.  
  5.     #pragma comment (lib, "ws2_32.lib"
  6.  
  7.     int main(void) { 
  8.         WSADATA wsaData = {0,}; 
  9.         struct in_addr addr = {0,}; 
  10.         struct hostent *res; 
  11.         int i = 0
  12.  
  13.         WSAStartup(MAKEWORD(22), &wsaData); 
  14.  
  15.         res = gethostbyname("IPv6test.ntes53.netease.com."); 
  16.         while (res->h_addr_list[i] != 0) { 
  17.             addr.s_addr = *(u_long *) res->h_addr_list[i++]; 
  18.             printf("IP Address: %s\n", inet_ntoa(addr)); 
  19.         } 
  20.  
  21.         WSACleanup(); 

 

getaddrinfo

  1. #include  
  2.     #include  
  3.     #include  
  4.     #include  
  5.     #include  
  6.     #include  
  7.     #include  
  8.  
  9.     int lookup_host () 
  10.       struct addrinfo hints, *res; 
  11.       int errcode; 
  12.       char addrstr[100]; 
  13.       void *ptr; 
  14.  
  15.       memset (&hints, 0, sizeof (hints)); 
  16.       hints.ai_family = AF_INET; 
  17.  
  18.       errcode = getaddrinfo ("IPv6test.ntes53.netease.com", NULL, &hints, &res); 
  19.       if (errcode != 0
  20.         { 
  21.           perror ("getaddrinfo"); 
  22.           return -1
  23.         } 
  24.       while (res) 
  25.         { 
  26.           inet_ntop (res->ai_family, res->ai_addr->sa_data, addrstr, 100); 
  27.           switch (res->ai_family) 
  28.             { 
  29.             case AF_INET: 
  30.               ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr; 
  31.               break
  32.             case AF_INET6: 
  33.               ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; 
  34.               break
  35.             } 
  36.           inet_ntop (res->ai_family, ptr, addrstr, 100); 
  37.           printf ("IPv%d address: %s (%s)\n", res->ai_family == PF_INET6 ? 6 : 4
  38.                   addrstr, res->ai_canonname); 
  39.           res = res->ai_next; 
  40.         } 
  41.       return 0
  42.     } 
  43.     int main (void
  44.         lookup_host(); 
  45.     } 

windows

 

 

  1. #define WIN32_LEAN_AND_MEAN 
  2.     #define _WIN32_WINNT 0x501 
  3.     #include  
  4.     #include  
  5.     #include  
  6.     #include  
  7.     #include  
  8.     #include  
  9.     #include  
  10.  
  11.     #pragma comment (lib, "Ws2_32.lib"
  12.  
  13.     // int iResult; 
  14.     WSADATA wsaData; 
  15.     int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); 
  16.  
  17.     int inet_pton(int af, const char *src, void *dst) 
  18.         struct sockaddr_storage ss; 
  19.         int size = sizeof(ss); 
  20.         char src_copy[INET6_ADDRSTRLEN+1]; 
  21.  
  22.         ZeroMemory(&ss, sizeof(ss)); 
  23.          
  24.         strncpy (src_copy, src, INET6_ADDRSTRLEN+1
  25.         src_copy[INET6_ADDRSTRLEN] = 0
  26.  
  27.         if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0) { 
  28.             switch(af) { 
  29.                 case AF_INET: 
  30.                     *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr; 
  31.                     return 1
  32.                 case AF_INET6: 
  33.                     *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr; 
  34.                     return 1
  35.             } 
  36.         } 
  37.         return 0
  38.     } 
  39.     const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) 
  40.         struct sockaddr_storage ss; 
  41.         unsigned long s = size; 
  42.         ZeroMemory(&ss, sizeof(ss)); 
  43.         ss.ss_family = af; 
  44.         switch(af) { 
  45.             case AF_INET: 
  46.                 ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src; 
  47.                 break
  48.             case AF_INET6: 
  49.                 ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src; 
  50.                 break
  51.             default
  52.                 return NULL; 
  53.         } 
  54.          
  55.         return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0)? 
  56.                dst : NULL; 
  57.     } 
  58.     int lookup_host () 
  59.         struct addrinfo hints, *res; 
  60.         int errcode; 
  61.         char addrstr[100]; 
  62.         void *ptr; 
  63.         memset (&hints, 0, sizeof (hints)); 
  64.         hints.ai_family = AF_INET6; 
  65.         errcode = getaddrinfo ("IPv6test.ntes53.netease.com", NULL, &hints, &res); 
  66.         if (errcode != 0
  67.         { 
  68.             perror ("getaddrinfo"); 
  69.             printf("%d",errcode); 
  70.             return -1
  71.         } 
  72.         while (res) 
  73.         { 
  74.             // inet_ntop (res->ai_family, res->ai_addr->sa_data, addrstr, 100); 
  75.             sockaddr_in in1; 
  76.             memcpy(&in1.sin_addr, res->ai_addr->sa_data, sizeof(res)); 
  77.             switch (res->ai_family) 
  78.             { 
  79.                 case AF_INET: 
  80.                     ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr; 
  81.                     break
  82.                 case AF_INET6: 
  83.                     ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; 
  84.                     break
  85.             } 
  86.             inet_ntop(res->ai_family, ptr, addrstr, 100); 
  87.             // sockaddr_in6 in; 
  88.             // memcpy(&in.sin6_addr, ptr, sizeof(ptr)); 
  89.             printf ("IPv%d address: %s (%s)\n", res->ai_family == PF_INET6 ? 6 : 4
  90.                    addrstr, res->ai_canonname); 
  91.             //printf ("IPv%d address: %s (%s)\n", res->ai_family == PF_INET6 ? 6 : 4, 
  92.             //        inet_ntoa(in.sin6_addr), res->ai_canonname); 
  93.             res = res->ai_next; 
  94.         } 
  95.         return 0
  96.     } 
  97.     int main (void
  98.         printf("start\n"); 
  99.         lookup_host(); 
  100.     } 

 

Python

  1. import socket 
  2. result = socket.gethostbyname("IPv6test.ntes53.netease.com"
  3. print result 
  1. import socket 
  2. result = socket.getaddrinfo("IPv6test.ntes53.netease.com"0, socket.AF_INET6) 
  3. print result 
  4. result = socket.getaddrinfo("IPv6test.ntes53.netease.com"0, socket.AF_INET) 
  5. print result 
  6. result = socket.getaddrinfo("IPv6test.ntes53.netease.com"0, socket.AF_UNSPEC) 
  7. print result 

当不指定 socktype 时,此值默认为 socket.AF_UNSPEC

HTTP 请求

Python

requests 包

 

 

  1. import requests 
  2. response = requests.get("http://IPv6test.ntes53.netease.com:8000", stream=True
  3. print response.raw._fp.fp._sock.getpeername() 

 

C++

  1. #include  
  2. #include  
  3.  
  4. int main(void
  5.   CURL *curl; 
  6.   CURLcode res; 
  7.  
  8.   curl = curl_easy_init(); 
  9.   if(curl) { 
  10.     curl_easy_setopt(curl, CURLOPT_URL, "http://IPv6test.ntes53.netease.com:8000"); 
  11.       
  12.     curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); 
  13.       // curl_easy_setopt(curl, CURL_IPRESOLVE_V6, 1L);  // 使用 IPv6 地址 
  14.       // curl_easy_setopt(curl, CURL_IPRESOLVE_V4, 1L);  // 使用 IPv4 地址 
  15.       // curl_easy_setopt(curl, CURL_IPRESOLVE_WHATEVER, 1L);  // 获取系统允许的 IPv4 或者 IPv6 地址  
  16.       
  17.     res = curl_easy_perform(curl); 
  18.       
  19.     if(res != CURLE_OK) 
  20.       fprintf(stderr, "curl_easy_perform() failed: %s\n"
  21.               curl_easy_strerror(res)); 
  22.  
  23.       
  24.     curl_easy_cleanup(curl); 
  25.   } 
  26.   return 0; 
 
来源:网易游戏运维平台内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯