获取域名/IP/DNS信息 如此简单!

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 获取域名/IP/DNS信息 如此简单!

一、获取域名 IP 地址

要获取某个域名对应的 IP 地址,可以使用 net 包中的 LookupIP 函数:


func LookupIP(host string) ([]IP, error)

它接受一个域名参数,返回一个 IPAddr 切片和错误。IPAddr 结构体中包含了 IP 地址,可以处理 IPv4 和 IPv6 两种情况:


type IPAddr {    IP IP}
type IP []byte

使用示例:


package main
import (  "fmt"  "net")
func main() {  ips, err := net.LookupIP("www.baidu.com")  if err != nil {    fmt.Println(err)    return  }
  for _, ip := range ips {    fmt.Println(ip)  }}
输出:120.232.145.1852409:8c54:870:67:0:ff:b0c2:ad75

上例中打印出了 www.baidu.com 目前解析到的两个 IP 地址,一个 IPv4 地址,一个 IPv6 地址。


 

二、获取 IP 地址信息

对应地,若已经有一个 IP 地址,想要知道它的域名是什么,就可以使用反向查询函数 net.LookupAddr:


func LookupAddr(addr string) (names []string, err error)

它会将 IP 地址解析为一个或多个域名,返回字符串 slice。例如:


package main
import (  "fmt"  "net")
func main() {  names, _ := net.LookupAddr("8.8.8.8")  fmt.Println(names)}
输出:[dns.google.]


 

三、探测域名是否可用

要检查某个域名是否已经被注册,或者是否可供注册,可以使用 net.LookupNS 函数探测域名是否可用:


func LookupNS(host string) (names []*NS, err error)

它会查找指定主机/域名的名称服务器(Name Server),返回 NS 记录 slice。

如果域名没有被注册,它会返回错误。如果域名可以使用,它会返回域名正在使用的名称服务器记录。这可以用来判断域名是否可用:


package main
import (  "fmt"  "net")
func main() {  ns, err := net.LookupNS("example.com")  if err != nil {    fmt.Println("域名不可用")   } else {    fmt.Println("域名可用")    fmt.Println(ns)    }}
输出:域名不可用

上例中,example.com 是一个虚构的域名,结果显示此域名未被注册,不可用。


 

四、获取域名的 MX 记录

MX 记录指定了电子邮件服务器的信息。要获取一个域名的 MX 记录,可以使用 net.LookupMX 函数:


func LookupMX(name string) ([]*MX, error)

它返回一个 MX 记录的 slice,每个 MX 记录包含 mail exchange 域名与优先级:


type MX struct {    Host string    Pref uint16}

使用示例:


package main
import (    "fmt"    "net")
func main() {    mxs, err := net.LookupMX("baidu.com")    if err != nil {        fmt.Println(err)        return    }
    for _, mx := range mxs {        fmt.Printf("Host: %s, Pref: %d \n", mx.Host, mx.Pref)    }}
输出:Host: mx.maillb.baidu.com., Pref: 10Host: mx.n.shifen.com., Pref: 15  Host: usmx01.baidu.com., Pref: 20 Host: mx50.baidu.com., Pref: 20   Host: mx1.baidu.com., Pref: 20    Host: jpmx.baidu.com., Pref: 20

结果显示了 baidu.com 使用的 5 个邮件服务器域名及其优先级。


 

五、实现 DNS 查询

Go 标准库 net 包中提供了 LookupHost 函数可以通过域名查询 IP:


func LookupHost(hostname string) (addrs []string, err error)

它接受主机域名作为参数,返回其 IP 地址切片。


package main 
import (    "fmt"    "net")
func main() {    ips, err := net.LookupHost("www.example.com")    if err != nil {        fmt.Println(err)        return    }
    for _, ip := range ips {        fmt.Println(ip)     }}

如果想要自定义更灵活的 DNS 查询,可直接使用 UDP 套接字,按照 DNS 协议组织数据包,和 DNS 服务器进行通信。

下面是一个简单的 DNS 客户端查询 A 记录的实现:


