找回密码
 FreeOZ用户注册
12
返回列表 发新帖回复
楼主: coredump
打印 上一主题 下一主题

[网络技术] DNS规模故障追踪:由24岁站长引发的蝴蝶效应

[复制链接]
31#
发表于 25-5-2009 19:52:35 | 只看该作者


下面是对一个不存在的域名进行查询的运行结果,运行了两次,第一次是对这个域名查了10次,
每次相隔2秒种,起初的查询需要时间为211毫秒,再后面的查询都在10毫秒以内完成。
由于我每次查询都会“重新连接”dns,所以需要加上“网络连接时间”。不过,我估计这个返回结果
是从本地的cache是获得的,一会有空可以tcpdump一下有没有dns流量。

停了几分钟后,我重新执行这个程序,依然很快获得结果。每论cache在哪一些,有cache这个是必然的了。

./hostest www.goog66le00.com 10 2
gethostbyname error: www.goog66le00.com, Unknown host, diff = 211
gethostbyname error: www.goog66le00.com, Unknown host, diff = 5
gethostbyname error: www.goog66le00.com, Unknown host, diff = 4
gethostbyname error: www.goog66le00.com, Unknown host, diff = 4
gethostbyname error: www.goog66le00.com, Unknown host, diff = 5
gethostbyname error: www.goog66le00.com, Unknown host, diff = 5
gethostbyname error: www.goog66le00.com, Unknown host, diff = 5
gethostbyname error: www.goog66le00.com, Unknown host, diff = 4
gethostbyname error: www.goog66le00.com, Unknown host, diff = 4
gethostbyname error: www.goog66le00.com, Unknown host, diff = 5
Total time = 252, Average time = 25, max = 211, min = 4

./hostest www.goog66le00.com 5 2
gethostbyname error: www.goog66le00.com, Unknown host, diff = 6(ms)
gethostbyname error: www.goog66le00.com, Unknown host, diff = 4(ms)
gethostbyname error: www.goog66le00.com, Unknown host, diff = 5(ms)
gethostbyname error: www.goog66le00.com, Unknown host, diff = 5(ms)
gethostbyname error: www.goog66le00.com, Unknown host, diff = 5(ms)
Total time = 25(ms), Average time = 5(ms), max = 6(ms), min = 4(ms)

那所有DOS攻击都是不可能的了?

不是不可以,而一般的dos攻击有两种手段:一种是利用特殊的协议漏洞来做,比如最著名的漏洞之一是tcp中的sync,
由多台机不断地发sync,但不产生真正的连接,这样服务器就会在那些傻等很久。这样攻击者只需要很轻的负荷就能让服务器
傻掉。另一种手段是通过很重的流量进行攻击,让服务器响应不过来,美国炸了咱大使馆那时就流行这个,用ping发flood包
来攻击。

我觉得因为一个client软件的问题而“失手”不断请求DNS解析而导致“攻击”的问题可能性少,是因为dns协议包很小,而且多级
解释。dns的设计本身就是分布试响应,有cache有时延控制。如何攻击成功呢?

我不懂网络,不过暴风自己都承认了,我看可能性还是很大的。除非谁给个更令人信服的解释


我觉得是联合炒作。承认自己“出错”其实是变相告诉大家我有大量的用户群,这样广告费就大大的赚了。
在这个事之前,大家只知道暴风“可能”有很多用户,但确切有多少?
而那个什么dns服务器就更是无名小卒,跳出来说自己每天有20亿访问,相当于中国的人口翻倍,自己就出名了。

评分

参与人数 1威望 +20 收起 理由
klux + 20 谢谢分享!

查看全部评分

回复  

使用道具 举报

32#
发表于 25-5-2009 19:55:39 | 只看该作者

