英文:
make http request with a specified ethernet ip
问题
我在我的机器上有几个公共IP地址。我想指定使用哪一个IP地址进行请求。
我可以使用curl命令来实现:
curl --interface 111.222.333.444 https://www.iplocation.net/find-ip-address | grep "Your IP address"
其中111.222.333.444
是我用于向互联网发出请求的本地IP地址之一。
如何在golang
中实现相同的功能?
#这个方法...
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)
// 创建一个类似http.DefaultTransport的传输对象,但指定了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 // 我机器上的主IP地址
expected ip is 111.222.333.444
#另一种方法
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秒的暂停
string(bytesResult)
// 空字符串
#ifconfig
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
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)
英文:
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\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
}
... 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
得分: 3
谢谢 @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, // 选择第3个IP地址
}
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
,与预期一致。
英文:
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\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
}
Prints in the end Your IP Address Is: 111.222.333.213
as expected.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论