如何将Go中的http.Client绑定到IP地址

时间:2015-11-17 22:46:39

标签: http go ip

我有一台带有多个网卡的客户端计算机,如何将Go中的http.Client绑定到某个网卡或某个SRC IP地址?

假设您有一些非常基本的http客户端代码,如下所示:

package main

import (
    "net/http"
)

func main() {
    webclient := &http.Client{}
    req, _ := http.NewRequest("GET", "http://www.google.com", nil)
    httpResponse, _ := webclient.Do(req)
    defer httpResponse.Body.Close()
}

有没有办法绑定到某个NIC或IP?

2 个答案:

答案 0 :(得分:12)

this question类似,您需要设置http.Client.Transport字段。将其设置为net.Transport的实例可让您指定要使用的net.Dialernet.Dialer然后允许您指定本地地址以进行连接。

示例:

localAddr, err := net.ResolveIPAddr("ip", "<my local address>")
if err != nil {
  panic(err)
}

// You also need to do this to make it work and not give you a 
// "mismatched local address type ip"
// This will make the ResolveIPAddr a TCPAddr without needing to 
// say what SRC port number to use.
localTCPAddr := net.TCPAddr{
    IP: localAddr.IP,
}


webclient := &http.Client{
    Transport: &http.Transport{
        Proxy: http.ProxyFromEnvironment,
        DialContext: (&net.Dialer{
            LocalAddr: &localTCPAddr,
            Timeout:   30 * time.Second,
            KeepAlive: 30 * time.Second,
            DualStack: true,
        }).DialContext,
        MaxIdleConns:          100,
        IdleConnTimeout:       90 * time.Second,
        TLSHandshakeTimeout:   10 * time.Second,
        ExpectContinueTimeout: 1 * time.Second,
    },
}

答案 1 :(得分:2)

这是一个完整的工作示例,其中包含了Tim的答案。我还打破了所有嵌套的部分,以便于阅读和学习。

package main

import (
    "fmt"
    "io/ioutil"
    "net"
    "net/http"
    "time"
)

func main() {
    localAddr, err := net.ResolveIPAddr("ip", "10.128.64.219")
    if err != nil {
        panic(err)
    }

    localTCPAddr := net.TCPAddr{
        IP: localAddr.IP,
    }

    d := net.Dialer{
        LocalAddr: &localTCPAddr,
        Timeout:   30 * time.Second,
        KeepAlive: 30 * time.Second,
    }

    tr := &http.Transport{
        Proxy:               http.ProxyFromEnvironment,
        Dial:                d.Dial,
        TLSHandshakeTimeout: 10 * time.Second,
    }

    webclient := &http.Client{Transport: tr}

    // Use NewRequest so we can change the UserAgent string in the header
    req, err := http.NewRequest("GET", "http://www.google.com:80", nil)
    if err != nil {
        panic(err)
    }

    res, err := webclient.Do(req)
    if err != nil {
        panic(err)
    }

    fmt.Println("DEBUG", res)
    defer res.Body.Close()

    content, err := ioutil.ReadAll(res.Body)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s", string(content))
}