如何捕获提供HTTP响应的服务器的IP地址

Using Go's default HTTP client, I am unable to directly determine the IP address of the server that processed the request. For instance, when requesting example.com, what is the IP address that example.com resolved to at the time of the request?

import "net/http"

resp, err := http.Get("http://example.com/")

The resp object contains the resp.RemoteAddr property, but as detailed below is not utilized during client operations.

 // RemoteAddr allows HTTP servers and other software to record
 // the network address that sent the request, usually for
 // logging. This field is not filled in by ReadRequest and
 // has no defined format. The HTTP server in this package
 // sets RemoteAddr to an "IP:port" address before invoking a
 // handler.
 // This field is ignored by the HTTP client.
 RemoteAddr string

Is there a straightforward way to accomplish this? My initial thought would be to:

  1. Initiate a DNS lookup to remote domain
  2. Create new http transport using returned A/AAAA records
  3. Make the request
  4. Set the RemoteAddr property on the response object

Is there a better way?

Thank you.

UPDATED - to use @flimzy's suggestion. This method stores the remote IP:PORT into the request.RemoteAddr property. I've also added support for multiple redirects so that each subsequent request has its RemoteAddr populated.

request, _ := http.NewRequest("GET", "http://www.google.com", nil)
client := &http.Client{
    Transport:&http.Transport{
        DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
            conn, err := net.Dial(network, addr)
            request.RemoteAddr = conn.RemoteAddr().String()
            return conn, err
        },
    },
    CheckRedirect: func(req *http.Request, via []*http.Request) error {
        request = req
        return nil
    },
}
resp, _ := client.Do(request)
dongzhangji4824
dongzhangji4824 响应链中的最后一个服务器很好。使用WARC标准创建档案具有IP地址的元数据字段。尽管有一些Golang的专门作家,但他们(目前)都不支持将响应处理为WARC格式。
2 年多之前 回复
doujia7779
doujia7779 充其量,您可以在一路上的某个时刻获取处理响应的服务器的IP地址。那可能是一个代理,一个负载平衡器,一个WAF,一个反向代理……您实际上在这里想要完成什么?为什么需要IP?
2 年多之前 回复

3个回答

As far as I can tell, the only way to accomplish this with the standard library is with a custom http.Transport that records the remote IP address, for example in the DialContext function.

client := &http.Client{
    Transport: &http.Transport{
        DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
            conn, err := net.Dial(network, addr)
            fmt.Printf("Remote IP: %s
", conn.RemoteAddr())
            return conn, err
        },
    },
}
resp, _ := client.Get("http://www.google.com")

Tying the connection IP to the response is left as an exercise for the reader.

dpqjvoq9033
dpqjvoq9033 将其保留在响应对象中的一种好方法是什么?
大约 2 年之前 回复

you also can build a request with trace:

request = request.WithContext(httptrace.WithClientTrace(request.Context(), &httptrace.ClientTrace{
        GotConn: func(connInfo httptrace.GotConnInfo) {
            fmt.Printf("target ip:%+v
", connInfo.Conn.RemoteAddr().String())
        },
    }))
response, _:= client.Do(request)

httptrace form https://golang.org/pkg/net/http/httptrace/

req, err := http.NewRequest(method, url, strings.NewReader(body))
    trace := &httptrace.ClientTrace{
        GotConn: func(connInfo httptrace.GotConnInfo) {
            fmt.Printf("Got Conn: %+v
", connInfo)
        },
        DNSDone: func(dnsInfo httptrace.DNSDoneInfo) {
            fmt.Printf("DNS Info: %+v
", dnsInfo)
        },
    }
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