前言
- 1
- 2
下实现dns的不同,分别分析,供学习dns参考。
一、DNS功能
- 1
- 2
主机名,你给我找出该主机名对应的ip地址。例如:给你www.baidu.com的主机名,你给
我查出对应的ip地址:163.177.151.109。一些主机名还会有别名,如www.baidu.com就
有别名www.a.shifen.com,甚至不止一个别名,或一个别名有2个ip地址。在linux机子
上,运行nslookup(name service lookup)就是进行域名解析。如下面:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
二、DNS的原理
- 1
- 2
服务器的ip地址(请求进行域名解析的地方);2、向dns服务器请求进行域名解析(dns
实质工作),3、缓存已经解析过的主机名与ip地址对应关系(这样已缓存的就不需要再向
dns服务器请求解析了)。
一个dns的解析过程如下:
1、 应用程序请求一个主机名解析,如:应用程序跟dns说,我需要知道www.baidu.com
的ip地址,你给我查一下;
2、 Dns先在本地缓存中查询,若查到,返回ip地址给应用,流程结束。若没查到, 进行
下一步;
3、 Dns把需要查询的主机名打包进dns数据包,然后把dns数据包发送到dns服务;
4、 DNS服务器返回查询的主机名的dns数据包;
5、 Dns解析数据包,把主机名对应的ip地址返回给应用程序;
下图为网卡抓到的dns数据包的收发,请求www.baidu.com的ip地址:
下图为dns运行流程:
上面是从本机看到的情况,实际上在向DNS服务器请求时,所请求的DNS服务器也不一
定知道主机名对应的ip地址,就会向上一级DNS请求,更多资料请自行查找dns协议。
下面代码片段为freescale小系统上的dns处理过程,看起来流程还是比较清晰简单的:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
三、Linux的dns实现
- 1
- 2
resolv.conf文件,配置完后,重启一下network就好了,至于为什么配置这些文件,dns
又是在哪里执行的,都没有说明。
在Linux上执行nslookup(name service lookup)或ping(ping主机名,如:ping
www.baidu.com)都会执行dns的动作。执行dns时都是调用gethostbyname函数,
gethostbyname函数,传入主机名,dns执行成功后,返回主机名对应的ip地址。
而gethostbyname函数的实现是在c库中完成的,也就是dns的整个执行过程都是由c库实
现,c库中dns实现过程与上一节介绍的流程原理是相同的,只是还多了一些配置文件用于
设置参数、dns ip地址什么的,就是前面提到的host.conf,resolv.conf文件,这就是为什
么Linux的dns只需要配置host.conf,resolv.conf文件,不需要再做其它工作的原因,因为
c库已经替你完成dns的实际工作。在Linux嵌入式系统中,若发现dns不能正常工作,那就
看一下host.conf,resolv.conf等文件是否配置正确,还有就是dns运行使用的c库在机子上
有没有。
想了解c库怎么实现dns的,请自行下载c库源码分析:http://www.gnu.org/software/libc/
四、Android的dns实现
- 1
- 2
些文件,但Android的dns也是能正常工作的。这是因为Android重写了libc库的dns实现
部分,重写的dns代码在android\bionic\libc\dns目录。重写后的dns,请求dns的接口,
有gethostbyname(兼容以前的c库接口)及android_gethostbynamefornet(给
android使用)接口,但根据不同的dns请求发起者,走的流程有点不一样,其中还涉及到
了netd的处理。Android java层请求dns时,是通过netd进行,netd调用
android_gethostbynamefornet接口。而Android下编译的ping程序是不通过netd而直
接调用gethostbyname接口,但最终还是要走到netd,由netd调用
android_gethostbynamefornet接口。Android下dns的请求流程如下图:
- 1
- 2
getenv(“ANDROID_DNS_MODE”)返回是否不为NULL并且值为“local”,而netd启动
时会设置setenv(“ANDROID_DNS_MODE”, “local”, 1),而ping程序不会。
五、Linux的dns缓存
- 1
- 2
127.0.0.1,也就是从本地dns缓存中查找,查找不到时再根据第二个、第三个dns ip地址
进行dns请求。
六、第三方dns库
- 1
- 2
方的dns库,如c-ares dns库,该dns库支持多种平台。例如:linux
平台上,它与linux的配置完全兼容,可以在现有的linux dns配置文
件上,直接编译c-ares库放到机子上即可使用。