Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I find the remote IP address for a Go http.Response?

Tags:

http

go

The http.Request struct includes the remote IP and port of the request's sender:

    // 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**

The http.Response object has no such field.

I would like to know the IP address that responded to the request I sent, even when I sent it to a DNS address.

I thought that net.LookupHost() might be helpful, but 1) it can return multiple IPs for a single host name, and 2) it ignores the hosts file unless cgo is available, which it is not in my case.

Is it possible to retrieve the remote IP address for an http.Response?

like image 467
Martin Del Vecchio Avatar asked Feb 17 '17 19:02

Martin Del Vecchio


People also ask

What is remote address in HTTP request?

REMOTE_ADDR refers to the IP address of the client. There would be times when the hostname is unresolvable so the REMOTE_HOST will return the REMOTE_ADDR or the IP address instead.

Is IP address included in HTTP request?

While the client IP address typically is not present in the HTTP headers, web servers can find the IP address of the other side of the TCP connection carrying the HTTP request.

What is remote IP address?

What is a remote IP address, or say what is my IP address for Remote Desktop Connection? An IP address is a prerequisite to achieving remote connection via Remote Desktop. If you don't know the remote computer's IP address, you won't be able to connect remotely.


1 Answers

Use the net/http/httptrace package and use the GotConnInfo hook to capture the net.Conn and its corresponding Conn.RemoteAddr().

This will give you the address the Transport actually dialled, as opposed to what was resolved in DNSDoneInfo:

package main

import (
    "log"
    "net/http"
    "net/http/httptrace"
)

func main() {
    req, err := http.NewRequest("GET", "https://example.com/", nil)
    if err != nil {
        log.Fatal(err)
    }

    trace := &httptrace.ClientTrace{
        GotConn: func(connInfo httptrace.GotConnInfo) {
            log.Printf("resolved to: %s", connInfo.Conn.RemoteAddr())
        },
    }

    req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))

    client := &http.Client{}
    _, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
}

Outputs:

~ go run ip.go
2017/02/18 19:38:11 resolved to: 104.16.xx.xxx:443
like image 76
elithrar Avatar answered Oct 19 '22 12:10

elithrar