dnsproxy icon indicating copy to clipboard operation
dnsproxy copied to clipboard

Support 0-RTT for DoQ

Open msoxzw opened this issue 3 years ago • 1 comments

According to RFC 9250,

   Using 0-RTT for DoQ has many compelling advantages.  Clients can
   establish connections and send queries without incurring a connection
   delay.  Servers can thus negotiate low values of the connection
   timers, which reduces the total number of connections that they need
   to manage.  They can do that because the clients that use 0-RTT will
   not incur latency penalties if new connections are required for a
   query.

dnsproxy, unfortunately, has not yet supported 0-RTT for DoQ, but nevertheless its dependent QUIC implementation has already supported 0-RTT. https://github.com/AdguardTeam/dnsproxy/blob/7f5cafa118a59337a3d8d7dc2faade89f91b114d/upstream/upstream_quic.go#L225 The dnsproxy uses DialAddrContext instead of DialAddrEarlyContext.

Last but not least, AdGuard DoQ does not support 0-RTT, either.

msoxzw avatar May 31 '22 21:05 msoxzw

Besides DialAddrEarlyContext, ClientSessionCache and TokenStore should be also set up. Even in absence of 0-RTT support, the handshake time could be reduced from 2 RTT to 1 RTT.

msoxzw avatar Jul 11 '22 21:07 msoxzw

This was added in https://github.com/AdguardTeam/dnsproxy/pull/268

kosekmi avatar Sep 17 '22 09:09 kosekmi

Yep, should be closed, thank you!

ameshkov avatar Sep 19 '22 10:09 ameshkov

I wonder whether there is a public DoQ server to test this feature.

msoxzw avatar Sep 21 '22 20:09 msoxzw

quic://dns.adguard.com, but it may not work since the traffic in a single location may be load-balanced between multiple servers that do not share tokens cache.

Alternatively, try running two instances of dnsproxy, one as a DoQ server with a self-signed cert, the other one with --insecure option.

Also, I haven't extensively tested 0-RTT support, quic-go does not expose enough information about the handshake (or I haven't found it).

ameshkov avatar Sep 22 '22 07:09 ameshkov

The TLS early_data extension in the NewSessionTicket message is defined to convey (in the max_early_data_size parameter) the amount of TLS 0-RTT data the server is willing to accept. Therefore, unlike dns.google and cloudflare-dns.com, dns.adguard.com does not seem to support 0-RTT.

echo GET / | openssl s_client -connect dns.adguard.com:443
    Max Early Data: 0
echo GET / | openssl s_client -connect dns.google:443
    Max Early Data: 14336
echo GET / | openssl s_client -connect cloudflare-dns.com:443
    Max Early Data: 14336

As far as I know, logging of quic-go could be enabled by https://github.com/lucas-clemente/quic-go/wiki/Logging, thereby providing information surrounding handshake.

msoxzw avatar Sep 22 '22 20:09 msoxzw

Well, bad news is that crypto/tls does not support early data extension on the server-side: https://go.dev/src/crypto/tls/handshake_server_tls13.go

   143  	if hs.clientHello.earlyData {
   144  		// See RFC 8446, Section 4.2.10 for the complicated behavior required
   145  		// here. The scenario is that a different server at our address offered
   146  		// to accept early data in the past, which we can't handle. For now, all
   147  		// 0-RTT enabled session tickets need to expire before a Go server can
   148  		// replace a server or join a pool. That's the same requirement that
   149  		// applies to mixing or replacing with any TLS 1.2 server.
   150  		c.sendAlert(alertUnsupportedExtension)
   151  		return errors.New("tls: client sent unexpected early data")
   152  	}

Therefore neither dnsproxy nor AdGuard DNS support it (both written in golang).

ameshkov avatar Sep 25 '22 08:09 ameshkov

After reading the comment I am now not sure if I quoted the right part of the code. Will do a more extensive search when I am at the laptop, doing this from mobile is not too convenient:)

edit: reading further confirms that 0rtt is not supported :(

ameshkov avatar Sep 25 '22 08:09 ameshkov

So TLS 1.3 implemented by golang does not support early data, while the quic-go supports 0-RTT on both client side and server side, which is shown by https://interop.seemann.io/

msoxzw avatar Sep 25 '22 21:09 msoxzw

@msoxzw thanks for checking it!

In this case it's not correct to examine standard TLS here.

Let's reopen this until I fully verify that everything works as it should.

ameshkov avatar Sep 26 '22 11:09 ameshkov