使用指定的以太网IP地址进行HTTP请求。

huangapple go评论136阅读模式
英文:

make http request with a specified ethernet ip

问题

我在我的机器上有几个公共IP地址。我想指定使用哪一个IP地址进行请求。

我可以使用curl命令来实现:

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

其中111.222.333.444是我用于向互联网发出请求的本地IP地址之一。

如何在golang中实现相同的功能?

#这个方法...

  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/PuerkitoBio/goquery"
  6. "io/ioutil"
  7. "net"
  8. "net/http"
  9. "os"
  10. "time"
  11. )
  12. func main() {
  13. var localAddr = "111.222.333.444"
  14. localAddress, _ := net.ResolveTCPAddr("tcp", localAddr)
  15. // 创建一个类似http.DefaultTransport的传输对象,但指定了localAddr
  16. transport := &http.Transport{
  17. Proxy: http.ProxyFromEnvironment,
  18. Dial: (&net.Dialer{
  19. Timeout: 30 * time.Second,
  20. KeepAlive: 30 * time.Second,
  21. LocalAddr: localAddress,
  22. }).Dial,
  23. TLSHandshakeTimeout: 10 * time.Second,
  24. }
  25. client := &http.Client{
  26. Transport: transport,
  27. }
  28. response, err := client.Get("https://www.whatismyip.com/")
  29. if err != nil {
  30. fmt.Printf("%s", err)
  31. os.Exit(1)
  32. } else {
  33. defer response.Body.Close()
  34. contents, err := ioutil.ReadAll(response.Body)
  35. if err != nil {
  36. fmt.Printf("%s", err)
  37. os.Exit(1)
  38. }
  39. var contentsStr = string(contents)
  40. fmt.Printf("%s\n", contentsStr)
  41. var doc = DocByHtmlString(contentsStr)
  42. doc.Find("div").Each(func(i int, s *goquery.Selection) {
  43. attr, exists := s.Attr("class")
  44. if exists {
  45. if attr == "ip" {
  46. fmt.Println(s.Text())
  47. fmt.Println("expected ip is " + localAddr)
  48. }
  49. }
  50. })
  51. }
  52. }
  53. func DocByHtmlString(html string) *goquery.Document {
  54. doc, err := goquery.NewDocumentFromReader(bytes.NewBufferString(html))
  55. if err != nil {
  56. panic(err)
  57. }
  58. return doc
  59. }

...总是给我返回以下结果:

  1. Your IP Address Is: 555.666.777.888 // 我机器上的主IP地址
  2. expected ip is 111.222.333.444

#另一种方法

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "log"
  6. "net"
  7. )
  8. func main() {
  9. ief, err := net.InterfaceByName("eth0")
  10. if err != nil {
  11. log.Fatal(err)
  12. }
  13. addrs, err := ief.Addrs()
  14. if err != nil {
  15. log.Fatal(err)
  16. }
  17. tcpAddr := &net.TCPAddr{
  18. IP: addrs[3].(*net.IPNet).IP,
  19. // Port: 8080,
  20. }
  21. d := net.Dialer{LocalAddr: tcpAddr}
  22. conn, err2 := d.Dial("tcp", "www.whatismyip.com:80")
  23. if err2 != nil {
  24. log.Fatal(err2)
  25. }
  26. fmt.Println(`conn.LocalAddr()`)
  27. fmt.Println(conn.LocalAddr())
  28. fmt.Println(`conn.RemoteAddr()`)
  29. fmt.Println(conn.RemoteAddr())
  30. defer conn.Close()
  31. bytesResult, err3 := ioutil.ReadAll(conn)
  32. if err3 != nil {
  33. log.Fatal(err3)
  34. }
  35. fmt.Println(`string(bytesResult)`)
  36. fmt.Println(string(bytesResult))
  37. }

输出结果为:

  1. conn.LocalAddr()
  2. 111.222.333.213:37036
  3. conn.RemoteAddr()
  4. 141.101.120.15:80
  5. // 15秒的暂停
  6. string(bytesResult)
  7. // 空字符串

#ifconfig

Ubuntu 14.04.3 LTS (GNU/Linux 3.13.0-63-generic x86_64)

  1. $ ifconfig
  2. eth0 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  3. inet addr:111.222.333.208 Bcast:111.222.333.255 Mask:255.255.255.0
  4. inet6 addr: de90::216:3cff:fe56:698c/64 Scope:Link
  5. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  6. RX packets:942000 errors:0 dropped:0 overruns:0 frame:0
  7. TX packets:336708 errors:0 dropped:0 overruns:0 carrier:0
  8. collisions:0 txqueuelen:1000
  9. RX bytes:133860794 (133.8 MB) TX bytes:84577381 (84.5 MB)
  10. eth0:0 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  11. inet addr:111.222.333.209 Bcast:111.222.333.255 Mask:255.255.255.0
  12. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  13. eth0:1 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  14. inet addr:111.222.333.212 Bcast:111.222.333.255 Mask:255.255.255.0
  15. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  16. eth0:2 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  17. inet addr:111.222.333.213 Bcast:111.222.333.255 Mask:255.255.255.0
  18. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  19. eth0:3 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  20. inet addr:111.222.333.216 Bcast:111.222.333.255 Mask:255.255.255.0
  21. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  22. eth0:4 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  23. inet addr:111.222.333.217 Bcast:111.222.333.255 Mask:255.255.255.0
  24. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  25. eth0:5 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  26. inet addr:111.222.333.220 Bcast:111.222.333.255 Mask:255.255.255.0
  27. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  28. eth0:6 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  29. inet addr:111.222.333.221 Bcast:111.222.333.255 Mask:255.255.255.0
  30. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  31. eth0:7 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  32. inet addr:111.222.333.224 Bcast:111.222.333.255 Mask:255.255.255.0
  33. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  34. eth0:8 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  35. inet addr:111.222.333.225 Bcast:111.222.333.255 Mask:255.255.255.0
  36. lo Link encap:Local Loopback
  37. inet addr:127.0.0.1 Mask:255.0.0.0
  38. inet6 addr: ::1/128 Scope:Host
  39. UP LOOPBACK RUNNING MTU:65536 Metric:1
  40. RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  41. TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
  42. collisions:0 txqueuelen:0
  43. 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:

  1. 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...

  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/PuerkitoBio/goquery"
  6. "io/ioutil"
  7. "net"
  8. "net/http"
  9. "os"
  10. "time"
  11. )
  12. func main() {
  13. var localAddr = "111.222.333.444"
  14. localAddress, _ := net.ResolveTCPAddr("tcp", localAddr)
  15. // Create a transport like http.DefaultTransport, but with a specified localAddr
  16. transport := &http.Transport{
  17. Proxy: http.ProxyFromEnvironment,
  18. Dial: (&net.Dialer{
  19. Timeout: 30 * time.Second,
  20. KeepAlive: 30 * time.Second,
  21. LocalAddr: localAddress,
  22. }).Dial,
  23. TLSHandshakeTimeout: 10 * time.Second,
  24. }
  25. client := &http.Client{
  26. Transport: transport,
  27. }
  28. response, err := client.Get("https://www.whatismyip.com/")
  29. if err != nil {
  30. fmt.Printf("%s", err)
  31. os.Exit(1)
  32. } else {
  33. defer response.Body.Close()
  34. contents, err := ioutil.ReadAll(response.Body)
  35. if err != nil {
  36. fmt.Printf("%s", err)
  37. os.Exit(1)
  38. }
  39. var contentsStr = string(contents)
  40. fmt.Printf("%s\n", contentsStr)
  41. var doc = DocByHtmlString(contentsStr)
  42. doc.Find("div").Each(func(i int, s *goquery.Selection) {
  43. attr, exists := s.Attr("class")
  44. if exists {
  45. if attr == "ip" {
  46. fmt.Println(s.Text())
  47. fmt.Println("expected ip is " + localAddr)
  48. }
  49. }
  50. })
  51. }
  52. }
  53. func DocByHtmlString(html string) *goquery.Document {
  54. doc, err := goquery.NewDocumentFromReader(bytes.NewBufferString(html))
  55. if err != nil {
  56. panic(err)
  57. }
  58. return doc
  59. }

... gives me always the following result:

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