package main
import (    "bytes"    "encoding/binary"    "fmt"    "net")
func main() {    // 连接DNS服务器      conn, err := net.Dial("udp", "8.8.8.8:53")    if err != nil {        fmt.Println(err)        return    }    defer conn.Close()
    // 构造DNS查询数据包    buf := new(bytes.Buffer)     // Transaction ID     var tranID uint16 = 0xABCD      binary.Write(buf, binary.BigEndian, tranID)
    flags := uint16(0x0100) // Standard query     binary.Write(buf, binary.BigEndian, flags) 
    var qds uint16 = 1 // Query Count    binary.Write(buf, binary.BigEndian, qds)
    // Only one question    var ans uint16 = 0     binary.Write(buf, binary.BigEndian, ans)    var auth uint16 = 0    binary.Write(buf, binary.BigEndian, auth)      var add uint16 = 0    binary.Write(buf, binary.BigEndian, add)
// 数据段开始// QNAMEbuf.WriteString("www.example.com") buf.WriteByte(0)
// QTYPE 和 QCLASSbinary.Write(buf, binary.BigEndian, uint16(1))binary.Write(buf, binary.BigEndian, uint16(1))
// 发送DNS查询请求conn.Write(buf.Bytes())
// 读取响应    reply := make([]byte, 512)_, err = conn.Read(reply)if err != nil {    fmt.Println("No reply")    return}
// 解析响应// 校验事务ID匹配tid := binary.BigEndian.Uint16(reply[0:2]) if tid != tranID {    fmt.Println("Wrong transaction ID")    return  }
// Response Coderescode := binary.BigEndian.Uint16(reply[3:5])if rescode != 0 {    fmt.Println("Server returned error")     return}
// 查询数应为1qdcount := binary.BigEndian.Uint16(reply[4:6])  if qdcount != 1 {    fmt.Println("Invalid query count")    return}
// 回答Resource记录数 >= 1ancount := binary.BigEndian.Uint16(reply[6:8])if ancount < 1 {     fmt.Println("No answer")    return}
// 跳过问题portionstart := 12  for {    if reply[start] == 0 {        break    }    start++}start += 5 
// 解析回答for i := 0; i < int(ancount); i++ {    // 跳过NAME    nameLen := int(reply[start])     start += 1 + nameLen  
    typ := binary.BigEndian.Uint16(reply[start : start+2])    start += 2    class := binary.BigEndian.Uint16(reply[start : start+2])     start += 2    ttl := binary.BigEndian.Uint32(reply[start : start+4])    start += 4
    rdlen := binary.BigEndian.Uint16(reply[start : start+2])    start += 2        // A记录为IP    if typ == 1 {         ip := net.IP(reply[start : start+rdlen]).String()          fmt.Println(ip)     }
    start += int(rdlen)}
}

上例实现了完整的 DNS 查询 client,自定义构造请求数据包,解析返回结果,打印查询 IP。使用 UDP socket 和 DNS 服务器通信。

这只是最基础的查询 A 记录的示例,可以扩展实现其他类型的 Resource Record 查询。


 

六、更多 DNS 记录查询

除了 A 记录(地址)查询,Go 标准库还提供了查询其他 DNS 记录的函数:

查询 TXT 记录


func LookupTXT(host string) ([]string, error)

查询 SRV 记录


func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error)

使用示例:


package main
import (  "fmt"  "net")
func main() {  texts, _ := net.LookupTXT("baidu.com")  for _, text := range texts {    fmt.Println(text)  }
  _, srvs, _ := net.LookupSRV("xmpp-server", "tcp", "baidu.com")  for _, srv := range srvs {    fmt.Println(srv.Target)  }}


 

七、域名/IP 相关实用包

除了标准库,Go 社区还提供了很多域名和 IP 地址操作相关的实用包,可以大大简化相关开发:

godns

godns 提供了便捷的域名查询和更新 API,支持不同类型的记录查询:


import "github.com/timshannon/godns"
A, _ := godns.Lookup("baidu.com", "A")MXs, _ := godns.Lookup("baidu.com", "MX"))

hosts

hosts 包实现了 hosts 文件(像 Linux 中的/etc/hosts)相关操作:


import "github.com/jaytaylor/go-hostsfile"
hosts, _ := hostsfile.NewHostsfile()ip := hosts.IP("localserver")hosts.Add("192.168.1.5", "test")

以上两个库可以大大简化域名/IP 相关操作。


 

八、模拟 NSLOOKUP

可编写一个类似 NSLOOKUP 命令行工具的程序,输入域名和 DNS 服务器地址,显示域名 lookup 的结果:


package main
import (    "flag"    "fmt"    "net"    "os")
func main() {    domain := flag.String("d", "baidu.com", "Domain to lookup")    server := flag.String("s", "8.8.8.8:53", "DNS server")    flag.Parse()        // UDP连接DNS服务器    conn, err := net.Dial("udp", *server)    if err != nil {        fmt.Println(err)        os.Exit(1)    }        // 模拟A记录查询    ips, err := lookupA(conn, *domain)    if err != nil {        fmt.Println(err)     } else {        fmt.Printf("Domain: %s\n", *domain)         fmt.Println(ips)    }          conn.Close()   }
// 模拟A记录查询func lookupA(conn net.Conn, domain string) ([]string, error) {        // 构造DNS查询请求数据包     buf := new(bytes.Buffer)
    // ..... 省略请求数据包组装过程            conn.Write(buf.Bytes())         // 解析返回数据包     reply := make([]byte, 512)        n, err := conn.Read(reply)         // ...... 省略解析过程获取IP        var ips []string     ips = append(ips, ip.String())     return ips, nil}

通过命令行参数指定域名和服务器地址模拟 NSLOOKUP 查询 IP 的功能。可以封装更多其他类型的查询。

目录
相关文章
|
4天前
|
网络协议 网络安全 网络虚拟化
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算。通过这些术语的详细解释,帮助读者更好地理解和应用网络技术,应对数字化时代的挑战和机遇。
27 3
|
6天前
|
运维 监控 安全
在实际应用中,如何选择基于不同域名还是不同 IP 进行代理多服务的配置?
综上所述,在实际应用中选择基于不同域名还是不同 IP 进行代理多服务的配置,需要根据具体的业务需求、可扩展性、性能、安全性以及维护和管理成本等多方面因素进行综合考虑,权衡利弊,选择最适合自己系统架构和运营需求的配置方式。
|
7天前
|
域名解析 网络协议 测试技术
IP、掩码、网关、DNS1、DNS2到底是什么东西,ping telnet测试
理解IP地址、子网掩码、默认网关和DNS服务器的概念是有效管理和配置网络的基础。通过使用ping和telnet命令,可以测试网络连通性和服务状态,快速诊断和解决网络问题。这些工具和概念是网络管理员和IT专业人员日常工作中不可或缺的部分。希望本文提供的详细解释和示例能够帮助您更好地理解和应用这些网络配置和测试工具。
25 2
|
17天前
|
域名解析 缓存 网络协议
浏览器中输入URL返回页面过程(超级详细)、DNS域名解析服务,TCP三次握手、四次挥手
浏览器中输入URL返回页面过程(超级详细)、DNS域名解析服务,TCP三次握手、四次挥手
|
7天前
|
安全 数据建模 测试技术
只有ip没有域名怎么申请SSL
在没有域名只有IP地址的情况下,仍可申请SSL证书。需确保拥有固定公网IP地址和服务器管理权限,选择支持IP SSL证书的CA(如JoySSL),完成注册、购买、验证、安装和测试等步骤,实现HTTPS加密访问。注意证书有效期、兼容性和安全性。
|
1月前
|
域名解析 网络协议
非阿里云注册域名如何在云解析DNS设置解析?
非阿里云注册域名如何在云解析DNS设置解析?
|
1月前
|
域名解析 网络协议 CDN
阿里云服务器购买后如何解析域名,三步操作即可解析绑定
阿里云服务器购买后如何解析域名,三步操作即可解析绑定
|
1月前
|
域名解析 弹性计算
内网域?名解析记录是否会覆盖公网域名解析记录?
内网域?名解析记录是否会覆盖公网域名解析记录?
|
1月前
|
域名解析 缓存 网络协议
Windows系统云服务器自定义域名解析导致网站无法访问怎么解决?
Windows系统云服务器自定义域名解析导致网站无法访问怎么解决?
|
1月前
|
运维 安全 网络协议
Python 网络编程:端口检测与IP解析
本文介绍了使用Python进行网络编程的两个重要技能:检查端口状态和根据IP地址解析主机名。通过`socket`库实现端口扫描和主机名解析的功能,并提供了详细的示例代码。文章最后还展示了如何整合这两部分代码,实现一个简单的命令行端口扫描器,适用于网络故障排查和安全审计。

热门文章

最新文章

推荐镜像

更多