Open mbinns opened 1 year ago
Hi @mbinns, to enable ECH in our test client, you need to
config.ECHEnabled = true
(you've alredy got this part)config.ClientECHConfigs
to the []ECHConfig
advertised by the DNS server.Looks like you've already done the hard part of fetching the ECH configs. To parse them:
echConfigListBase64 := "AEb+DQBClAAgACCA88XUXJSY8yxlp6HWzE6uW3fyWQRcLW1e8o48eVAIfQAEAAEAAQATY2xvdWRmbGFyZS1lc25pLmNvbQAA"
echConfigListBtyes, err := base64.StdEncoding.DecodeString(echConfigListBase64)
if err != nil {
panic(err)
}
echConfigList, err := tls.UnmarshalECHConfigs(echConfigListBtyes)
if err != nil {
panic(err)
}
Also, just FYI that we rotate our ECH config fairly frequently ... you should only expect a given config to be accepted for a couple of hours.
As an example of what I have so far in a toy example. I am fairly certain this is a successful GREASE request?
Yes, seting ECHEnabled
without providing ECH configs will result in a GREASE handshake.
Yup I have supporting code to grab the ECH config on an hourly basis since you guys mentioned you rotate frequently in one of your blog posts. I think you mentioned you guys leave some wiggle room in there because DNS cache issues on client systems/networks?
looks like I was able to successfully hit crypto.cloudflare.com/cdn-cgi/trace
I received this:
fl=541f47
h=crypto.cloudflare.com
ip=<removed>
ts=1673402819.281
visit_scheme=https
uag=Mozilla/5.0
colo=SEA
sliver=none
http=http/1.1
loc=US
tls=TLSv1.3
sni=encrypted
warp=off
gateway=off
kex=X25519
The SNI shows encrypted and the connection in wireshark looks good, so looks like things worked out great there!
Probably an obvious question, but how do I go about specifying the values like SNI inside the InnerHello. from reading the source it looks like the inner hello is derived from the outer hello. and there doesn't seem to be a way to modify the values separately?
My ignorant attempt would be to just change the tls.ServerName
and the req.Host
values to what I want the inner to represent.
When ECH is enabled, config.ServerName
is used as the inner SNI. The outer SNI is specified by the ECHConfig
.
I think you mentioned you guys leave some wiggle room in there because DNS cache issues on client systems/networks?
Yeah, there is wiggle room to allow for the DNS server and TLS server to get out of sync (very unlikely, at least in our deployment) or the TLS client and TLS server to get out of sync.
It looks like I have things working on my end.
Some other questions, if you have time (if not feel free to close)
tls: ech: rejected
According to this comment it looks like that functionality isn't supported/implemented?
// BUG(cjpatton): Upon ECH rejection, if retry configurations are provided, then // the client is expected to retry the connection. Otherwise, it may regard ECH // as being securely disabled by the client-facing server. The client in this // package does not attempt to retry the handshake.
If the server at crypto.cloudflare.com
supports a HelloRR I would be willing to put some time into trying to make the client side work if you guys are interested in an outside PR.
Also I wanted to say thanks for helping me out with all the questions!
I am trying to create an ECH connection as a client and I was hoping to use this fork in a proof of concept example.
Looking through the source it looks like if I specify
ECHEnabled: true
in my TLS config without specifying anECHConfig
it will fail over to GREASE. I am missing on what value/how to create my own ECHConfig struct to pass that in so that I can get a legitimate ECH connectionPerforming a
dig -t TYPE65 crypto.cloudflare.com
request provides me the following and I am assumingech=<value>
is the config I need?I see you guys have an
ECHConfig
struct intls/ech_config.go
and clearly the tls config options take an array for that is there a marshaling function that I should be using with the raw value that comes back from the DNS lookup?Also how then would I go about modifying the ClientHelloInner to point to the remote resource I am trying to access.
Sorry for the potentially naive questions, I've been reading over the source and trying to piece things together but I figured I might have better luck asking.
As an example of what I have so far in a toy example. I am fairly certain this is a successful GREASE request?
Thanks again for your time and work on this!