#Another method

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "log"
  6. "net"
  7. )
  8. func main() {
  9. ief, err := net.InterfaceByName("eth0")
  10. if err != nil {
  11. log.Fatal(err)
  12. }
  13. addrs, err := ief.Addrs()
  14. if err != nil {
  15. log.Fatal(err)
  16. }
  17. tcpAddr := &net.TCPAddr{
  18. IP: addrs[3].(*net.IPNet).IP,
  19. // Port: 8080,
  20. }
  21. d := net.Dialer{LocalAddr: tcpAddr}
  22. conn, err2 := d.Dial("tcp", "www.whatismyip.com:80")
  23. if err2 != nil {
  24. log.Fatal(err2)
  25. }
  26. fmt.Println(`conn.LocalAddr()`)
  27. fmt.Println(conn.LocalAddr())
  28. fmt.Println(`conn.RemoteAddr()`)
  29. fmt.Println(conn.RemoteAddr())
  30. defer conn.Close()
  31. bytesResult, err3 := ioutil.ReadAll(conn)
  32. if err3 != nil {
  33. log.Fatal(err3)
  34. }
  35. fmt.Println(`string(bytesResult)`)
  36. fmt.Println(string(bytesResult))
  37. }

gives output

  1. conn.LocalAddr()
  2. 111.222.333.213:37036
  3. conn.RemoteAddr()
  4. 141.101.120.15:80
  5. // 15 seconds pause
  6. string(bytesResult)
  7. // empty string

#ifcongif

Ubuntu 14.04.3 LTS (GNU/Linux 3.13.0-63-generic x86_64)

  1. $ ifconfig
  2. eth0 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  3. inet addr:111.222.333.208 Bcast:111.222.333.255 Mask:255.255.255.0
  4. inet6 addr: de90::216:3cff:fe56:698c/64 Scope:Link
  5. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  6. RX packets:942000 errors:0 dropped:0 overruns:0 frame:0
  7. TX packets:336708 errors:0 dropped:0 overruns:0 carrier:0
  8. collisions:0 txqueuelen:1000
  9. RX bytes:133860794 (133.8 MB) TX bytes:84577381 (84.5 MB)
  10. eth0:0 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  11. inet addr:111.222.333.209 Bcast:111.222.333.255 Mask:255.255.255.0
  12. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  13. eth0:1 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  14. inet addr:111.222.333.212 Bcast:111.222.333.255 Mask:255.255.255.0
  15. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  16. eth0:2 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  17. inet addr:111.222.333.213 Bcast:111.222.333.255 Mask:255.255.255.0
  18. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  19. eth0:3 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  20. inet addr:111.222.333.216 Bcast:111.222.333.255 Mask:255.255.255.0
  21. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  22. eth0:4 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  23. inet addr:111.222.333.217 Bcast:111.222.333.255 Mask:255.255.255.0
  24. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  25. eth0:5 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  26. inet addr:111.222.333.220 Bcast:111.222.333.255 Mask:255.255.255.0
  27. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  28. eth0:6 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  29. inet addr:111.222.333.221 Bcast:111.222.333.255 Mask:255.255.255.0
  30. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  31. eth0:7 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  32. inet addr:111.222.333.224 Bcast:111.222.333.255 Mask:255.255.255.0
  33. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  34. eth0:8 Link encap:Ethernet HWaddr 00:18:3c:96:69:8c
  35. inet addr:111.222.333.225 Bcast:111.222.333.255 Mask:255.255.255.0
  36. UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  37. lo Link encap:Local Loopback
  38. inet addr:127.0.0.1 Mask:255.0.0.0
  39. inet6 addr: ::1/128 Scope:Host
  40. UP LOOPBACK RUNNING MTU:65536 Metric:1
  41. RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  42. TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
  43. collisions:0 txqueuelen:0
  44. RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

答案1

得分: 3

