Closed as not planned
Description
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?