获取域名/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 的功能。可以封装更多其他类型的查询。

目录
相关文章
|
1月前
|
域名解析 缓存 网络协议
减少域名dns解析时间
域名解析中的TTL值设置多少合适
69 5
|
7天前
|
文字识别 自然语言处理 算法
从多模态到精准洞察:深度解析多模态文件信息提取解决方案!
阿里云推出《多模态数据信息提取》解决方案,涵盖文本、图像、音频、视频等多种数据形式的自动化处理。本文从部署体验、功能验证到实际应用,全面解析该方案的能力与潜力,帮助开发者高效提取和整合复杂数据,提升工作效率...
28 3
从多模态到精准洞察:深度解析多模态文件信息提取解决方案!
|
3天前
|
数据采集 XML API
深入解析BeautifulSoup:从sohu.com视频页面提取关键信息的实战技巧
深入解析BeautifulSoup:从sohu.com视频页面提取关键信息的实战技巧
|
22天前
|
域名解析 弹性计算 安全
阿里云服务器租用、注册域名、备案及域名解析完整流程参考(图文教程)
对于很多初次建站的用户来说,选购云服务器和注册应及备案和域名解析步骤必须了解的,目前轻量云服务器2核2G68元一年,2核4G4M服务器298元一年,域名注册方面,阿里云推出域名1元购买活动,新用户注册com和cn域名2年首年仅需0元,xyz和top等域名首年仅需1元。对于建站的用户来说,购买完云服务器并注册好域名之后,下一步还需要操作备案和域名绑定。本文为大家展示阿里云服务器的购买流程,域名注册、绑定以及备案的完整流程,全文以图文教程形式为大家展示具体细节及注意事项,以供新手用户参考。
|
2月前
|
网络协议 安全 文件存储
动态DNS(DDNS)技术在当前网络环境中日益重要,它允许使用动态IP地址的设备通过固定域名访问
动态DNS(DDNS)技术在当前网络环境中日益重要,它允许使用动态IP地址的设备通过固定域名访问,即使IP地址变化,也能通过DDNS服务保持连接。适用于家庭网络远程访问设备及企业临时或移动设备管理,提供便捷性和灵活性。示例代码展示了如何使用Python实现基本的DDNS更新。尽管存在服务可靠性和安全性挑战,DDNS仍极大提升了网络资源的利用效率。
88 6
|
2月前
|
域名解析 网络协议 安全
反向DNS解析是从IP地址到域名的映射,主要作用于验证和识别,提高通信来源的可信度和可追溯性
在网络世界中,反向DNS解析是从IP地址到域名的映射,主要作用于验证和识别,提高通信来源的可信度和可追溯性。它在邮件服务器验证、网络安全等领域至关重要,帮助识别恶意行为,增强网络安全性。尽管存在配置错误等挑战,但正确管理下,反向DNS解析能显著提升网络环境的安全性和可靠性。
146 3
|
2月前
|
网络协议 网络安全 网络虚拟化
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算。通过这些术语的详细解释,帮助读者更好地理解和应用网络技术,应对数字化时代的挑战和机遇。
130 3
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
96 2
|
16天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
16天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多
下一篇
开通oss服务