diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 377e3c07dc..954fae7f40 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -193,7 +193,7 @@ strengths of QUIC include: * Stream and connection flow control -* Connection migration and resilience to NAT rebinding +* Client connection migration and resilience to NAT rebinding * Version negotiation @@ -233,7 +233,7 @@ retransmissions from those for original transmissions, avoiding TCP's retransmission ambiguity problem. QUIC acknowledgments also explicitly encode the delay between the receipt of a packet and its acknowledgment being sent, and together with the monotonically-increasing packet numbers, this allows for -precise network roundtrip-time (RTT) calculation. QUIC's ACK frames support +precise network round-trip time (RTT) calculation. QUIC's ACK frames support multiple ACK blocks, so QUIC is more resilient to reordering than TCP with SACK support, as well as able to keep more bytes on the wire when there is reordering or loss. @@ -273,12 +273,12 @@ unencrypted handshake packets is later verified as part of cryptographic processing. -## Connection Migration and Resilience to NAT Rebinding +## Client Connection Migration and Resilience to NAT Rebinding QUIC connections are identified by a Connection ID, a 64-bit unsigned number randomly generated by the server. QUIC's consistent connection ID allows connections to survive changes to the client's IP and port, such as those caused -by NAT rebindings or by the client changing network connectivity to a new +by NAT rebinding or by the client changing network connectivity to a new address. QUIC provides automatic cryptographic verification of a rebound client, since the client continues to use the same session key for encrypting and decrypting packets. The consistent connection ID can be used to allow migration @@ -716,6 +716,9 @@ use it for all subsequent Handshake ({{packet-handshake}}) and 1-RTT Server's Version Negotiation ({{packet-version}}) and Retry ({{packet-retry}}) packets MUST use connection ID selected by the client. +The connection ID could change over the lifetime of a connection, especially in +response to connection migration ({{migration}}). NEW_CONNECTION_ID frames +({{frame-new-connection-id}}) are used to provide new connection ID values. ## Packet Numbers {#packet-numbers} @@ -1475,29 +1478,286 @@ failure. If integrity protection is performed by QUIC, QUIC MUST abort the connection if the integrity check fails with a PROTOCOL_VIOLATION error code. -## Connection Migration {#migration} +## Path Validation {#migrate-validate} -QUIC connections are identified by their 64-bit Connection ID. QUIC's -consistent connection ID allows connections to survive changes to the client's -IP and/or port, such as those caused by client or server migrating to a new -network. Connection migration allows a client to retain any shared state with a -connection when they move networks. This includes state that can be hard to -recover such as outstanding requests, which might otherwise be lost with no easy -way to retry them. +Path validation is used by an endpoint to verify reachability of a peer over a +specific path. That is, it tests reachability between a specific local address +and a specific peer address, where an address is the two-tuple of IP address and +port. Path validation tests that packets can be both sent to and received from +a peer. + +Path validation is used during connection migration (see {{migration}}) by the +migrating endpoint to verify reachability of a peer from a new local address. +Path validation is also used by the peer to verify that the migrating endpoint +is able to receive packets sent to the its new address. That is, that the +packets received from the migrating endpoint do not carry a spoofed source +address. + +Path validation can be used at any time by either endpoint. For instance, an +endpoint might check that a peer is still in possession of its address after a +period of quiescence. + +Path validation is not designed as a NAT traversal mechanism. Though the +mechanism described here might be effective for the creation of NAT bindings +that support NAT traversal, the expectation is that one or other peer is able to +receive packets without first having sent a packet on that path. Effective NAT +traversal needs additional synchronization mechanisms that are not provided +here. + +An endpoint MAY bundle PATH_CHALLENGE and PATH_RESPONSE frames that are used for +path validation with other frames. For instance, an endpoint may pad a packet +carrying a PATH_CHALLENGE for PMTU discovery, or an endpoint may bundle a +PATH_RESPONSE with its own PATH_CHALLENGE. + + +### Initiation + +To initiate path validation, an endpoint sends a PATH_CHALLENGE frame containing +a random payload that is hard to guess on the path to be validated. + +An endpoint MAY send additional PATH_CHALLENGE frames to handle packet loss. An +endpoint SHOULD NOT send a PATH_CHALLENGE more frequently than it would an +Initial packet, ensuring that connection migration is no more load on a new path +than establishing a new connection. + +The endpoint MUST use fresh random data in every PATH_CHALLENGE frame so that it +can associate the peer's response with the causative PATH_CHALLENGE. + + +### Response + +On receiving a PATH_CHALLENGE frame, an endpoint MUST respond immediately by +echoing the data contained in the PATH_CHALLENGE frame in a PATH_RESPONSE frame, +with the following stipulation. Since a PATH_CHALLENGE might be sent from a +spoofed address, an endpoint MAY limit the rate at which it sends PATH_RESPONSE +frames and MAY silently discard PATH_CHALLENGE frames that would cause it to +respond at a higher rate. + +To ensure that packets can be both sent to and received from the peer, the +PATH_RESPONSE MUST be sent on the same path as the triggering PATH_CHALLENGE: +from the same local address on which the PATH_CHALLENGE was received, to the +same remote address from which the PATH_CHALLENGE was received. + + +### Completion + +A new address is considered valid when a PATH_RESPONSE frame is received +containing data that was sent in a previous PATH_CHALLENGE. Receipt of an +acknowledgment for a packet containing a PATH_CHALLENGE frame is not adequate +validation, since the acknowledgment can be spoofed by a malicious client. + +For path validation to be successful, a PATH_RESPONSE frame MUST be received +from the same remote address to which the corresponding PATH_CHALLENGE was +sent. If a PATH_RESPONSE frame is received from a different remote address than +the one to which the PATH_CHALLENGE was sent, path validation is considered to +have failed, even if the data matches that sent in the PATH_CHALLENGE. + +Additionally, the PATH_RESPONSE frame MUST be received on the same local address +from which the corresponding PATH_CHALLENGE was sent. If a PATH_RESPONSE frame +is received on a different local address than the one from which the +PATH_CHALLENGE was sent, path validation is considered to have failed, even if +the data matches that sent in the PATH_CHALLENGE. Thus, the endpoint considers +the path to be valid when a PATH_RESPONSE frame is received on the same path +with the same payload as the PATH_CHALLENGE frame. + + +### Abandonment + +An endpoint SHOULD abandon path validation after sending some number of +PATH_CHALLENGE frames or after some time has passed. When setting this timer, +implementations are cautioned that the new path could have a longer round-trip +time than the original. + +Note that the endpoint might receive packets containing other frames on the new +path, but a PATH_RESPONSE frame with appropriate data is required for path +validation to succeed. + +If path validation fails, the path is deemed unusable. This does not +necessarily imply a failure of the connection - endpoints can continue sending +packets over other paths as appropriate. If no paths are available, an endpoint +can wait for a new path to become available or close the connection. + +A path validation might be abandoned for other reasons besides +failure. Primarily, this happens if a connection migration to a new path is +initiated while a path validation on the old path is in progress. + + +## Client Connection Migration {#migration} + +QUIC allows connections to survive changes to endpoint addresses (that is, IP +address and/or port), such as those caused by a client migrating to a new +network. This section describes the protocol for migrating a connection to a +new client address. + +Migrating a connection to a new server address is left for future work. If a +client receives packets from a new server address, the client MAY discard these +packets. + + +### Initiating Connection Migration {#initiating-migration} + +A client can migrate a connection to a new local address by sending all packets +from the new local address. Since the server's address is validated during +connection establishment, receiving acknowledgments for this data serves as +proof of the server's reachability from the new address. Note that since +acknowledgments may be received on any path, return reachability on the new path +is not established. To establish return reachability on the new path, a client +MAY concurrently initiate path validation {{migrate-validate}} on the new path. + +If it has an opportunity, a client MAY probe for server reachability from a new +local address using path validation {{migrate-validate}} prior to migrating the +connection to the new local address. Failure of path validation simply means +that the new local address is not usable for this connection. Failure to +validate a path does not cause the connection to end unless there are no valid +alternative paths available. + +A client migrating to a new local address should use a new connection ID for +packets sent from that address, see {{migration-linkability}} for further +discussion. + +A client MUST NOT initiate connection migration before the handshake is +finished and the client has 1-RTT keys. + + +### Responding to Connection Migration + +A server may receive a packet from a new client address at any time during the +connection after the handshake is complete. If the packet is authenticated, the +client might be either probing from a new address or migrating immediately, as +described in {{initiating-migration}}. -An endpoint that receives packets that contain a source IP address and port that -has not yet been used can start sending new packets with those as a destination -IP address and port. Packets exchanged between endpoints can then follow the -new path. -Due to variations in path latency or packet reordering, packets from different -source addresses might be reordered. The packet with the highest packet number -MUST be used to determine which path to use. Endpoints also need to be prepared -to receive packets from an older source address. +#### Responding to a Client Probe -An endpoint MUST validate that its peer can receive packets at the new address -before sending any significant quantity of data to that address, or it risks -being used for denial of service. See {{migrate-validate}} for details. +Receiving a PATH_CHALLENGE frame from the client indicates that the client is +probing for server reachability on this new path. The server sends a +PATH_RESPONSE to the new client address as per {{migrate-validate}}, but the +server MUST continue using the current client address for sending all other +packets. + +PATH_CHALLENGE, PATH_RESPONSE, and PADDING frames are "probing" frames, and +receiving only these frames from a new client address MUST NOT result in the +server sending any other frames to that address. + +#### Responding to an Immediate Migration {#migration-response} + +Receiving a packet from a new client address indicates that the client may be +immediately migrating if + +* the packet is a "non-probing" packet. That is, it contains a frame other than +PATH_CHALLENGE, PATH_RESPONSE, and PADDING; and + +* the packet carries a packet number that is the largest seen thus far. + +Upon receiving such a packet, the server MUST abandon any path validation it is +performing with other addresses on the expectation that those validations are +likely to fail. Abandoning path validation primarily means ceasing subsequent +transmissions of the PATH_CHALLENGE frame. An endpoint MAY ignore any +subsequently received PATH_RESPONSE frames from abandoned addresses. + +In response to such a packet, the server MUST start sending subsequent packets +to this client address and MUST initiate path validation to verify client +ownership of the unvalidated address. + +A server MAY skip validation of a client address if it has been seen recently or +if the server has reasonable certainty that the new address is the result of a +NAT rebinding. + +Note that the server MAY send data to an unvalidated client address, but it MUST +protect against potential attacks as described in {{address-spoofing}} and +{{on-path-spoofing}}. + +If a non-probing packet is received from a new client address but with a packet +number that is not the largest seen thus far, it is likely that it is a +reordered packet sent from an older client address. The server processes this +packet as usual, but it MUST ignore this client address under the assumption +that it is not the client's most recent address. + +After verifying a new client address, the server SHOULD send new address +validation tokens ({{address-validation}}) to the client if the current ones +will not be adequate to validate the new client address. + + +#### Handling Address Spoofing by a Client {#address-spoofing} + +It is possible that the client is spoofing its source address to cause the +server to send excessive amounts of data to an unwilling host. If the server +sends significantly more data than the client, connection migration might be +used to amplify the volume of data that an attacker can generate toward a +victim. + +As described in {{migration-response}}, a server is required to validate the +client's new address to confirm the client's possession of the new address. +Until a client's address is deemed valid, the server MUST limit the rate at +which it sends data to this address. The server MUST NOT send more than a +minimum congestion window's worth of data per estimated round-trip time (as +defined in {{QUIC-RECOVERY}}). In the absence of this limit, the server risks +being used for a denial of service attack against an unsuspecting victim. Note +that since the server will not have any round-trip time measurements to the new +address, the estimate SHOULD be the default initial value (see +{{QUIC-RECOVERY}}). + +A server SHOULD NOT apply this rate limit when the server skips validation of a +client address, as described in {{migration-response}}. + + +#### Handling Address Spoofing by an On-path Attacker {#on-path-spoofing} + +An on-path attacker could cause a spurious connection migration by capturing and +forwarding a packet such that it arrives before the legitimate copy of that +packet. Such a packet will appear to be a legitimate connection migration and +the legitimate copy will be dropped as a duplicate. After a spurious migration, +validation of the source address will fail because the entity at the source +address does not have the necessary cryptographic keys to read or respond to the +PATH_CHALLENGE frame that is sent to it, even if it wanted to. + +To protect the connection from failing due to such a spurious migration, the +server MUST revert to using the last validated client address when validation of +a new client address fails. + +If the server has no state about the last validated client address, it MUST +close the connection silently by discarding all connection state. This results +in new packets on the connection being handled generically. For instance, an +endpoint MAY send a stateless reset in response to any further incoming packets. + +Note that receipt of packets with higher packet numbers from the legitimate +client address will trigger another connection migration. This will cause the +validation of the address of the spurious migration to be abandoned. + + +### Loss Detection and Congestion Control + +The capacity available on the new path might not be the same as the old path. +Packets sent on the old path SHOULD NOT contribute to the state of the +congestion control and RTT estimation on the new path. If it is using a single +congestion controller and round-trip time estimator, the client SHOULD reset +them prior to sending any non-probing packets from a new local address. + +After successful validation of the client's new address, the server SHOULD reset +its congestion controller and round-trip time estimator prior to sending any +further non-probing packets. + +An endpoint MUST NOT return to the send rate used for the previous path unless +it is reasonably sure that the previous send rate is valid for the new path. +For instance, a change in the client's port number is likely indicative of a +rebinding in a middlebox and not a complete change in path. This determination +likely depends on heuristics, which could be imperfect; if the new path capacity +is significantly reduced, ultimately this relies on the congestion controller +responding to congestion signals and reducing send rates appropriately. + +There may be apparent reordering at the receiver when an endpoint sends data and +probes from/to multiple addresses during the migration period, since the two +resulting paths may have different round-trip times. A receiver of packets on +multiple paths will still send ACK frames covering all received packets. + +An endpoint MAY use a single congestion control context and a single loss +recovery context, as described in {{QUIC-RECOVERY}}. A sender MAY make +exceptions for probe packets so that their loss detection is independent and +does not unduly cause the congestion controller to reduce its sending rate. For +instance, an endpoint may run a separate alarm when a PATH_CHALLENGE is sent, +which is disarmed when the corresponding PATH_RESPONSE is received. If the +alarm fires before the PATH_RESPONSE is received, the endpoint might send a new +PATH_CHALLENGE, and restart the alarm for a longer period of time. ### Privacy Implications of Connection Migration {#migration-linkability} @@ -1505,7 +1765,7 @@ being used for denial of service. See {{migrate-validate}} for details. Using a stable connection ID on multiple network paths allows a passive observer to correlate activity between those paths. A client that moves between networks might not wish to have their activity correlated by any entity other than a -server. The NEW_CONNECTION_ID message can be sent by a server to provide an +server. The NEW_CONNECTION_ID message can be sent by a server to provide an unlinkable connection ID for use in case the client wishes to explicitly break linkability between two points of network attachment. @@ -1519,7 +1779,7 @@ used in the order in which they are numbered. A client which wishes to break linkability upon changing networks MUST use the connection ID provided by the server as well as incrementing the packet sequence number by an externally unpredictable value computed as described in -{{packet-number-gap}}. Packet number gaps are cumulative. A client might skip +{{packet-number-gap}}. Packet number gaps are cumulative. A client might skip connection IDs, but it MUST ensure that it applies the associated packet number gaps for connection IDs that it skips in addition to the packet number gap associated with the connection ID that it does use. @@ -1553,121 +1813,6 @@ number. "packet_number_secret" is derived from the TLS key exchange, as described in Section 5.6 of {{QUIC-TLS}}. -### Address Validation for Migrated Connections {#migrate-validate} - -An endpoint that receives a packet from a new remote IP address and port (or -just a new remote port) on packets from its peer is likely seeing a connection -migration at the peer. - -However, it is also possible that the peer is spoofing its source address in -order to cause the endpoint to send excessive amounts of data to an unwilling -host. If the endpoint sends significantly more data than the peer, connection -migration might be used to amplify the volume of data that an attacker can -generate toward a victim. - -Thus, when seeing a new remote transport address, an endpoint MUST verify that -its peer can receive and respond to packets at that new address. By providing -copies of the data that it receives, the peer proves that it is receiving -packets at the new address and consents to receive data. - -Prior to validating the new remote address, and endpoint MUST limit the amount -of data and packets that it sends to its peer. At a minimum, this needs to -consider the possibility that packets are sent without congestion feedback. - -Once a connection is established, address validation is relatively simple (see -{{address-validation}} for the process that is used during the handshake). An -endpoint validates a remote address by sending a PATH_CHALLENGE frame containing -a payload that is hard to guess. This frame MUST be sent in a packet that is -sent to the new address. Once a PATH_RESPONSE frame containing the same payload -is received, the address is considered to be valid. - -The new address is not considered valid until a PATH_RESPONSE frame containing -the same payload is received, even if the packet containing the PATH_CHALLENGE -frame is acknowledged. - -The PATH_RESPONSE frame can use any path on its return. - -An endpoint MAY send multiple PATH_CHALLENGE frames to handle packet loss or to -make additional measurements on a new network path. - -An endpoint MUST use fresh random data in every PATH_CHALLENGE frame so that it -can associate the peer's response with the causative PATH_CHALLENGE. - -If the PATH_CHALLENGE frame is determined to be lost, a new PATH_CHALLENGE frame -SHOULD be generated. This PATH_CHALLENGE frame MUST include new data that is -similarly difficult to guess. - -If validation of the new remote address fails, after allowing enough time for -recovering from possible loss of packets carrying PATH_CHALLENGE and -PATH_RESPONSE frames, the endpoint MUST terminate the connection. When setting -this timer, implementations are cautioned that the new path could have a longer -round trip time than the original. The endpoint MUST NOT send a -CONNECTION_CLOSE frame in this case; it has to assume that the remote peer -cannot want to receive any more packets. - -If the remote address is validated successfully, the endpoint MAY increase the -rate that it sends on the new path using the state from the previous path. The -capacity available on the new path might not be the same as the old path. An -endpoint MUST NOT restore its send rate unless it is reasonably sure that the -path is the same as the previous path. For instance, a change in only port -number is likely indicative of a rebinding in a middlebox and not a complete -change in path. This determination likely depends on heuristics, which could be -imperfect; if the new path capacity is significantly reduced, ultimately this -relies on the congestion controller responding to congestion signals and reduce -send rates appropriately. - -After verifying an address, the endpoint SHOULD update any address validation -tokens ({{address-validation}}) that it has issued to its peer if those are no -longer valid based on the changed address. - -Address validation using the PATH_CHALLENGE frame MAY be used at any time by -either peer. For instance, an endpoint might check that a peer is still in -possession of its address after a period of quiescence. - -Upon seeing a connection migration, an endpoint that sees a new address MUST -abandon any address validation it is performing with other addresses on the -expectation that the validation is likely to fail. Abandoning address -validation primarily means not closing the connection when a PATH_RESPONSE frame -is not received, but it could also mean ceasing subsequent transmissions of the -PATH_CHALLENGE frame. An endpoint MUST ignore any subsequently received -PATH_RESPONSE frames from that address. - - -## Spurious Connection Migrations - -A connection migration could be triggered by an attacker that is able to capture -and forward a packet such that it arrives before the legitimate copy of that -packet. Such a packet will appear to be a legitimate connection migration and -the legitimate copy will be dropped as a duplicate. - -After a spurious migration, validation of the source address will fail because -the entity at the source address does not have the necessary cryptographic keys -to read or respond to the PATH_CHALLENGE frame that is sent to it, even if it -wanted to. Such a spurious connection migration could result in the connection -being dropped when the source address validation fails. This grants an attacker -the ability to terminate the connection. - -Receipt of packets with higher packet numbers from the legitimate address will -trigger another connection migration. This will cause the validation of the -address of the spurious migration to be abandoned. - -To ensure that a peer sends packets from the legitimate address before the -validation of the new address can fail, an endpoint SHOULD attempt to validate -the old remote address before attempting to validate the new address. If the -connection migration is spurious, then the legitimate address will be used to -respond and the connection will migrate back to the old address. - -As with any address validation, packets containing a PATH_CHALLENGE frame -validating an address MUST be sent to the address being validated. -Consequently, during a migration of a peer, an endpoint could be sending to -multiple remote addresses. - -An endpoint MAY abandon address validation for an address that it considers to -be already valid. That is, if successive connection migrations occur in quick -succession with the final remote address being identical to the initial remote -address, the endpoint MAY abandon address validation for that address. - - ## Connection Termination {#termination} Connections should remain open until they become idle for a pre-negotiated @@ -1732,12 +1877,12 @@ An endpoint is not expected to handle key updates when it is closing or draining. A key update might prevent the endpoint from moving from the closing state to draining, but it otherwise has no impact. -An endpoint could receive packets from a new source address, indicating a +An endpoint could receive packets from a new source address, indicating a client connection migration ({{migration}}), while in the closing period. An endpoint in the closing state MUST strictly limit the number of packets it sends to this -new address as though the address were not validated (see {{migrate-validate}}). -A server in the closing state MAY instead choose to discard packets received -from a new source address. +new address until the address is validated (see {{migrate-validate}}). A server +in the closing state MAY instead choose to discard packets received from a new +source address. ### Idle Timeout @@ -2583,7 +2728,7 @@ to decipher the packet. ## PATH_CHALLENGE Frame {#frame-path-challenge} Endpoints can use PATH_CHALLENGE frames (type=0x0e) to check reachability to the -peer and for address validation during connection establishment and connection +peer and for path validation during connection establishment and connection migration. PATH_CHALLENGE frames contain an 8-byte payload. @@ -3459,7 +3604,7 @@ tradeoff between resource commitment and overhead when determining how large a limit is advertised. A receiver MAY use an autotuning mechanism to tune the frequency and amount that -it increases data limits based on a roundtrip time estimate and the rate at +it increases data limits based on a round-trip time estimate and the rate at which the receiving application consumes data, similar to common TCP implementations. @@ -3505,7 +3650,7 @@ entire round trip. For smooth operation of the congestion controller, it is generally considered best to not let the sender go into quiescence if avoidable. To avoid blocking a sender, and to reasonably account for the possibiity of loss, a receiver should -send a MAX_DATA or MAX_STREAM_DATA frame at least two roundtrips before it +send a MAX_DATA or MAX_STREAM_DATA frame at least two round trips before it expects the sender to get blocked. A sender sends a single BLOCKED or STREAM_BLOCKED frame only once when it