实现DNS查询

DNS全称Domain Name System(域名系统),它的作用是将IP地址转换为类似packt.com的域名,或者将域名转换为IP地址。本节中开发的DNS.go程序的处理逻辑非常简单:如果程序执行时的命令行参数是一个有效的IP地址,则程序将查询该IP地址对应的主机名;其他情况下,程序将假定它处理的是一个主机名,并将其转换成一个或多个IP地址。

程序DNS.go的代码将分三部分介绍。第一部分程序包含以下Go代码:

  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. "os"
  6. )
  7. func lookIP(address string) ([]string, error) {
  8. hosts, err := net.LookupAddr(address)
  9. if err != nil {
  10. return nil, err
  11. }
  12. return hosts, nil
  13. }
  14. func lookHostname(hostname string) ([]string, error) {
  15. IPs, err := net.LookupHost(hostname)
  16. if err != nil {
  17. return nil, err
  18. }
  19. return IPs, nil
  20. }

函数lookIP()将一个IP地址作为输入,然后返回与该IP地址匹配的主机列表,这个功能通过函数net.LookupAddr()的帮助来实现。

而函数lookHostname()将主机名作为输入,使用net.LookupHost()函数进行处理,返回一个相关IP地址的列表。

程序DNS.go的第二部分是以下Go代码:

  1. func main() {
  2. arguments := os.Args
  3. if len(arguments) == 1 {
  4. fmt.Println("Please provide an argument!")
  5. return
  6. }
  7. input := arguments[1]
  8. IPaddress := net.ParseIP(input)

函数net.ParseIP()可以将输入字符串解析为IPv4或IPv6地址。如果输入一个非法的IP地址,函数net.ParseIP()将返回nil

程序DNS.go的剩余Go代码如下:

  1. if IPaddress == nil {
  2. IPs, err := lookHostname(input)
  3. if err == nil {
  4. for _, singleIP := range IPs {
  5. fmt.Println(singleIP)
  6. }
  7. }
  8. } else {
  9. hosts, err := lookIP(input)
  10. if err == nil {
  11. for _, hostname := range hosts {
  12. fmt.Println(hostname)
  13. }
  14. }
  15. }
  16. }

执行DNS.go程序,并携带不同的输入参数,将生成以下输出:

  1. $ go run DNS.go 127.0.0.1
  2. localhost
  3. $ go run DNS.go 192.168.1.1
  4. cisco
  5. $ go run DNS.go packtpub.com
  6. 83.166.169.231
  7. $ go run DNS.go google.com
  8. 2a00:1450:4001:816::200e
  9. 216.58.210.14
  10. $ go run DNS.go www.google.com
  11. 2a00:1450:4001:816::2004
  12. 216.58.214.36
  13. $ go run DNS.go cnn.com
  14. 2a04:4e42::323
  15. 2a04:4e42:600::323
  16. 2a04:4e42:400::323
  17. 2a04:4e42:200::323
  18. 151.101.193.67
  19. 151.101.1.67
  20. 151.101.129.67
  21. 151.101.65.67

可以看到go run DNS.go 192.168.1.1命令的输出来自/etc/hosts文件,因为在/etc/hosts文件中配置了IP地址192.168.1.1的别名cisco

最后一个命令的输出演示了域名(cnn.com)可能有多个公网IP地址映射。请特别注意公网这个词,尽管www.google.com有多个IP地址,但是只有地址(216.58.214.36)是公网IP地址。