测试程序的源代码,不过只能跑linux。win的版本找人别人编一下,或者用cygwin也行吧

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <netdb.h>
  4. #include <unistd.h>
  5. #include <sys/types.h>
  6. #include <sys/time.h>
  7. #include <time.h>
  8. #include <errno.h>
  9. #include <arpa/inet.h>

  10. static void usage(const char * prog)
  11. {
  12.   fprintf(stderr, "Usage: %s <hostname> <n-times> <sec-interval>\n"
  13.             "\n"
  14.           "\thostname : the FQDN you want to seek, i.e. www.google.com\n"
  15.           "\tn-times  : the number of seekings you want to perform.\n"
  16.           "\tsec-interval : how many seconds you want to have a rest before the next seek.\n"
  17.           , prog);
  18. }

  19. int main(int argc, char ** argv)
  20. {
  21.   if(argc!=4)
  22.   {
  23.     usage(argv[0]);
  24.     exit(1);
  25.   }

  26.   const char * hostname = argv[1];
  27.   int ntimes = atoi(argv[2]);
  28.   int nsec   = atoi(argv[3]);
  29.   long total_time_diff = 0;
  30.   long min_time_diff = 0xFFFFFFF;
  31.   long max_time_diff = 0x0;

  32.   if(ntimes <= 0)
  33.   {
  34.     fprintf(stderr, "O... n-times should be 1 or more\n\n");
  35.     usage(argv[0]);
  36.     exit(1);
  37.   }

  38.   if(nsec <= 0)
  39.   {
  40.     fprintf(stderr, "Yeah.. sec-interval should be more than 0\n\n");
  41.     usage(argv[0]);
  42.     exit(1);
  43.   }

  44.   int orig_ntime = ntimes;

  45.   while(ntimes > 0)
  46.   {
  47.     struct timeval tv1, tv2;
  48.     struct hostent * pent;
  49.     long timediff;


  50.     if(gettimeofday(&tv1, NULL) == -1)
  51.     {
  52.       perror("Sorry your system could not support gettimeofday()");
  53.       exit(1);
  54.     }

  55.     pent = gethostbyname(hostname);
  56.     gettimeofday(&tv2, NULL);

  57.     timediff = ( tv2.tv_sec - tv1.tv_sec ) * 1000 + ( tv2.tv_usec - tv1.tv_usec) / 1000;
  58.     total_time_diff += timediff;
  59.     if(min_time_diff > timediff)
  60.       min_time_diff = timediff;
  61.     if(max_time_diff < timediff)
  62.       max_time_diff = timediff;

  63.     if(pent==NULL)
  64.     {
  65.       fprintf(stderr, "gethostbyname error: %s, %s, diff = %ld(ms)\n",
  66.         hostname, hstrerror(h_errno), timediff);
  67.     }
  68.     else
  69.     {
  70.       char ** pptr;
  71.       char str[128];

  72.       switch(pent->h_addrtype)
  73.       {
  74.         case AF_INET:
  75.         case AF_INET6:
  76.           for(pptr=pent->h_addr_list; * pptr!=NULL; pptr++)
  77.           {
  78.             printf(" address [%s], ",
  79.               inet_ntop(pent->h_addrtype, * pptr, str, sizeof(str)));
  80.           }
  81.           break;
  82.         default:
  83.           printf("Unknown address type, ");
  84.       }
  85.       printf("diff = %ld(ms)\n", timediff);
  86.     }

  87.     endhostent();
  88.     --ntimes;

  89.     sleep(nsec);
  90.   }


  91.   printf("Total time = %ld(ms), Average time = %ld(ms), max = %ld(ms), min = %ld(ms)\n",
  92.     total_time_diff, total_time_diff / orig_ntime, max_time_diff, min_time_diff);
  93.   
  94.   return 0;
  95. }
复制代码

评分

参与人数 2威望 +50 收起 理由
ubuntuhk + 30 你太有才了!
klux + 20 辛苦辛苦

查看全部评分

回复  

使用道具 举报

33#
 楼主| 发表于 25-5-2009 20:41:52 | 只看该作者
Linux下如果不装dnsmasq之类的软件是不会进行DNS缓存的,就像Windows下的DNS Client Cache的作用一样。你的程序第二次运行的快应该不是你本机在缓存,而是你机器的的DNS server在缓存,这一点你可以通过更改一下DNS server来验证一下。

但是DNS server对一个原来就不存在的域名的缓存策略,和一个原来存在的DNS域名的缓存策略是不一样的,前者使用默认缓存参数,后者受域名原配置信息影响。

PS:
............由于我每次查询都会“重新连接”dns,所以需要加上“网络连接时间”。...............


   你这个代码查询的是不存在的域名,不存在重新连接,只有gethostbyname()的DNS查询
回复  

使用道具 举报

34#
 楼主| 发表于 25-5-2009 21:15:29 | 只看该作者
