Change:
require different information in Retry, or use different packet type indicators. <ins> 7.1.1. Initial Packets are especially effective at consuming server resources because they cause the server to create connection state. Even when mitigating this load with Retry Packets, the act of validating an Initial Token and sending a Retry Packet is more expensive than the response to a non-Initial packet with an unknown Connection ID: simply dropping it and/or sending a Stateless Reset. Nevertheless, a Retry Service in Active Mode might desire to shield servers from non-Initial packets that do not correspond to a previously admitted Initial Packet.  This has a number of considerations. If a Retry Service maintains no per-flow state whatsoever, it cannot distinguish between valid and invalid non_Initial packets and MUST forward all non-Initial Packets to the server. For QUIC versions the Retry Service does not support and are present on the Allow-List (or absent from the Deny-List), the Retry Service cannot distinguish Initial Packets from other long headers and therefore MUST admit all long headers. If a Retry Service keeps per-flow state, it can identify 4-tuples that have been previously approved, admit non-Initial packets from those flows, and drop all others.  However, dropping short headers will effectively break Address Migration and NAT Rebinding when in Active Mode, as post-migration packets will arrive with a previously unknown 4-tuple.  This policy will also break connection attempts using any new QUIC versions that begin connections with a short header. If a Retry Service is integrated with a QUIC-LB compliant load balancer, it can verify that the Destination Connection ID is compliant, and only admit non-Initial packets with compliant DCIDs.  As the Connection ID encoding is invariant across QUIC versions, the Retry Service can do this for all short headers. Nothing in this section prevents Retry Services from making basic syntax correctness checks on packets with QUIC versions that it understands (e.g., enforcing the Initial Packet datagram size minimum in version 1) and dropping packets that are not compliant with the QUIC specification. </ins> 7.2. The no-shared-state retry service requires no coordination, except

Discussion:
In Section 7: "Retry services MUST forward all QUIC packets that are not of type Initial or 0-RTT. Other packet types might involve changed IP addresses or connection IDs, so it is not practical for Retry Services to identify such packets as valid or invalid." MUST is too strong. If it keeps any state (i.e. tracking 4-tuples) it can drop non-initial packets. (However, this would make migration not work). If the Retry Service is in front of a QUIC-LB load balancer, the LB will drop random 1-RTT packets but not Handshake and 0-RTT unless it is version-aware, so passing 1-RTT is "safe." If the Retry Service is behind the load balancer, which is probably better because LBs are often NATs, then random 1-RTT is already dropped and it is safe to forward 1-RTT to preserve migration. If there's a non QUIC-LB load balancers, migration doesn't work anyway; might as well drop it. If it's a single server and the CIDs are random, admitting 1-RTT is weakening the DoS defense. And then there is the issue with QUIC versions and admitting/dropping them, which is hard to adjudicate with short headers.
I don't know. Do you have a case where Retry services should not forward those packets? I don't want this to be a source of ossification because of a possibly incorrect assumption about placement of the retry service in the pipeline.
Well, the reason to not forward them is to block DDoS vectors. A garbage Handshake or 1-RTT packets is at least easily discarded by the server without much in the way of processing. I would actually appreciate some input from your Azure contacts about this; is filtering non-SYN packets important today?
Here's the data I can provide: As I understand it, the DDoS would be in front of the LB. It's all in hardware so it's update cycle could be very long, so any logic added there could effectively be written in stone for many years. So, I really want to be careful about any assumptions here.

If we get it wrong for a future version, either all of Azure might end up breaking/preventing future versions/features or we'd have to completely disable and lose the protection. On the topic of dropping garbage/invalid packets, I'd be Ok with that. Perhaps we could change the text to the following? This adds some wiggle room for what is considered "valid" or not. Obviously if the header is garbage it can be tossed. If a device knows a particular CID is invalid, then it could drop it. I'd just strongly caution any "smarts" here because of the possibility of changes in the future.
If "in front of the LB" is cancnical use case, I can shade the language towards that. However, this makes me wonder about the shared-state case. My perception is that combining a NAT with an LB is quite common; will shared token verification work if the server and retry service are seeing different client IP addresses? This calls into question the entire shared-state concept.