Search code examples
socketshttpgolang

Google Go Lang - Getting socket id/fd of net/http to use with syscall.Bind


I'm trying to get the socket id/fd of a net/http request so that i can use it with syscall.Bind() to bind the socket to one of my many public outgoing IPV4 addresses.

I want to be able to select which IP address is used for the outgoing request. This is for Windows.

Any help is greatly appreciated.

Below is some code which is for linux, but i need to get the http.Client's socket fd and not net.Conn.

func bindToIf(conn net.Conn, interfaceName string) {
    ptrVal := reflect.ValueOf(conn)
    val := reflect.Indirect(ptrVal)
    //next line will get you the net.netFD
    fdmember := val.FieldByName("fd")
    val1 := reflect.Indirect(fdmember)                                   
    netFdPtr := val1.FieldByName("sysfd")                                           
    fd := int(netFdPtr.Int())
    //fd now has the actual fd for the socket
    err := syscall.SetsockoptString(fd, syscall.SOL_SOCKET,
                syscall.SO_BINDTODEVICE, interfaceName)
    if err != nil {
        log.Fatal(err)
    }

}


Solution

  • I'm trying to get the socket id/fd of a net/http request

    Neither http.Request or http.Client have a socket for you to get.

    You can customize how an http.Client creates TCP connections by modifying it's Transport. See the Dial and DialTLS functions.

    From the docs:

    Dial specifies the dial function for creating unencrypted TCP connections. If Dial is nil, net.Dial is used.

    You may be interested in this question, which asks how to dial using a specific interface.

    You could set up the default transport do something like this:

    http.DefaultTransport.(*http.Transport).Dial = func(network, addr string) (net.Conn, error) {
        d := net.Dialer{LocalAddr: /* your addr here */}
        return d.Dial(network, addr) 
    }
    

    If you're using TLS, you'll want to do something similar for http.DefaultTransport.DialTLS.