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

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

目录
相关文章
|
安全 网络协议 网络安全
只有IP地址没有域名,如何实现HTTPS访问?
在仅有IP地址而无域名的情况下,实现HTTPS访问并非不可能。主要挑战包括证书颁发机构(CA)对IP地址的支持有限及浏览器兼容性问题。解决方案有:1) 搭建私有CA为内部IP地址颁发证书;2) 使用支持IP地址的公共CA服务。选择合适的方案需根据需求权衡。具体步骤包括选择证书类型、生成CSR文件、提交并完成验证、安装SSL证书和配置强制HTTPS访问。确保IP地址稳定,并定期维护安全性。 **申请优惠**:访问JoySSL官网并填写注册码“230907”可优惠申请IP地址证书。
3142 5
|
监控 负载均衡 安全
静态IP代理与动态IP代理:提升速度与保障隐私的技术解析
本文探讨了静态IP代理和动态IP代理的特性和应用场景。静态IP代理通过高质量服务提供商、网络设置优化、定期更换IP与负载均衡及性能监控提升网络访问速度;动态IP代理则通过隐藏真实IP、增强安全性、绕过封锁和提供独立IP保障用户隐私。结合实际案例与代码示例,展示了两者在不同场景下的优势,帮助用户根据需求选择合适的代理服务以实现高效、安全的网络访问。
566 1
|
Serverless 对象存储 人工智能
智能文件解析:体验阿里云多模态信息提取解决方案
在当今数据驱动的时代,信息的获取和处理效率直接影响着企业决策的速度和质量。然而,面对日益多样化的文件格式(文本、图像、音频、视频),传统的处理方法显然已经无法满足需求。
595 4
智能文件解析:体验阿里云多模态信息提取解决方案
|
文字识别 开发者 数据处理
多模态数据信息提取解决方案评测报告!
阿里云推出的《多模态数据信息提取》解决方案,利用AI技术从文本、图像、音频和视频中提取关键信息,支持多种应用场景,大幅提升数据处理效率。评测涵盖部署体验、文档清晰度、模板简化、示例验证及需求适配性等方面。方案表现出色,部署简单直观,功能强大,适合多种业务场景。建议增加交互提示、多语言支持及优化OCR和音频转写功能...
738 3
多模态数据信息提取解决方案评测报告!
|
网络协议 Unix Linux
深入解析:Linux网络配置工具ifconfig与ip命令的全面对比
虽然 `ifconfig`作为一个经典的网络配置工具,简单易用,但其功能已经不能满足现代网络配置的需求。相比之下,`ip`命令不仅功能全面,而且提供了一致且简洁的语法,适用于各种网络配置场景。因此,在实际使用中,推荐逐步过渡到 `ip`命令,以更好地适应现代网络管理需求。
970 11
|
机器学习/深度学习 人工智能 文字识别
从“泛读”到“精读”:合合信息文档解析如何让大模型更懂复杂文档?
随着deepseek等大模型逐渐步入视野,理论上文档解析工作应能大幅简化。 然而,实际情况却不尽如人意。当前的多模态大模型虽然具备强大的视觉与语言交互能力,但在解析非结构化文档时,仍面临复杂版式、多元素混排以及严密逻辑推理等挑战。
698 0
|
数据采集 XML API
深入解析BeautifulSoup:从sohu.com视频页面提取关键信息的实战技巧
深入解析BeautifulSoup:从sohu.com视频页面提取关键信息的实战技巧
|
缓存 算法 API
查询域名WHOIS信息免费API接口教程
该API用于查询顶级域名的WHOIS信息,不支持国别域名和中文域名。通过POST或GET请求,需提供用户ID、KEY及待查询域名。返回信息包括域名状态、注册商、时间等详细数据。示例与文档见官网。
1732 5
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
966 140
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1605 29

推荐镜像

更多
  • DNS