2015-09-11 72 views
2

我在我的機器上有幾個公共IP地址。我想指定哪一個用於請求。使用指定的以太網ip發出http請求

我可以使用curl做到這一點:

curl --interface 111.222.333.444 https://www.iplocation.net/find-ip-address | grep "Your IP address" 

其中111.222.333.444是我的本地IP地址,其中一個我使用提出要求到互聯網。

如何使用golang來做同樣的事情?

This方法...

package main 

import (
    "bytes" 
    "fmt" 
    "github.com/PuerkitoBio/goquery" 
    "io/ioutil" 
    "net" 
    "net/http" 
    "os" 
    "time" 
) 

func main() { 
    var localAddr = "111.222.333.444" 
    localAddress, _ := net.ResolveTCPAddr("tcp", localAddr) 

    // Create a transport like http.DefaultTransport, but with a specified localAddr 
    transport := &http.Transport{ 
     Proxy: http.ProxyFromEnvironment, 
     Dial: (&net.Dialer{ 
      Timeout: 30 * time.Second, 
      KeepAlive: 30 * time.Second, 
      LocalAddr: localAddress, 
     }).Dial, 
     TLSHandshakeTimeout: 10 * time.Second, 
    } 

    client := &http.Client{ 
     Transport: transport, 
    } 

    response, err := client.Get("https://www.whatismyip.com/") 

    if err != nil { 
     fmt.Printf("%s", err) 
     os.Exit(1) 
    } else { 
     defer response.Body.Close() 
     contents, err := ioutil.ReadAll(response.Body) 
     if err != nil { 
      fmt.Printf("%s", err) 
      os.Exit(1) 
     } 
     var contentsStr = string(contents) 
     fmt.Printf("%s\n", contentsStr) 
     var doc = DocByHtmlString(contentsStr) 

     doc.Find("div").Each(func(i int, s *goquery.Selection) { 
      attr, exists := s.Attr("class") 
      if exists { 
       if attr == "ip" { 
        fmt.Println(s.Text()) 
        fmt.Println("expected ip is " + localAddr) 
       } 
      } 
     }) 
    } 
} 

func DocByHtmlString(html string) *goquery.Document { 
    doc, err := goquery.NewDocumentFromReader(bytes.NewBufferString(html)) 
    if err != nil { 
     panic(err) 
    } 
    return doc 
} 

...讓我永遠以下結果:

Your IP Address Is: 555.666.777.888 // main IP address on my machine 
expected ip is 111.222.333.444 

Another方法

package main 

import (
    "fmt" 
    "io/ioutil" 
    "log" 
    "net" 
) 

func main() { 
    ief, err := net.InterfaceByName("eth0") 
    if err != nil { 
     log.Fatal(err) 
    } 
    addrs, err := ief.Addrs() 
    if err != nil { 
     log.Fatal(err) 
    } 
    tcpAddr := &net.TCPAddr{ 
     IP: addrs[3].(*net.IPNet).IP, 
     // Port: 8080, 
    } 
    d := net.Dialer{LocalAddr: tcpAddr} 
    conn, err2 := d.Dial("tcp", "www.whatismyip.com:80") 
    if err2 != nil { 
     log.Fatal(err2) 
    } 
    fmt.Println(`conn.LocalAddr()`) 
    fmt.Println(conn.LocalAddr()) 
    fmt.Println(`conn.RemoteAddr()`) 
    fmt.Println(conn.RemoteAddr()) 
    defer conn.Close() 
    bytesResult, err3 := ioutil.ReadAll(conn) 
    if err3 != nil { 
     log.Fatal(err3) 
    } 
    fmt.Println(`string(bytesResult)`) 
    fmt.Println(string(bytesResult)) 
} 

使輸出

conn.LocalAddr() 
111.222.333.213:37036 
conn.RemoteAddr() 
141.101.120.15:80 
        // 15 seconds pause 
string(bytesResult) 
        // empty string 

ifcongif

的Ubuntu 14.04.3 LTS(GNU/Linux的3.13.0-63泛型x86_64的)

$ ifconfig 
eth0  Link encap:Ethernet HWaddr 00:18:3c:96:69:8c 
      inet addr:111.222.333.208 Bcast:111.222.333.255 Mask:255.255.255.0 
      inet6 addr: de90::216:3cff:fe56:698c/64 Scope:Link 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 
      RX packets:942000 errors:0 dropped:0 overruns:0 frame:0 
      TX packets:336708 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:1000 
      RX bytes:133860794 (133.8 MB) TX bytes:84577381 (84.5 MB) 

