响应后验证证书

时间:2016-06-09 18:04:35

标签: go

我想连接到可能不安全的主机,因此我正在使用http.Client,如下所示:

client := &http.Client{
    Timeout: timeout,
    Transport: &http.Transport{
        TLSClientConfig: &tls.Config{
            InsecureSkipVerify: true,
        },
    },
}
resp, err := client.Get(url)

哪种方法运行良好,但事实上我似乎找不到检查SSL证书有效性的方法。我意识到我可以建立两个连接(一个连接InsecureSkipVerify,一个连接没有连接),但是我想在不进行其他连接的情况下这样做。

1 个答案:

答案 0 :(得分:3)

可行的。 =)

您应该在Transport上设置Dial和DialTLS字段并在那里进行检查。

希望代码是自我解释的,随意提问。

由于限制,在操场上不起作用!

https://play.golang.org/p/4TkczUEnKn

package main

import (
    "fmt"
    "net/http"
    "net"
    "time"
    "crypto/tls"
)

func DialTLS(network, addr string) (net.Conn, error) {
    conn, err := tls.Dial(network, addr, &tls.Config{
        InsecureSkipVerify: true,
    })

    cs := conn.ConnectionState()
    fmt.Println(cs.Version, cs.HandshakeComplete)
    // insert your check here!

    return conn, err
}

func Dial (network, addr string) (net.Conn, error) {    
    // Copied from DefaultTransport
    dialer := &net.Dialer{
                Timeout:   30 * time.Second,
                KeepAlive: 30 * time.Second,
        }
    conn, err := dialer.Dial(network, addr)

    fmt.Println("unsecure")

    return conn, err
}

func main() {
    client := &http.Client{
        Timeout: time.Second,
        Transport: &http.Transport{
            Dial: Dial,

        // If DialTLS is set, the Dial hook is not used for HTTPS
        // requests and the TLSClientConfig and TLSHandshakeTimeout
        // are ignored. The returned net.Conn is assumed to already be
        // past the TLS handshake.

        // TLSClientConfig: &tls.Config{
        //  InsecureSkipVerify: true,
        // },           
            DialTLS: DialTLS,
        },
    }

    // Deep in transport it checks "tlsDial := t.DialTLS != nil && cm.targetScheme == "https" && cm.proxyURL == nil"
    // https://golang.org/src/net/http/transport.go#L741
    resp, err := client.Get("https://www.google.com")
    fmt.Println(resp, err, "\n\n")

    resp , err = client.Get("http://www.google.com")
    fmt.Println(resp, err)
}

<强> UPD

UPD2 :以下代码不好主意=)。后备逻辑混淆了http.Client error = Get https://www.google.com: http: server gave HTTP response to HTTPS client或者我遗漏了一些东西,好吧,现在由你决定=)

甚至更好(取决于你的逻辑)。

func DialTLSWithFallback(network, addr string) (net.Conn, error) {
    conn, err := tls.Dial(network, addr, &tls.Config{
        InsecureSkipVerify: true,
    })

    if err != nil {
        // obviously, usecure
        // lets try net.Dial
        // and return, so check bellow wont trigger on wrong connection type
        return &(net.Dialer{
                Timeout:   30 * time.Second,
                KeepAlive: 30 * time.Second,
        }).Dial(network, addr)
    }

    cs := conn.ConnectionState()
    fmt.Println(cs.Version, cs.HandshakeComplete)
    // its "secure" connection
    // check is it strong enough here!

    return conn, err
}

然后你将收缩转移到

        Transport: &http.Transport{
            Dial: DialTLSWithFallback,          
            DialTLS: DialTLSWithFallback,
        }