wikipedia对这次事件的记录:
2009年5月19日中国时间晚间时分,中国电信属下的网络发生全国性的故障。20日,官方公布了故障原因,认为暴风影音向电信所属DNS服务器发出过多请求,造成了此次故障。
事件的背景是中国互联网络主要分割为中国网通中国电信两大骨干网络,两大网络之间的互联互通性能不好,因此许多网站的维护者都选择同时在两大网络设置服务器。为了使用户自动访问到正确的服务器,需要第三方根据用户所在网络提供区别对待的DNS服务,如果用户来自网通则返回网通的服务器地址,否则返回电信的地址。这样的第三方服务被称为DNS解析服务。
事件起因于一个受到黑客攻击的DNS解析服务供应商DNSpod。由于受到攻击,该供应商的一个服务器停止了运作,而该服务器正好负责解析暴风影音在下载弹出广告时候所连接的服务器。于是暴风影音自动转接到电信的一个固定DNS服务器进行解析。由于暴风影音的用户数量巨大,导致众多用户在同一时间向DNS服务器发出大量请求,而使该DNS服务器崩溃。
但官方的这个结论也有人提出疑问,比如为什么DNS缓存没有生效等等。

根据现有的资料分析大致的事情经过:

网通电信南北网络不通问题
需要第三方DNS解决方案
DNSPod 服务出现
暴风成为DNSPod的客户
暴风装机量非常大
暴风耍流氓
DNSPod被攻击
DNSPod被电信断网
暴风使用固定电信IP作为DNS SERVER进行请求
电信DNS SERVER game over .....





回复  

使用道具 举报

35#
发表于 25-5-2009 22:27:54 | 只看该作者
原帖由 coredump 于 25-5-2009 20:41 发表
Linux下如果不装dnsmasq之类的软件是不会进行DNS缓存的,就像Windows下的DNS Client Cache的作用一样。你的程序第二次运行的快应该不是你本机在缓存,而是你机器的的DNS server在缓存,这一点你可以通过更改一下DNS  ...



如果是我用的DNS Server在提供cache,那就更说明问题了,不是吗?
回复  

使用道具 举报

36#
 楼主| 发表于 25-5-2009 22:32:27 | 只看该作者
原帖由 key 于 25-5-2009 22:27 发表



如果是我用的DNS Server在提供cache,那就更说明问题了,不是吗?


DNS server对一个原来就不存在的域名的缓存策略,和一个原来存在的DNS域名的缓存策略是不一样的
回复  

使用道具 举报

37#
发表于 25-5-2009 22:36:13 | 只看该作者
原帖由 coredump 于 25-5-2009 21:15 发表
wikipedia对这次事件的记录:

根据现有的资料分析大致的事情经过:

网通电信南北网络不通问题
需要第三方DNS解决方案
DNSPod 服务出现
暴风成为DNSPod的客户
暴风装机量非常大
暴风耍流氓
DNSPod被攻击 ...


wiki上的东西不需要尽信。显然这个人并不是网络方面的专家。

需要第三方根据用户所在网络提供区别对待的DNS服务,如果用户来自网通则返回网通的服务器地址,否则返回电信的地址。这样的第三方服务被称为DNS解析服务。

传统的DNS解析是不做这事的。这个东西叫做DNS负载平衡器,是依据用户地区进行不同的地址返回。
我在00年的时候给BIND写过一个类似的扩展器。那时这个功能还用得不是太广,所以没有缺省的实现。

于是暴风影音自动转接到电信的一个固定DNS服务器进行解析

这是不可能的。除了傻的DNS服务器之外,一般的DNS服务器都只接受自己的客户的查询请求。
来自非授权用户客户端的查询请求是不可能获得通过的。所以,暴风XX不可能这样写程序,
否则对于大量用户他根本就不可能正常获得域名解析
回复  

使用道具 举报

38#
发表于 25-5-2009 22:38:43 | 只看该作者
原帖由 coredump 于 25-5-2009 22:32 发表


DNS server对一个原来就不存在的域名的缓存策略,和一个原来存在的DNS域名的缓存策略是不一样的


我可以相信你这句话,但我需要一些evidence
我一会可以找一下BIND的代码,看看是否有“历史上存在过的DNS”的特别策划。
如果电信自己搞过一套DNS,如无意外应该是derived from BIND的
回复  