eth0:0 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c 
      inet addr:111.222.333.209 Bcast:111.222.333.255 Mask:255.255.255.0 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 

eth0:1 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c 
      inet addr:111.222.333.212 Bcast:111.222.333.255 Mask:255.255.255.0 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 

eth0:2 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c 
      inet addr:111.222.333.213 Bcast:111.222.333.255 Mask:255.255.255.0 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 

eth0:3 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c 
      inet addr:111.222.333.216 Bcast:111.222.333.255 Mask:255.255.255.0 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 

eth0:4 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c 
      inet addr:111.222.333.217 Bcast:111.222.333.255 Mask:255.255.255.0 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 

eth0:5 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c 
      inet addr:111.222.333.220 Bcast:111.222.333.255 Mask:255.255.255.0 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 

eth0:6 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c 
      inet addr:111.222.333.221 Bcast:111.222.333.255 Mask:255.255.255.0 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 

eth0:7 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c 
      inet addr:111.222.333.224 Bcast:111.222.333.255 Mask:255.255.255.0 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 

eth0:8 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c 
      inet addr:111.222.333.225 Bcast:111.222.333.255 Mask:255.255.255.0 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 

lo  Link encap:Local Loopback 
      inet addr:127.0.0.1 Mask:255.0.0.0 
      inet6 addr: ::1/128 Scope:Host 
      UP LOOPBACK RUNNING MTU:65536 Metric:1 
      RX packets:0 errors:0 dropped:0 overruns:0 frame:0 
      TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 
      collisions:0 txqueuelen:0 
      RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) 
+0

在'net.TCPAddr'中指定一個端口(第二種方法)。它似乎默認爲80,並且該端口需要特權並且可能已經被綁定。 – thwd

+0

@thwd帶端口它不會給出錯誤,但會在10秒內給出空的響應(上面添加的代碼) –

+0

聞起來像某種超時。 – thwd

回答

2

謝謝@JimB。工作解決方案:

package main 

import (
    "bytes" 
    "fmt" 
    "github.com/PuerkitoBio/goquery" 
    "io/ioutil" 
    "log" 
    "net" 
    "net/http" 
    "os" 
    "time" 
) 

func main() { 
    ief, err := net.InterfaceByName("eth0") 
    if err != nil { 
     log.Fatal(err) 
    } 
    addrs, err := ief.Addrs() 
    if err != nil { 
     log.Fatal(err) 
    } 
    tcpAddr := &net.TCPAddr{ 
     IP: addrs[3].(*net.IPNet).IP, // Choosing ip address number 3 
    } 
    d := net.Dialer{LocalAddr: tcpAddr} 
    conn, err2 := d.Dial("tcp", "www.whatismyip.com:80") 
    if err2 != nil { 
     log.Fatal(err2) 
    } 
    fmt.Println(`conn.LocalAddr()`) 
    fmt.Println(conn.LocalAddr()) 
    fmt.Println(`conn.RemoteAddr()`) 
    fmt.Println(conn.RemoteAddr()) 
    defer conn.Close() 

    transport := &http.Transport{ 
     Proxy:    http.ProxyFromEnvironment, 
     Dial:    (&net.Dialer{LocalAddr: tcpAddr}).Dial, 
     TLSHandshakeTimeout: 10 * time.Second, 
    } 

    client := &http.Client{ 
     Transport: transport, 
    } 

    response, err := client.Get("https://www.whatismyip.com/") 

    if err != nil { 
     fmt.Printf("%s", err) 
     os.Exit(1) 
    } else { 
     defer response.Body.Close() 
     contents, err := ioutil.ReadAll(response.Body) 
     if err != nil { 
      fmt.Printf("%s", err) 
      os.Exit(1) 
     } 
     var contentsStr = string(contents) 
     fmt.Printf("%s\n", contentsStr) 
     var doc = DocByHtmlString(contentsStr) 

     doc.Find("div").Each(func(i int, s *goquery.Selection) { 
      attr, exists := s.Attr("class") 
      if exists { 
       if attr == "ip" { 
        fmt.Println(s.Text()) 
       } 
      } 
     }) 
    } 
} 

func DocByHtmlString(html string) *goquery.Document { 
    doc, err := goquery.NewDocumentFromReader(bytes.NewBufferString(html)) 
    if err != nil { 
     panic(err) 
    } 
    return doc 
} 

如預期打印Your IP Address Is: 111.222.333.213