普通网友 2015-09-11 08:04
浏览 139
已采纳

使用指定的以太网ip发出http请求

I have several public ip addresses on my machine. I want to specify which one to use for a request.

I can do it using curl:

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

where 111.222.333.444 is one of my local ip addresses which I am using to make requests to the internet.

How to do the same using golang?

This method...

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
", 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
}

... gives me always the following result:

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

Another method

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))
}

gives output

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-generic 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)
  • 写回答

1条回答 默认 最新

  • drbii0359 2015-09-11 15:53
    关注

    Thank you @JimB. Working solution:

    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
    ", 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
    }
    

    Prints in the end Your IP Address Is: 111.222.333.213 as expected.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥200 uniapp长期运行卡死问题解决
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?
  • ¥15 乘性高斯噪声在深度学习网络中的应用
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决