Golang DNS 随便写写

golang具有内置go解析器以及基于cgo的系统解析器两种DNS解析方式

其中在Linux下默认是go内置go解析器

DNS是什么?有什么?做什么?

域名系统( DNS)是一种用于 TCP/IP 应用程序的分布式数据库,它提供主机名字和IP地址之间的转换及有关电子邮件的选路信息

从应用的角度上看,对 DNS的访问是通过一个地址解析器( resolver )来完成的。解析器并不像 TCP/IP 协议那样是操作系统的内核。

当nameResolver发出查询请求,并且返回响应中的TC(删减标准)为1时,意味着响应长度超过了512字节,而仅返回前512字节。那么在这种情况下,nameResolver通常使用TCP重发原来的查询请求(TCP允许响应超过512字节)。

不过多数还是UDP更多,这也意味着对于DNS客户程序,一个好的重传和超时程序显得更重要了

报文格式

Golang DNS 随便写写_第1张图片

该报文由12bytes首部和4个长度可变字段组成

  • 标识:由client设置并由server返回结果,用以确认响应和查询是否匹配

  • 标志:在这里插入图片描述

    • OR: 0代表查询,1代表响应报文

    • opcode: 0标准查询,1方向查询,2服务器状态请求

    • AA: 标识授权回答

    • TC: 可截断的。使用UDP时,表示应答总长度超过512字节,只返回前512字节

    • RD: 期望递归。

      该比特能在一个查询中设置 ,并在响应中返回。这个标志告诉名字服务器必须处理这个查询,也称为一个递归查询。如 果该位为 0,且被请求的名字服务器没有一个授权回答,它就返回一个能解答该查询的 其他名字服务器列表,这称为迭代查询

    • RA: 可用递归。nameServer支持递归查询

    • rcode: 返回码字段。通常为0(没有差错)和3(名字差错,表示查询域名不存在)

  • 问题数、资源记录数、授权资源记录数和额外资源记录数分别对应最后 4 个可变长字段中包含的条目数

    对于查询报文,问题数通常是 1,而其他 3 项均为 0;对于应答报文,回答数至少为 1,剩下的两项可以是 0 或非 0;

  • 查询问题:
    Golang DNS 随便写写_第2张图片

    • 查询名: 要查找的DNS名,本质为分段带长度的字符序列。

      如baidu.com.就表示为字符序列5 b a i d u 3 c o m 0

    • 查询类型: 对应资源记录类型。比如A记录,记为1

    • 查询类:通常为1,指互联网地址(IP)

  • 回答:Golang DNS 随便写写_第3张图片

    域名是记录中资源数据对应的名字。它的格式和前面介绍的查询名字段格式(图 相同。

    类型说明 R R 的类型码。它的值和前面介绍的查询类型值是一样的。类通常为Internet数据。

    生存时间字段是客户程序保留该资源记录的秒数。资源记录通常的生存时间值为 2天。

    资源数据长度说明资源数据的数量。该数据的格式依赖于类型字段的值。对于类型 1(A 记录)资源数据是 4 字节的 I P 地址。

资源记录

  • A: 32bit二进制数,记录ipv4地址
  • AAAA: ipv6地址
  • cname: 表示规范名字(canonical name)。用来表示一个域名

go dns流程

  1. 读取/etc/resolv.conf
  2. 判断解析的network类型。默认ipv4、ipv6都解析,若指定了ip类型,则只解析该类型。
  3. 根据/etc/resolv.conf中single-request和single-request-reopen参数,决定是否串行或者并行请求ip类型
  4. 遍历nameserver以及解析ip类型,以获取cname、ip信息

cgo vs go

cgo调用的是getaddrinfo。

int getaddrinfo(const char *restrict node,
                       const char *restrict service,
                       const struct addrinfo *restrict hints,
                       struct addrinfo **restrict res);

相比而言,go的好处在于在堵塞情况下,只会消耗一个协程,而cgo则会堵塞系统线程

DNS相关配置介绍

/etc/resolv.conf文件介绍

resolv.conf用于设置DNS服务器的ip地址以及DNS域名,还包含主机域名搜索顺序

主要有以下参数

  • nameserver: 定义DNS服务器IP地址
  • domain: 定义本地域名
  • search: 定义域名搜索列表。指明域名查询顺序,当没有domain会用search
  • sortlist: 对返回域名进行排序

以及可选参数

  • ndots: 若请求域名参数点的个数比ndots小,则会按照配置的search内容,依次添加相应后缀知道获取域名解析后的地址

比如请求www.baidu.com时,因为www.baidu.com有两个点小于配置的3个点,那就会

nameserver 169.254.20.10
nameserver 172.16.0.10
search meipian-test.svc.cluster.local svc.cluster.local cluster.local
options ndots:3 
解析域名 查询类型 dns server
www.baidu.com.meipian-test.svc.cluster.local. A 169.254.20.10
www.baidu.com.meipian-test.svc.cluster.local. A 172.16.0.10
www.baidu.com.meipian-test.svc.cluster.local. AAAA 169.254.20.10
www.baidu.com.meipian-test.svc.cluster.local. AAAA 172.16.0.10
www.baidu.com.svc.cluster.local. A 169.254.20.10
www.baidu.com.svc.cluster.local. A 172.16.0.10
www.baidu.com.svc.cluster.local. AAAA 169.254.20.10
www.baidu.com.svc.cluster.local. AAAA 172.16.0.10
www.baidu.com.cluster.local. A 169.254.20.10
www.baidu.com.cluster.local. A 172.16.0.10
www.baidu.com.cluster.local. AAAA 169.254.20.10
www.baidu.com.cluster.local. AAAA 172.16.0.10
www.baidu.com. A 169.254.20.10
www.baidu.com. A 172.16.0.10
www.baidu.com. AAAA 169.254.20.10
www.baidu.com. AAAA 172.16.0.10

看看上面一长串,我们不禁要问为什么需要这样的拼接,并且最后的为什么多出来一个点

这又要引出一个新概念——FQDN(fully qualified domain name)。FQDN是完整域名,以.结束表示是FQDN

对于FQDN系统会直接查询DNS server

而对于非FQDN则会用到ndots结合search组合为FQDN

go内置DNS默认解析ipv6

由于现在很多域名都不支持ipv6,并且对于不支持的处理策略并不一致。

比如使用114.114.114.114 DNS服务器查询baidu ipv6会得到noerror,说是查询成功,可是却只有soa

Golang DNS 随便写写_第4张图片

再比如同样使用114.114.114.114 DNS服务器查询oauth-login.cloud.huawei.com ipv6,却得到servfail,并且查询时间实在感人。所以很多场景禁用ipv6解析还是很有意义

Golang DNS 随便写写_第5张图片

在go1.17之后,我们可以通过指定网络类型,达到查询host ip时禁用ipv6目的。

r:=net.Resolver{PreferGo: true}
ip, err := r.LookupIP(context.Background(), "ip4", host)
if err != nil {
  t.Fatal(err)
}
fmt.Println(ip)

DNS攻击

DDOS

分布式拒绝服务攻击(distributed denial-of-service, DDoS)是一种恶意攻击,目的是通过大量的Internet流量,使目标服务器或其周围的基础设施无法承受,从而破坏目标服务器、服务或网络的正常流量。

DDoS攻击是通过利用多个被破坏的计算机系统作为攻击流量的来源来实现的。被利用的机器可以包括计算机和其他联网资源,如物联网设备。

从高级别上看,DDoS攻击就像高速公路上突发的交通堵塞,使正常的交通无法到达目的地。

攻击者利用僵尸网络创建不同端口,在同一时间段向受害者域名服务器发送海量DNS请求。

为了应对,我们可以限制攻击者ip

ip欺骗

IP 欺骗是指创建源地址经过修改的 Internet 协议 (IP) 数据包,目的要么是隐藏发送方的身份,要么是冒充其他计算机系统,或者两者兼具。恶意用户往往采用这项技术对目标设备或周边基础设施发动 DDoS 攻击

DNS默认依赖UDP,不过由于UDP没有像TCP的握手过程,这使得ip欺骗变的更加容易。

并且对于很多基于UDP应用程序可能会被愚弄以使用更大UDP响应来回复小UDP查询,这将导致更大带宽浪费。这种现象称之为放大效应。

应对ip欺骗可以通过

  • DNS缓存:通过缓存吸收DNS流量。不过值得注意的是攻击者也可能利用这点,在缓存中添加大量错误ip地址
  • 入口过滤:在网络边缘设备检查传入ip数据包是否是其源头

DNS隧道

DNS隧道通过DNS解析器在攻击者和目标之间创建隐藏连接,可绕过防火墙,用于实施数据泄露等攻击。在大多数情况下,DNS隧道需要借助能够连接外网的受感染系统作为跳板,来访问具有网络访问权限的内部DNS服务器。

DNS挟持

在 DNS 劫持中,攻击者将查询重定向到其他域名服务器。这可通过恶意软件或未经授权的 DNS 服务器修改来实现。尽管其结果与 DNS 欺骗的结果相似,但这是一种截然不同的攻击,因为其目标是域名服务器上网站的 DNS 记录,而不是解析器的高速缓存。

Ref

  1. https://studygolang.com/topics/15021
  2. https://blog.csdn.net/mybelief321/article/details/10049429
  3. https://ieevee.com/tech/2019/06/22/ndots.html
  4. 《TCP/IP 详解》
  5. https://zhengyinyong.com/post/go-dns-library/
  6. https://juejin.cn/post/6948469896007122974
  7. https://www.infoq.cn/article/99agzwzlewtvqjvgrtth
  8. https://www.cloudflare.com/en-gb/learning/ddos/what-is-a-ddos-attack
  9. https://www.cloudflare.com/zh-cn/learning/ddos/glossary/ip-spoofing/
  10. https://security.stackexchange.com/questions/155082/how-realistic-is-it-to-spoof-a-specific-udp-ip-address

你可能感兴趣的:(net,lang,golang,网络)