• golang 发起 http 请求,获取访问域名的 ip 地址(net, httptrace)


    前言

    今天碰到了个需求,我要知道程序对外访问的 http 请求域名的 ip 地址

    直接查看 golangnet/http 包,发现 Response 中并没有我想要的 ip 信息。

    考虑到在 OSI 七层模型中,ip 是网络层协议,而 http 是应用层协议。去翻了下 net 包,发现了基础用法。

    先提一下,域名访问服务器是会通过 dns 服务器去获取服务器的 ip(这块知识不了解的可以先去了解下),我们日常访问域名的过程:域名 -> dns 服务器 -> 需要访问的服务器的 ipdns 服务器有可能回返回多个 ip,一般程序都会使用第一个进行数据交互。

    go 中的使用

    1. net 包

    源码 net/lookup.go 中有相关的获取方式,测试代码如下:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net"
    )
    
    func main() {
    	useNetParse()
    }
    
    func useNetParse() {
    	host := "www.baidu.com"
    	ips, err := net.LookupIP(host)
    	if err != nil {
    		log.Fatal(err)
    	}
    	for _, v := range ips {
    		fmt.Println("DNS 解析:", v.String())
    	}
    
    	ip, err := net.ResolveIPAddr("ip", host)
    	if err != nil {
    		log.Fatal(err)
    	}
    	fmt.Println("服务器 IP 地址:", ip.String())
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    输出

    DNS 解析: 180.101.50.188      
    DNS 解析: 180.101.50.242      
    服务器 IP 地址: 180.101.50.188
    
    • 1
    • 2
    • 3

    2. httptrace

    简单介绍下 httptrace,它是 go 1.17 后添加的新方法,用于在客户端请求的整个生命周期中收集细粒度信息的工具。

    它提供了许多的钩子,如:

    • 连接创建
    • 连接复用
    • DNS 查询
    • 将请求写入网路
    • 读取响应

    获取 DNS 查询使用的是 DNSDone 这个钩子,但是 DNS 解析后可能会解析出多个 IP 地址,而我需要的是访问服务器的 IP 地址,可以使用 GotConn 这个钩子,在连接成功创建后查看其访问的服务器的 IP 地址。

    测试代码如下:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    	"net/http/httptrace"
    )
    
    func main() {
    	req, _ := http.NewRequest("GET", "https://www.baidu.com", nil)
    	trace := &httptrace.ClientTrace{
    		DNSDone: func(dnsInfo httptrace.DNSDoneInfo) {
    			fmt.Printf("DNS Info: %+v\n", dnsInfo)
    		},
    		GotConn: func(connInfo httptrace.GotConnInfo) {
    			fmt.Printf("Got Conn: %+v\n", connInfo.Conn.RemoteAddr().String())
    		},
    	}
    	req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
    	_, err := http.DefaultTransport.RoundTrip(req)
    	if err != nil {
    		log.Fatal(err)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    输出:

    DNS Info: {Addrs:[{IP:180.101.50.188 Zone:} {IP:180.101.50.242 Zone:}] Err: Coalesced:false}
    Got Conn: 180.101.50.188:443
    
    • 1
    • 2

    可以看到这里访问的实际服务器的 IP 地址是 DNS 解析出的第一个 IP 地址。

    其他查看服务器 ip 的方法

    1. 浏览器 F12 调试

    可以通过浏览器调试进行查看
    在这里插入图片描述

    2. ping

    ping www.baidu.com
    
    • 1

    输出

    正在 Ping www.a.shifen.com [180.101.50.188] 具有 32 字节的数据:
    来自 180.101.50.188 的回复: 字节=32 时间=21ms TTL=50
    来自 180.101.50.188 的回复: 字节=32 时间=8ms TTL=50
    来自 180.101.50.188 的回复: 字节=32 时间=8ms TTL=50
    来自 180.101.50.188 的回复: 字节=32 时间=7ms TTL=50
    
    180.101.50.188 的 Ping 统计信息:
        数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
    往返行程的估计时间(以毫秒为单位):
        最短 = 7ms,最长 = 21ms,平均 = 11ms
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3. nslookup

    nslookup www.baidu.com
    
    • 1

    输出

    服务器:  public1.alidns.com
    Address:  223.5.5.5
    
    非权威应答:
    名称:    www.a.shifen.com
    Addresses:  240e:e9:6002:15a:0:ff:b05c:1278
              240e:e9:6002:15c:0:ff:b015:146f
              180.101.50.242
              180.101.50.188
    Aliases:  www.baidu.com
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    总结

    本篇介绍了在 go 中如何获取访问域名的 ip 地址,通过 go 官方 net 包可获取。

    如果有记录 http 请求的域名 ip 这种需求,可以使用 go 1.17 后添加的 httptrace 包来插入钩子获取请求的 ip 地址。当然了,httptrace 的作用不止于此,它可以搜集 http 客户端请求整个生命周期中的信息,本篇未做详细介绍,感兴趣的可自行探索。

    参考

  • 相关阅读:
    Chromebook文件夹应用新功能
    React UI组件库——如何快速实现antd的按需引入和自定义主题
    PDF格式分析(七十四)——自由文本注释(Free Text)
    2.2 IOC之基于XML管理bean
    【unity插件】UGUI的粒子效果(UI粒子)—— Particle Effect For UGUI (UI Particle)
    OpenCV 资料
    使用Caffeine实现帖子的缓存来优化网站的运行速度
    资源管理的部分
    ZZNUOJ_用C语言编写程序实现1211:日期排序(附完整源码)
    windows下flutter的环境安装
  • 原文地址:https://blog.csdn.net/DisMisPres/article/details/134176876