登录
首页 >  Golang >  Go问答

使用OpenVPN设置Golang HTTP客户端的网络接口

来源:stackoverflow

时间:2024-03-02 13:27:26 122浏览 收藏

Golang不知道大家是否熟悉?今天我将给大家介绍《使用OpenVPN设置Golang HTTP客户端的网络接口》,这篇文章主要会讲到等等知识点,如果你在看完本篇文章后,有更好的建议或者发现哪里有问题,希望大家都能积极评论指出,谢谢!希望我们能一起加油进步!

问题内容

我必须通过 vpn 发出 http 请求。有使用 curl 的 php 代码来满足我的需要,不需要额外的:

curl_setopt($cu, curlopt_interface, "tun0");

来自 ifconfig 的此接口:

tun0: flags=4305  mtu 1500
        inet 10.13.13.2  netmask 255.255.255.255  destination 10.13.13.1
        inet6 fe80::80ee:132:d102:a52d  prefixlen 64  scopeid 0x20
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (unspec)

我的go代码(据我了解,我应该绑定到tun0的ip):

package main

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

func main() {
    httptransport := &http.transport{}
    ief, err := net.interfacebyname("tun0")
    if err != nil {
        log.fatal(err)
    }
    addrs, err := ief.addrs()
    if err != nil {
        log.fatal(err)
    }
    tcpaddr := &net.tcpaddr{ip: addrs[0].(*net.ipnet).ip}
    println(tcpaddr.string())
    httptransport.dial = (&net.dialer{
        timeout:   20 * time.second,
        localaddr: tcpaddr,
    }).dial

    c := &http.client{
        transport: httptransport,
        timeout:   30 * time.second,
    }

    req, err := http.newrequest(
        http.methodget,
        "http://example.com/",
        nil,
    )
    if err != nil {
        log.fatal(err)
    }

    resp, err := c.do(req)
    if err != nil {
        log.fatal(err)
    }
    bytes, err := ioutil.readall(resp.body)
    if err != nil {
        log.fatal(err)
    }
    println(string(bytes))
}

所以我得到的是:

10.13.13.2:0
2019/03/21 15:29:42 get http://example.com/: dial tcp 10.13.13.2:0->93.184.216.34:80: i/o timeout
exit status 1

带有 curl 的 php 代码可以快速获取此页面。我用 go 代码尝试了很多次,所以超时无济于事。有什么想法如何替换 go 中的 php 字符串吗?

更新

php 代码通过 tun0 获取同一页面及其输出:



输出:




    Example Domain

    
    
    
        



Example Domain

This domain is established to be used for illustrative examples in documents. You may use this domain in examples without prior coordination or asking for permission.

More information...


解决方案


我有一个工作示例:

package main

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

func main() {
    ifname := "tun0"
    iface, err := net.interfacebyname(ifname)
    if err != nil {
        panic(fmt.sprintf("could not get interface: %s", err))
    }

    addrs, err := iface.addrs()
    if err != nil {
        panic(fmt.sprintf("could not get addresses from interface: %s", err))
    }

    fmt.printf("%+v\n", addrs)

    c := &http.client{
        transport: &http.transport{
            dial: (&net.dialer{
                localaddr: &net.tcpaddr{
                    ip: addrs[0].(*net.ipnet).ip,
                    //ip: net.parseip("192.168.0.2"),
                    //ip: net.parseip("127.0.0.1"),
                },
            }).dial,
        },
    }

    r, err := c.get("http://localhost/ip")
    if err != nil {
        panic(fmt.sprintf("couldn't get http:%s", err))
    }
    b, err := ioutil.readall(r.body)
    if err != nil {
        panic(fmt.sprintf("could not read body:%s", err))
    }
    fmt.printf("%s", b)
}

您可以在 localaddr 注释中看到我的环境中测试的不同地址。

我使用本地运行httpbin,我可以看到这个:

$ go run main.go
[myipv6 myipv4]
{"origin":"192.168.0.2"}

这里,第二行输出是服务器的响应。 如果我稍微更改一下代码以强制使用 127.0.0.1 (如注释所示),我会得到以下结果:

$ go run main.go
[myipv6 myipv4]
{"origin":"127.0.0.1"}

这意味着,服务器确实看到了不同的源地址。

我认为,您的代码可以工作,但正如您在输出中看到的那样,您有 i/o 超时。 造成这种情况的原因可能是因为您的 vpn 连接不允许连接到您的目的地。该程序似乎做了您要求的正确连接,消息 dial tcp 10.13.13.2:0->93.184.216.34:80 根据您的 ifconfig 输出,这是正确的。

此外,如果我特别连接到一个封闭的端口,我会得到以下信息:

panic: couldn't get http:Get http://localhost:81/ip: dial tcp 192.168.0.2:0->127.0.0.1:81: connect: connection refused

这表明您的地址是正确的。

今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>