为了账号安全,请及时绑定邮箱和手机立即绑定

golang 强制 net/http 客户端使用 IPv4 / IPv6

golang 强制 net/http 客户端使用 IPv4 / IPv6

Go
DIEA 2023-05-04 16:58:39
我正在使用 go1.11 net/http 并希望检测域是否仅支持 ipv6。你做了什么?我创建了自己的 DialContext,因为我想检测域是否仅支持 ipv6。下面的代码package mainimport (    "errors"    "fmt"    "net"    "net/http"    "syscall"    "time")func ModifiedTransport() {    var MyTransport = &http.Transport{        DialContext: (&net.Dialer{            Timeout:   30 * time.Second,            KeepAlive: 30 * time.Second,            DualStack: false,            Control: func(network, address string, c syscall.RawConn) error {                if network == "ipv4" {                    // I want to  cancel connection here client.Get("http://myexample.com") return a non-nil err.                    return errors.New("you should not use ipv4")                }                return nil            },        }).DialContext,        MaxIdleConns:          100,        IdleConnTimeout:       90 * time.Second,        TLSHandshakeTimeout:   10 * time.Second,        ExpectContinueTimeout: 1 * time.Second,    }    var myClient = http.Client{Transport: MyTransport}    resp, myerr := myClient.Get("http://www.github.com")    if myerr != nil {        fmt.Println("request error")        return     }    var buffer = make([]byte, 1000)    resp.Body.Read(buffer)    fmt.Println(string(buffer))}func main(){    ModifiedTransport();}我现在不知道如何关闭请求,即使我可以进入network == "ipv4".添加Python 可以通过Force requests to use IPv4 / IPv6 来解决这个问题。我不知道如何在 golang 中做到这一点。有人可以帮助我吗?非常感谢!
查看完整描述

4 回答

?
RISEBY

TA贡献1856条经验 获得超5个赞

传递networkControl函数的是tcp4IPv4 连接或tcp6IPv6 连接(如果您正在建立传出 TCP 连接)。

        // Network and address parameters passed to Control method are not

        // necessarily the ones passed to Dial. For example, passing "tcp" to Dial

        // will cause the Control function to be called with "tcp4" or "tcp6".

(在非 TCP 连接的情况下,其他字符串也是可能的。)

已知网络是“tcp”、“tcp4”(仅限 IPv4)、“tcp6”(仅限 IPv6)、“udp”、“udp4”(仅限 IPv4)、“udp6”(仅限 IPv6)、“ip” 、“ip4”(仅限 IPv4)、“ip6”(仅限 IPv6)、“unix”、“unixgram”和“unixpacket”。


查看完整回答
反对 回复 2023-05-04
?
弑天下

TA贡献1818条经验 获得超8个赞

哦。我自己解决了这个问题。


我们无法配置强制 ipv6 连接,因为它是硬编码的


...

if cm.scheme() == "https" && t.DialTLS != nil {

        var err error

        pconn.conn, err = t.DialTLS("tcp", cm.addr())

        if err != nil {

            return nil, wrapErr(err)

        }

...

我为 transport.go 添加了一个 ipv6only 标志,一个 getTcpString() 并且它有效。


查看完整回答
反对 回复 2023-05-04
?
30秒到达战场

TA贡献1828条经验 获得超6个赞

这适用于 go1.17.1:


var (

    zeroDialer net.Dialer

    httpClient = &http.Client{

        Timeout: 10 * time.Second,

    }

)


func init() {

    transport := http.DefaultTransport.(*http.Transport).Clone()

    transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {

        return zeroDialer.DialContext(ctx, "tcp4", addr)

    }

    httpClient.Transport = transport

}


查看完整回答
反对 回复 2023-05-04
?
慕雪6442864

TA贡献1812条经验 获得超5个赞

我认为即使服务器正在侦听“tcp6”,使用“tcp”运行 net.Dial 的客户端也应该可以正常工作——在双栈设置中。


当我遇到这个问题时,罪魁祸首是 /etc/hosts。它有一个主机条目,映射到 ipv4 地址而不是 ipv6 地址。这导致连接被拒绝。


我的测试示例如下:


客户端代码:


package main


import "net"

import "fmt"


func main() {

    conn, err := net.Dial("tcp", "hostname:9876")

    if err != nil {

        fmt.Println("Error in net.Dial", err)

        return

    }


    conn.Close()

    fmt.Println("Successful")

}

服务器代码:


package main


import "net"

import "fmt"


func main() {

    lis, err := net.Listen("tcp6", ":9876")

    if err != nil {

        fmt.Println("Error in listen", err)

        return

    }


    for {

        _, err := lis.Accept()

        if err != nil {

            fmt.Println("Error in Accept", err)

            return

        }

    }

}

这段代码应该可以在双堆栈设置上与干净的 /etc/hosts 文件一起正常工作。


谢谢。


查看完整回答
反对 回复 2023-05-04
  • 4 回答
  • 0 关注
  • 620 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信