每天进步一点点:DNS & 清除DNS缓存

in #cn4 years ago

DNS(Domain Name System)是互联网上将域名解析成IP的一整套系统/机制,这样大家就可以通过有意义的域名(比如hive.blog这样的形式)来访问网站了,如果没有DNS,我们只能记录看起来没有一丁点意义的IP了。

image.png
(图源 :https://cn.bing.com/images/)

DNS

DNS是一个层次化的系统,比如我们想查询hive.blog,这个域名,那么先需要向根服务器发起请求,比如我们向根服务器之一的a.root-servers.net来查询的话,a.root-servers.net会给我们如下应答:

image.png

也就是说.blog后缀的域名是由a.nic.blog等四台服务器负责解析的,再依次查下去,最终会找到hive.blog的IP:

image.png

缓存

从上述内容不难看出来,DNS查询的过程还是很麻烦的。如果我们每次访问某个域名,都要经过这么多次查询,那么效率会很低,对资源也是极大的浪费。

所以就有了缓存系统,比如上边的A记录之一:

hive.blog 300 IN A 172.67.181.43

其中的300,有个专门的名称,叫TTL(time to live),翻译过来叫做存活时间,就是指这个记录在DNS缓存中存在多久后会失效。

本地DNS解析器会根据这个时间来缓存这个A记录,直到TTL归零(再次重新请求)。

缓存极大地提升了DNS解析的效率,也大幅降低各级DNS系统的负载,设想一下如果每次域名解析都要访问一遍根服务器,那么根服务器铁定就会累瘫痪的。

Windows下清理缓存

缓存虽然很有用,但是有一种情况还是会很恼人的,那就是DNS那边修改了记录,而由于缓存生命期还没完结, 那么本地的DNS解析器中可能保留的就是错误的记录。

上边这种300秒的TTL设置还好,如果设置成24小时或者更高,那就会很恼人了,所以有时候需要清理缓存。

Windows下清理缓存很方便,执行如下命令即可:

ipconfig /flushdns

我做的一个小工具也提供了相应的功能:

image.png

我程序中使用类似如下代码:

bool (WINAPI *DoDnsFlushResolverCache) ();
*(FARPROC *)&DoDnsFlushResolverCache = GetProcAddress(LoadLibrary(_T("dnsapi.dll")), "DnsFlushResolverCache");

如果失败了,则去调用ipconfig执行:

system("ipconfig /flushdns");
system("ipconfig /release");
system("ipconfig /renew");

Ubuntu (18.04)下清理DNS缓存

相比于Windows的命令行操作或者我的小工具,Linux下如何操作我还真不熟悉,原本以为ifconfig会有类似的选项,后来发现我多想了。

网上各种教程,但是可能是不同发行版和不同版本号的问题,很多都并不适用。最终我发现我的Ubuntu 18.04下有这两条相关命令:

查看状态:

sudo systemd-resolve --statistics

来执行下试试看:

image.png

清空缓存:

sudo systemd-resolve --flush-caches

我们可以再清空缓存后再调用查看状态命令来看一下:

image.png

可见原本存在的四条缓存内容已被清空。

补充说明

可能有朋友会问缓存清空后,记录就一定更新到最新吗?这个主要取决于DNS解析器所依赖的DNS服务。

怎么说呢?之前说个DNS解析是层次化的结构,简单点形容,就是一层层向上问,如果上层有缓存且还没过生存期,就会直接答复回来,否则就继续向上问。

所以我们清空了本地缓存,但是如果上层DNS/ISP DNS等缓存还没过期,那么有可能拿到的还是旧的信息。

所以上述方法只能解决本地解析器的缓存问题,大部分情况就够用了,如果遇到复杂情况,还是具体处理。

image.png
(图源 :pixabay)

当然了,最简洁的方法就是等缓存失效了,这样什么都不用做,静静地等待就好了。😀