前言
今天碰到了个需求,我要知道程序对外访问的 http 请求域名的 ip 地址。
直接查看 golang 的 net/http 包,发现 Response 中并没有我想要的 ip 信息。
考虑到在 OSI 七层模型中,ip 是网络层协议,而 http 是应用层协议。去翻了下 net 包,发现了基础用法。
先提一下,域名访问服务器是会通过 dns 服务器去获取服务器的 ip(这块知识不了解的可以先去了解下),我们日常访问域名的过程:域名 -> dns 服务器 -> 需要访问的服务器的 ip 。 dns 服务器有可能回返回多个 ip,一般程序都会使用第一个进行数据交互。
go 中的使用
1. net 包
源码 net/lookup.go 中有相关的获取方式,测试代码如下:
package mainimport ("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())
}
输出
DNS 解析: 180.101.50.188
DNS 解析: 180.101.50.242
服务器 IP 地址: 180.101.50.188
2. httptrace
简单介绍下 httptrace,它是 go 1.17 后添加的新方法,用于在客户端请求的整个生命周期中收集细粒度信息的工具。
它提供了许多的钩子,如:
- 连接创建
- 连接复用
DNS查询- 将请求写入网路
- 读取响应
获取 DNS 查询使用的是 DNSDone 这个钩子,但是 DNS 解析后可能会解析出多个 IP 地址,而我需要的是访问服务器的 IP 地址,可以使用 GotConn 这个钩子,在连接成功创建后查看其访问的服务器的 IP 地址。
测试代码如下:
package mainimport ("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)}
}
输出:
DNS Info: {Addrs:[{IP:180.101.50.188 Zone:} {IP:180.101.50.242 Zone:}] Err:<nil> Coalesced:false}
Got Conn: 180.101.50.188:443
可以看到这里访问的实际服务器的 IP 地址是 DNS 解析出的第一个 IP 地址。
其他查看服务器 ip 的方法
1. 浏览器 F12 调试
可以通过浏览器调试进行查看

2. ping
ping www.baidu.com
输出
正在 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=50180.101.50.188 的 Ping 统计信息:数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):最短 = 7ms,最长 = 21ms,平均 = 11ms
3. nslookup
nslookup www.baidu.com
输出
服务器: public1.alidns.com
Address: 223.5.5.5非权威应答:
名称: www.a.shifen.com
Addresses: 240e:e9:6002:15a:0:ff:b05c:1278240e:e9:6002:15c:0:ff:b015:146f180.101.50.242180.101.50.188
Aliases: www.baidu.com
总结
本篇介绍了在 go 中如何获取访问域名的 ip 地址,通过 go 官方 net 包可获取。
如果有记录 http 请求的域名 ip 这种需求,可以使用 go 1.17 后添加的 httptrace 包来插入钩子获取请求的 ip 地址。当然了,httptrace 的作用不止于此,它可以搜集 http 客户端请求整个生命周期中的信息,本篇未做详细介绍,感兴趣的可自行探索。
参考
- 官博 Introducing HTTP Tracing