Skip to content

crypto/tls: After the ech key verification fails, the new key sent by the ech server will not be used for handshake. #70073

Closed as not planned
@xdown-dev

Description

@xdown-dev

Go version

go1.23.2 linux/amd64

Output of go env in your module/workspace:

GO111MODULE='off'
GOARCH='amd64'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/gopkg/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/gopkg'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.23.2'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/root/.config/go/telemetry'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD=''
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2771492357=/tmp/go-build -gno-record-gcc-switches'

What did you do?

package main

import (
	"crypto/tls"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

func main() {
	clientConfig := &tls.Config{}
	clientConfig.MinVersion = tls.VersionTLS13

	echValue := "AEX+DQBBBQAgACBlLBm5Ur9BQXNm0X50TDLFPd1YWz8s0Gx35z8T2ukeewAEAAEAAQASY2xvdWRmbGFyZS1lY2guY29tAAA="

	echBytes, err := base64.StdEncoding.DecodeString(echValue)
	if err != nil {
		log.Fatalf("解码Ech失败: %v", err)
	}
	clientConfig.EncryptedClientHelloConfigList = echBytes

	// 配置HTTP客户端
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: clientConfig,
		},
	}

	// cloudflare-ech.com
	// 发起HTTPS请求
	resp, err := client.Get("https://ok-ssl.xyz/cdn-cgi/trace")
	if err != nil {
		log.Fatalf("请求失败: %v", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("读取响应失败: %v", err)
	}

	fmt.Printf("响应内容: %s\n", body)
}

What did you see happen?

2024/10/28 10:05:19 请求失败: Get "https://ok-ssl.xyz/cdn-cgi/trace": tls: server rejected ECH

What did you expect to see?

ECH 的工作原理
ECH 同样采用 DoH (后文会进行详细介绍,此处可暂时理解成 DNS 安全层的一种实现)进行密钥的分发,但是在分发过程上进行了改进。如果解密失败,ESNI 服务器会中止连接,**而 ECH 服务器会提供给客户端一个公钥供客户端重试连接,**以期可以完成握手。

ECH 协议实际上涉及两个 ClientHello 消息:ClientHelloOuter,它像往常一样以明文形式发送;ClientHelloInner,它被加密并作为 [ Client](https://hijiangtao.github.io/2022/10/09/Secure-Your-Browsing-Experience-with-More-Encrypted-Tools/#)HelloOuter 的扩展发送。服务器仅使用其中一个 ClientHello 完成握手:如果解密成功,则继续使用 ClientHelloInner;否则,它只使用 ClientHelloOuter。

If I use an expired key for handshake, an error will be returned. This should not be the case. The key is obtained through DNS, but DNS may have cache errors. At this time, the new key returned by ECH should be used to re-handshake. I don't know if this understanding is correct?

Metadata

Metadata

Assignees

No one assigned

    Labels

    WaitingForInfoIssue is not actionable because of missing required information, which needs to be provided.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions