DNS域名解析

912 阅读3分钟

一次请求大致流程:

1. 通过输入的主机名去查找对应的IP地址
2. 获取根据DNS域名解析得到的IP地址, 访问指定的服务器
3. 通过IP+地址获取指定的资源

打算从以下几个方面学习DNS域名解析的知识:

  • 1、DNS域名解析的流程
  • 2、Android端对于DNS的缓存优化
  • 3、DNS域名解析中可能会遇到的问题, 以及如何处理
  • 4、关于面试DNS会涉及到哪些问题

一、DNS域名解析流程

  • 1、Android系统首先检查自身有没有缓存, 如果有, 直接返回缓存的IP地址.
  • 2、如果没有, 则会请求本地域名服务器(LDNS)进行解析, 这台服务器一般位于当地, 大于80%左右的域名解析到这里就结束了.
  • 3、如果LDNS也没有缓存该IP地址, 则直接跳到ROOT Server域名服务器请求解析
  • 4、根域名服务器返回LDNS一个所查询域的主域名服务器(gTLD Server)
  • 5、此时LDNS发请求给gTLD Server
  • 6、接受请求的gTLD Server返回域名对应的Name Server, Name Server指的是网站注册的域名服务器
  • 7、Name Server根据关系映射表找到对应的IP, 返回给LDNS
  • 8、LDNS缓存域名与IP
  • 9、LDNS将IP返回给访问者

二、Android NDS-IP缓存

根据流程图, 只列出主要流程

2.1 以okhttp中根据主机名获取ip为例
override fun lookup(hostname: String): List<InetAddress> {
	try {
		return InetAddress.getAllByName(hostname).toList()
    } catch (e: NullPointerException) {
		throw UnknownHostException("Broken system behaviour for dns lookup of $hostname").apply {
			initCause(e)
    	}
    }
}
2.2 Inet6AddressImpl.lookupAllHostAddr
private static InetAddress[] lookupHostByName(String host, int netId)
            throws UnknownHostException {
    // 1.从缓存中取host对应的IP
    Object cachedResult = addressCache.get(host, netId);
    // 2.如果缓存存在, 则返回缓存的IP
    if (cachedResult != null) {
        if (cachedResult instanceof InetAddress[]) {
            return (InetAddress[]) cachedResult;
        } else {
            // 3.结合下文可知, 缓存不仅仅缓存IP, 也可能缓存DNS解析中出现的异常情况, 如果当前
            //   DNS域名解析失败, 那么在缓存未失效之前, 获取的都是该异常?  
            throw new UnknownHostException((String) cachedResult);
        }
    }
    try {
    	// 4.获取IP
        InetAddress[] addresses = Libcore.os.android_getaddrinfo(host, hints, netId);
        // 5.缓存host对应的IP
        addressCache.put(host, netId, addresses);
        return addresses;
    } catch (GaiException gaiException) {
        String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error);
        // 6.缓存DNS域名解析时出现的异常
        addressCache.putUnknownHost(host, netId, detailMessage);
        throw gaiException.rethrowAsUnknownHostException(detailMessage);
    }
}
2.3 DNS域名解析的IP缓存

www.androidos.net.cn/android/9.0…

private final BasicLruCache<AddressCacheKey, AddressCacheEntry> cache
            = new BasicLruCache<AddressCacheKey, AddressCacheEntry>(MAX_ENTRIES);
            
// MAX_ENTRIES = 16, 默认缓存16个HOST

当缓存的HOST = 16时优先删除, 结合BasicLruCache源码, 其内部使用的是LinkedHashMap

三、DNS域名解析遇到的问题

3.1 域名劫持

  域名服务器会保存一大堆域名记录(每条记录包括"域名"和"IP地址"), 当域名服务器收到请求时, 就会返回域名对应的IP地址.

  如果域名服务器中保存的域名-IP的映射关系出现了错误, 也就是域名对应的IP地址发生了改变, 那么请求者获取到的IP地址就有问题, 这种就叫作**域名劫持**

3.2 域名污染

zhuanlan.zhihu.com/p/143824884 blog.csdn.net/wangcantian… zhuanlan.zhihu.com/p/79350395