谢谢 @JimB。工作解决方案:

  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/PuerkitoBio/goquery"
  6. "io/ioutil"
  7. "log"
  8. "net"
  9. "net/http"
  10. "os"
  11. "time"
  12. )
  13. func main() {
  14. ief, err := net.InterfaceByName("eth0")
  15. if err != nil {
  16. log.Fatal(err)
  17. }
  18. addrs, err := ief.Addrs()
  19. if err != nil {
  20. log.Fatal(err)
  21. }
  22. tcpAddr := &net.TCPAddr{
  23. IP: addrs[3].(*net.IPNet).IP, // 选择第3个IP地址
  24. }
  25. d := net.Dialer{LocalAddr: tcpAddr}
  26. conn, err2 := d.Dial("tcp", "www.whatismyip.com:80")
  27. if err2 != nil {
  28. log.Fatal(err2)
  29. }
  30. fmt.Println(`conn.LocalAddr()`)
  31. fmt.Println(conn.LocalAddr())
  32. fmt.Println(`conn.RemoteAddr()`)
  33. fmt.Println(conn.RemoteAddr())
  34. defer conn.Close()
  35. transport := &http.Transport{
  36. Proxy: http.ProxyFromEnvironment,
  37. Dial: (&net.Dialer{LocalAddr: tcpAddr}).Dial,
  38. TLSHandshakeTimeout: 10 * time.Second,
  39. }
  40. client := &http.Client{
  41. Transport: transport,
  42. }
  43. response, err := client.Get("https://www.whatismyip.com/")
  44. if err != nil {
  45. fmt.Printf("%s", err)
  46. os.Exit(1)
  47. } else {
  48. defer response.Body.Close()
  49. contents, err := ioutil.ReadAll(response.Body)
  50. if err != nil {
  51. fmt.Printf("%s", err)
  52. os.Exit(1)
  53. }
  54. var contentsStr = string(contents)
  55. fmt.Printf("%s\n", contentsStr)
  56. var doc = DocByHtmlString(contentsStr)
  57. doc.Find("div").Each(func(i int, s *goquery.Selection) {
  58. attr, exists := s.Attr("class")
  59. if exists {
  60. if attr == "ip" {
  61. fmt.Println(s.Text())
  62. }
  63. }
  64. })
  65. }
  66. }
  67. func DocByHtmlString(html string) *goquery.Document {
  68. doc, err := goquery.NewDocumentFromReader(bytes.NewBufferString(html))
  69. if err != nil {
  70. panic(err)
  71. }
  72. return doc
  73. }

最后打印出Your IP Address Is: 111.222.333.213,与预期一致。

英文:

Thank you @JimB. Working solution:

  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/PuerkitoBio/goquery"
  6. "io/ioutil"
  7. "log"
  8. "net"
  9. "net/http"
  10. "os"
  11. "time"
  12. )
  13. func main() {
  14. ief, err := net.InterfaceByName("eth0")
  15. if err != nil {
  16. log.Fatal(err)
  17. }
  18. addrs, err := ief.Addrs()
  19. if err != nil {
  20. log.Fatal(err)
  21. }
  22. tcpAddr := &net.TCPAddr{
  23. IP: addrs[3].(*net.IPNet).IP, // Choosing ip address number 3
  24. }
  25. d := net.Dialer{LocalAddr: tcpAddr}
  26. conn, err2 := d.Dial("tcp", "www.whatismyip.com:80")
  27. if err2 != nil {
  28. log.Fatal(err2)
  29. }
  30. fmt.Println(`conn.LocalAddr()`)
  31. fmt.Println(conn.LocalAddr())
  32. fmt.Println(`conn.RemoteAddr()`)
  33. fmt.Println(conn.RemoteAddr())
  34. defer conn.Close()
  35. transport := &http.Transport{
  36. Proxy: http.ProxyFromEnvironment,
  37. Dial: (&net.Dialer{LocalAddr: tcpAddr}).Dial,
  38. TLSHandshakeTimeout: 10 * time.Second,
  39. }
  40. client := &http.Client{
  41. Transport: transport,
  42. }
  43. response, err := client.Get("https://www.whatismyip.com/")
  44. if err != nil {
  45. fmt.Printf("%s", err)
  46. os.Exit(1)
  47. } else {
  48. defer response.Body.Close()
  49. contents, err := ioutil.ReadAll(response.Body)
  50. if err != nil {
  51. fmt.Printf("%s", err)
  52. os.Exit(1)
  53. }
  54. var contentsStr = string(contents)
  55. fmt.Printf("%s\n", contentsStr)
  56. var doc = DocByHtmlString(contentsStr)
  57. doc.Find("div").Each(func(i int, s *goquery.Selection) {
  58. attr, exists := s.Attr("class")
  59. if exists {
  60. if attr == "ip" {
  61. fmt.Println(s.Text())
  62. }
  63. }
  64. })
  65. }
  66. }
  67. func DocByHtmlString(html string) *goquery.Document {
  68. doc, err := goquery.NewDocumentFromReader(bytes.NewBufferString(html))
  69. if err != nil {
  70. panic(err)
  71. }
  72. return doc
  73. }

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

huangapple
  • 本文由 发表于 2015年9月11日 16:04:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/32518539.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定