前言
今天碰到了个需求,我要知道程序对外访问的 http 请求域名的 ip 地址。
直接查看 golang 的 net/http 包,发现 Response 中并没有我想要的 ip 信息。
考虑到在 OSI 七层模型中,ip 是网络层协议,而 http 是应用层协议。去翻了下 net 包,发现了基础用法。
先提一下,域名访问服务器是会通过 dns 服务器去获取服务器的 ip(这块知识不了解的可以先去了解下),我们日常访问域名的过程:域名 -> dns 服务器 -> 需要访问的服务器的 ip 。 dns 服务器有可能回返回多个 ip,一般程序都会使用第一个进行数据交互。
go 中的使用
1. net 包
源码 net/lookup.go 中有相关的获取方式,测试代码如下:
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())
}
输出
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 地址。
测试代码如下:
go
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)
}
}
输出:
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
shell
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=50
180.101.50.188 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 7ms,最长 = 21ms,平均 = 11ms
3. nslookup
shell
nslookup www.baidu.com
输出
服务器: 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
总结
本篇介绍了在 go 中如何获取访问域名的 ip 地址,通过 go 官方 net 包可获取。
如果有记录 http 请求的域名 ip 这种需求,可以使用 go 1.17 后添加的 httptrace 包来插入钩子获取请求的 ip 地址。当然了,httptrace 的作用不止于此,它可以搜集 http 客户端请求整个生命周期中的信息,本篇未做详细介绍,感兴趣的可自行探索。