使用道具 举报

39#
 楼主| 发表于 25-5-2009 22:44:24 | 只看该作者

回复 #38 key 的帖子

这句话我也是猜的,没有确切证据

等你发掘BIND的实现,我刚才查了查DNS的RFC,倒是没有找到相关说法。
回复  

使用道具 举报

40#
发表于 25-5-2009 23:42:20 | 只看该作者
暴风就是拿免费的MYMPC做内核包装了下,之前还抄CCF的大S的,被无数的小白列为装机必备软件,我一直不装这个垃圾。。。
回复  

使用道具 举报

41#
发表于 26-5-2009 00:43:00 | 只看该作者
原帖由 coredump 于 25-5-2009 22:44 发表
这句话我也是猜的,没有确切证据

等你发掘BIND的实现,我刚才查了查DNS的RFC,倒是没有找到相关说法。


你猜得有一定道理,虽然表述上可能有需改进的地方。

从RFC 1035 DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION
Section 4.1.1,这里把这两类出错返回分成:
Server Failer
Name Error

其中Name Error被又被称为NXDOMAIN,在BIND中是通过ncache来存放,时间缺省为3小时,最长可以是7天。
而对于server failure的情况,RFC 2038给出的建议是5分钟内下的cache。

然而,因为server failure可以通过icmp查询到,这是普下之下最轻松的任务(ping flooding除外),
所以,即使是5min的cache,对于服务器来说都已经足够了。即使以1min来计算,全天中该服务器需要做的icmp数量为:

  24 * 60 = 1440(次)

请告诉我,这1440次的icmp能让一台机瓜掉?下面是这1440次测试的psuedo code:
  1. r = request;
  2. if(check....)
  3. ...
  4. ...
  5. if(check_cache(r)==SERVER_FAILURE){
  6.   if(cache_timeout(r)){
  7.       if(icmp_check_server(r)==FAIL)
  8.          return client_response(SERVER_FAILURE);
  9.       }
  10.       else{
  11.          return do_further(r);
  12.       }
  13.   }
  14.   else
  15.       return client_response(SERVER_FAILURE);
  16. }
  17. ...
复制代码
这是多么轻松的一件事呀?不要告诉我实际的DNS会做得比这个复杂得多。。。哼,赌顿hungry jack如何?

所以,即使cache的时候不同,但即使是1分钟的cache,其实也很足够。毕竟authorized name server是有限的,
而unknown domain name是无限的,因此不同的cache policy是没有问题的。
回复  

使用道具 举报

42#
发表于 26-5-2009 00:57:10 | 只看该作者
原帖由 roymei 于 25-5-2009 23:42 发表
暴风就是拿免费的MYMPC做内核包装了下,之前还抄CCF的大S的,被无数的小白列为装机必备软件,我一直不装这个垃圾。。。



一个是暴风影音,一个是影音风暴,界面极其相似,谁抄谁的?
其实无论哪一个,都是在发扬中国的山寨精神,那些codecs应该没有一个是中国人原创的,
都是什么ffmpeg之流的东西吧?

至于插件,唉,上面几位同学说得好,流氓成性。的确就是这样。
似乎不做流氓就活不成似的。这也是事实,尤其对于freeware的生存环境来说。
这样已经形成一种生态环境,大家也真的习已为常了。
回复  

使用道具 举报

43#
发表于 26-5-2009 12:14:40 | 只看该作者
都是强人啊。。。
路过留个爪印
回复  

使用道具 举报

44#
发表于 27-5-2009 04:04:16 | 只看该作者

回复 #41 key 的帖子

我只知道一次TCP连接通常会保持一段时间(这个时间可能是2-5分钟),不知道ICMP和UDP是否也会这样?

一台服务器的端口有限,会不会因为大量的DNS查询导致网络端口资源耗尽而无法响应更多的DNS查询响应?如果这样的话,就不是流量导致DNS服务中断。

请key兄斧正。
回复  

使用道具 举报

您需要登录后才可以回帖 登录 | FreeOZ用户注册

本版积分规则

小黑屋|手机版|Archiver|FreeOZ论坛

GMT+10, 17-4-2025 14:31 , Processed in 0.038043 second(s), 33 queries , Gzip On, Redis On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表