前言
这里我们主要是 来看一下 dns 服务器这边的相关业务处理
通常来说 在我们日常生活中 还是经常会需要使用 dns 的情况, 主要是更加友好的去给一个主机命名一个别名
比如 现在我的应用在服务器 192.168.220.133 但是我不想记这个生硬的 ip, 我可能更期望记录一个域名, 比如 app.com, 这时候 就可以在 dns 服务器上面增加一个映射 app.com -> 192.168.220.133
比如 现在我的应用在服务器 192.168.220.133, 但是 之后服务可能会发生迁移更新到 10.60.50.16, 这种场景下面 我们仅仅需要在 dns 上面将 “app.com” -> 192.168.220.133 更新为 “app.com” -> 10.60.50.16 而客户端这边无需做任何改动
我们这里调试的 dns 服务器主要是基于 dnsmasq
在 /etc/hosts 中 映射配置如下, 存在一条 “master“ -> 10.60.50.16 的映射配置
dns 的请求 和 响应
dns 请求这边如下, 这里我们看基于 udp 的 dns 数据交互
dns 这边主要是包含了一个 txId, flags, questions, answterRRs, AuthorityRRs, AdditionalRRs, 以及具体的查询请求
具体的查询请求包含 待查询域名, type, class
dns 响应这边情况如下
可以看到 dns响应 是在 dns请求 的数据基础上面扩展的, 增加了 Answer 的结构
Answer的结构 主要包含了 查询的域名, type, class, ttl, lengthOfIp, 目标ip
dns 的请求处理
这里就是查询 dns容器 维护的 hash_table, 其中维护的映射类似于 Map<String, String> hostname2Ip;
这里的查询也是类似于 java.util.HashMap 的查询, 找到匹配的记录之后, 返回该记录
然后之后写出 dns 响应的数据是在这里
header 即为一个 dns 的请求头信息, 在上面 dns 的请求的基础上面去掉了 请求体
这里传入了 nameoffset 表示域名相对于 dns 请求的偏移, ttl 等等相关信息
传入的待写出的指针为 &ansp, 这个的处理在上面, 我们后面来看
写出响应中的 nameOffset, type, class, ttl, lengthOfIp
写出 ip, 这个 for 之后, 会填充写出的 ip 的长度
ansp 初始化的地方
首先是跳过了 dns_header 的部分, 然后接着是遍历每一个 dns请求体, 跳过该部分的 dns请求体
这里处理完成之后, ansp 的最终的位置是在 整个dns请求的末尾
dnsmasq 中的 dns_header 结构体
id 对应于数据包中的 trxId
hb3, hb4 对应于数据包中的 flags
qdcount 对应于 questions
ancount对应于 answterRRs
nscount对应于 AuthorityRRs
arcount对应于 AdditionalRRs
dns 配置的加载
读取 “/etc/hosts” 以及 “--addn-hosts” 的地方
如果是配置了 “--no-hosts” 则不会加载 “/etc/hosts” 文件
注册 “/etc/hosts” 中的条目到 hash_table 中的过程
完