Source file src/vendor/golang.org/x/net/quic/skip.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package quic
     6  
     7  // skipState is state for optimistic ACK defenses.
     8  //
     9  // An endpoint performs an optimistic ACK attack by sending acknowledgements for packets
    10  // which it has not received, potentially convincing the sender's congestion controller to
    11  // send at rates beyond what the network supports.
    12  //
    13  // We defend against this by periodically skipping packet numbers.
    14  // Receiving an ACK for an unsent packet number is a PROTOCOL_VIOLATION error.
    15  //
    16  // We only skip packet numbers in the Application Data number space.
    17  // The total data sent in the Initial/Handshake spaces should generally fit into
    18  // the initial congestion window.
    19  //
    20  // https://www.rfc-editor.org/rfc/rfc9000.html#section-21.4
    21  type skipState struct {
    22  	// skip is the next packet number (in the Application Data space) we should skip.
    23  	skip packetNumber
    24  
    25  	// maxSkip is the maximum number of packets to send before skipping another number.
    26  	// Increases over time.
    27  	maxSkip int64
    28  }
    29  
    30  func (ss *skipState) init(c *Conn) {
    31  	ss.maxSkip = 256 // skip our first packet number within this range
    32  	ss.updateNumberSkip(c)
    33  }
    34  
    35  // shouldSkip returns whether we should skip the given packet number.
    36  func (ss *skipState) shouldSkip(num packetNumber) bool {
    37  	return ss.skip == num
    38  }
    39  
    40  // updateNumberSkip schedules a packet to be skipped after skipping lastSkipped.
    41  func (ss *skipState) updateNumberSkip(c *Conn) {
    42  	// Send at least this many packets before skipping.
    43  	// Limits the impact of skipping a little,
    44  	// plus allows most tests to ignore skipping.
    45  	const minSkip = 64
    46  
    47  	skip := minSkip + c.prng.Int64N(ss.maxSkip-minSkip)
    48  	ss.skip += packetNumber(skip)
    49  
    50  	// Double the size of the skip each time until we reach 128k.
    51  	// The idea here is that an attacker needs to correctly ack ~N packets in order
    52  	// to send an optimistic ack for another ~N packets.
    53  	// Skipping packet numbers comes with a small cost (it causes the receiver to
    54  	// send an immediate ACK rather than the usual delayed ACK), so we increase the
    55  	// time between skips as a connection's lifetime grows.
    56  	//
    57  	// The 128k cap is arbitrary, chosen so that we skip a packet number
    58  	// about once a second when sending full-size datagrams at 1Gbps.
    59  	if ss.maxSkip < 128*1024 {
    60  		ss.maxSkip *= 2
    61  	}
    62  }
    63  

View as plain text