Releases: quic-go/quic-go
v0.37.2
This patch release
- contains a backport of the fix that triggered the Go 1.20.7 / 1.19.12 patch release (golang/go@2350afd): #4012
- sets a
net.Conn
with the correct addresses on thetls.ClientHelloInfo
used intls.Config.GetCertificate
: #4015
Note that in order to be protected against the DoS attack making use of large RSA keys, it's necessary to update to this patch release (for Go 1.20). For Go 1.21, please update the Go compiler.
Full Changelog: v0.37.1...v0.37.2
v0.36.3
This patch release contains a backport of the fix that triggered the Go 1.20.7 / 1.19.12 patch release (golang/go@2350afd).
Full Changelog: v0.36.2...v0.36.3
v0.37.1
This is a patch release fixing two regressions introduced in the v0.37.0 release:
- http3: fix check for content length of the response by @imroc in #3998
- set a net.Conn with the correct addresses on the tls.ClientHelloInfo by @marten-seemann in #4001
New Contributors
Full Changelog: v0.37.0...v0.37.1
v0.37.0
crypto/tls changes
With the upcoming Go 1.21 release, we're now able to rely on the Go standard library's TLS implementation's QUIC support.
If you're curious, here are the discussions that happened in the Go project's GitHub:
- QUIC support for crypto/tls (without 0-RTT): golang/go#44886
- QUIC 0-RTT support for crypto/tls: golang/go#60107
- Advanced session ticket API (needed for 0-RTT): golang/go#60105
Special thanks to @FiloSottile and @neild for the constructive discussions around the new API, and for making this happen!
Using this new API required major changes to the way quic-go interacts with the TLS stack (#3860 and #3939), but ultimately, the new API is a lot cleaner than what we had before.
This means that starting with Go 1.21, we won't have to fork crypto/tls anymore, resolving a longstanding issue (#2727). This also resolves a major pain point for the community, since quic-go now doesn't have to enforce a specific compiler version any longer.
Note that this release still supports Go 1.20 (in line with our policy to always support the two most recent Go versions), which still uses (a completely rewritten) fork of crypto/tls. We're looking forward to dropping support for Go 1.20 once Go 1.22 is released next year.
Other Notable Changes
- We dropped support for the QUIC draft-29. This draft version was somewhat widely deployed on the internet before RFC 9000 was finalized, but has been phased out since then. quic-go now supports QUIC version 1 (RFC 9000) and version 2 (RFC 9369).
Connection.ReceiveMessage
now takes acontext.Context
, allowing the caller to make the call return, even if no message is received: #3926. Thanks to @Glonee for the implementation!- A long list of added validations (as required by RFC 9114 and RFC 9110) for request and response parsing in the http3 package, mostly around the processing of headers. Thanks to @Mephue for finding one of the missing checks, and to @WeidiDeng for finding and fixing multiple of them!
- quic-go now sets the DF bit on packets sent on macOS (as we've done for a long time on Linux already). This allows us to do DPLPMTUD (Path MTU discovery): #3946. Thanks to @sukunrt for implementing!
- The stream and the connection errors are now surfaced via the contexts exposed by
Stream.Context
andConnection.Context
, and can be accessed by callingcontext.Cause
(#3961 and #3970). Thanks to @fholzer for suggesting and implementing this change! OptimizeConn
was removed in favor of a newWriteTo
method on theTransport
, which allows sending of (non-QUIC) packets on thenet.PacketConn
passed to theTransport
(#3957). Thanks to @MarcoPolo for helpful feedback on the API!
Changelog
- drop support for draft-29 by @marten-seemann in #3903
- use unix.IPV6_RECVPKTINFO and unix.IPV6_PKTINFO on all platforms by @marten-seemann in #3918
- simplify syscall consts used for requesting / parsing IPv4 packet info by @marten-seemann in #3919
- use the UDP_SEGMENT constant defined in the unix package (for GSO) by @marten-seemann in #3917
- Log stream frames in long header packets by @birneee in #3922
- add a context to Connection.ReceiveMessage by @Glonee in #3926
- transport: don't add connection to multiplexer if init fails by @kelmenhorst in #3931
- update link to the wiki page about UDP buffer sizes by @marten-seemann in #3924
- disable GSO unless QUIC_GO_ENABLE_GSO is set by @marten-seemann in #3934
- use the new crypto/tls QUIC Transport, drop support for Go 1.19 by @marten-seemann in #3860
- stop using math/rand.Seed and Read in tests, bump go.mod version to 1.20 by @marten-seemann in #3936
- assert the length of IPv4 packet info control messages, add log message by @marten-seemann in #3920
- move oss-fuzz build script to this repo by @marten-seemann in #3940
- oss-fuzz: manually install Go, fix paths by @marten-seemann in #3941
- http3: validate Host header before sending by @marten-seemann in #3948
- http3: don't write response headers if the handler panicked by @WeidiDeng in #3950
- http3: add Date response header if not set by @WeidiDeng in #3952
- perform send / receive buffer increases when setting up the connection by @marten-seemann in #3949
- http3: implement FlushError for the response writer by @WeidiDeng in #3951
- http3: return http.ErrContentLength when writing too large response by @WeidiDeng in #3953
- http3: don't send more than http.Request.ContentLength bytes by @marten-seemann in #3960
- http3: set the Content-Length header in the http.Request.Header map by @marten-seemann in #3963
- http3: reject header field that contain non-lowercase characters by @marten-seemann in #3964
- http3: reject header field names with invalid characters by @marten-seemann in #3965
- http3: reject header field values with invalid characters by @marten-seemann in #3967
- http3: reject negative values for the Content-Length header by @marten-seemann in #3966
- connection: surface connection error as connection context cancellation cause by @fholzer in #3961
- http3: enforce ordering requirement between pseudo and regular headers by @marten-seemann in #3968
- http3: refactor header field processing into a separate function by @marten-seemann in #3971
- http3: unify handling of request and response headers by @marten-seemann in #3969
- http3: deduplicate Content-Length headers by @marten-seemann in #3972
- http3: reject responses that don't set the :status header by @marten-seemann in #3975
- http3: reject unknown pseudo headers by @marten-seemann in #3973
- send stream: surface error as stream context cancellation cause by @fholzer in #3970
- remove OptimizeConn, add a Transport.WriteTo method instead by @marten-seemann in #3957
- http3: use correct error code when request header parsing fails by @marten-seemann in #3979
- enable the DF bit on macOS by @sukunrt in #3946
- http3: enforce that DATA frames don't exceed Content-Length by @marten-seemann in #3980
- http3: discard negative content-length header when writing response by @WeidiDeng in #3983
- check for WSAEMSGSIZE errors when receiving UDP packets on Windows by @marten-seemann in #3982
- http3: panic in ResponseWriter.WriteHeader for invalid status codes by @WeidiDeng in #3984
- use a synchronous API for the crypto setup by @marten-seemann in #3939
New Contributors
- @WeidiDeng made their first contribution in #3950
- @fholzer made their first contribution in #3961
Full Changelog: v0.36.0...v0.37.0
v0.36.2
This patch release contains (the backport of) 2 fixes:
- http3: validate Host header before sending (#3948)
- perform send / receive buffer increases when setting up the connection (#3949)
Full Changelog: v0.36.1...v0.36.2
v0.36.1
This patch release disables GSO support (#3934), unless explicitly enabled using an environment variable (QUIC_GO_ENABLE_GSO=true
). We discovered that GSO fails with some NICs and in some containerized environments. See #3911 for a detailed discussion.
From the user's perspective, GSO should "just work". Once we have a fix that correctly detects GSO support under all circumstances we'll re-enable GSO by default.
v0.36.0
Generic Segmentation Offload (GSO)
This release enables GSO (Generic Segmentation Offload) in the send path, drastically increasing the packet send rate. Without GSO, quic-go had to use a single (sendmsg) syscall for every UDP datagram sent. GSO allows us to pass one giant (up to 64k) datagram to the sendmsg syscall, and have the kernel chop it into MTU sized (~1300 bytes) datagrams before sending them out on the wire. For more details on syscall optimizations, CloudFlare published an excellent blog post about this a while ago. GSO is currently only available on Linux (and with kernels >4.18).
Users who are using the same net.PacketConn
for QUIC and to send out non-QUIC packets now need to call the newly introduced OptimizeConn
function before passing the connection to the Transport
. Otherwise, calls to WriteTo
will fail after GSO support was enabled. Users who are not using the same net.PacketConn
in this way don't need to change anything.
We also continued our effort to further reduce allocations during data transfers (#3526). Work on improving performance even further will continue in future releases.
Other Notable Changes
- http3: The server now returns http.ErrServerClosed instead of quic.ErrServerClosed (#3900)
- quic-go now correctly deals with super-short idle timeouts (#3909)
- uint62 overflows are now correctly handled in the Config (#3866)
- only run DPLPMTUD (RFC 8899) on connections that support setting the DF bit (#3879)
- switch to the packet number length derivation logic described in the RFC (#3885)
- fix panics when closing an uninitialized Transport (#3908)
Full Changelog
- use a ring buffer in the framer by @Glonee in #3857
- update Ginkgo to v2.9.5 and Gomega to v1.27.6 by @marten-seemann in #3845
- fix flaky client test by @marten-seemann in #3834
- ackhandler: simplify sentPacketHandler.SentPacket by @marten-seemann in #3847
- readme: restructure RFC section, add QUIC v2 (RFC 9369) by @marten-seemann in #3871
- remove stray print statement in datagram test by @marten-seemann in #3828
- ci: fix ordering of error output of the cross compilation workflow by @marten-seemann in #3809
- githooks: exclude deleted files from checks by @marten-seemann in #3864
- receive stream: put back the buffer for the last STREAM frame by @marten-seemann in #3832
- config: handle overflows of stream and flow control limits by @marten-seemann in #3866
- improve documentation of the Transport and the dial and listen functions by @marten-seemann in #3875
- don't use closures for passing OnLost and OnAcked STREAM frame callbacks by @marten-seemann in #3833
- use ackhandler.Frame directly, not as a pointer, remove its sync.Pool by @marten-seemann in #3835
- only run DPLPMTUD if the connection can send packets with the DF bit set by @marten-seemann in #3879
- use a single ACK frame in the receive path by @marten-seemann in #3878
- use the same ACK frame struct in the send path, remove ACK frame pool by @marten-seemann in #3831
- use GSO by @marten-seemann in #3808
- ci: run linter on all supported platforms by @marten-seemann in #3816
- packer: reduce number of calls to time.Now() when packing packets by @marten-seemann in #3815
- pass around receivedPacket as struct instead of as pointer by @marten-seemann in #3823
- pass the current timestamp to the pacer instead of calling time.Now() by @marten-seemann in #3824
- embed packetInfo in receivedPacket struct, use netip.Addr by @marten-seemann in #3881
- ci: run integration tests for all QUIC versions, even if steps failed by @marten-seemann in #3882
- ackhandler: apply logic from RFC 9000 to derive packet number length by @marten-seemann in #3885
- ackhandler: use a slice to keep track of sent packets by @marten-seemann in #3841
- ackhandler: don't log / trace skipped packets when declaring them lost by @marten-seemann in #3887
- ackhandler: be explicit about skipping packet numbers by @marten-seemann in #3886
- ackhandler: use a frame handler interface for OnAcked / OnLost of all frame types by @marten-seemann in #3888
- ackhandler: unexport the packet struct by @marten-seemann in #3889
- frame fuzzer: handle frames one by one by @marten-seemann in #3884
- docs: improve doc comments for the ConnectionState fields by @marten-seemann in #3901
- Respect minimum idle timeout of 3 PTOs by @birneee in #3909
- wire: switch to crypto/rand for greased transport parameter generation by @marten-seemann in #3904
- docs: add detailed description of the quic package by @marten-seemann in #3902
- http3: return http.ErrServerClosed instead of quic.ErrServerClosed by @jfgiorgi in #3900
- check for uninitialized fields when closing the Transport by @kelmenhorst in #3908
- docs: improve documentation of OptimizeConn by @marten-seemann in #3910
New Contributors
- @kelmenhorst made their first contribution in #3908
Full Changelog: v0.35.1...v0.36.0
v0.35.1
This patch release fixes a regression in the HTTP/3 roundtripper introduced in the v0.35.0 release.
Thanks to @kgersen for reporting and to @Glonee for contributing the fixes!
What's Changed
- http3: set tls.Config.ServerName for outgoing requests, if unset by @Glonee in #3867
- http3: correctly use the quic.Transport by @Glonee in #3869
- http3: close the connection when closing the roundtripper by @Glonee in #3873
Full Changelog: v0.35.0...v0.35.1
v0.35.0
Modernizing the quic-go connection API
In this release, we've completely revamped our connection establishment API, following an engaging discussion with the quic-go community (#3727).
Key modifications are as follows:
- The context variants of the dial functions, including
DialContext
, have been removed. In their place,Dial
now incorporates a context. This development stems from our drive to modernize the API, given thatcontext.Context
wasn't in existence when quic-go was launched eight years ago. quic.Listener
andquic.EarlyListener
have transitioned from interfaces to structs.
- We've introduced a
quic.Transport
. More about that below.
Introducing the Transport
The QUIC protocols demultiplexes connections based on the QUIC Connection IDs. This has interesting implications, first and foremost that multiple QUIC connections can run on the same UDP socket (and even connect to the same remote QUIC server). Interestingly, it's feasible to run a QUIC server on the same socket as outgoing QUIC connections. In fact, that's a really useful thing to do when using QUIC for holepunching through NATs.
Previously, it was possible to utilize this feature, but the API lacked clarity. When the same net.PacketConn
was passed to sequential Listen
and Dial
calls, quic-go would identify this and multiplex several QUIC connections on that net.PacketConn
. This behavior was not obvious and, additionally, it demanded that certain values of the Config
matched.
We've now made multiplexing explicit with the Transport
introduction. A Transport
manages a single net.PacketConn
. The usage is as follows:
laddr, err := net.ResolveUDPAddr("udp4", "0.0.0.0:443")
// handle err
conn, err := net.ListenUDP("udp4", laddr)
// handle err
tr := quic.Transport{
Conn: conn,
StatelessResetKey: <a key that survives reboots>,
}
// start listening for incoming QUIC connection
ln, err := tr.Listen(<tls.Config>, &quic.Config{})
// handle err
go func() {
conn, err := ln.Accept(context.Background())
if err != nil {
return
}
// handle accepted QUIC connection...
}()
// establish QUIC connections to remote nodes, on the same UDP socket
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel
conn, err := tr.Dial(ctx, <remote addr>, <tls.Config>, <quic.Config>)
// handle err
// handle dialed QUIC connection
This modification enables us to shift several configuration options logically tied to the UDP sockets from the Config
. Specifically, ConnectionIDLength
/ ConnectionIDGenerator
and StatelessResetKey
are now configured on the Transport
.
Migration Guide
To update to the new version, applications might need to:
- Substitute calls to
DialContext
with calls toDial
. - Replace all instances of
Listener
with*Listener
(and similarly forEarlyListener
).
Other Notable Changes
- The HTTP/3 response writer is now compatible with the
http.ResponseController
introduced in the Go 1.20 release (#3790). Thanks @dunglas! - The
http3.RoundTripper
now implementsCloseIdleConnections
method, allowing the use ofhttp.Client.CloseIdleConnections
. Thanks @Glonee! - DoS resiliency was improved by only using a single Go routine to send stateless reset, version negotiation and INVALID_TOKEN error packets (#3842 and #3854). Thanks @sukunrt!
- We now use the
SO_RCVBUFFORCE
syscall to attempt to increase the UDP receive buffer. Increasing the receive buffer is absolutely crucial for QUIC performance, and quic-go will print a log message if increasing the buffer size fails. Unfortunately, due to small default buffer sizes in most Linux distributions, this happened quite frequently and required manual configuration(https://github.com/quic-go/quic-go/wiki/UDP-Receive-Buffer-Size). UsingSO_RCVBUFFORCE
call will only succeed when the process hasCAP_NET_ADMIN
permissions, but in these cases no manual configuration will be necessary any more. Thanks to @MarcoPolo!
Full Changelog
- http3: add compatibility with net/http.ResponseController by @dunglas in #3790
- ci: allow changing runners through config vars by @marten-seemann in #3783
- set the version for integration tests using a command line flag by @marten-seemann in #3782
- ci: speed up the cross compilation job by parallelizing by @marten-seemann in #3784
- put a context on a dial functions, remove Dial*Context, remove host parameter by @marten-seemann in #3785
- congestion: fix overflow when calculating the pacing budget by @marten-seemann in #3796
- move 0-RTT queue handling from the packet handler map to the server by @marten-seemann in #3788
- make Listener and EarlyListener a struct by @marten-seemann in #3789
- docs: add Mercure in the list of projects using quic-go by @dunglas in #3791
- introduce a Transport by @marten-seemann in #3794
- docs: fix typo in documentation for EarlyConnection by @Zxilly in #3798
- transport: fix flaky stateless reset test by @marten-seemann in #3810
- use SO_RCVBUFFORCE to force receive buffer increase on Linux by @MarcoPolo in #3804
- increase the UDP send buffer size to 2 MB by @marten-seemann in #3812
- quicvarint: remove deprecated Write function by @marten-seemann in #3781
- change how the multiplex test is skipped on Linux by @marten-seemann in #3817
- fix flaky timeout integration test by @marten-seemann in #3818
- fix HTTP/3 connection test on draft-29 by @marten-seemann in #3819
- implement http3.RoundTripper.CloseIdleConnections by @Glonee in #3820
- ci: fix coverage report by @Glonee in #3837
- ackhandler: optimize memory layout of ackhandler.Packet by @marten-seemann in #3844
- transport: send stateless reset packets from a single Go routine by @sukunrt in #3842
- fix comment claiming ParseConnectionID reuses the data slice by @sukunrt in #3848
- rttstats: don't set initial RTT after obtaining a measurement by @marten-seemann in #3852
- wire: save ECN counts on the ACK frame by @marten-seemann in #3829
- quicproxy: increase UDP send and receive buffer sizes by @marten-seemann in #3813
- packet packer: don't try packing a 0-RTT packet with only an ACK by @marten-seemann in #3849
- server: send version negotiation and invalid token packets from a single Go routine by @sukunrt in #3854
- wire: apply the default value for the active_connection_id_limit by @marten-seemann in #3806
New Contributors
Full Changelog: v0.34.0...v0.35.0
v0.34.0
Breaking Changes
Connection.HandshakeComplete
now returns a channels instead of acontext.Context
Other notable Changes
- The QUIC version in use is now attached to the context returned from
ClientHelloInfo.Context()
intls.Config.GetConfigForClient
(#3721) - The
http3.RoundTripper
now multiplexes all connections on a singleUDPConn
(#3720)
What's Changed
- http3: use a single UDPConn in RoundTripper by @Glonee in #3720
- qlog: use version_mismatch trigger on transport:connection_closed event by @marten-seemann in #3724
- attach the QUIC version to context returned by ClientHelloInfo.Context by @marten-seemann in #3721
- use a chan instead of a context in Connection.HandshakeComplete by @marten-seemann in #3709
- add benchmark integration tests to measure allocations by @marten-seemann in #3697
- qtls: don't set the tls.Config.CipherSuites for cipher suite tests by @marten-seemann in #3726
- update golang.org/x/net from 0.4.0 to 0.7.0 by @dependabot in #3734
- add a security policy by @marten-seemann in #3733
- ci: update golangci-lint to v1.52.2, update Go version by @marten-seemann in #3740
- interop: build and publish Docker images for linux/amd64 and linux/arm64 by @marten-seemann in #3748
- http3: make error codes public and consistent with http2 package by @jfgiorgi in #3744
- http3: check scheme before host to be consistent with net/http by @jfgiorgi in #3774
- wire: correctly parse multi-byte frame types by @marten-seemann in #3736
- ci: update golangci-lint config, increase timeout by @marten-seemann in #3771
- add missing tracing for dropped 0-RTT packets by @marten-seemann in #3762
- wire: speed up identification of 0-RTT packets by @marten-seemann in #3761
- offer only TLS 1.3 cipher suites in ClientHello by @marten-seemann in #3749
- wire: use constants for frame types by @marten-seemann in #3739
- add a handshake test for post-quantum-size ClientHellos by @marten-seemann in #3759
- ci: remove special casing for AppVeyor by @marten-seemann in #3753
- githooks: add check that go.mod in integrationtests/gomodvendor is tidy by @marten-seemann in #3750
- qlog: move the quic-go version to the configuration field by @marten-seemann in #3735
- protocol: remove VersionWhatever, previously used for testing by @marten-seemann in #3763
- wire: use a dedicated rand.Rand for greasing transport parameters by @marten-seemann in #3758
- avoid copying when detecting stateless resets by @marten-seemann in #3767
- interop: fix setting of cipher suite for the ChaCha20 test by @marten-seemann in #3747
- protocol: remove VersionTLS, used during the gQUIC -> TLS 1.3 transition by @marten-seemann in #3764
- qtls: fix cipher suite selection for ClientHellos by @marten-seemann in #3751
- initiate the first key update after sending / receiving 100 packets by @marten-seemann in #3745
- simplify mockgen usage for private interfaces by @marten-seemann in #3769
- use larger range to draw greased value for post-quantum test from by @marten-seemann in #3780
New Contributors
- @dependabot made their first contribution in #3734
- @jfgiorgi made their first contribution in #3744
Full Changelog: v0.33.0...v0.34.0