使用golang的net包进行域名解析过程分析

背景: 在实际的互联网使用过程中,大家熟知的是使用域名来直接访问一个服务,但随着互联网业务架构的不断优化,可能对用用户来说访问一个域名获取到相关的资源是很简单的一步,但其实对于互联网整个请求过程其实是做了很多次调用,那最开始的一步就是dns解析。当然在linux环境下,用来做dns解析的工具有很多,比如dignslookup之类的,但是通常对于复杂问题的排查直接去机器上去很显然是不太现实的,因此打算使用golang的接口来封装域名解析服务,来提供后期的操作.

1. net包的使用

和dns相关结构体方法

# nameserver结构体
type NS struct {
    Host string
}


# srv记录 指定该域名由哪个DNS服务器来进行解析
type SRV struct {
    Target   string
    Port     uint16
    Priority uint16
    Weight   uint16
}


# dns正向解析(域名解析到cname或者实际的ip地址)
## 仅返回指定域名name的cname地址
func LookupCNAME(name string) (cname string, err error)

## 直接返回域名解析到地址.
func LookupHost(host string) (addrs []string, err error)

## 直接返回域名解析到地址,[]IP结构体.可以对具体ip进行相关操作(是否回环地址,子网,网络号等)
# type IP []byte
func LookupIP(host string) (addrs []IP, err error)

## DNS反向解析(ip地址反向解析查找解析到的域名)
# 根据ip地址查找主机名地址(必须得是可以解析到的域名)[dig -x ipaddress]
func LookupAddr(addr string) (name []string, err error)

使用net包进行dns解析查询

$ cat dns-test.go
package main

import (
  "net"
  "fmt"
  "os"
)


func main() {
  dns := "xxbandy.github.io"

  // 解析cname
  cname,_ := net.LookupCNAME(dns)

  // 解析ip地址
  ns, err := net.LookupHost(dns)
  if err != nil {
    fmt.Fprintf(os.Stderr, "Err: %s", err.Error())
    return
  }

  // 反向解析(主机必须得能解析到地址)
  dnsname,_ := net.LookupAddr("127.0.0.1")
  fmt.Println("hostname:",dnsname)

  // 对域名解析进行控制判断
  // 有些域名通常会先使用cname解析到一个别名上,然后再解析到实际的ip地址上
  switch {
    case cname != "":
        fmt.Println("cname:",cname)
        if len(ns) != 0 {
            fmt.Println("vips:")
            for _, n := range ns {
                fmt.Fprintf(os.Stdout, "%s\n", n)
            }
         }
    case len(ns) != 0:
        for _, n := range ns {
            fmt.Fprintf(os.Stdout, "%s\n", n)
        }
    default:
        fmt.Println(cname,ns)

  }

}

# 输出了本地127.0.0.1的主机名
# xxbandy.github.io的cname域名和实际解析的ip地址
$ go run dns-test.go
hostname: [localhost]
cname: xxbandy.github.io.
vips:
185.199.110.153
185.199.111.153
185.199.109.153
185.199.108.153

2. 分析dns解析过程以及系统调用

注意:在linux环境下可以使用dig trace来追踪域名解析过程

我们都知道,在计算机的世界,建立连接都是需要依靠五元组的(源ip,源端口,目的ip,目的端口,协议),而在实际用户使用过程中,浏览器会帮我们识别和管理源ip和端口以及协议(http,https),协议确定后其实目的端口也就确定了(80或443). 因此整个DNS系统要解决的问题就是将用户在浏览器中输入的域名最终转换成可识别的目的ip,进而进行连接通信。下面以一个简单例子来分析下dns解析的过程.

$ cat dns-test2.go
package main

import (
  "net"
  "fmt"
  "os"
)
func main() {
  dns := "xxbandy.github.io"
  ns, err := net.LookupHost(dns)
  if err != nil {
    fmt.Fprintf(os
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值