在等待*tls.certificateStatusMsg时收到类型为*tls.serverKeyExchangeMsg的意外握手消息

gre*_*key 2 ssl https go tls1.2

我需要检查一些网站的更新,我的脚本适用于我尝试的所有网站,除了一个.

我很确定它与TLS/SSL有关,但我没有找到任何关于错误的有用信息.

这是脚本:

package main

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

func main(){

    client := &http.Client{
        Transport: &http.Transport{
            DisableKeepAlives:   false,
            MaxIdleConnsPerHost: 10,
            TLSClientConfig: &tls.Config{
                InsecureSkipVerify: true,
            },
        },
    }

    fmt.Println(client)

    req, _ := http.NewRequest("GET", os.Args[1], nil)

    _, err := client.Do(req)
    if err != nil {
        fmt.Println("Something bad happened: ", err)
    }

}
Run Code Online (Sandbox Code Playgroud)

这是输出:

[root@74dfbb491710 wd]# go run ssl.go https://google.com
&{0xc4200ce000 <nil> <nil> 0s}
[root@74dfbb491710 wd]# go run ssl.go https://jobs-eu.hudson.com
&{0xc4200e4000 <nil> <nil> 0s}
Something bad happened:  Get https://jobs-eu.hudson.com: tls: received unexpected handshake message of type *tls.serverKeyExchangeMsg when waiting for *tls.certificateStatusMsg
Run Code Online (Sandbox Code Playgroud)

我是否需要添加一些代码来处理握手?为什么网站向我发送了意外消息?

Mar*_*arc 5

这是Go的TLS握手处理中的一个错误.在1.4附近发送了一个补丁:https://github.com/golang/go/issues/8549.但是,从1.9.2开始,它尚未应用.

补丁本身清楚地表明Go的实现是一个错误:

// RFC4366 on Certificate Status Request:       
// The server MAY return a "certificate_status" message.
Run Code Online (Sandbox Code Playgroud)

go TLS客户端基本上实现了"服务器必须返回...".

我们可以用一个较小的例子重现问题:

package main

import (
    "fmt"
    "net/http"
    "os"
)

func main() {
    _, err := http.Get(os.Args[1])
    fmt.Println(err)
}
Run Code Online (Sandbox Code Playgroud)

并运行:

$ go run foo.go https://jobs-eu.hudson.com
Get https://jobs-eu.hudson.com: tls: received unexpected handshake message of type *tls.serverKeyExchangeMsg when waiting for *tls.certificateStatusMsg
Run Code Online (Sandbox Code Playgroud)

将上述补丁应用于go 1.9.2源代码并立即重建会产生正确的功能:

~/tmp$ GOROOT=${HOME}/tmp/go go/bin/go run foo.go https://jobs-eu.hudson.com
<nil>
Run Code Online (Sandbox Code Playgroud)

要修补Go,我执行了以下操作:(但您可能希望按照指令进行安装,它们更彻底)

  • 下载go 1.9.2源码tarball
  • 提取它 ~/tmp/go
  • 应用补丁: ~/tmp/go$ patch -p1 < /tmp/OptionalCertificateStatus.patch
  • 重建: ~/tmp/go$ GOROOT_BOOTSTRAP=<my previous go install> ./all.bash
  • 如上所述运行

我已经解决了补丁问题,我很想知道为什么这个补丁没有被选中.

更新:补丁现已合并.1.11可能是最早发布的版本(我猜的是基于1.10已经处于测试阶段的事实).